<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/controllers/password_resets_controller.rb</filename>
    </added>
    <added>
      <filename>app/models/auth_session.rb</filename>
    </added>
    <added>
      <filename>app/views/mailer/password_reset.erb</filename>
    </added>
    <added>
      <filename>app/views/password_resets/index.html.erb</filename>
    </added>
    <added>
      <filename>app/views/password_resets/show.html.erb</filename>
    </added>
    <added>
      <filename>config/locales/session.en.yml</filename>
    </added>
    <added>
      <filename>spec/controllers/password_reset_controller_spec.rb</filename>
    </added>
    <added>
      <filename>spec/views/password_resets/index_spec.rb</filename>
    </added>
    <added>
      <filename>spec/views/password_resets/show_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -18,13 +18,9 @@ class ApplicationController &lt; ActionController::Base #:nodoc:
 
   helper :all # include all helpers, all the time
 
-  helper_method :current_session, :authenticated
-
-  class UserSession &lt;  Authlogic::Session::Base
-    authenticate_with Person
-    params_key :access_key
-    single_access_allowed_request_types [Mime::ATOM, Mime::ICS]
-  end
+  # Returns currently authenticated person.
+  attr_reader :authenticated
+  helper_method :authenticated
 
 private
 
@@ -38,25 +34,14 @@ private
   # See ActionController::RequestForgeryProtection for details
   protect_from_forgery
 
-  def current_session
-    return @current_session if defined?(@current_session)
-    @current_session = UserSession.find
-  end
-
-  # Returns currently authenticated user.
-  def authenticated
-    return @authenticated if defined?(@authenticated)
-    @authenticated = current_session &amp;&amp; current_session.person
-  end
-
   before_filter :authenticate
   # Authentication filter enabled by default since most resources are guarded.
   def authenticate
-    # TODO: HTTP Basic might need this
-    # params[request_forgery_protection_token] = form_authenticity_token
-    if authenticated
-      I18n.locale = authenticated.locale.to_sym if authenticated.locale
-      Time.zone = authenticated.timezone
+    auth_session = AuthSession.find
+    @authenticated = auth_session &amp;&amp; auth_session.person
+    if @authenticated
+      I18n.locale = @authenticated.locale.to_sym if @authenticated.locale
+      Time.zone = @authenticated.timezone
     elsif request.format.html?
       session[:return_url] = request.url
       redirect_to session_url</diff>
      <filename>app/controllers/application_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -19,23 +19,21 @@ class SessionsController &lt; ApplicationController #:nodoc:
   skip_before_filter :authenticate
 
   def show
+    @auth_session = AuthSession.new
   end
 
   def create
-    user_session = UserSession.new(params)
-    if user_session.save
-      redirect = session.delete(:return_url) || root_url
-      redirect_to redirect, :status=&gt;:see_other 
+    @auth_session = AuthSession.new(params)
+    if @auth_session.save
+      redirect_to session.delete(:return_url) || root_url
     else
-      flash[:error] = t('sessions.errors.nomatch') unless params[:login].blank?
-      redirect_to session_url, :status=&gt;:see_other
+      render :action=&gt;:show
     end
   end
 
   def destroy
-    @authenticated = nil
-    current_session.destroy
-    redirect_to root_url, :status=&gt;:see_other
+    AuthSession.find.destroy
+    redirect_to root_url
   end
 
 end</diff>
      <filename>app/controllers/sessions_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -19,6 +19,15 @@ class Mailer &lt; ActionMailer::Base
   helper :application
   layout 'mailer'
 
+  def password_reset(person)
+    subject       &quot;Instructions for resetting your password&quot;
+    from          &quot;Notifications &lt;notifications@#{default_url_options[:host]}&gt;&quot;
+    reply_to      &quot;Do not reply &lt;noreply@#{default_url_options[:host]}&gt;&quot;
+    recipients    person.email
+    body          :link=&gt;password_reset_url(person.perishable_token)
+
+  end
+
   def notification(notification, recipient)
     subject      notification.subject
     from         &quot;Notifications &lt;notifications@#{default_url_options[:host]}&gt;&quot;</diff>
      <filename>app/models/mailer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -109,7 +109,7 @@ class Person &lt; ActiveRecord::Base
   end
 
   acts_as_authentic do |config|
-    # Configuration comes here.
+    perishable_token_valid_for 1.hour
   end
   
 </diff>
      <filename>app/models/person.rb</filename>
    </modified>
    <modified>
      <diff>@@ -28,6 +28,7 @@
 					&lt;/ol&gt;
         &lt;/li&gt;
       &lt;/ol&gt;
+      &lt;%= [:error, :notice, :success].select { |k| flash[k] }.map { |k| content_tag('div', h(flash[k]), :class=&gt;k) }.join %&gt;
     &lt;/div&gt;
     &lt;div id='container'&gt;
       &lt;%= yield(:content) or yield %&gt;</diff>
      <filename>app/views/layouts/application.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,12 +1,14 @@
-&lt;% form_for :session, :url=&gt;session_url, :html=&gt;{ :class=&gt;'login' } do %&gt;
+&lt;% form_for @auth_session, :url=&gt;session_url, :html=&gt;{ :class=&gt;'login' } do |f| %&gt;
   &lt;fieldset&gt;
-    &lt;%= content_tag 'p', flash[:error], :class=&gt;'error' if flash[:error] %&gt;
+    &lt;%= f.error_messages :header_message=&gt;false, :message=&gt;false, :class=&gt;'error' %&gt;
     &lt;dl&gt;
       &lt;dt&gt;&lt;%= label_tag 'login', t('.login.label') %&gt;&lt;/dt&gt;
       &lt;dd&gt;&lt;%= text_field_tag 'login', nil, :size=&gt;40, :title=&gt;t('.login.hint'), :class=&gt;'auto_focus' %&gt;&lt;/dd&gt;
       &lt;dt&gt;&lt;%= label_tag 'password', t('.password.label') %&gt;&lt;/dt&gt;
       &lt;dd&gt;&lt;%= password_field_tag 'password', nil, :size=&gt;40, :title=&gt;t('.password.hint') %&gt;&lt;/dd&gt;
+      &lt;dt&gt;&lt;/dt&gt;&lt;dd&gt;&lt;label&gt;&lt;%= check_box_tag 'remember_me', 1, true %&gt; &lt;%= t('.remember_me.label') %&gt;&lt;/label&gt;&lt;/dd&gt;
       &lt;dt&gt;&lt;/dt&gt;&lt;dd&gt;&lt;%= submit_tag t('.submit.button'), :title=&gt;t('.submit.hint') %&gt;&lt;/dd&gt;
+      &lt;dt&gt;&lt;/dt&gt;&lt;dd&gt;&lt;%= link_to t('.recover'), password_resets_path %&gt;&lt;/dd&gt;
     &lt;/dl&gt; 
   &lt;/fieldset&gt;
 &lt;% end %&gt;</diff>
      <filename>app/views/sessions/show.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -25,19 +25,6 @@ en:
         header:    &quot;Time to complete each task (dd:hh)&quot;
         hover:     &quot;{{count}} tasks completed in under {{hours}} hours&quot;
         format:    &quot;%0d:%02d&quot;
-  sessions:
-    errors:
-      nomatch:  &quot;No account with this user name and password.&quot;
-    show:
-      submit:
-        button:   &quot;Login&quot;
-        hint:     &quot;&quot;
-      login:
-        label:    &quot;Username:&quot;
-        hint:     &quot;Your username&quot;
-      password:
-        label:    &quot;Password:&quot;
-        hint:     &quot;Your password is case sensitive&quot;
   # Layouts
   layouts:
     application:</diff>
      <filename>config/locales/en.yml</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,6 @@
 
 ActionController::Routing::Routes.draw do |map|
 
-  map.resource 'session'
   map.resources 'tasks', :collection=&gt;{ 'completed'=&gt;:get, 'following'=&gt;:get, 'complete_redirect'=&gt;:get },
     :member=&gt;['activities'] do |tasks|
     tasks.with_options :controller=&gt;'task_for' do |opts|
@@ -34,6 +33,8 @@ ActionController::Routing::Routes.draw do |map|
   map.resources 'notifications'
   map.resources 'activities'
   map.resource  'graphs'
+  map.resource 'session'
+  map.resources 'password_resets'
   
   map.root :controller=&gt;'tasks', :action=&gt;'index'
 
@@ -42,64 +43,66 @@ ActionController::Routing::Routes.draw do |map|
   map.connect ':controller/:action/:id.:format'
 end
 #== Route Map
-# Generated on 20 May 2009 16:20
+# Generated on 11 Jun 2009 22:44
 #
-#             new_session GET    /session/new(.:format)             {:action=&gt;&quot;new&quot;, :controller=&gt;&quot;sessions&quot;}
-#            edit_session GET    /session/edit(.:format)            {:action=&gt;&quot;edit&quot;, :controller=&gt;&quot;sessions&quot;}
-#                 session GET    /session(.:format)                 {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;sessions&quot;}
-#                         PUT    /session(.:format)                 {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;sessions&quot;}
-#                         DELETE /session(.:format)                 {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;sessions&quot;}
-#                         POST   /session(.:format)                 {:action=&gt;&quot;create&quot;, :controller=&gt;&quot;sessions&quot;}
-#         completed_tasks GET    /tasks/completed(.:format)         {:action=&gt;&quot;completed&quot;, :controller=&gt;&quot;tasks&quot;}
-# complete_redirect_tasks GET    /tasks/complete_redirect(.:format) {:action=&gt;&quot;complete_redirect&quot;, :controller=&gt;&quot;tasks&quot;}
-#         following_tasks GET    /tasks/following(.:format)         {:action=&gt;&quot;following&quot;, :controller=&gt;&quot;tasks&quot;}
-#                   tasks GET    /tasks(.:format)                   {:action=&gt;&quot;index&quot;, :controller=&gt;&quot;tasks&quot;}
-#                         POST   /tasks(.:format)                   {:action=&gt;&quot;create&quot;, :controller=&gt;&quot;tasks&quot;}
-#                new_task GET    /tasks/new(.:format)               {:action=&gt;&quot;new&quot;, :controller=&gt;&quot;tasks&quot;}
-#         activities_task        /tasks/:id/activities(.:format)    {:action=&gt;&quot;activities&quot;, :controller=&gt;&quot;tasks&quot;}
-#               edit_task GET    /tasks/:id/edit(.:format)          {:action=&gt;&quot;edit&quot;, :controller=&gt;&quot;tasks&quot;}
-#                    task GET    /tasks/:id(.:format)               {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;tasks&quot;}
-#                         PUT    /tasks/:id(.:format)               {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;tasks&quot;}
-#                         DELETE /tasks/:id(.:format)               {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;tasks&quot;}
-#                         PUT    /tasks/:task_id/for/:person_id     {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;task_for&quot;}
-#         task_for_person        /tasks/:task_id/for/:person_id     {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;task_for&quot;}
-#                         POST   /tasks/:id                         {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;tasks&quot;}
-#                  search        /search                            {:action=&gt;&quot;search&quot;, :controller=&gt;&quot;tasks&quot;}
-#             open_search        /search/osd                        {:action=&gt;&quot;opensearch&quot;, :controller=&gt;&quot;tasks&quot;}
-#                   forms GET    /forms(.:format)                   {:action=&gt;&quot;index&quot;, :controller=&gt;&quot;forms&quot;}
-#                         POST   /forms(.:format)                   {:action=&gt;&quot;create&quot;, :controller=&gt;&quot;forms&quot;}
-#                new_form GET    /forms/new(.:format)               {:action=&gt;&quot;new&quot;, :controller=&gt;&quot;forms&quot;}
-#               edit_form GET    /forms/:id/edit(.:format)          {:action=&gt;&quot;edit&quot;, :controller=&gt;&quot;forms&quot;}
-#                    form GET    /forms/:id(.:format)               {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;forms&quot;}
-#                         PUT    /forms/:id(.:format)               {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;forms&quot;}
-#                         DELETE /forms/:id(.:format)               {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;forms&quot;}
-#               templates GET    /templates(.:format)               {:action=&gt;&quot;index&quot;, :controller=&gt;&quot;templates&quot;}
-#                         POST   /templates(.:format)               {:action=&gt;&quot;create&quot;, :controller=&gt;&quot;templates&quot;}
-#            new_template GET    /templates/new(.:format)           {:action=&gt;&quot;new&quot;, :controller=&gt;&quot;templates&quot;}
-#           edit_template GET    /templates/:id/edit(.:format)      {:action=&gt;&quot;edit&quot;, :controller=&gt;&quot;templates&quot;}
-#                template GET    /templates/:id(.:format)           {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;templates&quot;}
-#                         PUT    /templates/:id(.:format)           {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;templates&quot;}
-#                         DELETE /templates/:id(.:format)           {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;templates&quot;}
-#           notifications GET    /notifications(.:format)           {:action=&gt;&quot;index&quot;, :controller=&gt;&quot;notifications&quot;}
-#                         POST   /notifications(.:format)           {:action=&gt;&quot;create&quot;, :controller=&gt;&quot;notifications&quot;}
-#        new_notification GET    /notifications/new(.:format)       {:action=&gt;&quot;new&quot;, :controller=&gt;&quot;notifications&quot;}
-#       edit_notification GET    /notifications/:id/edit(.:format)  {:action=&gt;&quot;edit&quot;, :controller=&gt;&quot;notifications&quot;}
-#            notification GET    /notifications/:id(.:format)       {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;notifications&quot;}
-#                         PUT    /notifications/:id(.:format)       {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;notifications&quot;}
-#                         DELETE /notifications/:id(.:format)       {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;notifications&quot;}
-#              activities GET    /activities(.:format)              {:action=&gt;&quot;index&quot;, :controller=&gt;&quot;activities&quot;}
-#                         POST   /activities(.:format)              {:action=&gt;&quot;create&quot;, :controller=&gt;&quot;activities&quot;}
-#            new_activity GET    /activities/new(.:format)          {:action=&gt;&quot;new&quot;, :controller=&gt;&quot;activities&quot;}
-#           edit_activity GET    /activities/:id/edit(.:format)     {:action=&gt;&quot;edit&quot;, :controller=&gt;&quot;activities&quot;}
-#                activity GET    /activities/:id(.:format)          {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;activities&quot;}
-#                         PUT    /activities/:id(.:format)          {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;activities&quot;}
-#                         DELETE /activities/:id(.:format)          {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;activities&quot;}
-#              new_graphs GET    /graphs/new(.:format)              {:action=&gt;&quot;new&quot;, :controller=&gt;&quot;graphs&quot;}
-#             edit_graphs GET    /graphs/edit(.:format)             {:action=&gt;&quot;edit&quot;, :controller=&gt;&quot;graphs&quot;}
-#                  graphs GET    /graphs(.:format)                  {:action=&gt;&quot;show&quot;, :controller=&gt;&quot;graphs&quot;}
-#                         PUT    /graphs(.:format)                  {:action=&gt;&quot;update&quot;, :controller=&gt;&quot;graphs&quot;}
-#                         DELETE /graphs(.:format)                  {:action=&gt;&quot;destroy&quot;, :controller=&gt;&quot;graphs&quot;}
-#                         POST   /graphs(.:format)                  {:action=&gt;&quot;create&quot;, :controller=&gt;&quot;graphs&quot;}
-#                    root        /                                  {:action=&gt;&quot;index&quot;, :controller=&gt;&quot;tasks&quot;}
+#         completed_tasks GET    /tasks/completed(.:format)         {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;completed&quot;}
+# complete_redirect_tasks GET    /tasks/complete_redirect(.:format) {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;complete_redirect&quot;}
+#         following_tasks GET    /tasks/following(.:format)         {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;following&quot;}
+#                   tasks GET    /tasks(.:format)                   {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;index&quot;}
+#                         POST   /tasks(.:format)                   {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;create&quot;}
+#                new_task GET    /tasks/new(.:format)               {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;new&quot;}
+#         activities_task        /tasks/:id/activities(.:format)    {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;activities&quot;}
+#               edit_task GET    /tasks/:id/edit(.:format)          {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;edit&quot;}
+#                    task GET    /tasks/:id(.:format)               {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;show&quot;}
+#                         PUT    /tasks/:id(.:format)               {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;update&quot;}
+#                         DELETE /tasks/:id(.:format)               {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;destroy&quot;}
+#                         PUT    /tasks/:task_id/for/:person_id     {:controller=&gt;&quot;task_for&quot;, :action=&gt;&quot;update&quot;}
+#         task_for_person        /tasks/:task_id/for/:person_id     {:controller=&gt;&quot;task_for&quot;, :action=&gt;&quot;show&quot;}
+#                         POST   /tasks/:id                         {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;update&quot;}
+#                  search        /search                            {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;search&quot;}
+#             open_search        /search/osd                        {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;opensearch&quot;}
+#                   forms GET    /forms(.:format)                   {:controller=&gt;&quot;forms&quot;, :action=&gt;&quot;index&quot;}
+#                         POST   /forms(.:format)                   {:controller=&gt;&quot;forms&quot;, :action=&gt;&quot;create&quot;}
+#                new_form GET    /forms/new(.:format)               {:controller=&gt;&quot;forms&quot;, :action=&gt;&quot;new&quot;}
+#               edit_form GET    /forms/:id/edit(.:format)          {:controller=&gt;&quot;forms&quot;, :action=&gt;&quot;edit&quot;}
+#                    form GET    /forms/:id(.:format)               {:controller=&gt;&quot;forms&quot;, :action=&gt;&quot;show&quot;}
+#                         PUT    /forms/:id(.:format)               {:controller=&gt;&quot;forms&quot;, :action=&gt;&quot;update&quot;}
+#                         DELETE /forms/:id(.:format)               {:controller=&gt;&quot;forms&quot;, :action=&gt;&quot;destroy&quot;}
+#               templates GET    /templates(.:format)               {:controller=&gt;&quot;templates&quot;, :action=&gt;&quot;index&quot;}
+#                         POST   /templates(.:format)               {:controller=&gt;&quot;templates&quot;, :action=&gt;&quot;create&quot;}
+#            new_template GET    /templates/new(.:format)           {:controller=&gt;&quot;templates&quot;, :action=&gt;&quot;new&quot;}
+#           edit_template GET    /templates/:id/edit(.:format)      {:controller=&gt;&quot;templates&quot;, :action=&gt;&quot;edit&quot;}
+#                template GET    /templates/:id(.:format)           {:controller=&gt;&quot;templates&quot;, :action=&gt;&quot;show&quot;}
+#                         PUT    /templates/:id(.:format)           {:controller=&gt;&quot;templates&quot;, :action=&gt;&quot;update&quot;}
+#                         DELETE /templates/:id(.:format)           {:controller=&gt;&quot;templates&quot;, :action=&gt;&quot;destroy&quot;}
+#           notifications GET    /notifications(.:format)           {:controller=&gt;&quot;notifications&quot;, :action=&gt;&quot;index&quot;}
+#                         POST   /notifications(.:format)           {:controller=&gt;&quot;notifications&quot;, :action=&gt;&quot;create&quot;}
+#        new_notification GET    /notifications/new(.:format)       {:controller=&gt;&quot;notifications&quot;, :action=&gt;&quot;new&quot;}
+#       edit_notification GET    /notifications/:id/edit(.:format)  {:controller=&gt;&quot;notifications&quot;, :action=&gt;&quot;edit&quot;}
+#            notification GET    /notifications/:id(.:format)       {:controller=&gt;&quot;notifications&quot;, :action=&gt;&quot;show&quot;}
+#                         PUT    /notifications/:id(.:format)       {:controller=&gt;&quot;notifications&quot;, :action=&gt;&quot;update&quot;}
+#                         DELETE /notifications/:id(.:format)       {:controller=&gt;&quot;notifications&quot;, :action=&gt;&quot;destroy&quot;}
+#              activities GET    /activities(.:format)              {:controller=&gt;&quot;activities&quot;, :action=&gt;&quot;index&quot;}
+#                         POST   /activities(.:format)              {:controller=&gt;&quot;activities&quot;, :action=&gt;&quot;create&quot;}
+#            new_activity GET    /activities/new(.:format)          {:controller=&gt;&quot;activities&quot;, :action=&gt;&quot;new&quot;}
+#           edit_activity GET    /activities/:id/edit(.:format)     {:controller=&gt;&quot;activities&quot;, :action=&gt;&quot;edit&quot;}
+#                activity GET    /activities/:id(.:format)          {:controller=&gt;&quot;activities&quot;, :action=&gt;&quot;show&quot;}
+#                         PUT    /activities/:id(.:format)          {:controller=&gt;&quot;activities&quot;, :action=&gt;&quot;update&quot;}
+#                         DELETE /activities/:id(.:format)          {:controller=&gt;&quot;activities&quot;, :action=&gt;&quot;destroy&quot;}
+#              new_graphs GET    /graphs/new(.:format)              {:controller=&gt;&quot;graphs&quot;, :action=&gt;&quot;new&quot;}
+#             edit_graphs GET    /graphs/edit(.:format)             {:controller=&gt;&quot;graphs&quot;, :action=&gt;&quot;edit&quot;}
+#                  graphs GET    /graphs(.:format)                  {:controller=&gt;&quot;graphs&quot;, :action=&gt;&quot;show&quot;}
+#                         PUT    /graphs(.:format)                  {:controller=&gt;&quot;graphs&quot;, :action=&gt;&quot;update&quot;}
+#                         DELETE /graphs(.:format)                  {:controller=&gt;&quot;graphs&quot;, :action=&gt;&quot;destroy&quot;}
+#                         POST   /graphs(.:format)                  {:controller=&gt;&quot;graphs&quot;, :action=&gt;&quot;create&quot;}
+#         recover_session GET    /session/recover(.:format)         {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;recover&quot;}
+#                         POST   /session/recover(.:format)         {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;recover&quot;}
+#             new_session GET    /session/new(.:format)             {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;new&quot;}
+#            edit_session GET    /session/edit(.:format)            {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;edit&quot;}
+#                 session GET    /session(.:format)                 {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;show&quot;}
+#                         PUT    /session(.:format)                 {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;update&quot;}
+#                         DELETE /session(.:format)                 {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;destroy&quot;}
+#                         POST   /session(.:format)                 {:controller=&gt;&quot;sessions&quot;, :action=&gt;&quot;create&quot;}
+#                    root        /                                  {:controller=&gt;&quot;tasks&quot;, :action=&gt;&quot;index&quot;}
 #                                /:controller/:action/:id           
 #                                /:controller/:action/:id(.:format) </diff>
      <filename>config/routes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -81,6 +81,9 @@ $(function() {
       return false;
     });
 
+
+  setTimeout(function() { $('#header div.error, #header div.success, #header div.notice').slideUp(500) }, 5000);
+
 })
 
 </diff>
      <filename>public/javascripts/singleshot.js</filename>
    </modified>
    <modified>
      <diff>@@ -45,6 +45,17 @@ form dl dd { margin: 0 0 0.9em 0; }
 form dl dd input[type=radio] { margin: 0.3em 0 0.6em 0.3em; }
 
 .hidden { display: none; }
+.error ul { list-style: none; padding: 0; margin: 0 }
+
+
+/** Message **/
+.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
+.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
+.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
+.success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
+.error a {color:#8a1f11;}
+.notice a {color:#514721;}
+.success a {color:#264409;}
 
 
 /** Pagination **/</diff>
      <filename>public/stylesheets/common.css</filename>
    </modified>
    <modified>
      <diff>@@ -41,7 +41,7 @@ class Person #:nodoc:
     end
 
     def me
-      named(ENV['USER'])
+      named('john')
     end
   end
 end</diff>
      <filename>spec/blueprints.rb</filename>
    </modified>
    <modified>
      <diff>@@ -32,6 +32,8 @@ end
 describe AuthenticationTestController do
   before { @person = Person.make(:email=&gt;'john@example.com', :locale=&gt;'tlh', :timezone=&gt;-11) }
 
+  should_filter_params :password, :password_confirmation
+
   describe 'unauthenticated request' do
     describe '(HTML)' do
       before { get :index }</diff>
      <filename>spec/controllers/authentication_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,16 +30,7 @@ module Spec::Helpers #:nodoc:
     #
     # Without arguments, authenticates as 'person'.
     def authenticate(person = Person.named('john'))
-      @controller.instance_eval do
-        previous, @authenticated = @authenticated, person
-        if block_given?
-          begin
-            yield
-          ensure
-            @authenticated = previous
-          end
-        end
-      end
+      session[:person_credentials] = person &amp;&amp; person.persistence_token
       self
     end
 </diff>
      <filename>spec/controllers/helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,66 +21,75 @@ describe SessionsController do
   controller_name :sessions
 
   should_route :get, '/session', :controller =&gt;'sessions', :action=&gt;'show'
-  should_route :post, '/session', :controller =&gt;'sessions', :action=&gt;'create'
-  should_route :delete, '/session', :controller =&gt;'sessions', :action=&gt;'destroy'
-  should_filter_params :password
-
   describe 'GET /session' do
     before { get :show }
 
     should_render_template 'sessions/show'
   end
 
+
+  should_route :post, '/session', :controller =&gt;'sessions', :action=&gt;'create'
   describe 'POST /session' do
     before { Person.me }
 
     describe '(no credentials)' do
       before { post :create }
 
-      it('should have no authenticated user in session')      { authenticated.should be_nil }
-      it('should have no error message in flash')             { flash.should be_empty }
-      should_redirect_to                                      { session_path }
+      should_not_login
+      should_render_template 'sessions/show'
     end
 
     describe '(wrong credentials)' do
       before { post :create, :login=&gt;Person.me.login, :password=&gt;'wrong' }
 
-      it('should have no authenticated user in session')      { authenticated.should be_nil }
-      it('should have error message in flash')                { flash[:error].should match(/no account/i) }
-      should_redirect_to                                      { session_path }
+      should_not_login
+      should_render_template 'sessions/show'
     end
 
     describe '(valid credentials)' do
       before { post :create, :login=&gt;Person.me.login, :password=&gt;'secret' }
 
-      it('should store authenticated user in session')        { authenticated.should == Person.me }
-      it('should clear flash')                                { flash.should be_empty }
+      should_login { Person.me }
       should_redirect_to                                      { root_path }
     end
 
     describe '(valid credentials and return url)' do
       before { post :create, { :login=&gt;Person.me.login, :password=&gt;'secret' }, { :return_url=&gt;'http://return_url' } }
 
-      it('should store authenticated user in session')        { authenticated.should == Person.me }
-      it('should clear return url from session')              { session[:return_url].should be_nil }
+      should_login { Person.me }
       should_redirect_to                                      { 'http://return_url' }
     end
 
   end
 
 
+  should_route :delete, '/session', :controller =&gt;'sessions', :action=&gt;'destroy'
   describe 'DELETE /session' do
     before do
-      @controller.instance_eval do
-        @current_session = ApplicationController::UserSession.new
-        @current_session.should_receive(:destroy)
-        @authenticated = Person.me
+      AuthSession.should_receive(:find).and_return do
+        AuthSession.new(Person.me).tap(&amp;:save)
       end
       delete :destroy
     end
 
-    it('should have no authenticated user in session')  { authenticated.should be_nil }
+    should_not_login
     should_redirect_to                                  { root_path }
   end
 
+
+  def login(&amp;block)
+    simple_matcher &quot;login&quot; do |given, matcher|
+      run_action!
+      if block
+        expected = block.call
+        actual = controller.session[:person_credentials_id] &amp;&amp; Person.find_by_id(controller.session[:person_credentials_id])
+        matcher.failure_message = &quot;expected #{expected.inspect} but got #{actual.inspect}&quot;
+        actual == expected
+      else
+        matcher.failure_message = &quot;expected authenticated person&quot;
+        controller.session[:person_credentials_id]
+      end
+    end
+  end
+
 end</diff>
      <filename>spec/controllers/sessions_controller_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,9 +26,4 @@ end
 
 Spec::Runner.configure do |config|
   config.include Spec::Helpers::Models, :type=&gt;:model
-  config.before :each do
-    ActionMailer::Base.delivery_method = :test  
-    ActionMailer::Base.perform_deliveries = true  
-    ActionMailer::Base.deliveries = []  
-  end
 end</diff>
      <filename>spec/models/helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,7 @@ require File.expand_path(File.dirname(__FILE__) + '/blueprints')
 require 'remarkable'
 require 'remarkable_activerecord'
 require 'remarkable_rails'
+require 'email_spec'
 trap(&quot;SIGINT&quot;){ exit! 0 }
 
 
@@ -50,4 +51,9 @@ Spec::Runner.configure do |config|
   # == Notes
   # 
   # For more information take a look at Spec::Runner::Configuration and Spec::Runner
+
+  config.before :each do
+    ActionMailer::Base.deliveries = []
+  end
+  config.include EmailSpec::Matchers
 end</diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,7 @@
 
 
 require File.dirname(__FILE__) + '/../spec_helper'
+require 'authlogic/test_case'
 
 
 module Spec::Helpers #:nodoc:</diff>
      <filename>spec/views/helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,9 @@ require File.dirname(__FILE__) + '/../helpers'
 
 describe '/sessions/show' do
   before do
-    @controller.allow_forgery_protection = true
+    controller.allow_forgery_protection = true
+    Authlogic::Session::Base.controller = Authlogic::TestCase::MockController.new
+    assigns[:auth_session] = AuthSession.new
     render '/sessions/show'
   end
 
@@ -30,7 +32,10 @@ describe '/sessions/show' do
           with_tag 'input[name=login][type=text][title=Your username]'
           with_tag 'label[for=password]', &quot;Password:&quot;
           with_tag 'input[name=password][type=password][title=Your password is case sensitive]'
+          with_tag 'label', &quot;Remember me on this computer&quot;
+          with_tag 'input[name=remember_me][type=checkbox][value=1][checked]'
           with_tag 'input[type=submit][value=Login]'
+          with_tag 'a[href=?]', password_resets_path, &quot;Help, I lost my password!&quot;
         end
       end
     end
@@ -43,10 +48,12 @@ end
 
 describe '/sessions/show with error message' do
   before do
-    @controller.allow_forgery_protection = true
-    flash[:error] = 'Error message'
+    controller.allow_forgery_protection = true
+    Authlogic::Session::Base.controller = Authlogic::TestCase::MockController.new
+    assigns[:auth_session] = AuthSession.new
+    assigns[:auth_session].errors.add_to_base &quot;Error message&quot;
     render '/sessions/show'
   end
 
-  should_have_tag 'form.login fieldset p.error', &quot;Error message&quot;
+  should_have_tag 'form.login fieldset div.error', &quot;Error message&quot;
 end</diff>
      <filename>spec/views/sessions/show_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>7040bd5f1ee115806485cb7e183de744239dfdb8</id>
    </parent>
  </parents>
  <author>
    <name>Assaf Arkin</name>
    <email>assaf@labnotes.org</email>
  </author>
  <url>http://github.com/intalio/singleshot/commit/181296932e308e279c72675d36abb336eb8c5703</url>
  <id>181296932e308e279c72675d36abb336eb8c5703</id>
  <committed-date>2009-06-12T12:50:55-07:00</committed-date>
  <authored-date>2009-06-11T21:02:21-07:00</authored-date>
  <message>Cleanup for authentication logic.

Added remember me option to login.

Cleanup of authentication UI.
Added password recovery.

Flash[:success/:notice/:error] now shown as part of layout and automatically removed after 5 seconds.

Password recovery token good for 1 hour.</message>
  <tree>dd12cdde6f4a77dde9c41a3ade41dc0a06145d8f</tree>
  <committer>
    <name>Assaf Arkin</name>
    <email>assaf@labnotes.org</email>
  </committer>
</commit>
