This commit is contained in:
Citlali del Rey 2022-11-04 17:31:41 -07:00
parent d051ed2777
commit 44c3ff4421
Signed by: nullobsi
GPG Key ID: 933A1F44222C2634
18 changed files with 259 additions and 39 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
ipfs_pinning_mojo.yml
ipfs_upload.yml

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@ -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'}
);

View File

@ -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

View File

@ -1,3 +0,0 @@
---
secrets:
- HERE

12
ipfs_upload.default.yml Normal file
View File

@ -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"

63
lib/IpfsUpload.pm Normal file
View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

17
lib/IpfsUpload/Util.pm Normal file
View File

@ -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;

View File

@ -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;

View File

@ -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;

32
schema.psql Normal file
View File

@ -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
);

View File

@ -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');

View File

@ -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();