<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/controllers/clients_controller.rb</filename>
    </added>
    <added>
      <filename>app/models/client_mailer.rb</filename>
    </added>
    <added>
      <filename>app/models/client_observer.rb</filename>
    </added>
    <added>
      <filename>app/views/client_mailer/forgot_password.erb</filename>
    </added>
    <added>
      <filename>app/views/client_mailer/reset_password.erb</filename>
    </added>
    <added>
      <filename>app/views/client_mailer/signup_notification.erb</filename>
    </added>
    <added>
      <filename>app/views/clients/forgot_password.html.erb</filename>
    </added>
    <added>
      <filename>app/views/clients/reset_password.html.erb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -14,6 +14,7 @@ FEATURES
 * Admin section where you can manage categories and their photos, and client's and their photo previews.
 * Client section where your client's can preview their photos.
 * Contact form.
+* Search Engine Optimization
 
 INSTALLATION
 ------------</diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ class Admin::ClientsController &lt; ResourceController::Base
   layout proc { |controller| controller.request.xhr? ? nil : 'admin' }
   
   # redirect to edit instead of show on create and update
-  [create, update].each { |action| action.wants.html { redirect_to edit_object_path } }
+  [create, update].each { |action| action.wants.html { redirect_to collection_path } }
   
   # set the meta titles for the different actions
   index.wants.html {
@@ -24,20 +24,16 @@ class Admin::ClientsController &lt; ResourceController::Base
     @meta_title = &quot;Client | #{@meta_title}&quot;
   }
   
-  def reset_password
-    # TODO
-  end
-  
   def login_as
     logout_keeping_session!
-    self.current_client = @object
+    self.current_client = Client.find(params[:id])
     if self.current_client
       logger.debug(&quot;Logged in.&quot;)
       # Protects against session fixation attacks, causes request forgery
       # protection if account resubmits an earlier form using back
       # button. Uncomment if you understand the tradeoffs.
       # reset_session
-      redirect_to client_path(@object)
+      redirect_to client_photos_path(current_client)
       flash[:notice] = &quot;Logged in successfully&quot;
     else
       logger.debug(&quot;Couldn't log in&quot;)</diff>
      <filename>app/controllers/admin/clients_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,19 +29,8 @@ class Client &lt; ActiveRecord::Base
 
   # use login as a route identifier
   has_friendly_id :login
-  
-  
-  def self.create_defaults
-    Client.create!(:login =&gt; 'rapind', :email =&gt; 'dave@rapin.com', :name =&gt; 'Dave Rapin', :password =&gt; '123456', :password_confirmation =&gt; '123456', :phone =&gt; '416-321-3214')
-    Client.create!(:login =&gt; 'jcoyle', :email =&gt; 'jaime@jaimecoyle.com', :name =&gt; 'Jaime Coyle', :password =&gt; '123456', :password_confirmation =&gt; '123456', :phone =&gt; '416-123-1234')
-  end
 
   # Authenticates a client by their login name and unencrypted password.  Returns the client or nil.
-  #
-  # uff.  this is really an authorization, not authentication routine.  
-  # We really need a Dispatch Chain here or something.
-  # This will also let us return a human error message.
-  #
   def self.authenticate(login, password)
     return nil if login.blank? || password.blank?
     u = find_by_login(login.downcase) # need to get the salt
@@ -55,9 +44,35 @@ class Client &lt; ActiveRecord::Base
   def email=(value)
     write_attribute :email, (value ? value.downcase : nil)
   end
+  
+  def forgot_password
+    @forgotten_password = true
+    self.make_password_reset_code
+  end
+
+  def reset_password
+    # First update the password_reset_code before setting the 
+    # reset_password flag to avoid duplicate email notifications.
+    update_attributes(:password_reset_code =&gt; nil)
+    @reset_password = true
+  end 
+
+  # used in user_observer
+  def recently_forgot_password?
+    @forgotten_password
+  end
 
+  # Returns true if the user has just reset their password.
+  def recently_reset_password?
+    @reset_password
+  end
+  
+  
+  #-----------
   protected
     
-
+    def make_password_reset_code
+      self.password_reset_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
+    end
 
 end</diff>
      <filename>app/models/client.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,8 +7,6 @@
     |
     &lt;%=link_to 'Login As', login_as_admin_client_path(row), :title =&gt; 'Login to your site as if you are this client' %&gt;
     |
-    &lt;%=link_to 'Reset Password', reset_password_admin_client_path(row), :title =&gt; 'Creates a new password and sends it to them via email' %&gt;
-    |
     &lt;%=link_to 'Remove', admin_client_path(row), :title =&gt; 'Remove this client permanently', :confirm =&gt; 'Are you sure? This cannot be undone!', :method =&gt; :delete %&gt;
   &lt;/td&gt;
 &lt;/tr&gt;</diff>
      <filename>app/views/admin/clients/_row.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,7 @@
+&lt;p&gt;
+  ** Important: When you create a new client account, a welcome email is sent to them containing their username and password.
+&lt;/p&gt;
+
 &lt;%= error_messages_for :object %&gt;
 
 &lt;% form_for(@object, :url =&gt; collection_path) do |f| %&gt;</diff>
      <filename>app/views/admin/clients/new.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -12,6 +12,7 @@
   &lt;li&gt;Admin section where you can manage categories and their photos, and client's and their photo previews.&lt;/li&gt;
   &lt;li&gt;Client section where your client's can preview their photos.&lt;/li&gt;
   &lt;li&gt;Contact form.&lt;/li&gt;
+  &lt;li&gt;Search Engine Optimization.&lt;/li&gt;
 &lt;/ul&gt;
 
 &lt;h2&gt;Installation&lt;/h2&gt;</diff>
      <filename>app/views/main/about.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,11 +1,10 @@
 &lt;% form_tag session_path do -%&gt;
   &lt;p&gt;
     &lt;label for=&quot;login&quot;&gt;Username&lt;/label&gt;&lt;br /&gt;
-    &lt;%= text_field_tag 'login', {}, :class =&gt; 'text' %&gt;
-  &lt;/p&gt;
-  &lt;p&gt;
+    &lt;%= text_field_tag 'login', {}, :class =&gt; 'text' %&gt;&lt;br /&gt;
     &lt;label for=&quot;password&quot;&gt;Password&lt;/label&gt;&lt;br /&gt;
-    &lt;%= password_field_tag 'password', {}, :class =&gt; 'text' %&gt;
+    &lt;%= password_field_tag 'password', {}, :class =&gt; 'text' %&gt;&lt;br /&gt;
+    &lt;%= link_to 'Forget your password?', forgot_password_path %&gt;
   &lt;/p&gt;
   &lt;p&gt;
     &lt;%= check_box_tag 'remember_me' %&gt; &amp;nbsp;</diff>
      <filename>app/views/sessions/new.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -36,6 +36,7 @@ Rails::Initializer.run do |config|
 
   # Activate observers that should always be running
   # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
+  config.active_record.observers = :client_observer
 
   # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
   # Run &quot;rake -D time&quot; for a list of tasks for finding time zone names.</diff>
      <filename>config/environment.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,17 +9,16 @@ ActionController::Routing::Routes.draw do |map|
   # Admin section
   map.admin '/admin', :controller =&gt; 'admin/categories'
   map.namespace :admin do |admin|
-    # displaying and managing photos for users
     admin.resources :categories do |category|
       category.resources :photos, :member =&gt; { :update_position =&gt; :put }
     end
-    #admin.resources :categories, :has_many =&gt; :photos
-    admin.resources :clients, :has_many =&gt; :photos, :member =&gt; { :login_as =&gt; :get, :reset_password =&gt; :get }
-    #admin.resources :photos, :member =&gt; { :update_position =&gt; :put }
+    admin.resources :clients, :has_many =&gt; :photos, :member =&gt; { :login_as =&gt; :get }
   end
   
   map.logout '/logout', :controller =&gt; 'sessions', :action =&gt; 'destroy'
   map.login '/login', :controller =&gt; 'sessions', :action =&gt; 'new'
+  map.forgot_password '/forgot_password', :controller =&gt; 'clients', :action =&gt; 'forgot_password'
+  map.reset_password '/reset_password/:id', :controller =&gt; 'clients', :action =&gt; 'reset_password'
   
   map.root :controller =&gt; &quot;main&quot;
   map.about '/about', :controller =&gt; 'main', :action =&gt; 'about'</diff>
      <filename>config/routes.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>app/views/clients/_client_bar.html.erb</filename>
    </removed>
    <removed>
      <filename>app/views/clients/new.html.erb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>af4011030bb3da86a007441d0006adba9ec77f0e</id>
    </parent>
  </parents>
  <author>
    <name>Dave Rapin</name>
    <email>dave@rapin.com</email>
  </author>
  <url>http://github.com/rapind/photographer/commit/62e601b71bba736ef0941e3016eb88e6f3ea09b9</url>
  <id>62e601b71bba736ef0941e3016eb88e6f3ea09b9</id>
  <committed-date>2009-06-23T14:47:03-07:00</committed-date>
  <authored-date>2009-06-23T14:47:03-07:00</authored-date>
  <message>client forgot and reset password implemented. system emails for new signups. minor form tweaks.</message>
  <tree>b5d007628aef5c2f031e8746312d8b705b7ff6de</tree>
  <committer>
    <name>Dave Rapin</name>
    <email>dave@rapin.com</email>
  </committer>
</commit>
