diff options
author | francis <francis> | 2008-02-20 12:51:29 +0000 |
---|---|---|
committer | francis <francis> | 2008-02-20 12:51:29 +0000 |
commit | fa2c655de7b795794b6de75ca0f6807f7c88a5ac (patch) | |
tree | d0ce6e67cfc677de8e922cdc39fb2ff10068db23 | |
parent | 5432e516c218e821f416e92fbcb3250bfe913d5c (diff) |
Forgotten password stuff.
-rw-r--r-- | app/controllers/user_controller.rb | 73 | ||||
-rw-r--r-- | app/models/application_mailer.rb | 4 | ||||
-rw-r--r-- | app/models/contact_mailer.rb | 4 | ||||
-rw-r--r-- | app/models/user.rb | 14 | ||||
-rw-r--r-- | app/views/user/_signin.rhtml | 2 | ||||
-rw-r--r-- | app/views/user/signchange.rhtml | 30 | ||||
-rw-r--r-- | app/views/user/signchange_email.rhtml | 30 | ||||
-rw-r--r-- | config/routes.rb | 3 | ||||
-rw-r--r-- | todo.txt | 2 |
9 files changed, 149 insertions, 13 deletions
diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index a764bdb35..baeffc7db 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -4,7 +4,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: user_controller.rb,v 1.25 2008-02-19 12:13:07 francis Exp $ +# $Id: user_controller.rb,v 1.26 2008-02-20 12:51:29 francis Exp $ class UserController < ApplicationController # XXX See controllers/application.rb simplify_url_part for reverse of expression in SQL below @@ -34,6 +34,7 @@ class UserController < ApplicationController # Successful login if @user_signin.email_confirmed session[:user_id] = @user_signin.id + session[:user_authtype] = :password do_post_redirect @post_redirect.uri, @post_redirect.post_params else send_confirmation_mail @user_signin @@ -76,6 +77,7 @@ class UserController < ApplicationController @user.save! session[:user_id] = @user.id + session[:user_authtype] = :email do_post_redirect post_redirect.uri, post_redirect.post_params end @@ -83,6 +85,7 @@ class UserController < ApplicationController # Logout form def signout session[:user_id] = nil + session[:user_authtype] = nil if params[:r] redirect_to params[:r] else @@ -90,6 +93,72 @@ class UserController < ApplicationController end end + # Change password and/or email - requires email authentication + def signchange + if @user and ((not session[:user_authtype]) or (session[:user_authtype] != :email)) + # Not logged in via email, so send confirmation + params[:submitted_signchange_email] = true + params[:signchange] = { :email => @user.email } + end + + if params[:submitted_signchange_email] + # They've entered the email, check it is OK and user exists + if not MySociety::Validate.is_valid_email(params[:signchange][:email]) + flash[:error] = "That doesn't look like a valid email address. Please check you have typed it correctly." + render :action => 'signchange_email' + return + end + user_signchange = User.find_user_by_email(params[:signchange][:email]) + if not user_signchange + flash[:error] = "There is no user with that email, please check you have typed it correctly." + render :action => 'signchange_email' + return + end + + # Send email with login link to go to signchange page + url = signchange_url + if params[:pretoken] + url += "?pretoken=" + params[:pretoken] + end + post_redirect = PostRedirect.new(:uri => url , :post_params => {}, + :reason_params => { + :web => "", + :email => "Then your can change your password on foi.mysociety.org", + :email_subject => "Change your password on foi.mysociety.org" + }) + post_redirect.user = user_signchange + post_redirect.save! + url = confirm_url(:email_token => post_redirect.email_token) + UserMailer.deliver_confirm_login(user_signchange, post_redirect.reason_params, url) + render :action => 'confirm' + elsif not @user + # Not logged in, prompt for email + render :action => 'signchange_email' + else + # Logged in via email link, so can offer form to change email/password + raise "internal error" unless (session[:user_authtype] == :email) + + if params[:submitted_signchange_password] + @user.password = params[:user][:password] + @user.password_confirmation = params[:user][:password_confirmation] + if not @user.valid? + render :action => 'signchange' + else + @user.save! + flash[:notice] = "Your password has been changed." + if params[:pretoken] and not params[:pretoken].empty? + post_redirect = PostRedirect.find_by_token(params[:pretoken]) + do_post_redirect post_redirect.uri, post_redirect.post_params + else + redirect_to :controller => "request", :action => "frontpage" # XXX should go back to login and where they were! + end + end + else + render :action => 'signchange' + end + end + end + private @@ -117,7 +186,7 @@ class UserController < ApplicationController # Ask for email confirmation def send_confirmation_mail(user) - raise "user #{user.id} already confirmed" if user.email_confirmed + #raise "user #{user.id} already confirmed" if user.email_confirmed post_redirect = PostRedirect.find_by_token(params[:token]) post_redirect.user = user diff --git a/app/models/application_mailer.rb b/app/models/application_mailer.rb index 9d61a16e6..71cc96ead 100644 --- a/app/models/application_mailer.rb +++ b/app/models/application_mailer.rb @@ -4,12 +4,14 @@ # Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: application_mailer.rb,v 1.4 2008-02-19 12:13:07 francis Exp $ +# $Id: application_mailer.rb,v 1.5 2008-02-20 12:51:29 francis Exp $ class ApplicationMailer < ActionMailer::Base # Include all the functions views get, as emails call similar things. helper :application + # This really should be the default - otherwise you lose any information + # about the errors, and have to do error checking on return codes. self.raise_delivery_errors = true def contact_from_name_and_email diff --git a/app/models/contact_mailer.rb b/app/models/contact_mailer.rb index 92547e2a5..77854a4ef 100644 --- a/app/models/contact_mailer.rb +++ b/app/models/contact_mailer.rb @@ -4,10 +4,9 @@ # Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: contact_mailer.rb,v 1.2 2008-02-20 07:40:43 francis Exp $ +# $Id: contact_mailer.rb,v 1.3 2008-02-20 12:51:29 francis Exp $ class ContactMailer < ApplicationMailer - def message(name, email, subject, message, request_details) @from = name + " <" + email + ">" @recipients = contact_from_name_and_email @@ -16,5 +15,4 @@ class ContactMailer < ApplicationMailer :request_details => request_details } end - end diff --git a/app/models/user.rb b/app/models/user.rb index 2c7466caa..659c176e9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -19,7 +19,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: user.rb,v 1.25 2008-02-14 15:31:22 francis Exp $ +# $Id: user.rb,v 1.26 2008-02-20 12:51:29 francis Exp $ require 'digest/sha1' @@ -50,7 +50,7 @@ class User < ActiveRecord::Base auth_fail_message = "Either the email or password was not recognised, please try again. Or create a new account using the form on the right." end - user = self.find(:first, :conditions => [ 'email ilike ?', params[:email] ] ) # using ilike for case insensitive + user = self.find_user_by_email(params[:email]) if user # There is user with email, check password expected_password = encrypted_password(params[:password], user.salt) @@ -67,13 +67,21 @@ class User < ActiveRecord::Base user end + # Case-insensitively find a user from their email + def self.find_user_by_email(email) + return self.find(:first, :conditions => [ 'email ilike ?', email ] ) # using ilike for case insensitive + end + # Virtual password attribute, which stores the hashed password, rather than plain text. def password @password end def password=(pwd) @password = pwd - return if pwd.blank? + if pwd.blank? + self.hashed_password = nil + return + end create_new_salt self.hashed_password = User.encrypted_password(self.password, self.salt) end diff --git a/app/views/user/_signin.rhtml b/app/views/user/_signin.rhtml index b4d0dda31..4b06b7e05 100644 --- a/app/views/user/_signin.rhtml +++ b/app/views/user/_signin.rhtml @@ -16,7 +16,7 @@ </p> <p class="form_note"> - Forgotten your password? Tough. + <%= link_to "Forgotten your password?", signchange_url + "?pretoken=" + h(params[:token]) %> </p> <div class="form_button"> diff --git a/app/views/user/signchange.rhtml b/app/views/user/signchange.rhtml new file mode 100644 index 000000000..8f6fe663c --- /dev/null +++ b/app/views/user/signchange.rhtml @@ -0,0 +1,30 @@ +<% @title = "Change password" %> + +<% raise "internal error" if not @user %> + +<div id="change_password"> + +<% form_tag({:action => "signchange"}, {:id => "signchange_form"}) do %> + <%= foi_error_messages_for :user %> + + <div class="form_note"> + <h1>Change your password</h1> + </div> + + <label class="form_label" for="user_password">New password:</label> + <%= password_field 'user', 'password', { :size => 15 } %> + </p> + + <p> + <label class="form_label" for="user_password_confirmation">New password: (again)</label> + <%= password_field 'user', 'password_confirmation', { :size => 15 } %> + </p> + + <div class="form_button"> + <%= hidden_field_tag 'submitted_signchange_password', 1 %> + <%= hidden_field_tag 'pretoken', params[:pretoken] %> + <%= submit_tag "Update" %> + </div> +<% end %> + +</div> diff --git a/app/views/user/signchange_email.rhtml b/app/views/user/signchange_email.rhtml new file mode 100644 index 000000000..5bd545d8d --- /dev/null +++ b/app/views/user/signchange_email.rhtml @@ -0,0 +1,30 @@ +<% @title = "Change password" %> + +<div id="change_password"> + +<% form_tag({:action => "signchange"}, {:id => "signchange_form"}) do %> + <%= foi_error_messages_for :signchange %> + + <div class="form_note"> + <h1>Change your password</h1> + </div> + + <p> + <label class="form_label" for="signchange_email">Your e-mail:</label> + <%= text_field 'signchange', 'email', { :size => 20 } %> + </p> + + <p class="form_note"> + <strong>Note:</strong> + We will send you an email. Follow the instructions in it to change + your password. + </p> + + <div class="form_button"> + <%= hidden_field_tag 'submitted_signchange_email', 1 %> + <%= hidden_field_tag 'pretoken', params[:pretoken] %> + <%= submit_tag "Submit" %> + </div> +<% end %> + +</div> diff --git a/config/routes.rb b/config/routes.rb index ec65a667c..494bfa41b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: routes.rb,v 1.32 2008-01-29 03:05:48 francis Exp $ +# $Id: routes.rb,v 1.33 2008-02-20 12:51:30 francis Exp $ ActionController::Routing::Routes.draw do |map| # The priority is based upon order of creation: first created -> highest priority. @@ -27,6 +27,7 @@ ActionController::Routing::Routes.draw do |map| user.signin '/signin', :action => 'signin' user.signup '/signup', :action => 'signup' user.signout '/signout', :action => 'signout' + user.signchange '/signchange', :action => 'signchange' user.confirm '/c/:email_token', :action => 'confirm' user.show_user '/user/:simple_name', :action => 'show' end @@ -38,8 +38,6 @@ Go through all requests and check status is shiny Next ==== -Forgotten password link - make go to contact form - Put the admin "Public page" link on request page somewhere clearer Lucene for search - use http://acts-as-solr.rubyforge.org/ |