1
00:00:00,000 --> 00:00:04,920
[MUSIC]
2
00:00:04,920 --> 00:00:08,100
Okay, so our application is
coming along pretty well.
3
00:00:08,100 --> 00:00:10,120
We've got authentication set up.
4
00:00:10,120 --> 00:00:15,312
We've scoped our todo list and todo
items to the currently logged in user.
5
00:00:15,312 --> 00:00:19,670
There is just one more problem,
which is that we don't have a way for
6
00:00:19,670 --> 00:00:24,780
a user to reset their password
once they've forgotten it.
7
00:00:24,780 --> 00:00:30,580
So if for some reason they can't log in,
what we wanna do is send them an email and
8
00:00:30,580 --> 00:00:33,230
give them some way to
reset their password.
9
00:00:33,230 --> 00:00:40,410
Now the way that we're gonna do this is by
generating a random token for the user.
10
00:00:40,410 --> 00:00:42,960
And we're gonna call that
the Password Reset Token.
11
00:00:44,000 --> 00:00:49,310
So in order to do that, we need to
add an attribute to our user model,
12
00:00:49,310 --> 00:00:51,820
which we're gonna call
Password Reset Token.
13
00:00:53,120 --> 00:00:56,390
Then what we'll do when somebody
clicks forgot their password,
14
00:00:56,390 --> 00:01:01,100
we'll generate a new random reset
token and email them a link to it.
15
00:01:01,100 --> 00:01:05,007
So let's go ahead and do that,
we're gonna create a migration first.
16
00:01:06,472 --> 00:01:12,851
And we'll call that
add_password_reset_token_to_users.
17
00:01:21,873 --> 00:01:24,670
Okay, now we've generated the migration.
18
00:01:24,670 --> 00:01:25,620
Let's go ahead and open it up.
19
00:01:25,620 --> 00:01:30,417
And this is a pretty easy migration
to write, we're gonna add
20
00:01:30,417 --> 00:01:35,596
a column on the :users table
called :password_reset_token,
21
00:01:39,460 --> 00:01:42,162
Which is a string.
22
00:01:42,162 --> 00:01:46,272
And since we're gonna occasionally
look that password_reset_token,
23
00:01:46,272 --> 00:01:47,911
we need to add an index for it.
24
00:01:50,165 --> 00:01:53,950
Now we'll go ahead and
migrate our database.
25
00:01:56,890 --> 00:01:59,310
And let's not forget to migrate
our test database as well.
26
00:02:00,340 --> 00:02:06,780
All right, so we've got that done,
now what we need to do is write a method
27
00:02:06,780 --> 00:02:11,880
that will change that password_reset_token
and generate one for us.
28
00:02:11,880 --> 00:02:15,940
Cuz that's what we're gonna call
from our password resets controller,
29
00:02:15,940 --> 00:02:16,850
as soon as we make it.
30
00:02:18,220 --> 00:02:22,300
So let's go ahead and
open up our user_spec here.
31
00:02:22,300 --> 00:02:26,141
Now we'll follow this same pattern
that we were doing before,
32
00:02:26,141 --> 00:02:29,556
where we write our test first,
and then we make it pass.
33
00:02:32,724 --> 00:02:36,492
So, let's call this method that
we're gonna write for the user,
34
00:02:36,492 --> 00:02:38,795
generate_password_reset_token.
35
00:02:40,360 --> 00:02:42,850
And, I'm adding
an exclamation point to it,
36
00:02:42,850 --> 00:02:45,590
because it is potentially
a dangerous method.
37
00:02:45,590 --> 00:02:50,690
And the first thing we'll
say is that it changes
38
00:02:50,690 --> 00:02:55,289
the password_reset_token attribute.
39
00:03:00,142 --> 00:03:05,042
So we'll expect that calling
generate_password_reset_token changes that
40
00:03:05,042 --> 00:03:06,780
attribute.
41
00:03:06,780 --> 00:03:10,932
We're gonna need a user to work with here,
so we'll use factory girl to create one.
42
00:03:13,653 --> 00:03:18,079
And we'll say,
user.generate_password_reset_token
43
00:03:19,967 --> 00:03:21,129
Changes.
44
00:03:27,305 --> 00:03:28,120
That attribute.
45
00:03:28,120 --> 00:03:32,650
Now you'll notice we're
using curly braces here
46
00:03:32,650 --> 00:03:37,480
instead of parentheses,
the reason is when we do that we're having
47
00:03:37,480 --> 00:03:41,990
it evoked as a block
instead of just a method.
48
00:03:44,180 --> 00:03:46,420
This will allow the code
inside to actually run,
49
00:03:46,420 --> 00:03:47,565
rather then just being called.
50
00:03:47,565 --> 00:03:52,581
Let's go ahead and run that test,
and watch it fail.
51
00:03:55,759 --> 00:03:58,950
Okay, undefined method
genereate_password_reset_token.
52
00:03:58,950 --> 00:04:00,662
Makes sense, haven't written it yet.
53
00:04:05,025 --> 00:04:07,180
Let's go ahead and open up our user model.
54
00:04:14,368 --> 00:04:18,730
All right, so
now we have that method in there.
55
00:04:18,730 --> 00:04:20,920
Let's watch that part of the test fail.
56
00:04:22,090 --> 00:04:24,493
Looks like I spelled it wrong here.
57
00:04:27,344 --> 00:04:28,923
More than one time.
58
00:04:33,168 --> 00:04:36,869
Okay, it should have changed,
but it is still nil.
59
00:04:40,303 --> 00:04:45,541
So the way that we're actually
gonna generate this password
60
00:04:45,541 --> 00:04:50,810
reset function is with a method
called urlsafe_base64.
61
00:04:50,810 --> 00:04:57,827
And what this does is generates
a random urlsafe_base64 string.
62
00:04:58,950 --> 00:05:04,880
So, the first argument is
the length of the string.
63
00:05:04,880 --> 00:05:08,770
And then the length of the result
string is about four thirds of n.
64
00:05:08,770 --> 00:05:12,160
So what we'll do is we get
a string like this, and
65
00:05:12,160 --> 00:05:16,880
then the reason we want your url safe
is that is the address that we're gonna
66
00:05:16,880 --> 00:05:19,900
send in the email for
the user to go reset it to.
67
00:05:19,900 --> 00:05:22,960
Now, this is a random string, so
68
00:05:22,960 --> 00:05:27,680
we can be pretty sure that we're
not gonna have any collisions.
69
00:05:27,680 --> 00:05:30,460
We're probably not gonna have tons of
users resetting their passwords at
70
00:05:30,460 --> 00:05:31,380
the same time.
71
00:05:31,380 --> 00:05:32,814
And, by the way,
72
00:05:32,814 --> 00:05:38,092
this is on the secure random method
in the Ruby standard library.
73
00:05:40,250 --> 00:05:44,883
So the way that we'll do
this is we'll say we'll
74
00:05:44,883 --> 00:05:49,860
update the attribute,
password_reset_token.
75
00:05:53,230 --> 00:06:00,210
And we'll call that method
securerandom.urlsafe_base64.
76
00:06:00,210 --> 00:06:04,610
Let's run that test again.
77
00:06:06,610 --> 00:06:08,181
Okay, that passes.
78
00:06:20,787 --> 00:06:24,660
And let's go ahead and make sure
that this method is actually called.
79
00:06:54,450 --> 00:06:59,350
So the way we do that is we expect
the secure random class to receive
80
00:06:59,350 --> 00:07:01,052
urlsafe_base64.
81
00:07:01,052 --> 00:07:02,520
And let's go ahead and run that.
82
00:07:05,120 --> 00:07:06,890
Okay, now that passes.
83
00:07:07,990 --> 00:07:11,660
Now, just to be sure, let's go ahead and
84
00:07:11,660 --> 00:07:14,590
specify that we want this
to be a certain length.
85
00:07:17,940 --> 00:07:22,604
And that'll just make sure that our
long random string is even longer.
86
00:07:24,438 --> 00:07:25,589
Cool.
Now, let's go ahead and
87
00:07:25,589 --> 00:07:27,235
just see how that works in the console.
88
00:07:53,420 --> 00:07:57,814
So here I am creating
a user in the console.
89
00:07:57,814 --> 00:08:00,983
Okay, the user is valid,
so I'm gonna save it.
90
00:08:00,983 --> 00:08:04,400
Okay, the user is saved,
we could see that right here.
91
00:08:05,780 --> 00:08:07,380
Now, let me go ahead and
92
00:08:07,380 --> 00:08:14,340
call that generate_password_reset_token
and see what happens.
93
00:08:14,340 --> 00:08:18,870
So when I call that,
it updates the user's table and
94
00:08:18,870 --> 00:08:22,050
it sets that password reset token
to that long random string.
95
00:08:22,050 --> 00:08:22,800
Lets take a look at it.
96
00:08:24,450 --> 00:08:25,730
And there we go.
97
00:08:26,730 --> 00:08:32,400
So what we're going to do in
the next screen cast is start our
98
00:08:32,400 --> 00:08:37,527
password reset controller, which will
call this password_reset_token method.