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 1 class ChangePassword < Task
2 2  
3   - settings_items :field, :value
  3 + settings_items :value
4 4 attr_accessor :password, :password_confirmation, :environment_id
5 5  
6 6 include Noosfero::Plugin::HotSpot
7 7  
8 8 def self.human_attribute_name(attrib)
9 9 case attrib.to_sym
10   - when :field
11   - _('Field')
12 10 when :value
13 11 _('Value')
14 12 when :password
... ... @@ -20,49 +18,54 @@ class ChangePassword &lt; Task
20 18 end
21 19 end
22 20  
23   - def plugins_fields
24   - plugins.dispatch(:change_password_fields).inject({}) { |result, fields| result.merge!(fields)}
25   - end
26   -
27 21 def environment
28 22 (requestor.environment if requestor) || Environment.find_by_id(environment_id)
29 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 37 def fields
32   - %w[login email] + plugins_fields.map { |field, name| field.to_s }
  38 + user_fields + person_fields
33 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 50 end
41 51  
42 52 ###################################################
43 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 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 62 end
60 63 end
61 64 end
62 65  
63 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 69 end
67 70  
68 71 ###################################################
... ... @@ -73,15 +76,18 @@ class ChangePassword &lt; Task
73 76 validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED }
74 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 91 end
86 92  
87 93 def title
... ...
app/views/account/forgot_password.rhtml
... ... @@ -4,8 +4,7 @@
4 4  
5 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 9 <div>
11 10 <% button_bar do %>
... ...
lib/noosfero/plugin.rb
... ... @@ -461,7 +461,7 @@ class Noosfero::Plugin
461 461 end
462 462  
463 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 465 def change_password_fields
466 466 nil
467 467 end
... ...
plugins/stoa/lib/stoa_plugin.rb
... ... @@ -121,7 +121,7 @@ class StoaPlugin &lt; Noosfero::Plugin
121 121 end
122 122  
123 123 def change_password_fields
124   - {:usp_id => _('USP Number')}
  124 + {:field => :usp_id, :name => _('USP Number'), :model => 'person'}
125 125 end
126 126  
127 127 end
... ...
plugins/stoa/test/functional/account_controller_test.rb
... ... @@ -67,7 +67,7 @@ class AccountControllerTest &lt; ActionController::TestCase
67 67 end
68 68  
69 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 71 assert_template 'password_recovery_sent'
72 72 end
73 73 end
... ...
test/functional/account_controller_test.rb
... ... @@ -217,19 +217,19 @@ class AccountControllerTest &lt; ActionController::TestCase
217 217  
218 218 should 'respond to forgotten password change request with login' do
219 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 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 224 assert_template 'password_recovery_sent'
225 225 end
226 226  
227 227 should 'respond to forgotten password change request with email' do
228 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 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 233 assert_template 'password_recovery_sent'
234 234 end
235 235  
... ... @@ -276,7 +276,7 @@ class AccountControllerTest &lt; ActionController::TestCase
276 276  
277 277 should 'require password confirmation correctly to enter new pasword' do
278 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 281 post :new_password, :code => change.code, :change_password => { :password => 'onepass', :password_confirmation => 'another_pass' }
282 282 assert_response :success
... ... @@ -862,7 +862,7 @@ class AccountControllerTest &lt; ActionController::TestCase
862 862 assert_response :redirect
863 863  
864 864 #Redirect on post action
865   - post :forgot_password, :change_password => { :field => 'login', :value => 'test' }
  865 + post :forgot_password, :change_password => { :value => 'test' }
866 866 assert_response :redirect
867 867 end
868 868  
... ...
test/unit/change_password_test.rb
... ... @@ -9,39 +9,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
9 9 assert !data.valid?
10 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 13 User.destroy_all
46 14 create_user('testuser', :email => 'test@example.com')
47 15  
... ... @@ -50,12 +18,10 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
50 18 assert !data.valid?
51 19 assert data.errors.invalid?(:value)
52 20  
53   - data.field = 'login'
54 21 data.value = 'testuser'
55 22 data.valid?
56 23 assert data.valid?
57 24  
58   - data.field = 'email'
59 25 data.value = 'test@example.com'
60 26 assert data.valid?
61 27 end
... ... @@ -65,7 +31,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
65 31  
66 32 change = ChangePassword.new
67 33 change.environment_id = Environment.default.id
68   - change.field = 'login'
69 34 change.value = 'testuser'
70 35 change.save!
71 36  
... ... @@ -86,7 +51,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
86 51  
87 52 change = ChangePassword.new
88 53 change.environment_id = Environment.default.id
89   - change.field = 'login'
90 54 change.value = 'testuser'
91 55 change.save!
92 56  
... ... @@ -105,7 +69,6 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
105 69  
106 70 change = ChangePassword.new
107 71 change.environment_id = Environment.default.id
108   - change.field = 'login'
109 72 change.value = 'testuser'
110 73 change.save!
111 74  
... ... @@ -127,8 +90,8 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
127 90 p1 = create_user('sample-user', :password => 'test', :password_confirmation => 'test', :email => 'sample-user@test.com', :environment => e1).person
128 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 96 assert_equal c1.requestor, p1
134 97 assert_equal c2.requestor, p2
... ... @@ -137,7 +100,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
137 100 should 'have target notification description' do
138 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 105 assert_match(/#{change.requestor.name} wants to change its password/, change.target_notification_description)
143 106 end
... ... @@ -145,7 +108,7 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
145 108 should 'deliver task created message' do
146 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 113 email = TaskMailer.deliver_task_created(task)
151 114 assert_match(/#{task.requestor.name} wants to change its password/, email.subject)
... ... @@ -154,12 +117,13 @@ class ChangePasswordTest &lt; ActiveSupport::TestCase
154 117 should 'allow extra fields provided by plugins' do
155 118 class Plugin1 < Noosfero::Plugin
156 119 def change_password_fields
157   - {:f1 => 'F1'}
  120 + {:field => 'f1', :name => 'F1', :model => 'person'}
158 121 end
159 122 end
160 123 class Plugin2 < Noosfero::Plugin
161 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 127 end
164 128 end
165 129  
... ...