Improve readme and allow password changing.
This commit is contained in:
parent
5bb8febfa2
commit
9a47d097bf
18
README.md
18
README.md
|
@ -2,11 +2,6 @@
|
||||||
Simple IPFS remote pinning service and
|
Simple IPFS remote pinning service and
|
||||||
HTTP upload provider.
|
HTTP upload provider.
|
||||||
|
|
||||||
Currently, it only supports Postgres and LDAP
|
|
||||||
as backends. LDAP is used to login while Postgres
|
|
||||||
is used to store information about pins and access tokens
|
|
||||||
used by tools.
|
|
||||||
|
|
||||||
In addition to providing a remote pinning endpoint
|
In addition to providing a remote pinning endpoint
|
||||||
at /api, you can also POST uploads directly to the
|
at /api, you can also POST uploads directly to the
|
||||||
root `/` with an access token and recieve a URL back:
|
root `/` with an access token and recieve a URL back:
|
||||||
|
@ -17,8 +12,8 @@ https://unix.dog/ipfs/Qm...
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
To setup this service locally, you will need:
|
To setup this service locally, you will need:
|
||||||
- PostgreSQL
|
- PostgreSQL (optional)
|
||||||
- LDAP service with password auth
|
- LDAP service with password auth (optional)
|
||||||
- IPFS node with RPC API (Kubo)
|
- IPFS node with RPC API (Kubo)
|
||||||
|
|
||||||
Copy the config ipfs_upload.default.yml to
|
Copy the config ipfs_upload.default.yml to
|
||||||
|
@ -26,3 +21,12 @@ ipfs_upload.yml, and edit the config appropriately.
|
||||||
Then use hypnotoad or morbo to run `script/IpfsUpload`.
|
Then use hypnotoad or morbo to run `script/IpfsUpload`.
|
||||||
Log in, generate tokens, and point your IPFS remote pinning
|
Log in, generate tokens, and point your IPFS remote pinning
|
||||||
to /api. Done!
|
to /api. Done!
|
||||||
|
|
||||||
|
## Databases
|
||||||
|
IPFS Upload supports PostgreSQL or SQLite. LDAP and in-database
|
||||||
|
password hashing with Argon2ID are also supported. Check the default
|
||||||
|
config to learn how to configure it properly.
|
||||||
|
|
||||||
|
When using in-database authentication, you can change your password
|
||||||
|
on the Access Token page. In the config, you can whitelist usernames.
|
||||||
|
The password will be set on first login.
|
||||||
|
|
|
@ -70,6 +70,7 @@ sub startup($self) {
|
||||||
$r->get('/login')->to('Login#login');
|
$r->get('/login')->to('Login#login');
|
||||||
$r->get('/my/logout')->to('Login#logout');
|
$r->get('/my/logout')->to('Login#logout');
|
||||||
$r->post('/auth')->to('Login#auth');
|
$r->post('/auth')->to('Login#auth');
|
||||||
|
$r->post('/my/password')->to('Login#change_password');
|
||||||
$r->get('/my')->to('Interface#landing');
|
$r->get('/my')->to('Interface#landing');
|
||||||
$r->get('/my/tokens')->to('Interface#token_list');
|
$r->get('/my/tokens')->to('Interface#token_list');
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ sub auth($c) {
|
||||||
my $mesg = $ldap->bind($bindDN, password=>$password);
|
my $mesg = $ldap->bind($bindDN, password=>$password);
|
||||||
$mesg->code and die $mesg->error;
|
$mesg->code and die $mesg->error;
|
||||||
})->then(sub ($res) {
|
})->then(sub ($res) {
|
||||||
return $c->users->getOrMake($username);
|
return $c->users->get_or_make($username);
|
||||||
})->then(sub ($res) {
|
})->then(sub ($res) {
|
||||||
$c->session->{uid} = $res;
|
$c->session->{uid} = $res;
|
||||||
$c->flash(msg => "Logged in.");
|
$c->flash(msg => "Logged in.");
|
||||||
|
@ -41,11 +41,26 @@ sub auth($c) {
|
||||||
$c->redirect_to('/login');
|
$c->redirect_to('/login');
|
||||||
});
|
});
|
||||||
} elsif ($config->{auth} eq 'db') {
|
} elsif ($config->{auth} eq 'db') {
|
||||||
|
# Check if whitelisted
|
||||||
|
if (not grep $_ eq $username, @{$config->{whitelist_names}}) {
|
||||||
|
$c->flash(msg => "Login failed.");
|
||||||
|
return $c->redirect_to('/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
# Attempt to get user from username
|
||||||
return $c->users->get($username)->then(sub ($uid) {
|
return $c->users->get($username)->then(sub ($uid) {
|
||||||
|
# Create if not exists
|
||||||
if (!defined $uid) {
|
if (!defined $uid) {
|
||||||
$c->flash(msg => "Login failed.");
|
# Hash pass + insert and create user
|
||||||
return $c->redirect_to('/login');
|
my $hash = IpfsUpload::Util::add_pass($password);
|
||||||
|
return $c->users->make_with_pass($username, $hash)->then(sub ($uid_new) {
|
||||||
|
$c->session->{uid} = $uid_new;
|
||||||
|
$c->flash(msg => "Logged in.");
|
||||||
|
return $c->redirect_to('/my');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Verify password
|
||||||
return $c->users->get_pass_hash($uid)->then(sub ($hash) {
|
return $c->users->get_pass_hash($uid)->then(sub ($hash) {
|
||||||
if (IpfsUpload::Util::check_pass($password, $hash)) {
|
if (IpfsUpload::Util::check_pass($password, $hash)) {
|
||||||
$c->session->{uid} = $uid;
|
$c->session->{uid} = $uid;
|
||||||
|
@ -55,6 +70,7 @@ sub auth($c) {
|
||||||
die "Login failed.";
|
die "Login failed.";
|
||||||
});
|
});
|
||||||
})->catch(sub ($err) {
|
})->catch(sub ($err) {
|
||||||
|
say $err;
|
||||||
$c->flash(msg => "Login failed.");
|
$c->flash(msg => "Login failed.");
|
||||||
$c->redirect_to('/login');
|
$c->redirect_to('/login');
|
||||||
});
|
});
|
||||||
|
@ -73,4 +89,25 @@ sub logout($c) {
|
||||||
return $c->redirect_to('/login');
|
return $c->redirect_to('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub change_password($c) {
|
||||||
|
if (!IpfsUpload::Util::check_auth($c)) {
|
||||||
|
return $c->redirect_to("/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($c->config->{auth} ne 'db') {
|
||||||
|
return $c->redirect_to('/my');
|
||||||
|
}
|
||||||
|
|
||||||
|
my $uid = $c->stash('uid');
|
||||||
|
my $v = $c->validation;
|
||||||
|
$v->required('password');
|
||||||
|
return $c->redirect_to('/my') if $v->has_error;
|
||||||
|
|
||||||
|
my $password = $c->param('password');
|
||||||
|
return $c->users->set_pass_hash($uid, IpfsUpload::Util::add_pass($password))->then(sub {
|
||||||
|
$c->flash(msg => "Password set.");
|
||||||
|
return $c->redirect_to('/my');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -57,7 +57,7 @@ sub list_tokens($self, $uid) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub getOrMake($self, $username) {
|
sub get_or_make($self, $username) {
|
||||||
return $self->sql->db->select_p('users', ['uid'], {username => $username})->then(sub ($res) {
|
return $self->sql->db->select_p('users', ['uid'], {username => $username})->then(sub ($res) {
|
||||||
my $val = $res->hash;
|
my $val = $res->hash;
|
||||||
if (defined $val) {
|
if (defined $val) {
|
||||||
|
@ -85,4 +85,13 @@ sub get_pass_hash($self, $uid) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub make_with_pass($self, $username, $hash) {
|
||||||
|
return $self->sql->db->insert_p('users', {username => $username, pass => $hash}, {returning => 'uid'})->then(sub ($n) {
|
||||||
|
return $n->hash->{uid};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sub set_pass_hash($self, $uid, $hash) {
|
||||||
|
return $self->sql->db->update_p('users', { pass => $hash }, { uid => $uid });
|
||||||
|
}
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use Bytes::Random::Secure qw/random_bytes_hex/;
|
||||||
|
|
||||||
sub add_pass($pass) {
|
sub add_pass($pass) {
|
||||||
my $salt = random_bytes_hex(16);
|
my $salt = random_bytes_hex(16);
|
||||||
my $encoded = argon2id_pass($pass, $salt, '32M', 1, 16);
|
my $encoded = argon2id_pass($pass, $salt, 3, '32M', 1, 16);
|
||||||
return $encoded;
|
return $encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,3 +45,15 @@
|
||||||
<p>
|
<p>
|
||||||
<a href="https://docs.ipfs.tech/how-to/work-with-pinning-services/">More info on pinning</a>
|
<a href="https://docs.ipfs.tech/how-to/work-with-pinning-services/">More info on pinning</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
% if ($c->config->{auth} eq 'db') {
|
||||||
|
<p>Change your password here:</p>
|
||||||
|
%= form_for '/my/password' => (method => 'POST') => begin
|
||||||
|
<p>
|
||||||
|
%= label_for password => 'New Password'
|
||||||
|
%= password_field 'password', id=>'password'
|
||||||
|
</p>
|
||||||
|
%= submit_button
|
||||||
|
% end
|
||||||
|
|
||||||
|
% }
|
||||||
|
|
Loading…
Reference in New Issue