Allow uploading from the web

This commit is contained in:
Citlali del Rey 2022-11-09 19:28:43 -08:00
parent 58b8d33e69
commit 58888bd58d
Signed by: nullobsi
GPG Key ID: 933A1F44222C2634
7 changed files with 170 additions and 46 deletions

View File

@ -7,6 +7,7 @@ use Mojo::Base 'Mojolicious', -signatures;
use Mojo::Pg;
use IpfsUpload::Model::Users;
use IpfsUpload::Model::Pins;
use IpfsUpload::Util;
# This method will run once at server start
sub startup($self) {
@ -19,30 +20,11 @@ sub startup($self) {
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 $tinfo = $c->users->token_info($auth);
if (defined $tinfo) {
$c->stash(
uid => $tinfo->{uid},
app_name => $tinfo->{app_name}
);
return $c->$cb();
}
}
# Try session auth
my $uid = $c->session->{uid};
if (defined $uid) {
$c->stash(
uid => $uid,
app_name => 'WebInterface',
);
if (IpfsUpload::Util::check_auth($c)) {
return $c->$cb();
} else {
return $c->$cb('Authorization header not present');
}
return $c->$cb('Authorization header not present');
},
},
},
@ -80,6 +62,9 @@ sub startup($self) {
$r->post('/my/tokens/generate')->to('Interface#gen_token_post');
$r->get('/my/tokens/#id/delete')->to('Interface#del_token');
$r->get('/my/pins/#id/delete')->to('Interface#del_pin');
$r->get('/')->to('Interface#upload_get');
$r->post('/')->to('Interface#upload_post');
}
1;

View File

@ -4,13 +4,15 @@ use warnings FATAL => 'all';
use experimental q/signatures/;
use Mojo::Base 'Mojolicious::Controller', -signatures;
use IpfsUpload::Util;
sub landing($c) {
my $uid = $c->session->{uid};
if (!defined $uid) {
if (!IpfsUpload::Util::check_auth($c)) {
return $c->redirect_to("/login");
}
my $uid = $c->stash('uid');
my $gateway = $c->config->{ipfs}->{gatewayPubUrl};
my $limit = $c->param('limit') || 10;
@ -42,6 +44,7 @@ sub landing($c) {
}
sub token_list($c) {
# Token should only be managed through Session auth
my $uid = $c->session->{uid};
if (!defined $uid) {
return $c->redirect_to("/login");
@ -54,6 +57,7 @@ sub token_list($c) {
}
sub gen_token_post($c) {
# Token should only be managed through Session auth
my $uid = $c->session->{uid};
if (!defined $uid) {
return $c->redirect_to("/login");
@ -74,6 +78,7 @@ sub gen_token_post($c) {
}
sub gen_token_get($c) {
# Token should only be managed through Session auth
my $uid = $c->session->{uid};
if (!defined $uid) {
return $c->redirect_to("/login");
@ -83,6 +88,7 @@ sub gen_token_get($c) {
}
sub del_token($c) {
# Token should only be managed through Session auth
my $uid = $c->session->{uid};
if (!defined $uid) {
return $c->redirect_to("/login");
@ -95,11 +101,11 @@ sub del_token($c) {
}
sub del_pin($c) {
my $uid = $c->session->{uid};
my $id = $c->param('id');
if (!defined $uid) {
if (!IpfsUpload::Util::check_auth($c)) {
return $c->redirect_to("/login");
}
my $uid = $c->stash('uid');
my $id = $c->param('id');
return $c->pins->get({
id => $id,
@ -146,4 +152,82 @@ sub del_pin($c) {
});
}
sub upload_post($c) {
if (!IpfsUpload::Util::check_auth($c)) {
return $c->redirect_to("/login");
}
my $uid = $c->stash('uid');
my $app_name = $c->stash('app_name');
my $file = $c->req->upload('file');
my $filename = $file->filename;
my $is_browser = $c->param('is_browser');
# Ten megabytes
my $max_size = 10 * 1024 * 1024;
unless ($file) {
$c->flash(msg => "No file specified.");
return $c->redirect_to('/my');
}
if ($file->size > $max_size) {
$c->flash(msg => "Max file size reached. (10MB)");
return $c->redirect_to('/my');
}
# TODO: streaming somehow
my $file_content = $file->slurp;
my $ua = $c->ua;
my $url = Mojo::URL->new($c->config->{ipfs}->{gatewayWriteUrl});
my $pub_url = Mojo::URL->new($c->config->{ipfs}->{gatewayPubUrl});
$url->path("api/v0/add");
$url->query(
progress => "false",
pin => "true",
);
return $ua->post_p($url => form => {
file => {
content => $file_content,
filename => $filename,
'Content-Type' => $file->headers->content_type,
},
})->then(sub ($tx) {
my $res = $tx->result;
if ($res->is_success) {
# Now we do DB stuff.
return $c->pins->add({
cid => $res->json->{Hash},
name => $filename,
app_name => $app_name,
uid => $uid,
});
} else {
# TODO: read error and use appropriate response
say $res->body;
die "Failed to pin.";
}
})->then(sub ($res) {
$pub_url->path($res->{cid});
my $s = $pub_url->to_string;
if ($is_browser) {
$c->flash(msg => "File uploaded! $s");
return $c->redirect_to("/my");
}
return $c->render(text => $s);
});
}
sub upload_get ($c) {
if (!IpfsUpload::Util::check_auth($c)) {
return $c->redirect_to("/login");
}
return $c->render('interface/uploadPage');
}
1;

View File

@ -4,6 +4,7 @@ use warnings FATAL => 'all';
use experimental q/signatures/;
use Mojo::Base 'Mojolicious::Controller', -signatures;
use IpfsUpload::Util;
use Net::LDAPS;
sub auth($c) {
@ -38,9 +39,8 @@ sub auth($c) {
}
sub login($c) {
my $uid = $c->session->{uid};
if (defined $uid) {
return $c->redirect_to('my');
if (IpfsUpload::Util::check_auth($c)) {
return $c->redirect_to("/my");
}
return $c->render();
}

View File

@ -8,7 +8,7 @@ use Mojo::Base -base, -signatures;
has 'pg';
sub add($self, $pin) {
return $self->pg->db->insert_p('pins', $pin, {returning => ['id', 'created_at']})->then(sub ($res) {
return $self->pg->db->insert_p('pins', $pin, {returning => ['id', 'created_at', 'cid']})->then(sub ($res) {
return $res->hash;
});
}

View File

@ -14,4 +14,31 @@ sub date_format($date) {
return $date;
}
sub check_auth($c) {
my $auth = $c->req->headers->authorization;
if (defined $auth) {
$auth =~ s/Bearer //;
my $tinfo = $c->users->token_info($auth);
if (defined $tinfo) {
$c->stash(
uid => $tinfo->{uid},
app_name => $tinfo->{app_name}
);
return 1;
}
}
# Try session auth
my $uid = $c->session->{uid};
if (defined $uid) {
$c->stash(
uid => $uid,
app_name => 'WebInterface',
);
return 1;
}
return 0;
}
1;

View File

@ -11,22 +11,28 @@
</p>
% }
<table>
<tr>
<th>Token ID</th>
<th>App Name</th>
<th>Actions</th>
</tr>
% for my $token (@$tokens) {
<tr>
<td><%= $token->{id} %></td>
<td><%= $token->{app_name} %></td>
<td>
<a href="/my/tokens/<%= $token->{id} %>/delete">Delete</a>
</td>
</tr>
% }
% if (scalar @$tokens == 0) {
<p>Seems like there's nothing here.</p>
% } else {
<table>
<tr>
<th>Token ID</th>
<th>App Name</th>
<th>Actions</th>
</tr>
% for my $token (@$tokens) {
<tr>
<td><%= $token->{id} %></td>
<td><%= $token->{app_name} %></td>
<td>
<a href="/my/tokens/<%= $token->{id} %>/delete">Delete</a>
</td>
</tr>
% }
</table>
% }
<a href="/my/tokens/generate">
Generate Token

View File

@ -0,0 +1,22 @@
% layout "default";
% title "Uploads";
<h1>Upload</h1>
<p>Here you can upload files.</p>
% if (my $msg = flash 'msg') {
<p>
<b>
%= $msg
</b>
</p>
% }
%= form_for '/' => (method => 'POST', enctype => 'multipart/form-data') => begin
<p>
%= label_for file => 'File:'
%= file_field 'file', id => 'file'
</p>
%= submit_button 'Upload!'
<input hidden type="text" name="is_browser" value="Yes">
% end