Commit 90a1b0b2ea88df9903f56def63bf7498d3db93d9

Authored by Rodrigo Souto
1 parent 25df24bd

forgot_password: search by all fields instead of field selection

app/models/change_password.rb
1 class ChangePassword < Task 1 class ChangePassword < Task
2 2
3 - settings_items :field, :value 3 + settings_items :value
4 attr_accessor :password, :password_confirmation, :environment_id 4 attr_accessor :password, :password_confirmation, :environment_id
5 5
6 include Noosfero::Plugin::HotSpot 6 include Noosfero::Plugin::HotSpot
7 7
8 def self.human_attribute_name(attrib) 8 def self.human_attribute_name(attrib)
9 case attrib.to_sym 9 case attrib.to_sym
10 - when :field  
11 - _('Field')  
12 when :value 10 when :value
13 _('Value') 11 _('Value')
14 when :password 12 when :password
@@ -20,49 +18,54 @@ class ChangePassword &lt; Task @@ -20,49 +18,54 @@ class ChangePassword &lt; Task
20 end 18 end
21 end 19 end
22 20
23 - def plugins_fields  
24 - plugins.dispatch(:change_password_fields).inject({}) { |result, fields| result.merge!(fields)}  
25 - end  
26 -  
27 def environment 21 def environment
28 (requestor.environment if requestor) || Environment.find_by_id(environment_id) 22 (requestor.environment if requestor) || Environment.find_by_id(environment_id)
29 end 23 end
30 24
  25 + def plugins_options
  26 + plugins.dispatch(:change_password_fields)
  27 + end
  28 +
  29 + def user_fields
  30 + %w[login email] + plugins_options.select {|options| options[:model].to_sym == :user }.map { |options| options[:field].to_s }
  31 + end
  32 +
  33 + def person_fields
  34 + %w[] + plugins_options.select {|options| options[:model].to_sym == :person }.map { |options| options[:field].to_s }
  35 + end
  36 +
31 def fields 37 def fields
32 - %w[login email] + plugins_fields.map { |field, name| field.to_s } 38 + user_fields + person_fields
33 end 39 end
34 40
35 - def fields_choice  
36 - [  
37 - [_('Username'), 'login'],  
38 - [_('Email'), 'email'],  
39 - ] + plugins_fields.map { |field, name| [name, field] } 41 + def fields_label
  42 + labels = [
  43 + _('Username'),
  44 + _('Email'),
  45 + ] + plugins_options.map { |options| options[:name] }
  46 +
  47 + last = labels.pop
  48 + label = labels.join(', ')
  49 + "#{label} #{_('or')} #{last}"
40 end 50 end
41 51
42 ################################################### 52 ###################################################
43 # validations for creating a ChangePassword task 53 # validations for creating a ChangePassword task
44 54
45 - validates_presence_of :field, :value, :environment_id, :on => :create, :message => _('must be filled in')  
46 - # TODO Only on rails3  
47 - # validates_inclusion_of :field, :in => lambda { |data| data.fields }  
48 - validates_each :field do |data, attr, value|  
49 - unless data.fields.include?(value)  
50 - data.errors.add(attr, _('is not in the list of valid fields.'))  
51 - end  
52 - end 55 + validates_presence_of :value, :environment_id, :on => :create, :message => _('must be filled in')
53 56
54 validates_each :value, :on => :create do |data,attr,value| 57 validates_each :value, :on => :create do |data,attr,value|
55 - unless data.field.blank? || data.value.blank?  
56 - user = data.user_find  
57 - if user.nil?  
58 - data.errors.add(:value, _('"%s" is not a valid %s.') % [value.to_s, human_attribute_name(data.field)]) 58 + unless data.value.blank?
  59 + users = data.find_users
  60 + if users.blank?
  61 + data.errors.add(:value, _('"%s" is not valid.') % value.to_s)
59 end 62 end
60 end 63 end
61 end 64 end
62 65
63 before_validation do |change_password| 66 before_validation do |change_password|
64 - user = change_password.user_find  
65 - change_password.requestor = user.person if user 67 + users = change_password.find_users
  68 + change_password.requestor ||= users.first.person if users.present?
66 end 69 end
67 70
68 ################################################### 71 ###################################################
@@ -73,15 +76,18 @@ class ChangePassword &lt; Task @@ -73,15 +76,18 @@ class ChangePassword &lt; Task
73 validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED } 76 validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED }
74 validates_confirmation_of :password, :if => lambda { |change| change.status != Task::Status::CANCELLED } 77 validates_confirmation_of :password, :if => lambda { |change| change.status != Task::Status::CANCELLED }
75 78
76 - def user_find  
77 - begin  
78 - method = "find_by_#{field}_and_environment_id"  
79 - user = nil  
80 - user = User.send(method, value, environment_id) if User.respond_to?(method)  
81 - user = Person.send(method, value, environment_id).user if user.nil? && Person.respond_to?(method)  
82 - rescue  
83 - end  
84 - user 79 + def build_query(fields)
  80 + fields.map {|field| "#{field} = '#{value}'"}.join(' OR ')
  81 + end
  82 +
  83 + def find_users
  84 + results = []
  85 + person_query = build_query(person_fields)
  86 + user_query = build_query(user_fields)
  87 +
  88 + results += Person.where(person_query).where(:environment_id => environment.id).map(&:user)
  89 + results += User.where(user_query).where(:environment_id => environment.id)
  90 + results
85 end 91 end
86 92
87 def title 93 def title
app/views/account/forgot_password.rhtml
@@ -4,8 +4,7 @@ @@ -4,8 +4,7 @@
4 4
5 <% labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %> 5 <% labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %>
6 6
7 - <%= labelled_form_field(_('What do you remember?'), f.select(:field, @change_password.fields_choice)) %>  
8 - <%= text_field_tag('change_password[value]') %> 7 + <%= labelled_form_field @change_password.fields_label, text_field_tag('change_password[value]') %>
9 8
10 <div> 9 <div>
11 <% button_bar do %> 10 <% button_bar do %>
lib/noosfero/plugin.rb
@@ -461,7 +461,7 @@ class Noosfero::Plugin @@ -461,7 +461,7 @@ class Noosfero::Plugin
461 end 461 end
462 462
463 # -> Adds aditional fields for change_password 463 # -> Adds aditional fields for change_password
464 - # returns = {:field1 => 'field1 name', :field2 => 'field2 name' ... } 464 + # returns = [{:field => 'field1', :name => 'field 1 name', :model => 'person'}, {...}]
465 def change_password_fields 465 def change_password_fields
466 nil 466 nil
467 end 467 end
plugins/stoa/lib/stoa_plugin.rb
@@ -121,7 +121,7 @@ class StoaPlugin &lt; Noosfero::Plugin @@ -121,7 +121,7 @@ class StoaPlugin &lt; Noosfero::Plugin
121 end 121 end
122 122
123 def change_password_fields 123 def change_password_fields
124 - {:usp_id => _('USP Number')} 124 + {:field => :usp_id, :name => _('USP Number'), :model => 'person'}
125 end 125 end
126 126
127 end 127 end
plugins/stoa/test/functional/account_controller_test.rb
@@ -67,7 +67,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -67,7 +67,7 @@ class AccountControllerTest &lt; ActionController::TestCase
67 end 67 end
68 68
69 should 'be able to recover password with usp_id' do 69 should 'be able to recover password with usp_id' do
70 - post :forgot_password, :change_password => { :field => 'usp_id', :value => '87654321' } 70 + post :forgot_password, :change_password => { :value => '87654321' }
71 assert_template 'password_recovery_sent' 71 assert_template 'password_recovery_sent'
72 end 72 end
73 end 73 end
test/functional/account_controller_test.rb
@@ -217,19 +217,19 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -217,19 +217,19 @@ class AccountControllerTest &lt; ActionController::TestCase
217 217
218 should 'respond to forgotten password change request with login' do 218 should 'respond to forgotten password change request with login' do
219 change = ChangePassword.new 219 change = ChangePassword.new
220 - ChangePassword.expects(:new).with('field' => 'login', 'value' => 'test').returns(change) 220 + ChangePassword.expects(:new).with('value' => 'test').returns(change)
221 change.expects(:save!).returns(true) 221 change.expects(:save!).returns(true)
222 222
223 - post :forgot_password, :change_password => { :field => 'login', :value => 'test' } 223 + post :forgot_password, :change_password => { :value => 'test' }
224 assert_template 'password_recovery_sent' 224 assert_template 'password_recovery_sent'
225 end 225 end
226 226
227 should 'respond to forgotten password change request with email' do 227 should 'respond to forgotten password change request with email' do
228 change = ChangePassword.new 228 change = ChangePassword.new
229 - ChangePassword.expects(:new).with('field' => 'email', 'value' => 'test@localhost.localdomain').returns(change) 229 + ChangePassword.expects(:new).with('value' => 'test@localhost.localdomain').returns(change)
230 change.expects(:save!).returns(true) 230 change.expects(:save!).returns(true)
231 231
232 - post :forgot_password, :change_password => { :field => 'email', :value => 'test@localhost.localdomain' } 232 + post :forgot_password, :change_password => { :value => 'test@localhost.localdomain' }
233 assert_template 'password_recovery_sent' 233 assert_template 'password_recovery_sent'
234 end 234 end
235 235
@@ -276,7 +276,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -276,7 +276,7 @@ class AccountControllerTest &lt; ActionController::TestCase
276 276
277 should 'require password confirmation correctly to enter new pasword' do 277 should 'require password confirmation correctly to enter new pasword' do
278 user = create_user('testuser', :email => 'testuser@example.com', :password => 'test', :password_confirmation => 'test') 278 user = create_user('testuser', :email => 'testuser@example.com', :password => 'test', :password_confirmation => 'test')
279 - change = ChangePassword.create!(:field => 'login', :value => 'testuser', :environment_id => Environment.default.id) 279 + change = ChangePassword.create!(:value => 'testuser', :environment_id => Environment.default.id)
280 280
281 post :new_password, :code => change.code, :change_password => { :password => 'onepass', :password_confirmation => 'another_pass' } 281 post :new_password, :code => change.code, :change_password => { :password => 'onepass', :password_confirmation => 'another_pass' }
282 assert_response :success 282 assert_response :success
@@ -862,7 +862,7 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -862,7 +862,7 @@ class AccountControllerTest &lt; ActionController::TestCase
862 assert_response :redirect 862 assert_response :redirect
863 863
864 #Redirect on post action 864 #Redirect on post action
865 - post :forgot_password, :change_password => { :field => 'login', :value => 'test' } 865 + post :forgot_password, :change_password => { :value => 'test' }
866 assert_response :redirect 866 assert_response :redirect
867 end 867 end
868 868
test/unit/change_password_test.rb
@@ -9,39 +9,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -9,39 +9,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
9 assert !data.valid? 9 assert !data.valid?
10 end 10 end
11 11
12 - should 'validate field is login or email' do  
13 - data = ChangePassword.new(:environment_id => Environment.default)  
14 - data.field = 'anything'  
15 - data.valid?  
16 - assert data.errors.invalid?(:field)  
17 -  
18 - data.field = 'login'  
19 - data.valid?  
20 - assert !data.errors.invalid?(:field)  
21 -  
22 - data.field = 'email'  
23 - data.valid?  
24 - assert !data.errors.invalid?(:field)  
25 - end  
26 -  
27 - should 'refuse invalid field' do  
28 - User.destroy_all  
29 -  
30 - data = ChangePassword.new  
31 - data.environment_id = Environment.default.id  
32 -  
33 - data.field = 'login'  
34 - data.value = 'unexisting'  
35 - data.valid?  
36 - assert data.errors.invalid?(:value)  
37 -  
38 - data.field = 'email'  
39 - data.value = 'example@example.com'  
40 - data.valid?  
41 - assert data.errors.invalid?(:value)  
42 - end  
43 -  
44 - should 'require only a valid field-value' do 12 + should 'require only a valid value' do
45 User.destroy_all 13 User.destroy_all
46 create_user('testuser', :email => 'test@example.com') 14 create_user('testuser', :email => 'test@example.com')
47 15
@@ -50,12 +18,10 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -50,12 +18,10 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
50 assert !data.valid? 18 assert !data.valid?
51 assert data.errors.invalid?(:value) 19 assert data.errors.invalid?(:value)
52 20
53 - data.field = 'login'  
54 data.value = 'testuser' 21 data.value = 'testuser'
55 data.valid? 22 data.valid?
56 assert data.valid? 23 assert data.valid?
57 24
58 - data.field = 'email'  
59 data.value = 'test@example.com' 25 data.value = 'test@example.com'
60 assert data.valid? 26 assert data.valid?
61 end 27 end
@@ -65,7 +31,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -65,7 +31,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
65 31
66 change = ChangePassword.new 32 change = ChangePassword.new
67 change.environment_id = Environment.default.id 33 change.environment_id = Environment.default.id
68 - change.field = 'login'  
69 change.value = 'testuser' 34 change.value = 'testuser'
70 change.save! 35 change.save!
71 36
@@ -86,7 +51,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -86,7 +51,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
86 51
87 change = ChangePassword.new 52 change = ChangePassword.new
88 change.environment_id = Environment.default.id 53 change.environment_id = Environment.default.id
89 - change.field = 'login'  
90 change.value = 'testuser' 54 change.value = 'testuser'
91 change.save! 55 change.save!
92 56
@@ -105,7 +69,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -105,7 +69,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
105 69
106 change = ChangePassword.new 70 change = ChangePassword.new
107 change.environment_id = Environment.default.id 71 change.environment_id = Environment.default.id
108 - change.field = 'login'  
109 change.value = 'testuser' 72 change.value = 'testuser'
110 change.save! 73 change.save!
111 74
@@ -127,8 +90,8 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -127,8 +90,8 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
127 p1 = create_user('sample-user', :password => 'test', :password_confirmation => 'test', :email => 'sample-user@test.com', :environment => e1).person 90 p1 = create_user('sample-user', :password => 'test', :password_confirmation => 'test', :email => 'sample-user@test.com', :environment => e1).person
128 p2 = create_user('sample-user', :password => 'test', :password_confirmation => 'test', :email => 'sample-user@test.com', :environment => e2).person 91 p2 = create_user('sample-user', :password => 'test', :password_confirmation => 'test', :email => 'sample-user@test.com', :environment => e2).person
129 92
130 - c1 = ChangePassword.create!(:field => 'login', :value => 'sample-user', :environment_id => e1.id)  
131 - c2 = ChangePassword.create!(:field => 'login', :value => 'sample-user', :environment_id => e2.id) 93 + c1 = ChangePassword.create!(:value => 'sample-user', :environment_id => e1.id)
  94 + c2 = ChangePassword.create!(:value => 'sample-user', :environment_id => e2.id)
132 95
133 assert_equal c1.requestor, p1 96 assert_equal c1.requestor, p1
134 assert_equal c2.requestor, p2 97 assert_equal c2.requestor, p2
@@ -137,7 +100,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -137,7 +100,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
137 should 'have target notification description' do 100 should 'have target notification description' do
138 person = create_user('testuser').person 101 person = create_user('testuser').person
139 102
140 - change = ChangePassword.create(:field => 'login', :value => 'testuser', :environment_id => Environment.default.id) 103 + change = ChangePassword.create(:value => 'testuser', :environment_id => Environment.default.id)
141 104
142 assert_match(/#{change.requestor.name} wants to change its password/, change.target_notification_description) 105 assert_match(/#{change.requestor.name} wants to change its password/, change.target_notification_description)
143 end 106 end
@@ -145,7 +108,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -145,7 +108,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
145 should 'deliver task created message' do 108 should 'deliver task created message' do
146 person = create_user('testuser').person 109 person = create_user('testuser').person
147 110
148 - task = ChangePassword.create(:field => 'login', :value => 'testuser', :environment_id => Environment.default.id) 111 + task = ChangePassword.create(:value => 'testuser', :environment_id => Environment.default.id)
149 112
150 email = TaskMailer.deliver_task_created(task) 113 email = TaskMailer.deliver_task_created(task)
151 assert_match(/#{task.requestor.name} wants to change its password/, email.subject) 114 assert_match(/#{task.requestor.name} wants to change its password/, email.subject)
@@ -154,12 +117,13 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase @@ -154,12 +117,13 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
154 should 'allow extra fields provided by plugins' do 117 should 'allow extra fields provided by plugins' do
155 class Plugin1 < Noosfero::Plugin 118 class Plugin1 < Noosfero::Plugin
156 def change_password_fields 119 def change_password_fields
157 - {:f1 => 'F1'} 120 + {:field => 'f1', :name => 'F1', :model => 'person'}
158 end 121 end
159 end 122 end
160 class Plugin2 < Noosfero::Plugin 123 class Plugin2 < Noosfero::Plugin
161 def change_password_fields 124 def change_password_fields
162 - {:f2 => 'F2', :f3 => 'F3'} 125 + [{:field => 'f2', :name => 'F2', :model => 'person'},
  126 + {:field => 'f3', :name => 'F3', :model => 'person'}]
163 end 127 end
164 end 128 end
165 129