diff --git a/lib/CharmBoard/Controller/Auth.pm b/lib/CharmBoard/Controller/Auth.pm index cd00ac1..25c1e15 100644 --- a/lib/CharmBoard/Controller/Auth.pm +++ b/lib/CharmBoard/Controller/Auth.pm @@ -2,7 +2,6 @@ package CharmBoard::Controller::Auth; use Mojo::Base 'Mojolicious::Controller', -signatures; use CharmBoard::Crypt::Password; use CharmBoard::Crypt::Seasoning; -use Time::HiRes qw(time); # initial registration page 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 $app->flash(error => 'Username and email already in use.'); $app->redirect_to('register')} + elsif ($userCheck) { # notify user that only username is already in use $app->flash(error => 'Username is already in use.'); $app->redirect_to('register')} + elsif ($emailCheck) { # notify user that only email is already in use $app->flash(error => 'email is already in use.'); $app->redirect_to('register')}} + else { # TODO: add more error handling here, in case SQL transact fails # append pepper to pass before hashing $password = $app->pepper . ':' . $password; # return hashed result + salt my ($salt, $hash) = passgen($password); + # add user info and pw/salt to DB $app->schema->resultset('Users')->create({ username => $username, @@ -59,6 +62,7 @@ sub register_do ($app) { password => $hash, salt => $salt, signup_date => time }); + $app->flash(message => 'User registered successfully!'); $app->redirect_to('register')}}; @@ -70,20 +74,47 @@ sub login ($app) { sub login_do ($app) { my $username = $app->param('username'); - my $password = $app->param('password'); - $password = $app->pepper . ':' . $password; + my $password = $app->pepper . ':' . $app->param('password'); + my $userInfoCheck = $app->schema->resultset('Users')->search({username => $username}); + if ($userInfoCheck) { - my $savedSalt = $userInfoCheck->get_column('salt')->first; - my $savedHash = $userInfoCheck->get_column('password')->first; - my $passCheckStatus = passchk($savedSalt, $savedHash, $password); + my $passCheckStatus = passchk($userInfoCheck->get_column('salt')->first, + $userInfoCheck->get_column('password')->first, $password); + if ($passCheckStatus) { - $app->flash(message => 'Password correct, but auth isn\'t implemented yet'); - $app->redirect_to('login') - } else { + my $userID = $userInfoCheck->get_column('user_id')->first; + + # 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->redirect_to('login')}} - else { + + else { $app->flash(error => 'User ' . $username . ' does not exist.'); $app->redirect_to('login')}; diff --git a/lib/CharmBoard/Crypt/Password.pm b/lib/CharmBoard/Crypt/Password.pm index 72300b8..187567a 100644 --- a/lib/CharmBoard/Crypt/Password.pm +++ b/lib/CharmBoard/Crypt/Password.pm @@ -1,5 +1,6 @@ package CharmBoard::Crypt::Password; use Authen::Passphrase::Argon2; +use CharmBoard::Crypt::Seasoning; use Exporter qw(import); our @EXPORT = qw(passgen passchk); @@ -10,26 +11,26 @@ our @EXPORT = qw(passgen passchk); # `my ($salt, $hash) = passgen($password);` sub passgen ($) { my $argon2 = Authen::Passphrase::Argon2->new( - salt_random => 1, + salt => seasoning(32), passphrase => $_[0], - cost => 3, + cost => 17, factor => '32M', 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 # `$_[0]` is the salt, `$_[1]` is the hashed pass, and # `$_[2]` is the inputted plaintext pepper:password to check sub passchk ($$$) { my $argon2 = Authen::Passphrase::Argon2->new( - salt => $_[0], - hash => $_[1], - cost => 3, + salt_hex => $_[0], + hash_hex => $_[1], + cost => 17, factor => '32M', parallelism => 1, - size => 16 ); + size => 32 ); return ($argon2->match($_[2]))} diff --git a/lib/CharmBoard/Schema/Result/Categories.pm b/lib/CharmBoard/Schema/Result/Categories.pm index e39134a..5e78132 100644 --- a/lib/CharmBoard/Schema/Result/Categories.pm +++ b/lib/CharmBoard/Schema/Result/Categories.pm @@ -10,6 +10,7 @@ __PACKAGE__->add_columns( cat_name => { data_type => 'text', is_nullable => 0, }); + __PACKAGE__->set_primary_key('cat_id'); 1 \ No newline at end of file diff --git a/lib/CharmBoard/Schema/Result/Posts.pm b/lib/CharmBoard/Schema/Result/Posts.pm index e74a958..cd09783 100644 --- a/lib/CharmBoard/Schema/Result/Posts.pm +++ b/lib/CharmBoard/Schema/Result/Posts.pm @@ -19,7 +19,9 @@ __PACKAGE__->add_columns( data_type => 'integer', is_auto_increment => 0, is_nullable => 0, }); + __PACKAGE__->set_primary_key('post_id'); + __PACKAGE__->belongs_to( user_id => 'CharmBoard::Schema::Result::Users', diff --git a/lib/CharmBoard/Schema/Result/Session.pm b/lib/CharmBoard/Schema/Result/Session.pm index 8361c6e..6c08a17 100644 --- a/lib/CharmBoard/Schema/Result/Session.pm +++ b/lib/CharmBoard/Schema/Result/Session.pm @@ -23,7 +23,9 @@ __PACKAGE__->add_columns( data_type => 'text', is_auto_increment => 0, is_nullable => 1, }); + __PACKAGE__->set_primary_key('user_id'); + __PACKAGE__->belongs_to( user_id => 'CharmBoard::Schema::Result::Users', diff --git a/lib/CharmBoard/Schema/Result/Subforums.pm b/lib/CharmBoard/Schema/Result/Subforums.pm index 167e4c4..7e112f1 100644 --- a/lib/CharmBoard/Schema/Result/Subforums.pm +++ b/lib/CharmBoard/Schema/Result/Subforums.pm @@ -19,7 +19,9 @@ __PACKAGE__->add_columns( data_type => 'text', is_auto_increment => 0, is_nullable => 1, }); + __PACKAGE__->set_primary_key('subf_id'); + __PACKAGE__->belongs_to( subf_cat => 'CharmBoard::Schema::Result::Categories', diff --git a/lib/CharmBoard/Schema/Result/Threads.pm b/lib/CharmBoard/Schema/Result/Threads.pm index 8162eca..9368f22 100644 --- a/lib/CharmBoard/Schema/Result/Threads.pm +++ b/lib/CharmBoard/Schema/Result/Threads.pm @@ -13,7 +13,9 @@ __PACKAGE__->add_columns( thread_subf => { data_type => 'integer', is_nullable => 1, }); + __PACKAGE__->set_primary_key('thread_id'); + __PACKAGE__->belongs_to( thread_subf => 'CharmBoard::Schema::Result::Subforums', diff --git a/lib/CharmBoard/Schema/Result/Users.pm b/lib/CharmBoard/Schema/Result/Users.pm index 09c262a..24701aa 100644 --- a/lib/CharmBoard/Schema/Result/Users.pm +++ b/lib/CharmBoard/Schema/Result/Users.pm @@ -10,20 +10,25 @@ __PACKAGE__->add_columns( is_auto_increment => 1, }, username => { data_type => 'text', + is_numeric => 0, is_nullable => 0, }, email => { data_type => 'text', + is_numeric => 0, is_nullable => 0, }, password => { data_type => 'text', + is_numeric => 0, is_nullable => 0, }, salt => { data_type => 'text', + is_numeric => 0, is_nullable => 0, }, signup_date => { - data_type => 'real', + data_type => 'integer', is_numeric => 1, is_nullable => 0, }); + __PACKAGE__->set_primary_key('user_id'); 1 \ No newline at end of file diff --git a/templates/index.html.ep b/templates/index.html.ep index 89db429..87cd4c7 100644 --- a/templates/index.html.ep +++ b/templates/index.html.ep @@ -1,3 +1,4 @@ % layout 'default', title => 'CharmBoard'; - -index page \ No newline at end of file +% my $hpm = "you are not logged in"; +% if ($self->session('is_auth')) {$hpm = "you're logged in!"}; +<%= $hpm %> \ No newline at end of file