package CF::Controller::Posts; use Mojo::Base 'Mojolicious::Controller'; use Mojo::Pg::PubSub; use feature 'signatures'; no warnings qw{ experimental::signatures }; sub create ($c) { $c->openapi->valid_input or return; my $args = $c->req->json; my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); # Navrh postupu muze predlozit jenom clen if ( $args->{type} == 0 && ! $c->user_roles->{member} ) { return $c->error(401, 'Insufficient permissions'); } my $program_entry = $c->schema->resultset('ProgramEntry')->search({ is_live => 1, })->first; # Neni zadny aktivnibod rozpravy if ( ! $program_entry ) { return $c->error(403, 'Debate closed'); } my $post = $program_entry->add_to_posts({ user_id => $c->user->{id}, type => $args->{type}, content => $args->{content}, }); $pubsub->json('posts')->notify( posts => { event => 'created', payload => $post->view->format(), }); $c->render( status => 201, openapi => { id => $post->id }, ); }; sub get ($c) { $c->openapi->valid_input or return; my $post = $c->schema->resultset('Post_view')->find($c->stash->{id}); return $c->error(404, 'Post not found') if ! $post; my $formatted = $post->format(); if (my $my_vote = $post->rankings({ user_id => $c->user->{id} })->first) { $formatted->{ranking}{my_vote} = $my_vote->ranking; } foreach my $history ( $post->history() ) { push @{ $formatted->{history_log} }, { attribute => 'content', value => $history->content, datetime => $history->datetime, originator => '', } } $c->render(openapi => $c->spec_filter($formatted, 'Post')); } sub list ($c) { $c->openapi->valid_input or return; my $args = $c->validation->output; my ($cond, $attrs) = $c->search_parametrs( $args ); # Vzdy jen k jednemu programovemu bodu - parametr nebo aktualni if ( $args->{program_entry_id} ) { $cond->{program_entry_id} = $args->{program_entry_id}; } else { my $program_entry = $c->schema->resultset('ProgramEntry')->search({ is_live => 1, })->first; # Neni zadny aktivnibod rozpravy if ( ! $program_entry ) { return $c->error(403, 'Debate closed'); } $cond->{program_entry_id} = $program_entry->id; } if ( exists $args->{archived} && defined $args->{archived}) { $cond->{is_archived} = $args->{archived}; } # omezeni zobrazovani nepotvrzenych navrhu postupu if ( $args->{type} ) { $cond->{type} = $args->{type}; if ( $args->{type} == 0 && ! $c->user_roles->{chairman} ) { $cond->{state} = {'-in' => [1,2,3,4]} } } elsif (! $c->user_roles->{chairman}) { $cond->{'-or'} = { type => 1, state => { '-in' => [1,2,3,4] }, }; } # hodnoceni aktualniho uzivatele my $my_vote = {}; my $rankings = $c->schema->resultset('PostRanking')->search({ user_id => $c->user->{id} }); while ( my $record = $rankings->next() ) { $my_vote->{ $record->post_id } = $record->ranking; } my @posts = (); my $count = $c->schema->resultset('Post_view')->count($cond); if ( $count ) { my $posts = $c->schema->resultset('Post_view')->search($cond, $attrs); POST: while ( my $post = $posts->next() ) { my $formatted = $post->format(); $formatted->{ranking}{my_vote} = $my_vote->{ $post->id } // 0; push @posts, $c->spec_filter($formatted, 'Post'); } } $c->render(json => { data => \@posts, total => $count, }); } sub update ($c) { $c->openapi->valid_input or return; my $args = $c->req->json; my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); my $update = {}; my $post = $c->schema->resultset('Post')->find($c->stash->{id}); return $c->error(404, 'Post not found') if ! $post; if ( ! $c->user_roles->{chairman} ) { if ( $post->user_id != $c->user->{id} ) { return $c->error(403, 'Access deined'); } else { delete $args->{is_archived}; delete $args->{state}; } } foreach my $key (qw(is_archoved state content)) { $update->{$key} = $args->{$key} if exists $args->{$key}; } my $guard = $c->schema->txn_scope_guard; $post->add_to_history({ user_id => $c->user->{id}, datetime => $post->changed // $post->datetime, content => $post->content, }); $post->update({ %{ $update }, changed => \'now()', }); $pubsub->json('posts')->notify( posts => { event => 'changed', payload => { id => $post->id, %{ $update }, } }); $guard->commit; $c->render(status => 204, text => ''); } sub ranking ($c) { $c->openapi->valid_input or return; my $args = $c->validation->output; my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); my $post = $c->schema->resultset('Post')->find($c->stash->{id}); return $c->error(404, 'Post not found') if ! $post; my $user_ranking = $post->rankings({ user_id => $c->user->{id}, })->first; my $update = { ranking_likes => $post->ranking_likes, ranking_dislikes => $post->ranking_dislikes, }; my $user_ranking_update; if ($user_ranking && $user_ranking->ranking == $args->{ranking} ) { $user_ranking_update = 0; } else { $user_ranking_update = $args->{ranking}; } if ($user_ranking && $user_ranking->ranking == 1 ) { $update->{ranking_likes}--; $update->{ranking_dislikes}++ if $args->{ranking} == -1; } elsif ($user_ranking && $user_ranking->ranking == -1 ) { $update->{ranking_dislikes}--; $update->{ranking_likes}++ if $args->{ranking} == 1; } else { $update->{ranking_likes}++ if $args->{ranking} == 1; $update->{ranking_dislikes}++ if $args->{ranking} == -1; } my $guard = $c->schema->txn_scope_guard; $post->update( $update ); if ( $user_ranking ) { $user_ranking->update( { ranking => $user_ranking_update } ); } else { $post->add_to_rankings({ user_id => $c->user->{id}, ranking => $user_ranking_update, }); } $pubsub->json('posts')->notify(posts => { event => 'ranked', payload => { id => $post->id, %{ $update }, } }); $guard->commit; $c->render(status => 204, text => ''); } sub ws { my $c = shift; $c->inactivity_timeout(600); my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); $pubsub->listen(posts => sub($pubsub, $payload) { if ( $payload->{type} == 0 && $payload->{state} == 0 && ! $c->user_roles->{chairman} ) { return; } $c->send($payload); }); $c->on(finish => sub ($c, $code, $reason = undef) { $pubsub->unlisten('streams'); $c->app->log->debug("WebSocket closed with status $code"); }); } 1;