Skip to content

Commit a1dc2ee

Browse files
author
Kaitlyn Parkhurst
committed
Add forgot password workflow.
1 parent e0cdea8 commit a1dc2ee

File tree

3 files changed

+136
-4
lines changed

3 files changed

+136
-4
lines changed

Web/lib/BlogDB/Web/Controller/Root.pm

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package BlogDB::Web::Controller::Root;
22
use Mojo::Base 'Mojolicious::Controller', -signatures;
33
use Try::Tiny;
4+
use Data::UUID;
45

56
sub get_register ($c) {
67
$c->set_template( 'register' );
@@ -63,27 +64,82 @@ sub post_register ($c) {
6364

6465
sub get_forgot ($c) {
6566
$c->set_template( 'forgot' );
66-
6767
}
6868

6969
sub post_forgot ($c) {
7070
$c->set_template( 'forgot' );
71+
72+
my $username = $c->stash->{form_username} = $c->param('username');
7173

74+
# Find the user -- if they have an @, assume it's an email addresss.
75+
my $person = $c->db->resultset('Person')->find( index($username, '@') == -1
76+
? { username => $username }
77+
: { email => $username }
78+
);
79+
80+
push @{$c->stash->{errors}}, "No such username or email address."
81+
unless $person;
82+
83+
return 0 if $c->stash->{errors}; # Drop out of processing if there are errors.
84+
85+
my $reset_token = $person->create_related( 'password_tokens', {
86+
token => Data::UUID->new->create_str,
87+
});
88+
89+
# TODO
90+
# This is the part where we email $person->email with $c->url_for( 'reset', { token => $reset_token->token } );
91+
92+
$c->stash->{success} = 1;
7293
}
7394

7495
sub get_reset ($c) {
7596
$c->set_template( 'reset' );
7697

98+
$c->stash->{form_token} = $c->param('token');
99+
77100
}
78101

79102
sub post_reset ($c) {
80103
$c->set_template( 'reset' );
104+
105+
my $form_token = $c->stash->{form_token} = $c->param('reset_token');
106+
my $password = $c->stash->{form_password} = $c->param('password');
107+
my $confirm = $c->stash->{form_confirm} = $c->param('confirm');
81108

82-
}
109+
# Error Checking - We have all of the information.
110+
push @{$c->stash->{errors}}, "Password is required." unless $password;
111+
push @{$c->stash->{errors}}, "Confirm password is required." unless $password;
112+
push @{$c->stash->{errors}}, "Password & Confirmation must match." unless $password eq $confirm;
113+
push @{$c->stash->{errors}}, "Password must be at least 7 chars." unless 7 < length($password);
83114

84-
sub post_reset ($c) {
85-
$c->set_template( 'login' );
115+
return 0 if $c->stash->{errors}; # Drop out of processing, there are errors..
116+
117+
my $token = $c->db->resultset('PasswordToken')->search({
118+
token => $form_token,
119+
is_redeemed => 0,
120+
})->first;
121+
122+
push @{$c->stash->{errors}}, "Invalid token" unless $token;;
123+
return 0 if $c->stash->{errors}; # Drop out of processing, there are errors..
124+
125+
my $person = try {
126+
$c->db->storage->schema->txn_do( sub {
127+
# Update the user's password.
128+
$token->person->auth_password->update_password( $password );
129+
130+
# Mark the token used.
131+
$token->is_redeemed( 1 );
132+
$token->update;
133+
134+
return $token->person;
135+
});
136+
} catch {
137+
push @{$c->stash->{errors}}, "The password could not be reset: $_";
138+
};
139+
140+
return 0 if $c->stash->{errors}; # Drop out of processing the registration if there are any errors.
86141

142+
$c->stash->{success} = 1;
87143
}
88144

89145
sub post_login ($c) {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
%% cascade default::_::layout { title => 'Forgot Password',
2+
%%
3+
%% }
4+
5+
%% override panel -> {
6+
<div class="row">
7+
<!-- Error Handling On LHS -->
8+
<div class="col">
9+
%% if ( $errors.size() ) {
10+
<div style="margin-top: 2em" class="alert alert-danger" role="alert">
11+
There were errors with your request that could not be resolved:
12+
<ul>
13+
%% for $errors -> $error {
14+
<li>[% $error %]</li>
15+
%% }
16+
</ul>
17+
</div>
18+
%% }
19+
</div>
20+
21+
<!-- Forgot Handling On RHS -->
22+
<div class="col">
23+
<form method="post" action="[% $c.url_for( 'do_forgot_password' ) %]">
24+
%% include 'default/_/form/input.tx' { type => 'text', name => 'username',
25+
%% title => 'Username (or email)',
26+
%% help => 'The username or email address you signed up with.',
27+
%% value => $form_username,
28+
%% };
29+
30+
<button type="submit" class="btn btn-primary float-end">Send Reset Email</button>
31+
32+
</form>
33+
</div>
34+
%% }
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
%% cascade default::_::layout { title => 'Reset Password',
2+
%%
3+
%% }
4+
5+
%% override panel -> {
6+
<div class="row">
7+
<!-- Error Handling On LHS -->
8+
<div class="col">
9+
%% if ( $errors.size() ) {
10+
<div style="margin-top: 2em" class="alert alert-danger" role="alert">
11+
There were errors with your request that could not be resolved:
12+
<ul>
13+
%% for $errors -> $error {
14+
<li>[% $error %]</li>
15+
%% }
16+
</ul>
17+
</div>
18+
%% }
19+
</div>
20+
21+
<!-- Forgot Handling On RHS -->
22+
<div class="col">
23+
<form method="post" action="[% $c.url_for( 'do_reset_password' ) %]">
24+
<input type="hidden" name="reset_token" value="[% $form_token %]">
25+
26+
%% include 'default/_/form/input.tx' { type => 'password', name => 'password',
27+
%% title => 'Password',
28+
%% help => 'You will need your password to login.',
29+
%% value => $form_password,
30+
%% };
31+
32+
%% include 'default/_/form/input.tx' { type => 'password', name => 'confirm',
33+
%% title => 'Confirm password',
34+
%% help => mark_raw('Just to <strike>annoy you</strike> be sure it is correct.'),
35+
%% value => $form_confirm,
36+
%% };
37+
38+
<button type="submit" class="btn btn-primary float-end">Change Password</button>
39+
40+
</form>
41+
</div>
42+
%% }

0 commit comments

Comments
 (0)