Permalink
Browse files

mongoid part 3

  • Loading branch information...
Elad Meidar
Elad Meidar committed Mar 9, 2010
1 parent f44ab2e commit 1345c7c600d39930abffcb01062b73d2f2f845c8
@@ -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.
@@ -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 #&lt;EladMeidar::Developer:0x12e0670&gt;</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 &#8220;Remember me&#8221; 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&#8217;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&#8217;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 &#8220;reset password&#8221; 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&#8217;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&#8217;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&#8217;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>, &#8220;UserMailer model&#8221;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&#8217;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&amp;fg=444444&amp;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>
View
@@ -64,6 +64,11 @@ <h3 id="get-info">GET</h3>
<div id="post">
<h3 id="post-info">POST</h3>
+ <div class="post">
+ <h4><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></h4>
+ <em>08/03/2010</em>
+ </div>
+
<div class="post">
<h4><a href="/2010/03/creating-a-rails-authentication-system-on-mongoid-part-2-7-3-2010">Creating a Rails authentication system on Mongoid Part 2 - Remember me and Account activation</a></h4>
<em>07/03/2010</em>
Oops, something went wrong.

0 comments on commit 1345c7c

Please sign in to comment.