Implement password resets

This commit is contained in:
Al Beano 2017-08-19 15:03:54 +01:00
parent 5e4ba72357
commit fb17a96c26
8 changed files with 207 additions and 2 deletions

2
dbupdate/2.sql Normal file
View File

@ -0,0 +1,2 @@
alter table user add column recoverytoken text;
update cyberman set dbrev=3;

View File

@ -9,6 +9,7 @@ use cyberman::Account;
use cyberman::Helper;
use cyberman::API;
use cyberman::Records;
use cyberman::Forgot;
# Index route, hook and helper functions for authentication

117
lib/cyberman/Forgot.pm Normal file
View File

@ -0,0 +1,117 @@
package cyberman::Forgot;
use Dancer2 appname => "cyberman";
use Dancer2::Plugin::Database;
use URI::Escape;
use cyberman::Helper;
post '/forgot' => sub {
my $user = database->quick_select(
"user",
{
"email" => param("email"),
},
);
if (!$user) {
return template 'forgot' => {
err => 1,
e_no_user => 1,
};
}
my $token = randstring(32);
database->quick_update(
"user",
{
"id" => $user->{"id"},
},
{
"recoverytoken" => $token,
},
);
my $email = template 'email/forgot' => {
"link" => config->{"mail"}->{"baseurl"} . "/confirm_forgot?e=" . uri_escape(param("email")) . "&t=$token",
},
{
"layout" => undef,
};
send_email(param("email"), $email);
template 'forgot' => {
success => 1,
};
};
post '/confirm_forgot' => sub {
my %errs;
if (!param("e") || !param("t")) {
$errs{"e_bad_link"} = 1;
} elsif (!param("password")) {
$errs{"e_no_pass"} = 1;
} elsif (length(param("password")) < 8) {
$errs{"e_pass_len"} = 1;
} elsif (param("password") ne param("password2")) {
$errs{"e_pass_mismatch"} = 1;
}
if (scalar(keys(%errs)) == 0) {
my $user = database->quick_select(
"user",
{
"email" => param("e"),
"recoverytoken" => param("t"),
},
);
if (!$user) {
$errs{"e_bad_link"} = 1;
} else {
# Update the password
my ($hash, $salt) = hash_password(param "password");
database->quick_update(
"user",
{
"id" => $user->{"id"},
},
{
"password" => $hash,
"salt" => $salt,
},
);
database->quick_delete(
"session",
{
"uid" => $user->{"id"},
},
);
database->quick_update(
"user",
{
"id" => $user->{"id"},
},
{
"recoverytoken" => "",
},
);
}
}
if (scalar(keys(%errs)) != 0) {
return template 'confirm_forgot' => {
"err" => 1,
%errs,
};
}
template 'redir' => {
"redir" => "login?pwchange=1",
};
};
true;

View File

@ -3,7 +3,7 @@ create table cyberman (
id integer primary key,
dbrev integer not null
);
insert into cyberman (dbrev) values (2);
insert into cyberman (dbrev) values (3);
drop table if exists user;
create table user (
@ -13,7 +13,8 @@ create table user (
salt text not null,
active integer not null default 0,
conftoken text not null,
newemail text
newemail text,
recoverytoken text
);
drop table if exists session;

49
views/confirm_forgot.tt Normal file
View File

@ -0,0 +1,49 @@
<center>
<br />
<h1>Update your password</h1>
<br />
<% IF err %>
<div class="msgBox">
Error:
<% IF e_bad_link %>
The link you clicked on is invalid!
<% ELSIF e_no_pass %>
You must enter a password.
<% ELSIF e_pass_len %>
Your password must be at least 8 characters long.
<% ELSIF e_pass_mismatch %>
The two passwords you entered do not match.
<% END%>
</div>
<br /><br />
<% END %>
</center>
<div class="body">
Enter a new password and click update.
<br />
<form method="POST" class="login" action="confirm_forgot">
<input type="hidden" name="e" value="<% params.e | html_entity %>" />
<input type="hidden" name="t" value="<% params.t | html_entity %>" />
<table>
<tr>
<td>
<label for="password">New password:</label>
</td>
<td>
<input type="password" name="password" id="password" />
</td>
</tr>
<tr>
<td>
<label for="password2">New password (confirm):</label>
</td>
<td>
<input type="password" name="password2" id="password2" />
</td>
</tr>
</table>
<br />
[&nbsp;<button class="textButton" action="submit">update</button>&nbsp;]
</form>
</div>

6
views/email/forgot.tt Normal file
View File

@ -0,0 +1,6 @@
Hello!
You're receiving this email because someone tried to reset your cybNIC password. If this was you, please click the link below:
<% link %>
If it wasn't, you can safely ignore this email.

27
views/forgot.tt Normal file
View File

@ -0,0 +1,27 @@
<center>
<br />
<h1 >Forgotten password</h1>
<br />
<% IF err || success %>
<div class="msgBox">
<% IF e_no_user %>
Error: There is no user account associated with that email address.
<% END %>
<% IF success %>
An email has been sent to <% params.email | html_entity %>. Please click the link to reset your password.
<% END %>
</div>
<br /><br />
<% END %>
</center>
<div class="body">
Enter your email into the field below and we'll send an email with a link to reset your password.
<br />
<form method="POST">
<label for="email">Email address:</label>
<input type="email" name="email" id="email" value="<% params.email | html_entity %>"/>
<br />
[&nbsp;<button action="submit" class="textButton">submit</button>&nbsp;]
</form>
</div>

View File

@ -57,5 +57,7 @@
<br />
[&nbsp;<button action="submit" class="textButton">log&nbsp;in</button>&nbsp;]
[&nbsp;<a href="index" class="bracketButton">go&nbsp;back</a>&nbsp;]
<br /><br />
[&nbsp;<a href="forgot" class="bracketButton">recover forgotten password</a>&nbsp;]
</form>
</div>