Implement login, fix more formatting
This commit is contained in:
parent
c5785301ca
commit
e12849508e
|
@ -2,7 +2,6 @@ package CharmBoard::Controller::Auth;
|
||||||
use Mojo::Base 'Mojolicious::Controller', -signatures;
|
use Mojo::Base 'Mojolicious::Controller', -signatures;
|
||||||
use CharmBoard::Crypt::Password;
|
use CharmBoard::Crypt::Password;
|
||||||
use CharmBoard::Crypt::Seasoning;
|
use CharmBoard::Crypt::Seasoning;
|
||||||
use Time::HiRes qw(time);
|
|
||||||
|
|
||||||
# initial registration page
|
# initial registration page
|
||||||
sub register ($app) {
|
sub register ($app) {
|
||||||
|
@ -41,17 +40,21 @@ sub register_do ($app) {
|
||||||
if ($userCheck && $emailCheck) { # notify user that username and email are both already being used
|
if ($userCheck && $emailCheck) { # notify user that username and email are both already being used
|
||||||
$app->flash(error => 'Username and email already in use.');
|
$app->flash(error => 'Username and email already in use.');
|
||||||
$app->redirect_to('register')}
|
$app->redirect_to('register')}
|
||||||
|
|
||||||
elsif ($userCheck) { # notify user that only username is already in use
|
elsif ($userCheck) { # notify user that only username is already in use
|
||||||
$app->flash(error => 'Username is already in use.');
|
$app->flash(error => 'Username is already in use.');
|
||||||
$app->redirect_to('register')}
|
$app->redirect_to('register')}
|
||||||
|
|
||||||
elsif ($emailCheck) { # notify user that only email is already in use
|
elsif ($emailCheck) { # notify user that only email is already in use
|
||||||
$app->flash(error => 'email is already in use.');
|
$app->flash(error => 'email is already in use.');
|
||||||
$app->redirect_to('register')}}
|
$app->redirect_to('register')}}
|
||||||
|
|
||||||
else { # TODO: add more error handling here, in case SQL transact fails
|
else { # TODO: add more error handling here, in case SQL transact fails
|
||||||
# append pepper to pass before hashing
|
# append pepper to pass before hashing
|
||||||
$password = $app->pepper . ':' . $password;
|
$password = $app->pepper . ':' . $password;
|
||||||
# return hashed result + salt
|
# return hashed result + salt
|
||||||
my ($salt, $hash) = passgen($password);
|
my ($salt, $hash) = passgen($password);
|
||||||
|
|
||||||
# add user info and pw/salt to DB
|
# add user info and pw/salt to DB
|
||||||
$app->schema->resultset('Users')->create({
|
$app->schema->resultset('Users')->create({
|
||||||
username => $username,
|
username => $username,
|
||||||
|
@ -59,6 +62,7 @@ sub register_do ($app) {
|
||||||
password => $hash,
|
password => $hash,
|
||||||
salt => $salt,
|
salt => $salt,
|
||||||
signup_date => time });
|
signup_date => time });
|
||||||
|
|
||||||
$app->flash(message => 'User registered successfully!');
|
$app->flash(message => 'User registered successfully!');
|
||||||
$app->redirect_to('register')}};
|
$app->redirect_to('register')}};
|
||||||
|
|
||||||
|
@ -70,20 +74,47 @@ sub login ($app) {
|
||||||
|
|
||||||
sub login_do ($app) {
|
sub login_do ($app) {
|
||||||
my $username = $app->param('username');
|
my $username = $app->param('username');
|
||||||
my $password = $app->param('password');
|
my $password = $app->pepper . ':' . $app->param('password');
|
||||||
$password = $app->pepper . ':' . $password;
|
|
||||||
my $userInfoCheck = $app->schema->resultset('Users')->search({username => $username});
|
my $userInfoCheck = $app->schema->resultset('Users')->search({username => $username});
|
||||||
|
|
||||||
if ($userInfoCheck) {
|
if ($userInfoCheck) {
|
||||||
my $savedSalt = $userInfoCheck->get_column('salt')->first;
|
my $passCheckStatus = passchk($userInfoCheck->get_column('salt')->first,
|
||||||
my $savedHash = $userInfoCheck->get_column('password')->first;
|
$userInfoCheck->get_column('password')->first, $password);
|
||||||
my $passCheckStatus = passchk($savedSalt, $savedHash, $password);
|
|
||||||
if ($passCheckStatus) {
|
if ($passCheckStatus) {
|
||||||
$app->flash(message => 'Password correct, but auth isn\'t implemented yet');
|
my $userID = $userInfoCheck->get_column('user_id')->first;
|
||||||
$app->redirect_to('login')
|
|
||||||
} else {
|
# delete old session from DB if exists
|
||||||
|
if ($app->schema->resultset('Session')->search({user_id => $userID})) {
|
||||||
|
$app->schema->resultset('Session')->search({user_id => $userID})->delete; };
|
||||||
|
|
||||||
|
# gen session key and set expiry time
|
||||||
|
my $sessionKey = seasoning(16);
|
||||||
|
my $sessionExpiry = time + 604800;
|
||||||
|
|
||||||
|
# add session to database
|
||||||
|
$app->schema->resultset('Session')->create({
|
||||||
|
user_id => $userID,
|
||||||
|
session_key => $sessionKey,
|
||||||
|
session_expiry => $sessionExpiry,
|
||||||
|
is_ip_bound => 0,
|
||||||
|
bound_ip => undef });
|
||||||
|
|
||||||
|
# now create session cookie for user
|
||||||
|
$app->session(is_auth => 1);
|
||||||
|
$app->session(user_id => $userID);
|
||||||
|
$app->session(session_key => $sessionKey);
|
||||||
|
$app->session(expires => $sessionExpiry);
|
||||||
|
|
||||||
|
# redirect to index
|
||||||
|
$app->redirect_to('/')}
|
||||||
|
|
||||||
|
else {
|
||||||
$app->flash(error => 'Password incorrect');
|
$app->flash(error => 'Password incorrect');
|
||||||
$app->redirect_to('login')}}
|
$app->redirect_to('login')}}
|
||||||
else {
|
|
||||||
|
else {
|
||||||
$app->flash(error => 'User ' . $username . ' does not exist.');
|
$app->flash(error => 'User ' . $username . ' does not exist.');
|
||||||
$app->redirect_to('login')};
|
$app->redirect_to('login')};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package CharmBoard::Crypt::Password;
|
package CharmBoard::Crypt::Password;
|
||||||
use Authen::Passphrase::Argon2;
|
use Authen::Passphrase::Argon2;
|
||||||
|
use CharmBoard::Crypt::Seasoning;
|
||||||
|
|
||||||
use Exporter qw(import);
|
use Exporter qw(import);
|
||||||
our @EXPORT = qw(passgen passchk);
|
our @EXPORT = qw(passgen passchk);
|
||||||
|
@ -10,26 +11,26 @@ our @EXPORT = qw(passgen passchk);
|
||||||
# `my ($salt, $hash) = passgen($password);`
|
# `my ($salt, $hash) = passgen($password);`
|
||||||
sub passgen ($) {
|
sub passgen ($) {
|
||||||
my $argon2 = Authen::Passphrase::Argon2->new(
|
my $argon2 = Authen::Passphrase::Argon2->new(
|
||||||
salt_random => 1,
|
salt => seasoning(32),
|
||||||
passphrase => $_[0],
|
passphrase => $_[0],
|
||||||
cost => 3,
|
cost => 17,
|
||||||
factor => '32M',
|
factor => '32M',
|
||||||
parallelism => 1,
|
parallelism => 1,
|
||||||
size => 16 );
|
size => 32 );
|
||||||
|
|
||||||
return ($argon2->salt, $argon2->as_crypt)};
|
return ($argon2->salt_hex, $argon2->hash_hex)};
|
||||||
|
|
||||||
# subroutine to check inputted password against one in DB
|
# subroutine to check inputted password against one in DB
|
||||||
# `$_[0]` is the salt, `$_[1]` is the hashed pass, and
|
# `$_[0]` is the salt, `$_[1]` is the hashed pass, and
|
||||||
# `$_[2]` is the inputted plaintext pepper:password to check
|
# `$_[2]` is the inputted plaintext pepper:password to check
|
||||||
sub passchk ($$$) {
|
sub passchk ($$$) {
|
||||||
my $argon2 = Authen::Passphrase::Argon2->new(
|
my $argon2 = Authen::Passphrase::Argon2->new(
|
||||||
salt => $_[0],
|
salt_hex => $_[0],
|
||||||
hash => $_[1],
|
hash_hex => $_[1],
|
||||||
cost => 3,
|
cost => 17,
|
||||||
factor => '32M',
|
factor => '32M',
|
||||||
parallelism => 1,
|
parallelism => 1,
|
||||||
size => 16 );
|
size => 32 );
|
||||||
|
|
||||||
return ($argon2->match($_[2]))}
|
return ($argon2->match($_[2]))}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ __PACKAGE__->add_columns(
|
||||||
cat_name => {
|
cat_name => {
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
is_nullable => 0, });
|
is_nullable => 0, });
|
||||||
|
|
||||||
__PACKAGE__->set_primary_key('cat_id');
|
__PACKAGE__->set_primary_key('cat_id');
|
||||||
|
|
||||||
1
|
1
|
|
@ -19,7 +19,9 @@ __PACKAGE__->add_columns(
|
||||||
data_type => 'integer',
|
data_type => 'integer',
|
||||||
is_auto_increment => 0,
|
is_auto_increment => 0,
|
||||||
is_nullable => 0, });
|
is_nullable => 0, });
|
||||||
|
|
||||||
__PACKAGE__->set_primary_key('post_id');
|
__PACKAGE__->set_primary_key('post_id');
|
||||||
|
|
||||||
__PACKAGE__->belongs_to(
|
__PACKAGE__->belongs_to(
|
||||||
user_id =>
|
user_id =>
|
||||||
'CharmBoard::Schema::Result::Users',
|
'CharmBoard::Schema::Result::Users',
|
||||||
|
|
|
@ -23,7 +23,9 @@ __PACKAGE__->add_columns(
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
is_auto_increment => 0,
|
is_auto_increment => 0,
|
||||||
is_nullable => 1, });
|
is_nullable => 1, });
|
||||||
|
|
||||||
__PACKAGE__->set_primary_key('user_id');
|
__PACKAGE__->set_primary_key('user_id');
|
||||||
|
|
||||||
__PACKAGE__->belongs_to(
|
__PACKAGE__->belongs_to(
|
||||||
user_id =>
|
user_id =>
|
||||||
'CharmBoard::Schema::Result::Users',
|
'CharmBoard::Schema::Result::Users',
|
||||||
|
|
|
@ -19,7 +19,9 @@ __PACKAGE__->add_columns(
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
is_auto_increment => 0,
|
is_auto_increment => 0,
|
||||||
is_nullable => 1, });
|
is_nullable => 1, });
|
||||||
|
|
||||||
__PACKAGE__->set_primary_key('subf_id');
|
__PACKAGE__->set_primary_key('subf_id');
|
||||||
|
|
||||||
__PACKAGE__->belongs_to(
|
__PACKAGE__->belongs_to(
|
||||||
subf_cat =>
|
subf_cat =>
|
||||||
'CharmBoard::Schema::Result::Categories',
|
'CharmBoard::Schema::Result::Categories',
|
||||||
|
|
|
@ -13,7 +13,9 @@ __PACKAGE__->add_columns(
|
||||||
thread_subf => {
|
thread_subf => {
|
||||||
data_type => 'integer',
|
data_type => 'integer',
|
||||||
is_nullable => 1, });
|
is_nullable => 1, });
|
||||||
|
|
||||||
__PACKAGE__->set_primary_key('thread_id');
|
__PACKAGE__->set_primary_key('thread_id');
|
||||||
|
|
||||||
__PACKAGE__->belongs_to(
|
__PACKAGE__->belongs_to(
|
||||||
thread_subf =>
|
thread_subf =>
|
||||||
'CharmBoard::Schema::Result::Subforums',
|
'CharmBoard::Schema::Result::Subforums',
|
||||||
|
|
|
@ -10,20 +10,25 @@ __PACKAGE__->add_columns(
|
||||||
is_auto_increment => 1, },
|
is_auto_increment => 1, },
|
||||||
username => {
|
username => {
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
|
is_numeric => 0,
|
||||||
is_nullable => 0, },
|
is_nullable => 0, },
|
||||||
email => {
|
email => {
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
|
is_numeric => 0,
|
||||||
is_nullable => 0, },
|
is_nullable => 0, },
|
||||||
password => {
|
password => {
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
|
is_numeric => 0,
|
||||||
is_nullable => 0, },
|
is_nullable => 0, },
|
||||||
salt => {
|
salt => {
|
||||||
data_type => 'text',
|
data_type => 'text',
|
||||||
|
is_numeric => 0,
|
||||||
is_nullable => 0, },
|
is_nullable => 0, },
|
||||||
signup_date => {
|
signup_date => {
|
||||||
data_type => 'real',
|
data_type => 'integer',
|
||||||
is_numeric => 1,
|
is_numeric => 1,
|
||||||
is_nullable => 0, });
|
is_nullable => 0, });
|
||||||
|
|
||||||
__PACKAGE__->set_primary_key('user_id');
|
__PACKAGE__->set_primary_key('user_id');
|
||||||
|
|
||||||
1
|
1
|
|
@ -1,3 +1,4 @@
|
||||||
% layout 'default', title => 'CharmBoard';
|
% layout 'default', title => 'CharmBoard';
|
||||||
|
% my $hpm = "you are not logged in";
|
||||||
index page
|
% if ($self->session('is_auth')) {$hpm = "you're logged in!"};
|
||||||
|
<%= $hpm %>
|
Loading…
Reference in New Issue