From 44c3ff44219807d533315afffcf9623d042c4287 Mon Sep 17 00:00:00 2001 From: Kayden Tebau Date: Fri, 4 Nov 2022 17:31:41 -0700 Subject: [PATCH] Add pins --- .gitignore | 2 +- .idea/codeStyles/codeStyleConfig.xml | 5 ++ Makefile.PL | 5 +- ipfs-pinning-service.yaml | 7 ++- ipfs_pinning_mojo.default.yml | 3 - ipfs_upload.default.yml | 12 ++++ lib/IpfsUpload.pm | 63 +++++++++++++++++++++ lib/IpfsUpload/Controller/Example.pm | 11 ++++ lib/IpfsUpload/Controller/Login.pm | 21 +++++++ lib/IpfsUpload/Controller/Pins.pm | 42 ++++++++++++++ lib/IpfsUpload/Model/Pins.pm | 22 +++++++ lib/IpfsUpload/Model/Users.pm | 21 +++++++ lib/IpfsUpload/Util.pm | 17 ++++++ lib/ipfs_pinning_mojo.pm | 20 ------- lib/ipfs_pinning_mojo/Controller/Example.pm | 11 ---- schema.psql | 32 +++++++++++ script/{ipfs-pinning-mojo => IpfsUpload} | 2 +- t/basic.t | 2 +- 18 files changed, 259 insertions(+), 39 deletions(-) create mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 ipfs_pinning_mojo.default.yml create mode 100644 ipfs_upload.default.yml create mode 100644 lib/IpfsUpload.pm create mode 100644 lib/IpfsUpload/Controller/Example.pm create mode 100644 lib/IpfsUpload/Controller/Login.pm create mode 100644 lib/IpfsUpload/Controller/Pins.pm create mode 100644 lib/IpfsUpload/Model/Pins.pm create mode 100644 lib/IpfsUpload/Model/Users.pm create mode 100644 lib/IpfsUpload/Util.pm delete mode 100644 lib/ipfs_pinning_mojo.pm delete mode 100644 lib/ipfs_pinning_mojo/Controller/Example.pm create mode 100644 schema.psql rename script/{ipfs-pinning-mojo => IpfsUpload} (78%) diff --git a/.gitignore b/.gitignore index 99128f2..2548474 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -ipfs_pinning_mojo.yml +ipfs_upload.yml diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/Makefile.PL b/Makefile.PL index 3b78f8e..a8ae086 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -6,7 +6,10 @@ use ExtUtils::MakeMaker; WriteMakefile( VERSION => '0.01', PREREQ_PM => { - 'Mojolicious' => '9.27', + 'Mojolicious' => '9.27', + 'Mojolicious::Plugin::OpenAPI' => '5.07', + 'Mojo::Pg' => '4.27', + 'DateTime::Format::Pg' => '0.16001' }, test => {TESTS => 't/*.t'} ); diff --git a/ipfs-pinning-service.yaml b/ipfs-pinning-service.yaml index 8c38988..9127b1c 100644 --- a/ipfs-pinning-service.yaml +++ b/ipfs-pinning-service.yaml @@ -275,7 +275,7 @@ Pin objects can be listed by executing `GET /pins` with optional parameters: " servers: - - url: https://pinning-service.example.com + - url: "/api/" tags: - name: pins @@ -283,6 +283,7 @@ tags: paths: /pins: get: + x-mojo-to: "Pins#list" operationId: getPins summary: List pin objects description: List all the pin objects, matching optional filters; when no filter is provided, only successful pins are returned @@ -317,6 +318,7 @@ paths: '5XX': $ref: '#/components/responses/InternalServerError' post: + x-mojo-to: "Pins#add" operationId: addPin summary: Add pin object description: Add a new pin object for the current access token @@ -356,6 +358,7 @@ paths: schema: type: string get: + x-mojo-to: "Pins#get" operationId: getPinByRequestId summary: Get pin object description: Get a pin object and its status @@ -381,6 +384,7 @@ paths: '5XX': $ref: '#/components/responses/InternalServerError' post: + x-mojo-to: "Pins#replace" operationId: replacePinByRequestId summary: Replace pin object description: Replace an existing pin object (shortcut for executing remove and add operations in one step to avoid unnecessary garbage collection of blocks present in both recursive pins) @@ -412,6 +416,7 @@ paths: '5XX': $ref: '#/components/responses/InternalServerError' delete: + x-mojo-to: "Pins#delete" operationId: deletePinByRequestId summary: Remove pin object description: Remove a pin object diff --git a/ipfs_pinning_mojo.default.yml b/ipfs_pinning_mojo.default.yml deleted file mode 100644 index 7bd21b0..0000000 --- a/ipfs_pinning_mojo.default.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -secrets: - - HERE diff --git a/ipfs_upload.default.yml b/ipfs_upload.default.yml new file mode 100644 index 0000000..cd9e9e8 --- /dev/null +++ b/ipfs_upload.default.yml @@ -0,0 +1,12 @@ +--- +secrets: + - HERE + +database: + type: 'postgres' + connection: 'postgresql://' + +ipfs: + gatewayWriteUrl: "http://localhost:5001/" + delegates: + - "/ip4/203.0.113.1/tcp/4001/p2p/QmServicePeerId" diff --git a/lib/IpfsUpload.pm b/lib/IpfsUpload.pm new file mode 100644 index 0000000..c17ee00 --- /dev/null +++ b/lib/IpfsUpload.pm @@ -0,0 +1,63 @@ +package IpfsUpload; +use strict; +use warnings FATAL => 'all'; +use experimental q/signatures/; + +use Mojo::Base 'Mojolicious', -signatures; +use Mojo::Pg; +use IpfsUpload::Model::Users; +use IpfsUpload::Model::Pins; + +# This method will run once at server start +sub startup($self) { + + # Load configuration from config file + my $config = $self->plugin('NotYAMLConfig'); + + $self->plugin( + OpenAPI => { + url => $self->home->rel_file("ipfs-pinning-service.yaml"), + security => { + accessToken => sub($c, $def, $scopes, $cb) { + my $auth = $c->req->headers->authorization; + if (defined $auth) { + $auth =~ s/Bearer //; + my $uid = $c->users->id($auth); + if (defined $uid) { + $c->stash(uid => $uid); + return $c->$cb(); + } + } + return $c->$cb('Authorization header not present'); + }, + }, + }, + ); + + if ($config->{database}->{type} ne "postgres") { + die "Only postgres is supported"; + } + + $self->helper(pg => sub ($app) { + state $pg = Mojo::Pg->new($config->{'database'}->{connection}); + }); + + $self->helper(pins => sub ($app) { + state $pins = IpfsUpload::Model::Pins->new(pg => $app->pg); + }); + + $self->helper(users => sub ($app) { + state $users = IpfsUpload::Model::Users->new(pg => $app->pg); + }); + + # Configure the application + $self->secrets($config->{secrets}); + + # Router + my $r = $self->routes; + + # Normal route to controller + $r->get('/')->to('Example#welcome'); +} + +1; diff --git a/lib/IpfsUpload/Controller/Example.pm b/lib/IpfsUpload/Controller/Example.pm new file mode 100644 index 0000000..5e9b58c --- /dev/null +++ b/lib/IpfsUpload/Controller/Example.pm @@ -0,0 +1,11 @@ +package IpfsUpload::Controller::Example; +use Mojo::Base 'Mojolicious::Controller', -signatures; + +# This action will render a template +sub welcome($self) { + + # Render template "example/welcome.html.ep" with message + $self->render(msg => 'Welcome to the Mojolicious real-time web framework!'); +} + +1; diff --git a/lib/IpfsUpload/Controller/Login.pm b/lib/IpfsUpload/Controller/Login.pm new file mode 100644 index 0000000..148e8fb --- /dev/null +++ b/lib/IpfsUpload/Controller/Login.pm @@ -0,0 +1,21 @@ +package IpfsUpload::Controller::Login; +use strict; +use warnings FATAL => 'all'; +use experimental q/signatures/; + +use Mojo::Base 'Mojolicious::Controller', -signatures; +use Net::LDAPS; +use Net::LDAP::Extension::SetPassword; + +sub auth($c) { + $c->openapi->valid_input or return; + + my $token = $c->req->headers->authorization; + + $c->render(openapi => { + count => 0, + results => [], + }); +} + +1; diff --git a/lib/IpfsUpload/Controller/Pins.pm b/lib/IpfsUpload/Controller/Pins.pm new file mode 100644 index 0000000..9ca6513 --- /dev/null +++ b/lib/IpfsUpload/Controller/Pins.pm @@ -0,0 +1,42 @@ +package IpfsUpload::Controller::Pins; +use strict; +use warnings FATAL => 'all'; +use experimental q/signatures/; + +use Mojo::Base 'Mojolicious::Controller', -signatures; +use IpfsUpload::Util; + +sub list($c) { + $c->openapi->valid_input or return; + + my $uid = $c->stash('uid'); + + $c->pins->list({ + uid => $uid, + }, 10)->then(sub ($res) { + + my @formatted; + + for my $v (@$res) { + push @formatted, { + requestid => $v->{id}, + # TODO + status => "pinned", + created => IpfsUpload::Util::date_format($v->{created_at}), + pin => { + cid => $v->{cid}, + name => $v->{name}, + }, + delegates => $c->config->{ipfs}->{delegates}, + }; + } + + + $c->render(openapi => { + count => scalar(@formatted), + results => \@formatted, + }); + }); +} + +1; diff --git a/lib/IpfsUpload/Model/Pins.pm b/lib/IpfsUpload/Model/Pins.pm new file mode 100644 index 0000000..180e310 --- /dev/null +++ b/lib/IpfsUpload/Model/Pins.pm @@ -0,0 +1,22 @@ +package IpfsUpload::Model::Pins; +use strict; +use warnings FATAL => 'all'; +use experimental q/signatures/; + +use Mojo::Base -base, -signatures; + +has 'pg'; + +sub add($self, $pin) { + return $self->pg->db->insert_p('pins', $pin, {returning => 'id'})->then(sub ($res) { + return $res->hash->{id}; + }); +} + +sub list($self, $where, $limit) { + return $self->pg->db->select_p('pins', '*', $where, {order_by => {-desc => 'created_at'}, limit => $limit})->then(sub ($res) { + return $res->hashes; + }); +} + +1; diff --git a/lib/IpfsUpload/Model/Users.pm b/lib/IpfsUpload/Model/Users.pm new file mode 100644 index 0000000..efee6a7 --- /dev/null +++ b/lib/IpfsUpload/Model/Users.pm @@ -0,0 +1,21 @@ +package IpfsUpload::Model::Users; +use strict; +use warnings FATAL => 'all'; +use experimental q/signatures/; + +use Mojo::Base -base, -signatures; + +has 'pg'; + +sub id($self, $token) { + my $res = $self->pg->db->select('access_token', ['uid'], { token => $token })->hash; + + if (!defined $res) { + return undef; + } + + return $res->{uid}; +} + + +1; diff --git a/lib/IpfsUpload/Util.pm b/lib/IpfsUpload/Util.pm new file mode 100644 index 0000000..fcbd765 --- /dev/null +++ b/lib/IpfsUpload/Util.pm @@ -0,0 +1,17 @@ +package IpfsUpload::Util; +use strict; +use warnings FATAL => 'all'; +use experimental qw/signatures/; + +use Time::Piece; + + +sub date_format($date) { + print "$date\n"; + $date =~ s/ /T/; + $date =~ s/(\d\d)$/$1:00/; + print "$date\n"; + return $date; +} + +1; diff --git a/lib/ipfs_pinning_mojo.pm b/lib/ipfs_pinning_mojo.pm deleted file mode 100644 index b7c84f1..0000000 --- a/lib/ipfs_pinning_mojo.pm +++ /dev/null @@ -1,20 +0,0 @@ -package ipfs_pinning_mojo; -use Mojo::Base 'Mojolicious', -signatures; - -# This method will run once at server start -sub startup ($self) { - - # Load configuration from config file - my $config = $self->plugin('NotYAMLConfig'); - - # Configure the application - $self->secrets($config->{secrets}); - - # Router - my $r = $self->routes; - - # Normal route to controller - $r->get('/')->to('Example#welcome'); -} - -1; diff --git a/lib/ipfs_pinning_mojo/Controller/Example.pm b/lib/ipfs_pinning_mojo/Controller/Example.pm deleted file mode 100644 index d09d20c..0000000 --- a/lib/ipfs_pinning_mojo/Controller/Example.pm +++ /dev/null @@ -1,11 +0,0 @@ -package ipfs_pinning_mojo::Controller::Example; -use Mojo::Base 'Mojolicious::Controller', -signatures; - -# This action will render a template -sub welcome ($self) { - - # Render template "example/welcome.html.ep" with message - $self->render(msg => 'Welcome to the Mojolicious real-time web framework!'); -} - -1; diff --git a/schema.psql b/schema.psql new file mode 100644 index 0000000..6257503 --- /dev/null +++ b/schema.psql @@ -0,0 +1,32 @@ +create table users +( + uid uuid default gen_random_uuid() not null + constraint users_pk primary key, + username varchar(64) not null +); + + +create table pins +( + id uuid default gen_random_uuid() not null + constraint pins_pk + primary key, + created_at date default now() not null, + cid varchar(128) not null, + name varchar(512), + uid uuid not null + constraint pins_uid_users_uid_fk + references users (uid) +); + + +create table access_token +( + uid uuid not null + constraint access_token_users_null_fk + references users (uid), + token varchar(512) not null + constraint access_token_pk + primary key +); + diff --git a/script/ipfs-pinning-mojo b/script/IpfsUpload similarity index 78% rename from script/ipfs-pinning-mojo rename to script/IpfsUpload index c30d63a..c613c65 100755 --- a/script/ipfs-pinning-mojo +++ b/script/IpfsUpload @@ -8,4 +8,4 @@ use lib curfile->dirname->sibling('lib')->to_string; use Mojolicious::Commands; # Start command line interface for application -Mojolicious::Commands->start_app('ipfs_pinning_mojo'); +Mojolicious::Commands->start_app('IpfsUpload'); diff --git a/t/basic.t b/t/basic.t index 965f1fc..10850e2 100644 --- a/t/basic.t +++ b/t/basic.t @@ -3,7 +3,7 @@ use Mojo::Base -strict; use Test::More; use Test::Mojo; -my $t = Test::Mojo->new('ipfs_pinning_mojo'); +my $t = Test::Mojo->new('IpfsUpload'); $t->get_ok('/')->status_is(200)->content_like(qr/Mojolicious/i); done_testing();