From 8d7256911fcd2f44fc446f03acb39dd08e90024d Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sun, 1 Mar 2015 14:05:40 +0200 Subject: [PATCH] Use Plack::Middleware::Auth::Complex for auth --- Makefile.PL | 32 +++++++------- a/account.en | 3 +- app.psgi | 19 ++------- lib/Plack/App/Gruntmaster.pm | 70 +------------------------------ lib/Plack/App/Gruntmaster/Auth.pm | 24 +++++++++++ 5 files changed, 47 insertions(+), 101 deletions(-) create mode 100644 lib/Plack/App/Gruntmaster/Auth.pm diff --git a/Makefile.PL b/Makefile.PL index 796f5d7..0407ab7 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -16,7 +16,6 @@ WriteMakefile( }, PREREQ_PM => { qw/Carp 0 - Digest::SHA 0 Encode 0 List::Util 0 POSIX 0 @@ -26,22 +25,21 @@ WriteMakefile( strict 0 warnings 0 - CSS::Minifier::XS 0 - Email::Simple 0 - Email::Sender::Simple 0 - File::Slurp 0 - Gruntmaster::Data 0 - HTML::Seamstress 0 - JavaScript::Minifier::XS 0 - JSON::MaybeXS 0 - Log::Log4perl 0 - PerlX::Maybe 0 - Plack::Builder 0 - Plack::Request 0 - Plack::Util 0 - Scope::Upper 0 - Tie::Hash::Expire 0 - Web::Simple 0.019/, + CSS::Minifier::XS 0 + Email::Simple 0 + Email::Sender::Simple 0 + File::Slurp 0 + Gruntmaster::Data 0 + HTML::Seamstress 0 + JavaScript::Minifier::XS 0 + JSON::MaybeXS 0 + Log::Log4perl 0 + PerlX::Maybe 0 + Plack::Builder 0 + Plack::Middleware::Auth::Complex 0 + Plack::Util 0 + Scope::Upper 0 + Web::Simple 0.019/, }, META_MERGE => { dynamic_config => 0, diff --git a/a/account.en b/a/account.en index 422b949..6c1b8cc 100644 --- a/a/account.en +++ b/a/account.en @@ -278,7 +278,8 @@

Reset password

-
+
+
diff --git a/app.psgi b/app.psgi index 85e8847..5372109 100644 --- a/app.psgi +++ b/app.psgi @@ -5,11 +5,8 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch'; use Gruntmaster::Data; use Plack::App::Gruntmaster; use Plack::Builder; -use Plack::Request; use Plack::Util; -use Digest::SHA qw/sha256/; use Log::Log4perl; -use Tie::Hash::Expire; use constant AUTH_TIMEOUT => 5 * 60; use constant ACCESSLOG_FORMAT => 'combined'; @@ -31,17 +28,6 @@ CSP my $db; -tie my %auth, 'Tie::Hash::Expire', {expire_seconds => AUTH_TIMEOUT}; - -sub authenticate { - my ($user, $pass, $env) = @_; - my $key = sha256 "$user:$pass"; - $env->{'gruntmaster.user'} = $user; - return 1 if exists $auth{$key}; - return unless $db->user($user) && $db->user($user)->check_passphrase($pass); - $auth{key} = 1; -} - sub add_database { my $app = $_[0]; sub { @@ -76,6 +62,9 @@ builder { enable 'Static', path => qr,^/static/,; enable 'Log4perl', category => 'plack'; enable \&add_database; - enable_if { shift->{HTTP_AUTHORIZATION} } 'Auth::Basic', authenticator => \&authenticate, realm => 'Gruntmaster 6000'; + enable '+Plack::App::Gruntmaster::Auth', + dbi_connect => [$ENV{GRUNTMASTER_DSN} // 'dbi:Pg:', '', ''], + realm => 'Gruntmaster 6000', + mail_from => $ENV{GRUNTMASTER_RESET_FROM}; Plack::App::Gruntmaster->run_if_script } diff --git a/lib/Plack/App/Gruntmaster.pm b/lib/Plack/App/Gruntmaster.pm index 3a7b9db..87e9e5a 100644 --- a/lib/Plack/App/Gruntmaster.pm +++ b/lib/Plack/App/Gruntmaster.pm @@ -54,7 +54,6 @@ use constant FORMAT_EXTENSION => { }; use constant NOT_FOUND => [404, ['X-Forever' => 1, 'Content-Type' => 'text/plain'], ['Not found']]; -use constant FORBIDDEN => [401, ['Content-Type' => 'text/plain', 'WWW-Authenticate' => 'Basic realm="Gruntmaster 6000"'], ['Forbidden']]; sub development() { ($ENV{PLACK_ENV} // 'development') eq 'development' } @@ -63,7 +62,7 @@ my ($env, $privacy); sub db { $env->{'gruntmaster.dbic'} } sub remote_user { - my $user = $env->{'gruntmaster.user'}; + my $user = $env->{REMOTE_USER}; $user &&= db->user($user); $user } @@ -91,7 +90,7 @@ sub forbid { my ($condition) = @_; $privacy = 'private' if $condition; return if !$condition || admin; - unwind FORBIDDEN, SUB UP + unwind $env->{authcomplex}->unauthorized, SUB UP } sub dispatch_request{ @@ -217,26 +216,6 @@ sub dispatch_request{ }, sub (POST) { - sub (/action/register + %:username=&:password=&:confirm_password=&:name=&:email=&:phone=&:town=&:university=&:country=&:level=) { - return reply 'Parameter too long' if grep { length > 200 } values %_; - return reply 'Bad username. Allowed characters are letters, digits and underscores, and the username must be between 2 and 20 characters long.' unless $_{username} =~ USER_REGEX; - return reply 'Username already in use' if db->user($_{username}); - return reply 'The two passwords do not match' unless $_{password} eq $_{confirm_password}; - - db->users->create({id => $_{username}, name => $_{name}, email => $_{email}, phone => $_{phone}, town => $_{town}, university => $_{university}, country => $_{country}, level => $_{level}}); - db->user($_{username})->set_passphrase($_{password}); - - reply 'Registered successfully'; - }, - - sub (/action/passwd + %:password=&:new_password=&:confirm_new_password=) { - forbid !remote_user; - return reply 'Incorrect password' unless remote_user->check_passphrase($_{password}); - return reply 'The two passwords do not match' unless $_{new_password} eq $_{confirm_new_password}; - remote_user->set_passphrase($_{new_password}); - reply 'Password changed successfully'; - }, - sub (/action/submit + %:problem=&:contest~&:prog_format=&:source_code~ + *prog~) { my (undef, undef, $prog) = @_; forbid !remote_user; @@ -264,51 +243,6 @@ sub dispatch_request{ [303, [Location => '/log/' . $newjob->id], []] }, - - sub (/action/request-reset + %:username=) { - return reply 'Password resets are disabled' unless $ENV{GRUNTMASTER_RESET_FROM}; - my $user = db->user($_{username}); - return reply 'No such user' unless $user; - my $token = join ':', $user->make_reset_hmac; - my $body = < -Reset token: $token - -The token is valid for 24 hours. -EOF - my $email = Email::Simple->create( - header => [ - From => $ENV{GRUNTMASTER_RESET_FROM}, - To => $user->email, - Subject => 'Password reset token', - ], - body => $body, - ); - - my $ok = 0; - eval { - sendmail $email; - $ok = 1; - }; - return reply 'Email sent' if $ok; - reply "Failure sending email: $@"; - }, - - sub (/action/reset + %:username=&:password=&:token=) { - my $user = db->user($_{username}); - return reply 'No such user' unless $user; - my ($token, $exp) = split ':', $_{token}; - return reply 'Reset token is expired' if time >= $exp; - return reply 'Bad reset token' unless $user->make_reset_hmac($exp) eq $token; - $user->set_passphrase($_{password}); - reply 'Password reset successfully'; - }, } } diff --git a/lib/Plack/App/Gruntmaster/Auth.pm b/lib/Plack/App/Gruntmaster/Auth.pm new file mode 100644 index 0000000..40ff41b --- /dev/null +++ b/lib/Plack/App/Gruntmaster/Auth.pm @@ -0,0 +1,24 @@ +package Plack::App::Gruntmaster::Auth; + +use 5.014000; +use strict; +our $VERSION = '5999.000_001'; + +use parent qw/Plack::Middleware::Auth::Complex/; + +sub call_register { + my ($self, $req) = @_; + return $self->bad_request('Parameter too long') if grep { length > 100 } $req->parameters->values; + + $self->SUPER::call_register($req); +} + +sub create_user { + my ($self, $parms) = @_; + my %parms = $parms->flatten; + my $sth = $self->{dbh}->prepare_cached('INSERT INTO users (id, name, email, phone, town, university, country, level, passphrase) VALUES (?,?,?,?,?,?,?,?,?)'); + $sth->execute(@parms{qw/username name email phone town university country level/}, $self->hash_passphrase($parms{password})); +} + +1; +__END__ -- 2.39.2