From f867429bab6efe18a21c4fd531ecbe4eff8cff40 Mon Sep 17 00:00:00 2001 From: Buchan Milne Date: Thu, 4 Nov 2010 11:59:43 +0000 Subject: Switch to View::Email::Template for emails Complete password reset by admin, and localise in user's preferredLanguage Localise all /user content Require re-entry of current password on password change Clean up debugging --- lib/CatDap/Controller/admin.pm | 75 ++++++++++++++++++++++++++------------- lib/CatDap/Controller/register.pm | 40 ++++++++------------- lib/CatDap/Controller/user.pm | 47 +++++++++++++++--------- 3 files changed, 96 insertions(+), 66 deletions(-) (limited to 'lib/CatDap/Controller') diff --git a/lib/CatDap/Controller/admin.pm b/lib/CatDap/Controller/admin.pm index 19fa15f..7632df4 100644 --- a/lib/CatDap/Controller/admin.pm +++ b/lib/CatDap/Controller/admin.pm @@ -48,11 +48,11 @@ sub auto : Private { my $mesg; my $dn; my $keyprefix = sprintf( "%02x%02x%02x", split /\./, $c->req->address ); - if ( !defined $c->user ) { + if ( !defined $c->user or not $c->req->cookie('key') ) { $c->detach('/user/login') if ( not $c->req->param('username') or not $c->req->param('password') ); - $c->log->info("No session, logging user in"); + $c->log->debug("No session, logging user in"); if ( !$c->authenticate( { @@ -67,7 +67,7 @@ sub auto : Private { #TODO: ppolicy .... $c->stash( errors => ['Incorrect username or password'] ); $c->stash( template => 'index.tt' ); - $c->log->info("Logging user in failed, forwarding to login page"); + $c->log->debug("Logging user in failed, forwarding to login page"); $c->visit('/user/login'); $c->detach; return 1; @@ -78,7 +78,7 @@ sub auto : Private { # $c->res->redirect('/user'); #} #$c->persist_user; - $c->log->info('Logging user in to LDAP'); + $c->log->debug('Logging user in to LDAP'); my $ug = Data::UUID->new; my $key = $ug->create_str(); $cipher = Crypt::CBC->new( @@ -103,7 +103,7 @@ sub auto : Private { -cipher => 'Blowfish' ) or die $!; $password = $cipher->decrypt( $c->session->{enc_password} ); - $c->log->info( "Re-authenticating user " . $c->session->{user} ); + $c->log->debug( "Re-authenticating user " . $c->session->{user} ); $c->authenticate( { username => $c->session->{user}, password => $password } ) or $c->view('/user/login'); @@ -126,7 +126,7 @@ sub account : Local { #my $attribute =~ m/^([\w\d]*)/,$c->req->param('attribute'); my $attribute = $c->req->param('attribute'); - $c->log->info("Searching for account using attribute $attribute"); + $c->log->debug("Searching for account using attribute $attribute"); #my $value =~ /^[\w\d]*/,$c->req->param('attribute'); my $value = $c->req->param('value'); @@ -180,13 +180,14 @@ sub account_promote : Local { $idpool->replace( uidNumber => $newuidnum ); $idpool->update; - $mesg = $entry->update or $c->log->info("LDAP update failed: $!"); + $mesg = $entry->update; if ($mesg->code) { + $c->log->info('LDAP update failed: ' . $mesg->error); push @errors, $mesg->error; #reverse idpool update $idpool->replace( uidNumber => $uidnum ); $mesg = $idpool->update; - $c->log->info("ERROR IdPool could not be reset to $uidnum"); + $c->log->info("ERROR IdPool could not be reset to $uidnum: ", $mesg->error) if $mesg->code; } } } @@ -221,7 +222,7 @@ sub account_modify : Local { my $attrdef; my $entry; - $c->log->info("Searching for user $user"); + $c->log->debug("Searching for user $user"); $mesg = $c->model('User')->search("(&(objectclass=inetOrgPerson)(uid=$user))"); $entry = $mesg->entry; @@ -241,7 +242,7 @@ sub account_modify : Local { next if $req !~ /(.+)_new/; my $attrname = $1; next if $params{ $attrname . '_new' } eq $params{ $attrname . '_old' }; - $c->log->info("Received update request for attribute $attrname"); + $c->log->debug("Received update request for attribute $attrname"); $update = 1; $attrdef = $schema->attribute($attrname) or die("getting schema failed: $!"); @@ -261,9 +262,9 @@ sub account_modify : Local { $mesg = $c->model('User')->search("(&(objectclass=inetOrgPerson)(uid=$user))"); - $c->log->info( $mesg->error ) if $mesg->code; + $c->log->debug( $mesg->error ) if $mesg->code; $entry = $mesg->entry; - $c->log->info( $mesg->error ) if $mesg->code; + $c->log->debug( $mesg->error ) if $mesg->code; my @values; my @attributes = $entry->attributes; @@ -421,9 +422,9 @@ sub account_addoc : Local { my $schema = $schemaldap->schema or die("Searching schema failed: $!"); $mesg = $c->model('user')->search("(&(objectclass=inetOrgPerson)(uid=$uid))"); - $c->log->info( $mesg->error ) if $mesg->code; + $c->log->debug( $mesg->error ) if $mesg->code; my $entry = $mesg->entry; - $c->log->info( $mesg->error ) if $mesg->code; + $c->log->debug( $mesg->error ) if $mesg->code; foreach my $attr ( $schema->must($objectclass) ) { push @must, $$attr{name} if not $entry->get_value( $$attr{name} ); @@ -439,14 +440,14 @@ sub account_addoc : Local { $entry->add( $addattr => $c->req->param($addattr) ); } else { - $c->log->info("Missing attribute $addattr"); + $c->log->debug("Missing attribute $addattr"); $haveall = 0; } } if ($haveall) { $entry->add( objectClass => [$objectclass] ); - $c->log->info("About to push updates to $dn"); - $c->log->info( Dumper( \$entry->changes ) ); + $c->log->debug("About to push updates to $dn"); + $c->log->debug( Dumper( \$entry->changes ) ); $mesg = $entry->update; push @errors, $mesg->error if $mesg->code; $c->stash( template => 'admin/account.tt', errors => @errors ); @@ -490,7 +491,7 @@ sub password : Local { $c->stash( uid => $uid, txnid => $txnid, mails => @mail); return 1; } - if ($c->req->param('txnid') != $c->session->{txnid}) { + if ($c->req->param('txnid') ne $c->session->{txnid}) { push @errors,'Transaction ID mismatch'; $c->detach; } @@ -501,13 +502,35 @@ sub password : Local { push @errors,"Password reset failed: " . $mesg->error; $c->detach; } - $c->stash->{email} = { - to => join ',',@mail, - subject => $c->config->{apptitle} . " - " . $c->loc('password reset'), - from => $c->config->{emailfrom}, - template => 'admin/password.tt', - }; - $c->forward( $c->view('Email::Template') ); + my $email = join(',',@mail); + # send the mail in the users preferred language + my @oldlang = $c->languages; + if ($entry->preferredLanguage) { + $c->log->debug("Setting languages to: " . Dumper($entry->preferredLanguage)); + $c->languages([$entry->preferredLanguage]); + } + $c->stash( + email => { + 'to' => $email, + 'subject' => $c->config->{apptitle} . " - " + . $c->loc('password reset'), + 'from' => $c->config->{emailfrom}, + 'template' => 'admin/password.tt', + 'content_type' => 'text/plain', + }, + entry => $entry, + url => $c->uri_for('/user/firstlogin') . "/?username=$uid&key=$newpass", + ); + $c->forward( $c->view('Email::Template') ); + $c->languages(@oldlang); + if ( @{ $c->error } ) { + my $errors = join "\n",@{ $c->error }; + $c->log->info("Sending reset mail to $email failed: $errors"); + $c->response->body($c->loc('An error occured sending the email, but your account was created. Please try the password recovery process f you entered the correct email address: [_1]', $errors)); + $c->error(0); # Reset the error condition if you need to + } + push @errors,$c->loc('Password reset and email sent'); + $c->res->redirect($c->uri_for('/admin/account_modify') . "/$uid"); } @@ -560,6 +583,8 @@ sub group_modify : Local { sub index : Path : Args(0) { my ( $self, $c ) = @_; + $c->detach('/index') if not $c->user; + $c->assert_user_roles('Account Admins'); $c->stash( pages => roles2pages( $c->user->roles ) ); #$c->response->body("Matched CatDap::Controller::admin in admin, roles $rolelist"); diff --git a/lib/CatDap/Controller/register.pm b/lib/CatDap/Controller/register.pm index 3838f26..5ad8e19 100644 --- a/lib/CatDap/Controller/register.pm +++ b/lib/CatDap/Controller/register.pm @@ -91,6 +91,8 @@ sub check : Local { my $password = $ug->create_str(); my $cn = $c->request->params->{gn} . " " . $c->request->params->{sn}; $c->log->info("Creating account for user $username"); + $c->log->debug("Preferred language(s)"); + $c->log->debug(Dumper($c->languages)); $mesg = $c->model('Proxy')->add($dn, attr => [ objectclass => [ 'inetOrgPerson' ], @@ -100,48 +102,36 @@ sub check : Local { mail => $email, pwdReset => 'TRUE', userPassword => $password, + preferredLanguage => $c->{languages}[0], ] ); - if ($mesg) { + if ($mesg->code) { push @errors,$mesg->error; $c->log->info( sprintf("Creating DN $dn failed: %s", $mesg->error) ); $c->stash(errors => \@errors); #$c->stash(template => 'register/index.tt'); } - my $text = <loc( - sprintf( - $text, - $c->request->params->{gn}, - $c->uri_for('/user/firstlogin'), - $username, - $password - ) + $c->stash( + email => { + 'to' => $email, + 'from' => ${$c->config}{'emailfrom'}, + 'subject' => ${$c->config}{'apptitle'} . " - " . $c->loc('Activation'), + 'template' => 'activation.tt', + }, + cn => $cn, + url => $c->uri_for('/user/firstlogin') . "?username=$username&key=$password", ); - $c->stash->{email} = { - to => $email, - from => ${$c->config}{emailfrom}, - subject => ${$c->config}{apptitle} . " - " . $c->loc('Activation'), - body => $body, - }; $c->log->info("Sending activation mail for user $username to $email"); - $c->forward( $c->view('Email') ); + $c->forward( $c->view('Email::Template') ); if ( @{ $c->error } ) { my $errors = join "\n",@{ $c->error }; $c->log->info("Sending activation mail to $email failed: $errors"); - $c->response->body($c->loc('An error occured sending the email, but your account was created. Please try the password recovery process f you entered the correct email address: [_1]', $errors)); + $c->response->body($c->loc('An error occured sending the email, but your account was created. Please try the password recovery process if you entered the correct email address. Errors [_1]', $errors)); $c->error(0); # Reset the error condition if you need to } - $c->stash(template => 'register/complete.tt'); - $c->stash(message => 'Check your email'); } sub captcha : Local { diff --git a/lib/CatDap/Controller/user.pm b/lib/CatDap/Controller/user.pm index e2ce800..f0220f2 100644 --- a/lib/CatDap/Controller/user.pm +++ b/lib/CatDap/Controller/user.pm @@ -47,8 +47,6 @@ it (we need to handle failure to decrypt it better) sub auto : Private { my ( $self, $c ) = @_; - $c->log->info("Request path is currently: " . $c->req->path); - $c->log->info(Dumper($c->req->path)); if ($c->req->path eq 'user/firstlogin') { return 1; } @@ -56,9 +54,16 @@ sub auto : Private { my $password; my $mesg; my $dn; + my @errors; my $keyprefix = sprintf("%02x%02x%02x",split /\./,$c->req->address); - if (! defined $c->user) { - $c->log->info("No session, logging user in"); + if (! defined $c->user or not $c->req->cookie('key')) { + if (not $c->req->param('password')) { + push @errors,$c->loc('Your session has expired'); + $c->stash(template => 'index.tt',errors => \@errors); + $c->detach; + } + + $c->log->debug("No session, logging user in"); if (! $c->authenticate({ username => $c->req->param('username'), password => $c->req->param('password') || $c->req->param('key')}) ) { @@ -74,7 +79,7 @@ sub auto : Private { # $c->res->redirect('/user'); #} #$c->persist_user; - $c->log->info('Logging user in to LDAP'); + $c->log->debug('Logging user in to LDAP'); my $ug = Data::UUID->new; my $key = $ug->create_str(); @@ -96,7 +101,7 @@ sub auto : Private { -cipher => 'Blowfish' ) or die $!; $password = $cipher->decrypt($c->session->{enc_password}); - $c->log->info("Re-authenticating user " . $c->user->username); + $c->log->debug("Re-authenticating user " . $c->user->username); $c->authenticate({username => $c->user->username,password => $password}); $c->res->cookies->{'key'} = {value => $key, expires => '+10m'}; @@ -131,7 +136,7 @@ sub index :Path :Args(0) { my $user = $c->user->username; my $entry; - $c->log->info("Searching for user $user"); + $c->log->debug("Searching for user $user"); $mesg = $c->model('User')->search("(&(objectclass=inetOrgPerson)(uid=$user))"); $entry = $mesg->entry; my %mods; @@ -157,9 +162,9 @@ sub index :Path :Args(0) { } $mesg = $c->model('User')->search("(&(objectclass=inetOrgPerson)(uid=$user))"); - $c->log->info($mesg->error) if $mesg->code; + $c->log->debug($mesg->error) if $mesg->code; $entry = $mesg->entry; - $c->log->info($mesg->error) if $mesg->code; + $c->log->debug($mesg->error) if $mesg->code; my @values; my @attributes = $entry->attributes; @@ -217,7 +222,7 @@ sub add : Local { $attr = $c->req->param('attribute'); $value = $c->req->param('value'); $user = $c->user->username; - $c->log->info("Searching for user $user"); + $c->log->debug("Searching for user $user"); $mesg = $c->model('User')->search("(&(objectclass=inetOrgPerson)(uid=$user))"); $entry = $mesg->entry; $entry->add( $attr => $value); @@ -232,7 +237,7 @@ sub delete : Local : Args(2) { my ( $self, $c, $attrname,$attrvalue) = @_; my ($mesg,$entry,$user); $user = $c->user->username; - $c->log->info("Searching for user $user"); + $c->log->debug("Searching for user $user"); $mesg = $c->model('User')->search("(&(objectclass=inetOrgPerson)(uid=$user))"); $entry = $mesg->entry; $c->log->info("Deleting $attrname = $attrvalue from user $user"); @@ -253,14 +258,24 @@ sub password : Local { $c->detach; } + # Re-authenticate to check the user has the right password + if (not $c->authenticate({ + 'username' => $c->user->username, + 'password' => $c->req->param('password'), + }) + ) { + $c->stash(errors => [ $c->loc('Password incorrect') ]); + $c->detach; + } if ($c->req->param('newpassword1') eq $c->req->param('newpassword2')) { $newpass = $c->req->param('newpassword1'); } else { - push @{${$c->stash}{'errors'}},"New passwords dont match"; + push @{${$c->stash}{'errors'}},$c->loc('New passwords dont match'); + $c->detach; } my $pp = Net::LDAP::Control::PasswordPolicy->new; $mesg = $c->model('User')->set_password( - oldpasswd => $c->req->param('password'), + #oldpasswd => $c->req->param('password'), newpasswd => $newpass, control => [ $pp ], ); @@ -278,7 +293,7 @@ sub password : Local { ) or die $!; $c->session->{enc_password} = $cipher->encrypt($newpass); push @{${$c->stash}{'errors'}},"Password change succeeded"; - $c->res->redirect('/user'); + #$c->res->redirect('/user'); } } @@ -386,8 +401,8 @@ sub gensubpages : Private { my ($type) = @_; my @subpagenames; @subpagenames = ( - { page => './', title => "Edit"}, - { page => 'password', title => "Change password"}, + { page => './', title => 'Edit'}, + { page => 'password', title => 'Change password'}, ); return \@subpagenames; } -- cgit v1.2.1