forked from .cyb/cyberman
Split auth code into a separate file
This commit is contained in:
parent
b549ab3e79
commit
c56ab7dfec
143
lib/cyberman.pm
143
lib/cyberman.pm
|
@ -1,20 +1,13 @@
|
||||||
package cyberman;
|
package cyberman;
|
||||||
|
|
||||||
use Dancer2;
|
use Dancer2;
|
||||||
|
use Dancer2::Plugin::Database;
|
||||||
|
|
||||||
use cyberman::Domains;
|
use cyberman::Domains;
|
||||||
|
use cyberman::Auth;
|
||||||
|
use cyberman::Helper;
|
||||||
|
|
||||||
use Dancer2::Plugin::Database;
|
# Index route, hook and helper functions for authentication
|
||||||
use Digest::Bcrypt;
|
|
||||||
use Math::Random::Secure qw(rand irand);
|
|
||||||
|
|
||||||
#####
|
|
||||||
# cyberman.pm
|
|
||||||
# index page and authentication
|
|
||||||
# maybe this could be split into another file at a later juncture
|
|
||||||
#####
|
|
||||||
|
|
||||||
# misc authentication subs
|
|
||||||
|
|
||||||
sub get_auth {
|
sub get_auth {
|
||||||
my $uid = shift;
|
my $uid = shift;
|
||||||
|
@ -29,20 +22,6 @@ sub get_auth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub randstring {
|
|
||||||
my $len = shift;
|
|
||||||
|
|
||||||
my @chars = (0..9, "a".."z", "A".."Z");
|
|
||||||
my $ret;
|
|
||||||
|
|
||||||
for (1..$len) {
|
|
||||||
$ret .= $chars[irand(scalar(@chars))];
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
prefix undef;
|
|
||||||
|
|
||||||
hook 'before' => sub {
|
hook 'before' => sub {
|
||||||
sub cookieval {
|
sub cookieval {
|
||||||
my $name = shift;
|
my $name = shift;
|
||||||
|
@ -83,118 +62,4 @@ get qr{^/(index)?$} => sub {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
post '/register' => sub {
|
|
||||||
my %errs;
|
|
||||||
|
|
||||||
for my $param ("password", "password2", "email") {
|
|
||||||
if (!param($param)) {
|
|
||||||
$errs{"e_no_$param"} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!exists $errs{"e_no_password"} || !exists $errs{"e_no_password2"}) {
|
|
||||||
if (param("password") ne param("password2")) {
|
|
||||||
$errs{"e_pass_match"} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length param("password") < 8) {
|
|
||||||
$errs{"e_pass_len"} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalar(keys(%errs)) != 0) {
|
|
||||||
return template 'register' => {
|
|
||||||
error => 1,
|
|
||||||
%errs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
# Hash password
|
|
||||||
my $salt = randstring(16);
|
|
||||||
|
|
||||||
my $b = new Digest::Bcrypt;
|
|
||||||
$b->cost(8);
|
|
||||||
$b->salt($salt);
|
|
||||||
$b->add(param "password");
|
|
||||||
|
|
||||||
# Create the account in the database
|
|
||||||
database->quick_insert(
|
|
||||||
"user",
|
|
||||||
{
|
|
||||||
"email" => param("email"),
|
|
||||||
"password" => $b->bcrypt_b64digest,
|
|
||||||
"salt" => $salt,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
# TODO: send confirmation email
|
|
||||||
|
|
||||||
template 'login' => {
|
|
||||||
account_created => 1,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
post '/login' => sub {
|
|
||||||
my %errs;
|
|
||||||
|
|
||||||
my $user = database->quick_select(
|
|
||||||
"user",
|
|
||||||
{
|
|
||||||
"email" => param("email"),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
$errs{"e_no_user"} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalar(keys(%errs)) == 0) {
|
|
||||||
my $b = new Digest::Bcrypt;
|
|
||||||
$b->cost(8);
|
|
||||||
$b->salt($user->{"salt"});
|
|
||||||
$b->add(param "password");
|
|
||||||
|
|
||||||
$errs{"e_pass"} = 1 unless $b->bcrypt_b64digest eq $user->{"password"};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalar(keys(%errs)) == 0) {
|
|
||||||
$errs{"e_not_confirmed"} = 1 unless $user->{"active"};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalar(keys(%errs)) != 0) {
|
|
||||||
return template 'login' => {
|
|
||||||
error => 1,
|
|
||||||
%errs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
# checks finished, we can create a session now
|
|
||||||
|
|
||||||
my $token = randstring(32);
|
|
||||||
|
|
||||||
database->quick_insert(
|
|
||||||
"session",
|
|
||||||
{
|
|
||||||
"token" => $token,
|
|
||||||
"uid" => $user->{"id"},
|
|
||||||
"since" => time,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
cookie id => $user->{"id"}, http_only => 1;
|
|
||||||
cookie token => $token, http_only => 1;
|
|
||||||
|
|
||||||
template 'redir' => {
|
|
||||||
"redir" => "domains",
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
post '/logout' => sub {
|
|
||||||
cookie 'id' => undef;
|
|
||||||
cookie 'token' => undef;
|
|
||||||
template 'redir' => {
|
|
||||||
"redir" => "index",
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
true;
|
true;
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
package cyberman::Auth;
|
||||||
|
|
||||||
|
use Dancer2 appname => "cyberman";
|
||||||
|
use Dancer2::Plugin::Database;
|
||||||
|
use Digest::Bcrypt;
|
||||||
|
use Math::Random::Secure qw(irand);
|
||||||
|
|
||||||
|
use cyberman::Helper;
|
||||||
|
|
||||||
|
# This file: auth-related routes (register, login, logout)
|
||||||
|
# Hooks and helper functions for authentication are in cyberman.pm
|
||||||
|
|
||||||
|
post '/register' => sub {
|
||||||
|
my %errs;
|
||||||
|
|
||||||
|
for my $param ("password", "password2", "email") {
|
||||||
|
if (!param($param)) {
|
||||||
|
$errs{"e_no_$param"} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists $errs{"e_no_password"} || !exists $errs{"e_no_password2"}) {
|
||||||
|
if (param("password") ne param("password2")) {
|
||||||
|
$errs{"e_pass_match"} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length param("password") < 8) {
|
||||||
|
$errs{"e_pass_len"} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalar(keys(%errs)) != 0) {
|
||||||
|
return template 'register' => {
|
||||||
|
error => 1,
|
||||||
|
%errs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hash password
|
||||||
|
my $salt = randstring(16);
|
||||||
|
|
||||||
|
my $b = new Digest::Bcrypt;
|
||||||
|
$b->cost(8);
|
||||||
|
$b->salt($salt);
|
||||||
|
$b->add(param "password");
|
||||||
|
|
||||||
|
# Create the account in the database
|
||||||
|
database->quick_insert(
|
||||||
|
"user",
|
||||||
|
{
|
||||||
|
"email" => param("email"),
|
||||||
|
"password" => $b->bcrypt_b64digest,
|
||||||
|
"salt" => $salt,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
# TODO: send confirmation email
|
||||||
|
|
||||||
|
template 'login' => {
|
||||||
|
account_created => 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
post '/login' => sub {
|
||||||
|
my %errs;
|
||||||
|
|
||||||
|
my $user = database->quick_select(
|
||||||
|
"user",
|
||||||
|
{
|
||||||
|
"email" => param("email"),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
$errs{"e_no_user"} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalar(keys(%errs)) == 0) {
|
||||||
|
my $b = new Digest::Bcrypt;
|
||||||
|
$b->cost(8);
|
||||||
|
$b->salt($user->{"salt"});
|
||||||
|
$b->add(param "password");
|
||||||
|
|
||||||
|
$errs{"e_pass"} = 1 unless $b->bcrypt_b64digest eq $user->{"password"};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalar(keys(%errs)) == 0) {
|
||||||
|
$errs{"e_not_confirmed"} = 1 unless $user->{"active"};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalar(keys(%errs)) != 0) {
|
||||||
|
return template 'login' => {
|
||||||
|
error => 1,
|
||||||
|
%errs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
# checks finished, we can create a session now
|
||||||
|
|
||||||
|
my $token = randstring(32);
|
||||||
|
|
||||||
|
database->quick_insert(
|
||||||
|
"session",
|
||||||
|
{
|
||||||
|
"token" => $token,
|
||||||
|
"uid" => $user->{"id"},
|
||||||
|
"since" => time,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
cookie id => $user->{"id"}, http_only => 1;
|
||||||
|
cookie token => $token, http_only => 1;
|
||||||
|
|
||||||
|
template 'redir' => {
|
||||||
|
"redir" => "domains",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
post '/logout' => sub {
|
||||||
|
cookie 'id' => undef;
|
||||||
|
cookie 'token' => undef;
|
||||||
|
template 'redir' => {
|
||||||
|
"redir" => "index",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
true;
|
|
@ -1,9 +1,14 @@
|
||||||
package cyberman::Helper;
|
package cyberman::Helper;
|
||||||
use base qw(Exporter);
|
use base qw(Exporter);
|
||||||
use Dancer2 appname => "cyberman";
|
use Dancer2 appname => "cyberman";
|
||||||
|
|
||||||
|
use Math::Random::Secure qw(irand);
|
||||||
|
|
||||||
use Exporter qw(import);
|
use Exporter qw(import);
|
||||||
|
|
||||||
our @EXPORT = qw(auth_test);
|
our @EXPORT = qw(auth_test randstring);
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
|
||||||
sub auth_test {
|
sub auth_test {
|
||||||
my $id = undef;
|
my $id = undef;
|
||||||
|
@ -24,4 +29,16 @@ sub auth_test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub randstring {
|
||||||
|
my $len = shift;
|
||||||
|
|
||||||
|
my @chars = (0..9, "a".."z", "A".."Z");
|
||||||
|
my $ret;
|
||||||
|
|
||||||
|
for (1..$len) {
|
||||||
|
$ret .= $chars[irand(scalar(@chars))];
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
Loading…
Reference in New Issue