[Mageia-sysadm] [249] commit implement forgot_password patch from Maarten Vanraes
root at mageia.org
root at mageia.org
Sat Jan 8 00:20:15 CET 2011
Revision: 249
Author: rda
Date: 2011-01-08 00:20:14 +0100 (Sat, 08 Jan 2011)
Log Message:
-----------
commit implement forgot_password patch from Maarten Vanraes
Modified Paths:
--------------
identity/CatDap/trunk/catdap.yml
identity/CatDap/trunk/root/index.tt
Added Paths:
-----------
identity/CatDap/trunk/lib/CatDap/Controller/forgot_password.pm
identity/CatDap/trunk/root/email/forgot_password.tt
identity/CatDap/trunk/root/forgot_password/
identity/CatDap/trunk/root/forgot_password/check.tt
identity/CatDap/trunk/root/forgot_password/complete.tt
identity/CatDap/trunk/root/forgot_password/confirm.tt
identity/CatDap/trunk/root/forgot_password/index.tt
Modified: identity/CatDap/trunk/catdap.yml
===================================================================
--- identity/CatDap/trunk/catdap.yml 2011-01-07 23:15:42 UTC (rev 248)
+++ identity/CatDap/trunk/catdap.yml 2011-01-07 23:20:14 UTC (rev 249)
@@ -35,6 +35,12 @@
login_blacklist:
- apache
+forgot_password:
+ secret:
+ path: '/tmp/'
+ prefix: 'catdap-forgot_password-'
+ timeout: 259200
+
authentication:
default_realm: ldap
realms:
@@ -55,6 +61,7 @@
user_filter: '(&(objectClass=inetOrgPerson)(uid=%s))'
user_scope: 'one'
user_field: 'uid'
+ email_filter: '(&(objectClass=inetOrgPerson)(|(mail=%s)(mailAlternateAddress=%s)))'
use_roles: 1
role_basedn: 'dc=mageia,dc=org'
role_scope: 'sub'
Added: identity/CatDap/trunk/lib/CatDap/Controller/forgot_password.pm
===================================================================
--- identity/CatDap/trunk/lib/CatDap/Controller/forgot_password.pm (rev 0)
+++ identity/CatDap/trunk/lib/CatDap/Controller/forgot_password.pm 2011-01-07 23:20:14 UTC (rev 249)
@@ -0,0 +1,270 @@
+package CatDap::Controller::forgot_password;
+use Moose;
+use namespace::autoclean;
+use Email::Valid;
+use Data::UUID;
+
+BEGIN {extends 'Catalyst::Controller'; }
+
+=head1 NAME
+
+CatDap::Controller::forgot_password - Catalyst Controller
+
+=head1 DESCRIPTION
+
+Catalyst Controller.
+
+=head1 METHODS
+
+=cut
+
+
+=head2 index
+
+=cut
+
+sub index :Path :Args(0) : Form {
+ my ( $self, $c ) = @_;
+
+ if (defined $c->user) {
+ # if we're logged in, we haven't forgotten the password
+ $c->log->debug('Redirecting to /user');
+ $c->res->redirect('/user');
+ }
+}
+
+sub check : Local {
+ my ( $self, $c ) = @_;
+
+ my %details = %{$c->request->params};
+ my $username = lc($c->request->params->{uid});
+ my @errors;
+ $c->stash(errors => []);
+ my $email = $c->request->params->{mail};
+ if (! Email::Valid->address($email)) {
+ push @errors, $c->loc('Invalid email address');
+ }
+
+ if (@errors) {
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/index.tt');
+ return;
+ }
+
+ # check in LDAP now that we have validated username and email
+ my $emailfilter = $c->config->{'authentication'}{'realms'}{'ldap'}{'store'}{'email_filter'};
+ $emailfilter =~ s/\%s/$email/g,
+ $c->log->debug("Searching for email $email with filter $emailfilter");
+ my $mesg = $c->model('Proxy')->search($emailfilter);
+ if (!$mesg->entries()) {
+ push @errors,$c->loc(
+ 'This email address is not bound to an account'
+ );
+ }
+
+ if (@errors) {
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/index.tt');
+ return;
+ }
+
+ if ($mesg->code) {
+ push @errors,$mesg->error;
+ $c->log->info( sprintf("finding email $email failed: %s", $mesg->error) );
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'register/index.tt');
+ return;
+ }
+
+ my $secret = gen_secret($c, $email);
+
+ $c->stash(
+ email => {
+ 'to' => $email,
+ 'from' => ${$c->config}{'emailfrom'},
+ 'subject' => ${$c->config}{'apptitle'} . " - " . $c->loc('Forgot password'),
+ 'template' => 'forgot_password.tt',
+ },
+ url => $c->uri_for('/forgot_password/confirm') . "?secret=$secret",
+ );
+
+ $c->log->info("Sending forgot password mail to email address $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, please try again later. Errors [_1]', $errors));
+ $c->error(0); # Reset the error condition if you need to
+ }
+ $c->stash(template => 'forgot_password/complete.tt');
+}
+
+sub confirm : Local {
+ my ($self, $c) = @_;
+ my $secret = $c->req->param('secret');
+ my @errors;
+
+ # show confirm page which can enter new password
+ if (defined $c->user) {
+ # if we're logged in, we haven't forgotten the password
+ $c->log->debug('Redirecting to /user');
+ $c->res->redirect('/user');
+ }
+
+ # find secret
+ my $email = find_secret($c, $secret);
+ if (!$email) {
+ push @errors, "Secret has expired, please try again.";
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/index.tt');
+ return;
+ }
+ my $mesg = find_user_email($c, $email);
+ if ($mesg->code) {
+ push @errors, "Secret has expired, please try again.";
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/index.tt');
+ return;
+ }
+
+ # show template to enter a new password
+ $c->stash(secret => $secret, template => 'forgot_password/confirm.tt');
+}
+
+sub change_password : Local {
+ my ($self, $c) = @_;
+ my @errors = ();
+ my $secret = $c->req->param('secret');
+ my $newpass;
+
+ # find secret
+ my $email = find_secret($c, $secret);
+ if (!$email) {
+ push @errors, "Secret has expired, please try again.";
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/index.tt');
+ return;
+ }
+ my $mesg = find_user_email($c, $email);
+ if ( $mesg->code) {
+ push @errors, "Secret has expired, please try again.";
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/index.tt');
+ return;
+ }
+ my $entry = $mesg->entry;
+
+ # check if both passwords are equal and are confirm the validation norms
+ if ($c->req->param('newpassword1') eq $c->req->param('newpassword2')) {
+ $newpass = $c->req->param('newpassword1');
+ } else {
+ push @errors, "New passwords dont match";
+ }
+ # if error show confirm page again to retry
+ if (@errors) {
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/confirm.tt');
+ return;
+ }
+
+ # change password
+ my $pp = Net::LDAP::Control::PasswordPolicy->new;
+ $mesg = $c->model('Proxy')->set_password(
+ user => $entry->dn,
+ newpasswd => $newpass,
+ control => [ $pp ],
+ );
+ if ($mesg->code) {
+ my $perror = $mesg->error;
+ push @errors, "Password change failed: $perror";
+ $c->detach;
+ }
+
+ # if error show confirm page again to retry
+ if (@errors) {
+ $c->stash(errors => \@errors);
+ $c->stash(template => 'forgot_password/confirm.tt');
+ return;
+ }
+
+ # TODO: log in by setting the $c->user
+
+ # remove the stored secret
+ remove_secret($c, $secret);
+
+ # redirect to /
+ $c->log->debug('Redirecting to /');
+ $c->res->redirect('/');
+}
+
+sub gen_secret {
+ my ($c, $email) = @_;
+ my $ug = new Data::UUID;
+ # generate a unique secret
+ my $secret = $ug->create_str();
+ my $filename = $c->config->{'forgot_password'}{'secret'}{'path'} .'/'. $c->config->{'forgot_password'}{'secret'}{'prefix'} . $secret;
+ # store secret with email
+ open FILE, ">$filename";
+ print FILE $email;
+ close FILE;
+ return $secret;
+}
+
+sub find_secret {
+ my ($c, $secret) = @_;
+ my $email;
+ my $filename = $c->config->{'forgot_password'}{'secret'}{'path'} .'/'. $c->config->{'forgot_password'}{'secret'}{'prefix'} . $secret;
+ my $timeout = 259200; # 3days in seconds
+ if ($c->config->{'forgot_password'}{'secret'}{'timeout'}) {
+ $timeout = $c->config->{'forgot_password'}{'secret'}{'timeout'};
+ }
+
+ # find secret
+ if (!$secret || !open(FILE, "<$filename")) {
+ # if secret is wrong, timeout expired?
+ return '';
+ }
+ read(FILE, $email, 255);
+ close FILE;
+
+ # check the time, and see if it's longer than timeout
+ my @s = stat($filename);
+ if (time() > $s[9] + $timeout) {
+ # expired
+ return '';
+ }
+
+ return $email;
+}
+
+sub remove_secret {
+ my ($c, $secret) = @_;
+ my $filename = $c->config->{'forgot_password'}{'secret'}{'path'} .'/'. $c->config->{'forgot_password'}{'secret'}{'prefix'} . $secret;
+ unlink $filename;
+}
+
+sub find_user_email {
+ my ($c, $email) = @_;
+
+ # find user by email;
+ my $emailfilter = $c->config->{'authentication'}{'realms'}{'ldap'}{'store'}{'email_filter'};
+ $emailfilter =~ s/\%s/$email/g,
+ $c->log->debug("Searching for email $email with filter $emailfilter");
+ return $c->model('Proxy')->search($emailfilter);
+}
+
+
+=head1 AUTHOR
+
+Buchan Milne
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+__PACKAGE__->meta->make_immutable;
+
+1;
Added: identity/CatDap/trunk/root/email/forgot_password.tt
===================================================================
--- identity/CatDap/trunk/root/email/forgot_password.tt (rev 0)
+++ identity/CatDap/trunk/root/email/forgot_password.tt 2011-01-07 23:20:14 UTC (rev 249)
@@ -0,0 +1,7 @@
+[% l('Dear [_1],',cn) %]
+[% l('Your [_1] account has been requested to change the password. If you did not do this, or you do not want to change your password; you can just do nothing.',c.config.organisation) %]
+[% l('To reset your password, please follow the link below.') %]
+[% url %]
+
+--
+http://mageia.org/
Added: identity/CatDap/trunk/root/forgot_password/check.tt
===================================================================
--- identity/CatDap/trunk/root/forgot_password/check.tt (rev 0)
+++ identity/CatDap/trunk/root/forgot_password/check.tt 2011-01-07 23:20:14 UTC (rev 249)
@@ -0,0 +1,4 @@
+<h2>Success</h2>
+<p>
+[% message %]
+</p>
\ No newline at end of file
Added: identity/CatDap/trunk/root/forgot_password/complete.tt
===================================================================
--- identity/CatDap/trunk/root/forgot_password/complete.tt (rev 0)
+++ identity/CatDap/trunk/root/forgot_password/complete.tt 2011-01-07 23:20:14 UTC (rev 249)
@@ -0,0 +1,6 @@
+<h2>[% l('Email sent.') %]</h2>
+
+<p>
+ [% l('Operation was successful.') %]
+ [% l('Check your mail for password reset instructions.') %]
+</p>
Added: identity/CatDap/trunk/root/forgot_password/confirm.tt
===================================================================
--- identity/CatDap/trunk/root/forgot_password/confirm.tt (rev 0)
+++ identity/CatDap/trunk/root/forgot_password/confirm.tt 2011-01-07 23:20:14 UTC (rev 249)
@@ -0,0 +1,21 @@
+
+<h1>[% l('Enter new password.') %]</h1>
+
+<div id="input_form">
+<form method="post" action="/forgot_password/change_password">
+ <table>
+ <tr>
+ <td><label for="newpassword1_">[% l('New Password') %]</label></td>
+ <td><input id="newpassword1_" name="newpassword1" type="password" value="" /></td>
+ </tr><tr>
+ <td><label for="newpassword2_">[% l('Repeat New Password') %]</label></td>
+ <td><input id="newpassword2_" name="newpassword2" type="password" value="" /></td>
+ </tr><tr>
+ <td colspan="2" style="text-align:center;">
+ <input type="hidden" name="secret" value="[% secret %]" />
+ <button type="submit" value="[% l('Set new password') %]">[% l('Set new password') %]</button>
+ </td>
+ </tr>
+ </table>
+</form>
+</div>
Added: identity/CatDap/trunk/root/forgot_password/index.tt
===================================================================
--- identity/CatDap/trunk/root/forgot_password/index.tt (rev 0)
+++ identity/CatDap/trunk/root/forgot_password/index.tt 2011-01-07 23:20:14 UTC (rev 249)
@@ -0,0 +1,17 @@
+
+<h1>[% l('Forgot your password?') %]</h1>
+
+<div id="input_form">
+<form method="post" action="/forgot_password/check">
+ <table>
+ <tr>
+ <td><label for="mail_">[% l('Email address') %]</label></td>
+ <td><input id="mail_" type="text" name="mail" value="[% c.request.params.mail %]" /></td>
+ </tr><tr>
+ <td colspan="2" style="text-align:center;">
+ <button type="submit" value="[% l('Reset password') %]">[% l('Reset password') %]</button>
+ </td>
+ </tr>
+ </table>
+</form>
+</div>
Modified: identity/CatDap/trunk/root/index.tt
===================================================================
--- identity/CatDap/trunk/root/index.tt 2011-01-07 23:15:42 UTC (rev 248)
+++ identity/CatDap/trunk/root/index.tt 2011-01-07 23:20:14 UTC (rev 249)
@@ -14,8 +14,7 @@
</div>
<div id="login_form_line">
<span><a href="/register">[% l('Register') %]</a> |
- @todo [% l('Forgotten password?') %]
- <!--<a href="/forgot_password">[% l('Forgotten password?') %]</a> -->
+ <a href="/forgot_password">[% l('Forgotten password?') %]</a>
</span>
</div>
</form>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/mageia-sysadm/attachments/20110108/f0712891/attachment-0001.html>
More information about the Mageia-sysadm
mailing list