From 6b5f3228f80ad5c44d53d9e05d0e4b2dbbb3dba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrej=20Rama=C5=A1euski?= <andrej@x2.cz> Date: Tue, 22 Dec 2020 22:47:30 +0100 Subject: [PATCH] Pocitani aktivnich uzivatelu, ban, unban, userinfo, autorizace v socketu --- lib/CF/Controller/Users.pm | 63 ++++++++++++++++++++++++++++ lib/CF/Controller/Websockets.pm | 35 +++++++++++++++- lib/CF/Schema/Result/Announcement.pm | 3 +- lib/CF/Schema/Result/User.pm | 15 +++++++ openapi.yaml | 61 ++++++++++++++++++++++++++- sql/1/up.sql | 2 + 6 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 lib/CF/Controller/Users.pm diff --git a/lib/CF/Controller/Users.pm b/lib/CF/Controller/Users.pm new file mode 100644 index 0000000..6d6ba2c --- /dev/null +++ b/lib/CF/Controller/Users.pm @@ -0,0 +1,63 @@ +package CF::Controller::Users; + +use Mojo::Base 'Mojolicious::Controller'; +use Mojo::Pg::PubSub; +use feature 'signatures'; +no warnings qw{ experimental::signatures }; + +sub me ($c){ + my $user = $c->_get( $c->user->{id} ) // return; + $c->render(openapi => $c->spec_filter($user->formatted, 'User')); +} + +sub ban ($c){ + my $user = $c->_get( $c->stash->{id} ) // return; + my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); + my $guard = $c->schema->txn_scope_guard; + + $user->update({ banned_until => \"now()+'8 hour'", }); + #TODO: ANN + + $pubsub->json('notify')->notify( notify => { + event => 'user_banned', + payload => $c->spec_filter($user->formatted, 'User'), + }); + + $guard->commit; + $c->render(status => 204, text => ''); +} + +sub unban ($c){ + my $user = $c->_get( $c->stash->{id} ) // return; + my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); + my $guard = $c->schema->txn_scope_guard; + + + $user->update({ banned_until => undef }); + #TODO: ANN + + $pubsub->json('notify')->notify( notify => { + event => 'user_unbanned', + payload => $c->spec_filter($user->formatted, 'User'), + }); + + $guard->commit; + $c->render(status => 204, text => ''); +} + +sub _get ($c, $id ) { + + my $user; + + if ( $id =~ /^\d+$/) { + $user = $c->schema->resultset('User')->find( { id => $id } ); + } + else { + $user = $c->schema->resultset('User')->find( { uuid => $id } ); + } + + return $c->error(404, 'User not found') if ! $user; + return $user; +} + +1; diff --git a/lib/CF/Controller/Websockets.pm b/lib/CF/Controller/Websockets.pm index 04bad7e..3b3daf9 100644 --- a/lib/CF/Controller/Websockets.pm +++ b/lib/CF/Controller/Websockets.pm @@ -2,13 +2,32 @@ package CF::Controller::Websockets; use Mojo::Base 'Mojolicious::Controller'; use Mojo::Pg::PubSub; +use JSON; use feature 'signatures'; no warnings qw{ experimental::signatures }; +use constant SOCKET_INACTIVITY_TIMEOUT => 300; +use constant USER_ALIVE_TIMEOUT => 100; + sub main { my $c = shift; - $c->inactivity_timeout(600); + $c->inactivity_timeout(SOCKET_INACTIVITY_TIMEOUT); + + my $user; + + if ( my $key = $c->req->headers->authorization ) { + if ( $key =~ s/Bearer\s+//i ) { + $c->oauth_token($key); + + if ( $c->user ) { + $user = $c->schema->resultset('User')->find_or_create( + $c->user, { key => 'uuid'} + ); + } + } + } + my $pubsub = Mojo::Pg::PubSub->new(pg => $c->pg); @@ -16,6 +35,20 @@ sub main { $c->send($payload); }); + $c->on(message => sub( $c, $message ) { + $user->update({keepalive => \'now()'}) if $user; + + my $min_alive_time = "now() - '" . USER_ALIVE_TIMEOUT. " s'::interval"; + + my $alive = $c->schema->resultset('User')->count( + { + keepalive => { '>' => \$min_alive_time }, + } + ); + $c->send(to_json({ online_users => $alive })); + + }); + $c->on(finish => sub ($c, $code, $reason = undef) { $pubsub->unlisten('notify'); $c->app->log->debug("WebSocket closed with status $code"); diff --git a/lib/CF/Schema/Result/Announcement.pm b/lib/CF/Schema/Result/Announcement.pm index 97c4159..bf12c5b 100644 --- a/lib/CF/Schema/Result/Announcement.pm +++ b/lib/CF/Schema/Result/Announcement.pm @@ -29,7 +29,6 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key('id'); -1; sub format { my $self = shift; @@ -46,3 +45,5 @@ sub format { return $announcement; } + +1; diff --git a/lib/CF/Schema/Result/User.pm b/lib/CF/Schema/Result/User.pm index bc54616..3bf40ca 100644 --- a/lib/CF/Schema/Result/User.pm +++ b/lib/CF/Schema/Result/User.pm @@ -22,6 +22,8 @@ __PACKAGE__->add_columns( username name main_group_name + keepalive + banned_until ), ); @@ -36,4 +38,17 @@ __PACKAGE__->has_many( { 'foreign.user_id' => 'self.id', }, ); +sub formatted { + my $self = shift; + + my $user = { + $self->get_columns, + group => $self->main_group_name, + is_banned => $self->banned_until ? 1:0, + }; + + return $user; + +} + 1; diff --git a/openapi.yaml b/openapi.yaml index 2e30286..41226eb 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -92,7 +92,7 @@ components: type: string originator: type: string - Author: + User: type: object properties: id: @@ -103,6 +103,8 @@ components: type: string username: type: string + is_banned: + type: boolean Announcement: type: object description: Notifikace @@ -144,7 +146,7 @@ components: is_archived: type: boolean author: - $ref: '#/components/schemas/Author' + $ref: '#/components/schemas/User' ranking: $ref: '#/components/schemas/Ranking' history_log: @@ -419,6 +421,18 @@ paths: 204: description: Post updated + delete: + x-mojo-to: posts#delete + security: + - Bearer: ['chairman'] + tags: + - posts + summary: "Smazat zpravu" + operationId: deletePost + responses: + 204: + description: Post deleted + /posts/{id}/like: patch: security: @@ -460,3 +474,46 @@ paths: responses: 204: description: Post disliked + + /users/me: + get: + x-mojo-to: users#me + security: + - Bearer: [] + tags: + - users + summary: "Detail uzivatele" + operationId: getCurrentUser + responses: + 200: + description: User + content: + application/json: + schema: + $ref: '#/components/schemas/User' + + /users/{id}/ban: + patch: + security: + - Bearer: ['chairman'] + x-mojo-to: users#ban + tags: + - users + summary: Ban user + operationId: banUser + responses: + 204: + description: User banned + + /users/{id}/unban: + patch: + security: + - Bearer: ['chairman'] + x-mojo-to: users#unban + tags: + - users + summary: Unban user + operationId: UnbanUser + responses: + 204: + description: User banned diff --git a/sql/1/up.sql b/sql/1/up.sql index 8917a50..b7e7770 100644 --- a/sql/1/up.sql +++ b/sql/1/up.sql @@ -21,6 +21,8 @@ create table "users" ( "username" text, "name" text, "main_group_name" text, + "keepalive" timestamp, + "banned_until" timestamp, primary key("id"), unique("uuid") ); -- GitLab