-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Elad Meidar
committed
Mar 9, 2010
1 parent
f44ab2e
commit 1345c7c
Showing
14 changed files
with
320 additions
and
74 deletions.
There are no files selected for viewing
53 changes: 53 additions & 0 deletions
53
...-rails-authentication-system-on-mongoid-part-3-password-resets-8-3-2010.textile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,53 @@ | |||
--- | |||
title: Creating a Rails authentication system on Mongoid Part 3 - Password Resets | |||
layout: post | |||
--- | |||
|
|||
In the last "post":http://blog.eizesus.com/2010/03/creating-a-rails-authentication-system-on-mongoid-part-2-7-3-2010/ we added some functionality to our authentication system. We added a "Remember me" functionality to allow users to log in using a cookie and we also added an activation process that authenticates the email address we get from the user. | |||
|
|||
On this post, i'll cover *password resets*: | |||
|
|||
|
|||
h4. Password Resets | |||
|
|||
The logic behind a password reset process is rather simple, basically it is very similar to the *activation* process we did before. | |||
|
|||
* We create some kind of a temporary (perishable) token that identifies the user who wishes to reset the password. | |||
* We send the user an email with a link that contains that token and leads to a page that allows the user to choose a new password. | |||
* We update the new password, and start dancing. | |||
|
|||
h5. User.rb | |||
|
|||
First, we are going to add a field that will contain that reset token, and a method to generate it when required: | |||
|
|||
<script src="http://gist.github.com/325301.js?file=user.rb"></script> | |||
|
|||
That's basically it. | |||
|
|||
h5. UsersController | |||
|
|||
We need to add a few actions: | |||
|
|||
* one to generate the token and trigger the reset password email. | |||
* one to show a "reset password" form with password and password confirmation field. | |||
* and last, an action to save the new password and log in the user. We can't use the @#update@ action because we need a little different behavior that i think is enough to justify a separate action: First we need to find the user record based on a token not by @id@ and second, we need to use our @logout_keeping_session@ to make sure no malicious changes are made to a logged in user if it exists. | |||
|
|||
The process will work like that: | |||
|
|||
* The user will be able to go on a form and enter his email in case they forgot the password, that action will be @UsersController#forgot_password@. | |||
* If the user entered a valid email address (and one that identifies a user on the application), then @UsersController#send_password_reset@ will generate a new reset token and send the user with reset instructions. | |||
* When the user follows the reset link on the email, they'll arrive on @UsersController#reset_password@ that will match the reset token from the URI to a specific user on the system and allow the user to enter a new password if matched. | |||
* Once the user had changed and saved the password, they will be logged off and asked to re-login with their new password. | |||
|
|||
Here's the current @UsersController@: | |||
|
|||
<script src="http://gist.github.com/325973.js?file=users_controller.rb"></script> | |||
|
|||
Source for the "UsersController#forgot_password view":http://gist.github.com/325981, "UsersController#send_password_reset view":http://gist.github.com/325982, "UserMailer model"http://gist.github.com/325983, "Reset instructions mail template":http://gist.github.com/325984 and "UsersController#reset_password":http://gist.github.com/325986 added. | |||
|
|||
|
|||
h4. Conclusion | |||
|
|||
Again, it seems that we tackled most of the problems we had with Mongoid in the early stages and practically nothing bothered us too much since the first part of this series. | |||
|
|||
I keep the implementation of a background processor until a bit later, it is not that important at this stage so we'll get back to it later. |
173 changes: 173 additions & 0 deletions
173
...ating-a-rails-authentication-system-on-mongoid-part-3-password-resets-8-3-2010/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,173 @@ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | |||
<title>Emphasized Insanity - Creating a Rails authentication system on Mongoid Part 3 - Password Resets</title> | |||
<script type="text/javascript" src="/javascripts/application.js"></script> | |||
<link rel="stylesheet" type="text/css" href="/stylesheets/application.css"> | |||
<link rel="alternate" type="application/rss+xml" title="Emphasized Insanity - Elad Meidar" href="http://feeds.feedburner.com/EladOnRails" /> | |||
</head> | |||
<body> | |||
<div id="wrap"> | |||
<div id="header"> | |||
<img src="/images/500.png" alt="Emphasized Insanity" /> | |||
<div id="summary"> | |||
<h1><strong>EmphasizedInsanity</strong> at <strong>/life | |||
</strong></h1> | |||
<h2>undefined method `Sanity` for #<EladMeidar::Developer:0x12e0670></h2> | |||
<ul> | |||
<li class="first"><strong>file:</strong> <code> | |||
brain.rb</code></li> | |||
<li><strong>location:</strong> <code>instance_missing | |||
</code></li> | |||
<li class="last"><strong>line: | |||
</strong> 1</li> | |||
</ul> | |||
</div> | |||
<div class="clear"></div> | |||
</div> | |||
|
|||
<div id="backtrace" class='expanded'> | |||
<h3>BACKTRACE</h3> | |||
<p><a href="#" id="expando" | |||
onclick="toggleBacktrace(); return false">(condense)</a></p> | |||
<p id="nav"><strong>JUMP TO:</strong> | |||
<a href="#get-info">GET</a> | |||
<a href="#post-info">POSTS</a> | |||
<a href="#cookie-info">COOKIES</a> | |||
<a href="#env-info">ENV</a> | |||
</p> | |||
<div class="clear"></div> | |||
|
|||
<ul id="backtrace-ul"> | |||
|
|||
<li class="frame-info framework"> | |||
<code> | |||
No, this is not a real Sinatra error :). <br/> | |||
This is the personal homepage of Elad Meidar, a web developer and an entrepreneur specializing in Ruby on Rails. I hang around Fort Lauderdale, FL and Tel-Aviv in Israel, and i am currently running <a href="http://www.nautilus6.com">Nautilus6</a> so Feel free to contact me regarding projects :).<br/> | |||
I am a proud member of <a href="http://www.railsbridge.org">RailsBridge</a>, Helping new <a href="http://www.railsmentors.org/users/185">Rails developers</a> get into our world and also contributed a few <a href="http://contributors.rubyonrails.org/contributors/elad-meidar/commits">Patches</a> to the Ruby on Rails core. | |||
</code> | |||
</li> | |||
<li class="code framework"> | |||
</li> | |||
</ul> | |||
</div> <!-- /BACKTRACE --> | |||
|
|||
<div id="get"> | |||
<a id="homepage_link" href="/">Back to Posts List</a> | |||
<h3 id="get-info">GET</h3> | |||
<h3 class="post_title"><a href="/2010/03/creating-a-rails-authentication-system-on-mongoid-part-3-password-resets-8-3-2010">Creating a Rails authentication system on Mongoid Part 3 - Password Resets</a></h3> | |||
<div class="single_post"> | |||
<p>In the last <a href="http://blog.eizesus.com/2010/03/creating-a-rails-authentication-system-on-mongoid-part-2-7-3-2010/">post</a> we added some functionality to our authentication system. We added a “Remember me” functionality to allow users to log in using a cookie and we also added an activation process that authenticates the email address we get from the user.</p> | |||
<p>On this post, i’ll cover <strong>password resets</strong>:</p> | |||
<h4>Password Resets</h4> | |||
<p>The logic behind a password reset process is rather simple, basically it is very similar to the <strong>activation</strong> process we did before.</p> | |||
<ul> | |||
<li>We create some kind of a temporary (perishable) token that identifies the user who wishes to reset the password.</li> | |||
<li>We send the user an email with a link that contains that token and leads to a page that allows the user to choose a new password.</li> | |||
<li>We update the new password, and start dancing.</li> | |||
</ul> | |||
<h5>User.rb</h5> | |||
<p>First, we are going to add a field that will contain that reset token, and a method to generate it when required:</p> | |||
<script src="http://gist.github.com/325301.js?file=user.rb"></script><p>That’s basically it.</p> | |||
<h5>UsersController</h5> | |||
<p>We need to add a few actions:</p> | |||
<ul> | |||
<li>one to generate the token and trigger the reset password email.</li> | |||
<li>one to show a “reset password” form with password and password confirmation field.</li> | |||
<li>and last, an action to save the new password and log in the user. We can’t use the <code>#update</code> action because we need a little different behavior that i think is enough to justify a separate action: First we need to find the user record based on a token not by <code>id</code> and second, we need to use our <code>logout_keeping_session</code> to make sure no malicious changes are made to a logged in user if it exists.</li> | |||
</ul> | |||
<p>The process will work like that:</p> | |||
<ul> | |||
<li>The user will be able to go on a form and enter his email in case they forgot the password, that action will be <code>UsersController#forgot_password</code>.</li> | |||
<li>If the user entered a valid email address (and one that identifies a user on the application), then <code>UsersController#send_password_reset</code> will generate a new reset token and send the user with reset instructions.</li> | |||
<li>When the user follows the reset link on the email, they’ll arrive on <code>UsersController#reset_password</code> that will match the reset token from the <span class="caps">URI</span> to a specific user on the system and allow the user to enter a new password if matched.</li> | |||
<li>Once the user had changed and saved the password, they will be logged off and asked to re-login with their new password.</li> | |||
</ul> | |||
<p>Here’s the current <code>UsersController</code>:</p> | |||
<script src="http://gist.github.com/325973.js?file=users_controller.rb"></script><p>Source for the <a href="http://gist.github.com/325981">UsersController#forgot_password view</a>, <a href="http://gist.github.com/325982">UsersController#send_password_reset view</a>, “UserMailer model”http://gist.github.com/325983, <a href="http://gist.github.com/325984">Reset instructions mail template</a> and <a href="http://gist.github.com/325986">UsersController#reset_password</a> added.</p> | |||
<h4>Conclusion</h4> | |||
<p>Again, it seems that we tackled most of the problems we had with Mongoid in the early stages and practically nothing bothered us too much since the first part of this series.</p> | |||
<p>I keep the implementation of a background processor until a bit later, it is not that important at this stage so we’ll get back to it later.</p> | |||
</div> | |||
<div class="clear"></div> | |||
</div> <!-- /GET --> | |||
|
|||
<div id="post"> | |||
<h3 id="post-info">POST</h3> | |||
<div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/emphasizedinsanity/embed.js"></script><noscript><a href="http://emphasizedinsanity.disqus.com/?url=ref">View the discussion thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a> | |||
<div class="clear"></div> | |||
</div> <!-- /POST --> | |||
|
|||
<div id="cookies"> | |||
<h3 id="cookie-info">COOKIES</h3> | |||
|
|||
<p class="no-data">I Don't have cookies.</p> | |||
|
|||
<div class="clear"></div> | |||
</div> <!-- /COOKIES --> | |||
|
|||
<div id="rack"> | |||
<h3 id="env-info">ELAD ENV</h3> | |||
<table class="req"> | |||
<tr> | |||
<th>Variable</th> | |||
<th>Value</th> | |||
</tr> | |||
|
|||
<tr> | |||
<td>LINKEDIN</td> | |||
<td class="code"><div><a href="http://www.linkedin.com/in/eladmeidar">http://www.linkedin.com/in/eladmeidar</a></div></td> | |||
</tr> | |||
|
|||
<tr> | |||
<td>TWITTER</td> | |||
<td class="code"><div><a href="http://www.twitter.com/eladmeidar">http://www.twitter.com/eladmeidar</a></div></td> | |||
</tr> | |||
|
|||
<tr> | |||
<td>FACEBOOK</td> | |||
<td class="code"><div><a href="http://www.facebook.com/eladmeidar">http://www.facebook.com/eladmeidar</a></div></td> | |||
</tr> | |||
|
|||
<tr> | |||
<td>GITHUB</td> | |||
<td class="code"><div><a href="http://github.com/eladmeidar">http://github.com/eladmeidar</a></div></td> | |||
</tr> | |||
|
|||
<tr> | |||
<td>WWR</td> | |||
<td class="code"><div><code>{ :working_with_rails => '<a href="http://www.workingwithrails.com/person/5844-elad-meidar">http://www.workingwithrails.com/person/5844-elad-meidar</a>' }</code></div></td> | |||
</tr> | |||
|
|||
<tr> | |||
<td>IRC</td> | |||
<td class="code"><div><code>{ 'irc.freenode.net' => [ '#rubyonrails', '#railsbridge', '#ruby', '#jquery' ]}</code></div></td> | |||
</tr> | |||
<tr> | |||
<td>SKYPE</td> | |||
<td class="code"><div>eladmeidar</div></td> | |||
</tr> | |||
</table> | |||
<div class="clear"></div> | |||
</div> <!-- /RACK ENV --> | |||
|
|||
<div class="stats"> | |||
<p> | |||
<a href="http://feeds2.feedburner.com/EladOnRails"><img src="http://feeds2.feedburner.com/~fc/EladOnRails?bg=FFFFFF&fg=444444&anim=0" height="26" width="88" style="border:0" alt="" /></a> | |||
<script type="text/javascript" language="javascript" src="http://twittercounter.com/embed/?username=eladmeidar&style=white"></script> | |||
</p> | |||
<p> | |||
<script type="text/javascript" src="http://s51.sitemeter.com/js/counter.js?site=s51eizesusrulez"></script> | |||
<noscript> | |||
<a href="http://s51.sitemeter.com/stats.asp?site=s51eizesusrulez" target="_top"> | |||
<img src="http://s51.sitemeter.com/meter.asp?site=s51eizesusrulez" alt="Site Meter" border="0"/></a> | |||
</noscript> | |||
</p> | |||
<div class="clear"></div> | |||
</div> | |||
<p id="explanation">You're seeing this error because I think it is funny.</p> | |||
|
|||
</div> <!-- /WRAP --> | |||
</body> | |||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.