Commit 94d199c1da9865092f83bc170d9fc9aac6bd30d0
1 parent
abd673e1
Exists in
master
and in
29 other branches
ActionItem78: implementing password recovery
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@640 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
7 changed files
with
97 additions
and
13 deletions
Show diff stats
app/controllers/public/account_controller.rb
... | ... | @@ -70,19 +70,43 @@ class AccountController < PublicController |
70 | 70 | end |
71 | 71 | end |
72 | 72 | |
73 | - # posts back | |
73 | + # The user requests a password change. She forgot her old password. | |
74 | + # | |
75 | + # Posts back. | |
74 | 76 | def forgot_password |
75 | 77 | @change_password = ChangePassword.new(params[:change_password]) |
76 | 78 | if request.post? |
77 | 79 | begin |
78 | - @change_password.confirm! | |
80 | + @change_password.save! | |
79 | 81 | render :action => 'password_recovery_sent' |
80 | - rescue Exception => e | |
82 | + rescue ActiveRecord::RecordInvalid => e | |
81 | 83 | nil # just pass and render at the end of the action |
82 | 84 | end |
83 | 85 | end |
84 | 86 | end |
85 | 87 | |
88 | + # The user has a code for a ChangePassword request object. | |
89 | + # | |
90 | + # Posts back. | |
91 | + def new_password | |
92 | + @change_password = ChangePassword.find_by_code(params[:code]) | |
93 | + | |
94 | + unless @change_password | |
95 | + render :action => 'invalid_change_password_code' | |
96 | + return | |
97 | + end | |
98 | + | |
99 | + if request.post? | |
100 | + begin | |
101 | + @change_password.update_attributes!(params[:change_password]) | |
102 | + @change_password.finish | |
103 | + render :action => 'new_password_ok' | |
104 | + rescue ActiveRecord::RecordInvalid => e | |
105 | + nil # just render new_password | |
106 | + end | |
107 | + end | |
108 | + end | |
109 | + | |
86 | 110 | protected |
87 | 111 | |
88 | 112 | before_filter :load_profile_for_user | ... | ... |
app/models/change_password.rb
... | ... | @@ -8,12 +8,18 @@ class ChangePassword < Task |
8 | 8 | end |
9 | 9 | |
10 | 10 | attr_accessor :login, :email, :password, :password_confirmation |
11 | + N_('ChangePassword|Login') | |
12 | + N_('ChangePassword|Email') | |
13 | + N_('ChangePassword|Password') | |
14 | + N_('ChangePassword|Password Confirmation') | |
11 | 15 | |
12 | 16 | ################################################### |
13 | 17 | # validations for creating a ChangePassword task |
14 | 18 | |
15 | 19 | validates_presence_of :login, :email, :on => :create |
16 | 20 | |
21 | + validates_presence_of :requestor_id | |
22 | + | |
17 | 23 | validates_format_of :email, :on => :create, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |obj| !obj.email.blank? }) |
18 | 24 | |
19 | 25 | validates_each :login, :on => :create do |data,attr,value| |
... | ... | @@ -29,7 +35,7 @@ class ChangePassword < Task |
29 | 35 | end |
30 | 36 | end |
31 | 37 | |
32 | - before_create do |change_password| | |
38 | + before_validation_on_create do |change_password| | |
33 | 39 | change_password.requestor = Person.find_by_identifier(change_password.login) |
34 | 40 | end |
35 | 41 | |
... | ... | @@ -47,7 +53,7 @@ class ChangePassword < Task |
47 | 53 | end |
48 | 54 | |
49 | 55 | def perform |
50 | - user = User.find_by_login(self.login) | |
56 | + user = self.requestor.user | |
51 | 57 | user.force_change_password!(self.password, self.password_confirmation) |
52 | 58 | end |
53 | 59 | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<h2><%= _('Enter new password') %></h2> | |
2 | + | |
3 | +<%= error_messages_for :change_password %> | |
4 | + | |
5 | +<% form_for(:change_password) do |f| %> | |
6 | + | |
7 | + <%= labelled_form_field(_('Enter new password'), (f.password_field :password)) %> | |
8 | + <%= labelled_form_field(_('Confirm the new password'), (f.password_field :password_confirmation)) %> | |
9 | + <%= submit_tag _('Change password') %> | |
10 | + | |
11 | +<% end %> | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<h2><%= _('Password changed sucessfully') %></h2> | |
2 | + | |
3 | +<p> | |
4 | +<%= _('%s, your new password was successfully installed.') % @change_password.requestor.identifier %> | |
5 | +</p> | |
6 | + | |
7 | +<p> | |
8 | +<%= _("You can <a href='%s'>login</a> now.") % url_for(:action => 'login') %> | |
9 | +</p> | ... | ... |
test/functional/account_controller_test.rb
... | ... | @@ -183,11 +183,43 @@ class AccountControllerTest < Test::Unit::TestCase |
183 | 183 | end |
184 | 184 | |
185 | 185 | should 'respond to forgotten password change request' do |
186 | - flunk 'not implemented yet' | |
186 | + change = ChangePassword.new | |
187 | + ChangePassword.expects(:new).returns(change) | |
188 | + change.expects(:save!).returns(true) | |
189 | + | |
190 | + post :forgot_password | |
191 | + assert_template 'password_recovery_sent' | |
192 | + end | |
193 | + | |
194 | + should 'provide interface for entering new password' do | |
195 | + change = ChangePassword.new | |
196 | + ChangePassword.expects(:find_by_code).with('osidufgiashfkjsadfhkj99999').returns(change) | |
197 | + | |
198 | + get :new_password, :code => 'osidufgiashfkjsadfhkj99999' | |
199 | + assert_equal change, assigns(:change_password) | |
187 | 200 | end |
188 | 201 | |
189 | - should 'provide interface for entering new password to replace forgotten one' do | |
190 | - flunk 'not implemented yet' | |
202 | + should 'actually change password after entering new password' do | |
203 | + change = ChangePassword.new | |
204 | + ChangePassword.expects(:find_by_code).with('osidufgiashfkjsadfhkj99999').returns(change) | |
205 | + | |
206 | + requestor = mock | |
207 | + requestor.stubs(:identifier).returns('joe') | |
208 | + change.stubs(:requestor).returns(requestor) | |
209 | + change.expects(:update_attributes!).with({'password' => 'newpass', 'password_confirmation' => 'newpass'}) | |
210 | + change.expects(:finish) | |
211 | + | |
212 | + post :new_password, :code => 'osidufgiashfkjsadfhkj99999', :change_password => { :password => 'newpass', :password_confirmation => 'newpass' } | |
213 | + | |
214 | + assert_template 'new_password_ok' | |
215 | + end | |
216 | + | |
217 | + should 'require a valid change_password code' do | |
218 | + ChangePassword.destroy_all | |
219 | + | |
220 | + assert_raise RuntimeError do | |
221 | + get :new_password, :code => 'dontexist' | |
222 | + end | |
191 | 223 | end |
192 | 224 | |
193 | 225 | protected | ... | ... |
test/unit/change_password_test.rb
... | ... | @@ -74,21 +74,18 @@ class ChangePasswordTest < Test::Unit::TestCase |
74 | 74 | |
75 | 75 | should 'actually change password' do |
76 | 76 | User.destroy_all |
77 | - User.create!(:login => 'testuser', :password => 'test', :password_confirmation => 'test', :email => 'test@example.com') | |
77 | + person = User.create!(:login => 'testuser', :password => 'test', :password_confirmation => 'test', :email => 'test@example.com').person | |
78 | 78 | |
79 | 79 | change = ChangePassword.new |
80 | 80 | change.login = 'testuser' |
81 | 81 | change.email = 'test@example.com' |
82 | 82 | change.save! |
83 | 83 | |
84 | - user = User.new | |
85 | - User.expects(:find_by_login).with('testuser').returns(user) | |
86 | - user.expects(:force_change_password!).with('newpass', 'newpass') | |
84 | + change.expects(:requestor).returns(person).at_least_once | |
87 | 85 | |
88 | 86 | change.password = 'newpass' |
89 | 87 | change.password_confirmation = 'newpass' |
90 | 88 | change.finish |
91 | - | |
92 | 89 | end |
93 | 90 | |
94 | 91 | end | ... | ... |