package Gitprep::API; use Mojo::Base -base; use Digest::MD5 'md5_hex'; use Text::Markdown::Hoedown qw(HOEDOWN_EXT_FENCED_CODE HOEDOWN_EXT_TABLES HOEDOWN_EXT_NO_INTRA_EMPHASIS); has 'cntl'; sub get_pull_request_count { my ($self, $user_id, $project_id, $opt) = @_; $opt ||= {}; my $project_row_id = $self->get_project_row_id($user_id, $project_id); my $where = $self->app->dbi->where; my $clause = ['and', 'pull_request <> 0', ':project{=}']; my $param = {project => $project_row_id}; # Open if (exists $opt->{open}) { push @$clause, ':issue.open{=}'; $param->{'issue.open'} = $opt->{open}; } $where->clause($clause); $where->param($param); my $pull_request_count = $self->app->dbi->model('issue')->select( 'count(*)', where => $where )->value; return $pull_request_count; } sub get_open_pull_request_count { my ($self, $user_id, $project_id) = @_; return $self->get_pull_request_count($user_id, $project_id, {open => 1}); } sub get_close_pull_request_count { my ($self, $user_id, $project_id) = @_; return $self->get_pull_request_count($user_id, $project_id, {open => 0}); } sub get_issue_count { my ($self, $user_id, $project_id, $opt) = @_; $opt ||= {}; my $project_row_id = $self->get_project_row_id($user_id, $project_id); my $where = $self->app->dbi->where; my $clause = ['and', 'pull_request = 0', ':project{=}']; my $param = {project => $project_row_id}; # Open if (exists $opt->{open}) { push @$clause, ':issue.open{=}'; $param->{'issue.open'} = $opt->{open}; } $where->clause($clause); $where->param($param); my $issue_count = $self->app->dbi->model('issue')->select( 'count(*)', where => $where )->value; return $issue_count; } sub get_open_issue_count { my ($self, $user_id, $project_id) = @_; return $self->get_issue_count($user_id, $project_id, {open => 1}); } sub get_close_issue_count { my ($self, $user_id, $project_id) = @_; return $self->get_issue_count($user_id, $project_id, {open => 0}); } sub api_update_issue_message { my ($self, $issue_message_row_id, $message, $user_id) = @_; my $issue_message = $self->app->dbi->model('issue_message')->select( {user => ['id']}, where => {'issue_message.row_id' => $issue_message_row_id} )->one; my $session_user_id = $self->session_user_id; my $is_my_project = $user_id eq $session_user_id; my $is_my_comment = $issue_message->{'user.id'} eq $session_user_id; my $can_modify = $is_my_project || $is_my_comment; my $json; if ($can_modify) { my $now_tm = Time::Moment->now; my $update_time = $now_tm->epoch; $self->app->log->info($update_time); $self->app->dbi->model('issue_message')->update( { message => $message, update_time => $update_time }, where => {row_id => $issue_message_row_id} ); my $markdown_message = $self->markdown($message); $json = { success => 1, markdown_message => $markdown_message }; } else { $json = {success => 0}; } return $json; } sub api_delete_issue_message { my ($self, $issue_message_row_id, $user_id) = @_; my $issue_message = $self->app->dbi->model('issue_message')->select( {user => ['id']}, where => {'issue_message.row_id' => $issue_message_row_id} )->one; my $session_user_id = $self->session_user_id; my $is_my_project = $user_id eq $session_user_id; my $is_my_comment = $issue_message->{'user.id'} eq $session_user_id; my $can_modify = $is_my_project || $is_my_comment; my $json; if ($can_modify) { $self->app->dbi->model('issue_message')->delete( where => {row_id => $issue_message_row_id} ); $json = {success => 1}; } else { $json = {success => 0}; } return $json; } sub add_issue_message { my ($self, $user_id, $project_id, $number, $message) = @_; $self->app->dbi->connector->txn(sub { my $issue_row_id = $self->app->dbi->model('issue')->select( 'issue.row_id', where => { 'project__user.id' => $user_id, 'project.id' => $project_id, number => $number } )->value; # Issue message number my $issue_message_number = $self->app->dbi->model('issue_message')->select( 'max(number)', where => {issue => $issue_row_id} )->value; $issue_message_number++; # New issue message my $now_tm = Time::Moment->now_utc; my $now_epoch = $now_tm->epoch; my $session_user_row_id = $self->session_user_row_id; my $new_issue_message = { issue => $issue_row_id, number => $issue_message_number, message => $message, create_time => $now_epoch, update_time => $now_epoch, user => $session_user_row_id }; $self->app->dbi->model('issue_message')->insert($new_issue_message); }); } sub markdown { my ($self, $markdown_text) = @_; # Remove script tags $markdown_text =~ s/\<\s*script\s*.*?\>//g; $markdown_text =~ s/\<\s*\/\s*script\s*.*?\>//g; my $html_text = Text::Markdown::Hoedown::markdown( $markdown_text, extensions => HOEDOWN_EXT_FENCED_CODE|HOEDOWN_EXT_TABLES|HOEDOWN_EXT_NO_INTRA_EMPHASIS ); return $html_text; } sub age_string { my ($self, $epoch_time) = @_; my $age = time - $epoch_time; my $age_string = $self->cntl->app->git->_age_string($age); return $age_string; } sub get_user_row_id { my ($self, $user_id) = @_; my $user_row_id = $self->app->dbi->model('user')->select('row_id', where => {id => $user_id})->value; return $user_row_id; } sub get_project_row_id { my ($self, $user_id, $project_id) = @_; my $user_row_id = $self->app->dbi->model('user')->select('row_id', where => {id => $user_id})->value; my $project_row_id = $self->app->dbi->model('project')->model('project')->select( 'row_id', where => {user => $user_row_id, id => $project_id} )->value; return $project_row_id; } sub app { shift->cntl->app } sub encrypt_password { my ($self, $password) = @_; my $salt; $salt .= int(rand 10) for (1 .. 40); my $password_encryped = md5_hex md5_hex "$salt$password"; return ($password_encryped, $salt); } sub check_password { my ($self, $password, $salt, $password_encrypted) = @_; return unless defined $password && $salt && $password_encrypted; return md5_hex(md5_hex "$salt$password") eq $password_encrypted; } sub check_user_and_password { my ($self, $user_id, $password) = @_; my $row = $self->app->dbi->model('user')->select(['password', 'salt'], where => {id => $user_id})->one; return unless $row; my $is_valid = $self->check_password( $password, $row->{salt}, $row->{password} ); return $is_valid; } sub is_collaborator { my ($self, $collaborator_id, $user_id, $project_id) = @_; my $user_row_id = $self->get_user_row_id($user_id); my $project_row_id = $self->app->dbi->model('project')->select( where => {user => $user_row_id, id => $project_id} )->value; my $collaborator_row_id = $self->get_user_row_id($collaborator_id); my $row = $self->app->dbi->model('collaboration')->select( where => {project => $project_row_id, user => $collaborator_row_id} )->one; return $row ? 1 : 0; } sub can_access_private_project { my ($self, $user_id, $project_id) = @_; my $session_user_row_id = $self->cntl->session('user_row_id'); return unless defined $session_user_row_id; my $session_user_id = $self->app->dbi->model('user')->select( 'id', where => {row_id => $session_user_row_id} )->value; my $is_valid = ($user_id eq $session_user_id || $self->is_collaborator($session_user_id, $user_id, $project_id)) && $self->logined; return $is_valid; } sub can_write_access { my ($self, $session_user_id, $user_id, $project_id) = @_; return unless $session_user_id; my $can_write_access = length $session_user_id && ( $session_user_id eq $user_id || $self->is_collaborator($session_user_id, $user_id, $project_id) ); return $can_write_access; } sub new { my ($class, $cntl) = @_; my $self = $class->SUPER::new(cntl => $cntl); return $self; } sub logined_admin { my $self = shift; # Controler my $c = $self->cntl; # Check logined as admin my $session_user_id = $self->session_user_id; return $self->app->manager->is_admin($session_user_id) && $self->logined($session_user_id); } sub session_user_row_id { my $self = shift; my $session_user_row_id = $self->cntl->session('user_row_id'); return $session_user_row_id; } sub session_user_id { my $self = shift; my $session_user_row_id = $self->cntl->session('user_row_id'); my $session_user_id = $self->app->dbi->model('user')->select( 'id', where => {row_id => $session_user_row_id} )->value; return $session_user_id; } sub logined { my ($self, $user_id) = @_; my $c = $self->cntl; my $dbi = $c->app->dbi; my $session_user_row_id = $c->session('user_row_id'); my $session_user_id = $self->session_user_id; my $password = $c->session('password'); return unless defined $password; my $correct_password = $dbi->model('user')->select( 'password', where => {row_id => $session_user_row_id} )->value; return unless defined $correct_password; my $logined; if (defined $user_id) { $logined = $user_id eq $session_user_id && $password eq $correct_password; } else { $logined = $password eq $correct_password } return $logined; } sub params { my $self = shift; my $c = $self->cntl; my %params; for my $name ($c->param) { my @values = $c->param($name); if (@values > 1) { $params{$name} = \@values; } elsif (@values) { $params{$name} = $values[0]; } } return \%params; } 1;