aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfrancis <francis>2008-02-20 12:51:29 +0000
committerfrancis <francis>2008-02-20 12:51:29 +0000
commitfa2c655de7b795794b6de75ca0f6807f7c88a5ac (patch)
treed0ce6e67cfc677de8e922cdc39fb2ff10068db23
parent5432e516c218e821f416e92fbcb3250bfe913d5c (diff)
Forgotten password stuff.
-rw-r--r--app/controllers/user_controller.rb73
-rw-r--r--app/models/application_mailer.rb4
-rw-r--r--app/models/contact_mailer.rb4
-rw-r--r--app/models/user.rb14
-rw-r--r--app/views/user/_signin.rhtml2
-rw-r--r--app/views/user/signchange.rhtml30
-rw-r--r--app/views/user/signchange_email.rhtml30
-rw-r--r--config/routes.rb3
-rw-r--r--todo.txt2
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
diff --git a/todo.txt b/todo.txt
index 19973ae4c..4afb3cf28 100644
--- a/todo.txt
+++ b/todo.txt
@@ -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/