##// END OF EJS Templates
Merged r16287 to r16289 (#24416)....
Jean-Philippe Lang -
r15916:e360394be7a4
parent child
Show More
@@ -1,361 +1,369
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class AccountController < ApplicationController
19 19 helper :custom_fields
20 20 include CustomFieldsHelper
21 21
22 22 # prevents login action to be filtered by check_if_login_required application scope filter
23 23 skip_before_filter :check_if_login_required, :check_password_change
24 24
25 25 # Overrides ApplicationController#verify_authenticity_token to disable
26 26 # token verification on openid callbacks
27 27 def verify_authenticity_token
28 28 unless using_open_id?
29 29 super
30 30 end
31 31 end
32 32
33 33 # Login request and validation
34 34 def login
35 35 if request.get?
36 36 if User.current.logged?
37 37 redirect_back_or_default home_url, :referer => true
38 38 end
39 39 else
40 40 authenticate_user
41 41 end
42 42 rescue AuthSourceException => e
43 43 logger.error "An error occured when authenticating #{params[:username]}: #{e.message}"
44 44 render_error :message => e.message
45 45 end
46 46
47 47 # Log out current user and redirect to welcome page
48 48 def logout
49 49 if User.current.anonymous?
50 50 redirect_to home_url
51 51 elsif request.post?
52 52 logout_user
53 53 redirect_to home_url
54 54 end
55 55 # display the logout form
56 56 end
57 57
58 58 # Lets user choose a new password
59 59 def lost_password
60 60 (redirect_to(home_url); return) unless Setting.lost_password?
61 if params[:token]
62 @token = Token.find_token("recovery", params[:token].to_s)
61 if prt = (params[:token] || session[:password_recovery_token])
62 @token = Token.find_token("recovery", prt.to_s)
63 63 if @token.nil? || @token.expired?
64 64 redirect_to home_url
65 65 return
66 66 end
67
68 # redirect to remove the token query parameter from the URL and add it to the session
69 if request.query_parameters[:token].present?
70 session[:password_recovery_token] = @token.value
71 redirect_to lost_password_url
72 return
73 end
74
67 75 @user = @token.user
68 76 unless @user && @user.active?
69 77 redirect_to home_url
70 78 return
71 79 end
72 80 if request.post?
73 81 @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation]
74 82 if @user.save
75 83 @token.destroy
76 84 Mailer.password_updated(@user)
77 85 flash[:notice] = l(:notice_account_password_updated)
78 86 redirect_to signin_path
79 87 return
80 88 end
81 89 end
82 90 render :template => "account/password_recovery"
83 91 return
84 92 else
85 93 if request.post?
86 94 email = params[:mail].to_s
87 95 user = User.find_by_mail(email)
88 96 # user not found
89 97 unless user
90 98 flash.now[:error] = l(:notice_account_unknown_email)
91 99 return
92 100 end
93 101 unless user.active?
94 102 handle_inactive_user(user, lost_password_path)
95 103 return
96 104 end
97 105 # user cannot change its password
98 106 unless user.change_password_allowed?
99 107 flash.now[:error] = l(:notice_can_t_change_password)
100 108 return
101 109 end
102 110 # create a new token for password recovery
103 111 token = Token.new(:user => user, :action => "recovery")
104 112 if token.save
105 113 # Don't use the param to send the email
106 114 recipent = user.mails.detect {|e| email.casecmp(e) == 0} || user.mail
107 115 Mailer.lost_password(token, recipent).deliver
108 116 flash[:notice] = l(:notice_account_lost_email_sent)
109 117 redirect_to signin_path
110 118 return
111 119 end
112 120 end
113 121 end
114 122 end
115 123
116 124 # User self-registration
117 125 def register
118 126 (redirect_to(home_url); return) unless Setting.self_registration? || session[:auth_source_registration]
119 127 if request.get?
120 128 session[:auth_source_registration] = nil
121 129 @user = User.new(:language => current_language.to_s)
122 130 else
123 131 user_params = params[:user] || {}
124 132 @user = User.new
125 133 @user.safe_attributes = user_params
126 134 @user.pref.attributes = params[:pref] if params[:pref]
127 135 @user.admin = false
128 136 @user.register
129 137 if session[:auth_source_registration]
130 138 @user.activate
131 139 @user.login = session[:auth_source_registration][:login]
132 140 @user.auth_source_id = session[:auth_source_registration][:auth_source_id]
133 141 if @user.save
134 142 session[:auth_source_registration] = nil
135 143 self.logged_user = @user
136 144 flash[:notice] = l(:notice_account_activated)
137 145 redirect_to my_account_path
138 146 end
139 147 else
140 148 @user.login = params[:user][:login]
141 149 unless user_params[:identity_url].present? && user_params[:password].blank? && user_params[:password_confirmation].blank?
142 150 @user.password, @user.password_confirmation = user_params[:password], user_params[:password_confirmation]
143 151 end
144 152
145 153 case Setting.self_registration
146 154 when '1'
147 155 register_by_email_activation(@user)
148 156 when '3'
149 157 register_automatically(@user)
150 158 else
151 159 register_manually_by_administrator(@user)
152 160 end
153 161 end
154 162 end
155 163 end
156 164
157 165 # Token based account activation
158 166 def activate
159 167 (redirect_to(home_url); return) unless Setting.self_registration? && params[:token].present?
160 168 token = Token.find_token('register', params[:token].to_s)
161 169 (redirect_to(home_url); return) unless token and !token.expired?
162 170 user = token.user
163 171 (redirect_to(home_url); return) unless user.registered?
164 172 user.activate
165 173 if user.save
166 174 token.destroy
167 175 flash[:notice] = l(:notice_account_activated)
168 176 end
169 177 redirect_to signin_path
170 178 end
171 179
172 180 # Sends a new account activation email
173 181 def activation_email
174 182 if session[:registered_user_id] && Setting.self_registration == '1'
175 183 user_id = session.delete(:registered_user_id).to_i
176 184 user = User.find_by_id(user_id)
177 185 if user && user.registered?
178 186 register_by_email_activation(user)
179 187 return
180 188 end
181 189 end
182 190 redirect_to(home_url)
183 191 end
184 192
185 193 private
186 194
187 195 def authenticate_user
188 196 if Setting.openid? && using_open_id?
189 197 open_id_authenticate(params[:openid_url])
190 198 else
191 199 password_authentication
192 200 end
193 201 end
194 202
195 203 def password_authentication
196 204 user = User.try_to_login(params[:username], params[:password], false)
197 205
198 206 if user.nil?
199 207 invalid_credentials
200 208 elsif user.new_record?
201 209 onthefly_creation_failed(user, {:login => user.login, :auth_source_id => user.auth_source_id })
202 210 else
203 211 # Valid user
204 212 if user.active?
205 213 successful_authentication(user)
206 214 update_sudo_timestamp! # activate Sudo Mode
207 215 else
208 216 handle_inactive_user(user)
209 217 end
210 218 end
211 219 end
212 220
213 221 def open_id_authenticate(openid_url)
214 222 back_url = signin_url(:autologin => params[:autologin])
215 223 authenticate_with_open_id(
216 224 openid_url, :required => [:nickname, :fullname, :email],
217 225 :return_to => back_url, :method => :post
218 226 ) do |result, identity_url, registration|
219 227 if result.successful?
220 228 user = User.find_or_initialize_by_identity_url(identity_url)
221 229 if user.new_record?
222 230 # Self-registration off
223 231 (redirect_to(home_url); return) unless Setting.self_registration?
224 232 # Create on the fly
225 233 user.login = registration['nickname'] unless registration['nickname'].nil?
226 234 user.mail = registration['email'] unless registration['email'].nil?
227 235 user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
228 236 user.random_password
229 237 user.register
230 238 case Setting.self_registration
231 239 when '1'
232 240 register_by_email_activation(user) do
233 241 onthefly_creation_failed(user)
234 242 end
235 243 when '3'
236 244 register_automatically(user) do
237 245 onthefly_creation_failed(user)
238 246 end
239 247 else
240 248 register_manually_by_administrator(user) do
241 249 onthefly_creation_failed(user)
242 250 end
243 251 end
244 252 else
245 253 # Existing record
246 254 if user.active?
247 255 successful_authentication(user)
248 256 else
249 257 handle_inactive_user(user)
250 258 end
251 259 end
252 260 end
253 261 end
254 262 end
255 263
256 264 def successful_authentication(user)
257 265 logger.info "Successful authentication for '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}"
258 266 # Valid user
259 267 self.logged_user = user
260 268 # generate a key and set cookie if autologin
261 269 if params[:autologin] && Setting.autologin?
262 270 set_autologin_cookie(user)
263 271 end
264 272 call_hook(:controller_account_success_authentication_after, {:user => user })
265 273 redirect_back_or_default my_page_path
266 274 end
267 275
268 276 def set_autologin_cookie(user)
269 277 token = Token.create(:user => user, :action => 'autologin')
270 278 secure = Redmine::Configuration['autologin_cookie_secure']
271 279 if secure.nil?
272 280 secure = request.ssl?
273 281 end
274 282 cookie_options = {
275 283 :value => token.value,
276 284 :expires => 1.year.from_now,
277 285 :path => (Redmine::Configuration['autologin_cookie_path'] || RedmineApp::Application.config.relative_url_root || '/'),
278 286 :secure => secure,
279 287 :httponly => true
280 288 }
281 289 cookies[autologin_cookie_name] = cookie_options
282 290 end
283 291
284 292 # Onthefly creation failed, display the registration form to fill/fix attributes
285 293 def onthefly_creation_failed(user, auth_source_options = { })
286 294 @user = user
287 295 session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
288 296 render :action => 'register'
289 297 end
290 298
291 299 def invalid_credentials
292 300 logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
293 301 flash.now[:error] = l(:notice_account_invalid_credentials)
294 302 end
295 303
296 304 # Register a user for email activation.
297 305 #
298 306 # Pass a block for behavior when a user fails to save
299 307 def register_by_email_activation(user, &block)
300 308 token = Token.new(:user => user, :action => "register")
301 309 if user.save and token.save
302 310 Mailer.register(token).deliver
303 311 flash[:notice] = l(:notice_account_register_done, :email => ERB::Util.h(user.mail))
304 312 redirect_to signin_path
305 313 else
306 314 yield if block_given?
307 315 end
308 316 end
309 317
310 318 # Automatically register a user
311 319 #
312 320 # Pass a block for behavior when a user fails to save
313 321 def register_automatically(user, &block)
314 322 # Automatic activation
315 323 user.activate
316 324 user.last_login_on = Time.now
317 325 if user.save
318 326 self.logged_user = user
319 327 flash[:notice] = l(:notice_account_activated)
320 328 redirect_to my_account_path
321 329 else
322 330 yield if block_given?
323 331 end
324 332 end
325 333
326 334 # Manual activation by the administrator
327 335 #
328 336 # Pass a block for behavior when a user fails to save
329 337 def register_manually_by_administrator(user, &block)
330 338 if user.save
331 339 # Sends an email to the administrators
332 340 Mailer.account_activation_request(user).deliver
333 341 account_pending(user)
334 342 else
335 343 yield if block_given?
336 344 end
337 345 end
338 346
339 347 def handle_inactive_user(user, redirect_path=signin_path)
340 348 if user.registered?
341 349 account_pending(user, redirect_path)
342 350 else
343 351 account_locked(user, redirect_path)
344 352 end
345 353 end
346 354
347 355 def account_pending(user, redirect_path=signin_path)
348 356 if Setting.self_registration == '1'
349 357 flash[:error] = l(:notice_account_not_activated_yet, :url => activation_email_path)
350 358 session[:registered_user_id] = user.id
351 359 else
352 360 flash[:error] = l(:notice_account_pending)
353 361 end
354 362 redirect_to redirect_path
355 363 end
356 364
357 365 def account_locked(user, redirect_path=signin_path)
358 366 flash[:error] = l(:notice_account_locked)
359 367 redirect_to redirect_path
360 368 end
361 369 end
@@ -1,465 +1,476
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class AccountControllerTest < ActionController::TestCase
21 21 fixtures :users, :email_addresses, :roles
22 22
23 23 def setup
24 24 User.current = nil
25 25 end
26 26
27 27 def test_get_login
28 28 get :login
29 29 assert_response :success
30 30 assert_template 'login'
31 31
32 32 assert_select 'input[name=username]'
33 33 assert_select 'input[name=password]'
34 34 end
35 35
36 36 def test_get_login_while_logged_in_should_redirect_to_back_url_if_present
37 37 @request.session[:user_id] = 2
38 38 @request.env["HTTP_REFERER"] = 'http://test.host/issues/show/1'
39 39
40 40 get :login, :back_url => 'http://test.host/issues/show/1'
41 41 assert_redirected_to '/issues/show/1'
42 42 assert_equal 2, @request.session[:user_id]
43 43 end
44 44
45 45 def test_get_login_while_logged_in_should_redirect_to_referer_without_back_url
46 46 @request.session[:user_id] = 2
47 47 @request.env["HTTP_REFERER"] = 'http://test.host/issues/show/1'
48 48
49 49 get :login
50 50 assert_redirected_to '/issues/show/1'
51 51 assert_equal 2, @request.session[:user_id]
52 52 end
53 53
54 54 def test_get_login_while_logged_in_should_redirect_to_home_by_default
55 55 @request.session[:user_id] = 2
56 56
57 57 get :login
58 58 assert_redirected_to '/'
59 59 assert_equal 2, @request.session[:user_id]
60 60 end
61 61
62 62 def test_login_should_redirect_to_back_url_param
63 63 # request.uri is "test.host" in test environment
64 64 back_urls = [
65 65 'http://test.host/issues/show/1',
66 66 'http://test.host/',
67 67 '/'
68 68 ]
69 69 back_urls.each do |back_url|
70 70 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
71 71 assert_redirected_to back_url
72 72 end
73 73 end
74 74
75 75 def test_login_with_suburi_should_redirect_to_back_url_param
76 76 @relative_url_root = Redmine::Utils.relative_url_root
77 77 Redmine::Utils.relative_url_root = '/redmine'
78 78
79 79 back_urls = [
80 80 'http://test.host/redmine/issues/show/1',
81 81 '/redmine'
82 82 ]
83 83 back_urls.each do |back_url|
84 84 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
85 85 assert_redirected_to back_url
86 86 end
87 87 ensure
88 88 Redmine::Utils.relative_url_root = @relative_url_root
89 89 end
90 90
91 91 def test_login_should_not_redirect_to_another_host
92 92 back_urls = [
93 93 'http://test.foo/fake',
94 94 '//test.foo/fake'
95 95 ]
96 96 back_urls.each do |back_url|
97 97 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
98 98 assert_redirected_to '/my/page'
99 99 end
100 100 end
101 101
102 102 def test_login_with_suburi_should_not_redirect_to_another_suburi
103 103 @relative_url_root = Redmine::Utils.relative_url_root
104 104 Redmine::Utils.relative_url_root = '/redmine'
105 105
106 106 back_urls = [
107 107 'http://test.host/',
108 108 'http://test.host/fake',
109 109 'http://test.host/fake/issues',
110 110 'http://test.host/redmine/../fake',
111 111 'http://test.host/redmine/../fake/issues',
112 112 'http://test.host/redmine/%2e%2e/fake',
113 113 '//test.foo/fake',
114 114 'http://test.host//fake',
115 115 'http://test.host/\n//fake',
116 116 '//bar@test.foo',
117 117 '//test.foo',
118 118 '////test.foo',
119 119 '@test.foo',
120 120 'fake@test.foo',
121 121 '.test.foo'
122 122 ]
123 123 back_urls.each do |back_url|
124 124 post :login, :username => 'jsmith', :password => 'jsmith', :back_url => back_url
125 125 assert_redirected_to '/my/page'
126 126 end
127 127 ensure
128 128 Redmine::Utils.relative_url_root = @relative_url_root
129 129 end
130 130
131 131 def test_login_with_wrong_password
132 132 post :login, :username => 'admin', :password => 'bad'
133 133 assert_response :success
134 134 assert_template 'login'
135 135
136 136 assert_select 'div.flash.error', :text => /Invalid user or password/
137 137 assert_select 'input[name=username][value=admin]'
138 138 assert_select 'input[name=password]'
139 139 assert_select 'input[name=password][value]', 0
140 140 end
141 141
142 142 def test_login_with_locked_account_should_fail
143 143 User.find(2).update_attribute :status, User::STATUS_LOCKED
144 144
145 145 post :login, :username => 'jsmith', :password => 'jsmith'
146 146 assert_redirected_to '/login'
147 147 assert_include 'locked', flash[:error]
148 148 assert_nil @request.session[:user_id]
149 149 end
150 150
151 151 def test_login_as_registered_user_with_manual_activation_should_inform_user
152 152 User.find(2).update_attribute :status, User::STATUS_REGISTERED
153 153
154 154 with_settings :self_registration => '2', :default_language => 'en' do
155 155 post :login, :username => 'jsmith', :password => 'jsmith'
156 156 assert_redirected_to '/login'
157 157 assert_include 'pending administrator approval', flash[:error]
158 158 end
159 159 end
160 160
161 161 def test_login_as_registered_user_with_email_activation_should_propose_new_activation_email
162 162 User.find(2).update_attribute :status, User::STATUS_REGISTERED
163 163
164 164 with_settings :self_registration => '1', :default_language => 'en' do
165 165 post :login, :username => 'jsmith', :password => 'jsmith'
166 166 assert_redirected_to '/login'
167 167 assert_equal 2, @request.session[:registered_user_id]
168 168 assert_include 'new activation email', flash[:error]
169 169 end
170 170 end
171 171
172 172 def test_login_should_rescue_auth_source_exception
173 173 source = AuthSource.create!(:name => 'Test')
174 174 User.find(2).update_attribute :auth_source_id, source.id
175 175 AuthSource.any_instance.stubs(:authenticate).raises(AuthSourceException.new("Something wrong"))
176 176
177 177 post :login, :username => 'jsmith', :password => 'jsmith'
178 178 assert_response 500
179 179 assert_select_error /Something wrong/
180 180 end
181 181
182 182 def test_login_should_reset_session
183 183 @controller.expects(:reset_session).once
184 184
185 185 post :login, :username => 'jsmith', :password => 'jsmith'
186 186 assert_response 302
187 187 end
188 188
189 189 def test_get_logout_should_not_logout
190 190 @request.session[:user_id] = 2
191 191 get :logout
192 192 assert_response :success
193 193 assert_template 'logout'
194 194
195 195 assert_equal 2, @request.session[:user_id]
196 196 end
197 197
198 198 def test_get_logout_with_anonymous_should_redirect
199 199 get :logout
200 200 assert_redirected_to '/'
201 201 end
202 202
203 203 def test_logout
204 204 @request.session[:user_id] = 2
205 205 post :logout
206 206 assert_redirected_to '/'
207 207 assert_nil @request.session[:user_id]
208 208 end
209 209
210 210 def test_logout_should_reset_session
211 211 @controller.expects(:reset_session).once
212 212
213 213 @request.session[:user_id] = 2
214 214 post :logout
215 215 assert_response 302
216 216 end
217 217
218 218 def test_get_register_with_registration_on
219 219 with_settings :self_registration => '3' do
220 220 get :register
221 221 assert_response :success
222 222 assert_template 'register'
223 223 assert_not_nil assigns(:user)
224 224
225 225 assert_select 'input[name=?]', 'user[password]'
226 226 assert_select 'input[name=?]', 'user[password_confirmation]'
227 227 end
228 228 end
229 229
230 230 def test_get_register_should_detect_user_language
231 231 with_settings :self_registration => '3' do
232 232 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
233 233 get :register
234 234 assert_response :success
235 235 assert_not_nil assigns(:user)
236 236 assert_equal 'fr', assigns(:user).language
237 237 assert_select 'select[name=?]', 'user[language]' do
238 238 assert_select 'option[value=fr][selected=selected]'
239 239 end
240 240 end
241 241 end
242 242
243 243 def test_get_register_with_registration_off_should_redirect
244 244 with_settings :self_registration => '0' do
245 245 get :register
246 246 assert_redirected_to '/'
247 247 end
248 248 end
249 249
250 250 def test_get_register_should_show_hide_mail_preference
251 251 get :register
252 252 assert_select 'input[name=?][checked=checked]', 'pref[hide_mail]'
253 253 end
254 254
255 255 def test_get_register_should_show_hide_mail_preference_with_setting_turned_off
256 256 with_settings :default_users_hide_mail => '0' do
257 257 get :register
258 258 assert_select 'input[name=?]:not([checked=checked])', 'pref[hide_mail]'
259 259 end
260 260 end
261 261
262 262 # See integration/account_test.rb for the full test
263 263 def test_post_register_with_registration_on
264 264 with_settings :self_registration => '3' do
265 265 assert_difference 'User.count' do
266 266 post :register, :user => {
267 267 :login => 'register',
268 268 :password => 'secret123',
269 269 :password_confirmation => 'secret123',
270 270 :firstname => 'John',
271 271 :lastname => 'Doe',
272 272 :mail => 'register@example.com'
273 273 }
274 274 assert_redirected_to '/my/account'
275 275 end
276 276 user = User.order('id DESC').first
277 277 assert_equal 'register', user.login
278 278 assert_equal 'John', user.firstname
279 279 assert_equal 'Doe', user.lastname
280 280 assert_equal 'register@example.com', user.mail
281 281 assert user.check_password?('secret123')
282 282 assert user.active?
283 283 end
284 284 end
285 285
286 286 def test_post_register_with_registration_off_should_redirect
287 287 with_settings :self_registration => '0' do
288 288 assert_no_difference 'User.count' do
289 289 post :register, :user => {
290 290 :login => 'register',
291 291 :password => 'test',
292 292 :password_confirmation => 'test',
293 293 :firstname => 'John',
294 294 :lastname => 'Doe',
295 295 :mail => 'register@example.com'
296 296 }
297 297 assert_redirected_to '/'
298 298 end
299 299 end
300 300 end
301 301
302 302 def test_post_register_should_create_user_with_hide_mail_preference
303 303 with_settings :default_users_hide_mail => '0' do
304 304 user = new_record(User) do
305 305 post :register, :user => {
306 306 :login => 'register',
307 307 :password => 'secret123', :password_confirmation => 'secret123',
308 308 :firstname => 'John', :lastname => 'Doe',
309 309 :mail => 'register@example.com'
310 310 }, :pref => {
311 311 :hide_mail => '1'
312 312 }
313 313 end
314 314 assert_equal true, user.pref.hide_mail
315 315 end
316 316 end
317 317
318 318 def test_get_lost_password_should_display_lost_password_form
319 319 get :lost_password
320 320 assert_response :success
321 321 assert_select 'input[name=mail]'
322 322 end
323 323
324 324 def test_lost_password_for_active_user_should_create_a_token
325 325 Token.delete_all
326 326 ActionMailer::Base.deliveries.clear
327 327 assert_difference 'ActionMailer::Base.deliveries.size' do
328 328 assert_difference 'Token.count' do
329 329 post :lost_password, :mail => 'JSmith@somenet.foo'
330 330 assert_redirected_to '/login'
331 331 end
332 332 end
333 333
334 334 token = Token.order('id DESC').first
335 335 assert_equal User.find(2), token.user
336 336 assert_equal 'recovery', token.action
337 337
338 338 assert_select_email do
339 339 assert_select "a[href=?]", "http://localhost:3000/account/lost_password?token=#{token.value}"
340 340 end
341 341 end
342 342
343 343 def test_lost_password_using_additional_email_address_should_send_email_to_the_address
344 344 EmailAddress.create!(:user_id => 2, :address => 'anotherAddress@foo.bar')
345 345 Token.delete_all
346 346
347 347 assert_difference 'ActionMailer::Base.deliveries.size' do
348 348 assert_difference 'Token.count' do
349 349 post :lost_password, :mail => 'ANOTHERaddress@foo.bar'
350 350 assert_redirected_to '/login'
351 351 end
352 352 end
353 353 mail = ActionMailer::Base.deliveries.last
354 354 assert_equal ['anotherAddress@foo.bar'], mail.bcc
355 355 end
356 356
357 357 def test_lost_password_for_unknown_user_should_fail
358 358 Token.delete_all
359 359 assert_no_difference 'Token.count' do
360 360 post :lost_password, :mail => 'invalid@somenet.foo'
361 361 assert_response :success
362 362 end
363 363 end
364 364
365 365 def test_lost_password_for_non_active_user_should_fail
366 366 Token.delete_all
367 367 assert User.find(2).lock!
368 368
369 369 assert_no_difference 'Token.count' do
370 370 post :lost_password, :mail => 'JSmith@somenet.foo'
371 371 assert_redirected_to '/account/lost_password'
372 372 end
373 373 end
374 374
375 375 def test_lost_password_for_user_who_cannot_change_password_should_fail
376 376 User.any_instance.stubs(:change_password_allowed?).returns(false)
377 377
378 378 assert_no_difference 'Token.count' do
379 379 post :lost_password, :mail => 'JSmith@somenet.foo'
380 380 assert_response :success
381 381 end
382 382 end
383 383
384 def test_get_lost_password_with_token_should_display_the_password_recovery_form
384 def test_get_lost_password_with_token_should_redirect_with_token_in_session
385 385 user = User.find(2)
386 386 token = Token.create!(:action => 'recovery', :user => user)
387 387
388 388 get :lost_password, :token => token.value
389 assert_redirected_to '/account/lost_password'
390
391 assert_equal token.value, request.session[:password_recovery_token]
392 end
393
394 def test_get_lost_password_with_token_in_session_should_display_the_password_recovery_form
395 user = User.find(2)
396 token = Token.create!(:action => 'recovery', :user => user)
397 request.session[:password_recovery_token] = token.value
398
399 get :lost_password
389 400 assert_response :success
390 401 assert_template 'password_recovery'
391 402
392 403 assert_select 'input[type=hidden][name=token][value=?]', token.value
393 404 end
394 405
395 406 def test_get_lost_password_with_invalid_token_should_redirect
396 407 get :lost_password, :token => "abcdef"
397 408 assert_redirected_to '/'
398 409 end
399 410
400 411 def test_post_lost_password_with_token_should_change_the_user_password
401 412 ActionMailer::Base.deliveries.clear
402 413 user = User.find(2)
403 414 token = Token.create!(:action => 'recovery', :user => user)
404 415
405 416 post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
406 417 assert_redirected_to '/login'
407 418 user.reload
408 419 assert user.check_password?('newpass123')
409 420 assert_nil Token.find_by_id(token.id), "Token was not deleted"
410 421 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
411 422 assert_select_email do
412 423 assert_select 'a[href^=?]', 'http://localhost:3000/my/password', :text => 'Change password'
413 424 end
414 425 end
415 426
416 427 def test_post_lost_password_with_token_for_non_active_user_should_fail
417 428 user = User.find(2)
418 429 token = Token.create!(:action => 'recovery', :user => user)
419 430 user.lock!
420 431
421 432 post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
422 433 assert_redirected_to '/'
423 434 assert ! user.check_password?('newpass123')
424 435 end
425 436
426 437 def test_post_lost_password_with_token_and_password_confirmation_failure_should_redisplay_the_form
427 438 user = User.find(2)
428 439 token = Token.create!(:action => 'recovery', :user => user)
429 440
430 441 post :lost_password, :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'wrongpass'
431 442 assert_response :success
432 443 assert_template 'password_recovery'
433 444 assert_not_nil Token.find_by_id(token.id), "Token was deleted"
434 445
435 446 assert_select 'input[type=hidden][name=token][value=?]', token.value
436 447 end
437 448
438 449 def test_post_lost_password_with_invalid_token_should_redirect
439 450 post :lost_password, :token => "abcdef", :new_password => 'newpass', :new_password_confirmation => 'newpass'
440 451 assert_redirected_to '/'
441 452 end
442 453
443 454 def test_activation_email_should_send_an_activation_email
444 455 User.find(2).update_attribute :status, User::STATUS_REGISTERED
445 456 @request.session[:registered_user_id] = 2
446 457
447 458 with_settings :self_registration => '1' do
448 459 assert_difference 'ActionMailer::Base.deliveries.size' do
449 460 get :activation_email
450 461 assert_redirected_to '/login'
451 462 end
452 463 end
453 464 end
454 465
455 466 def test_activation_email_without_session_data_should_fail
456 467 User.find(2).update_attribute :status, User::STATUS_REGISTERED
457 468
458 469 with_settings :self_registration => '1' do
459 470 assert_no_difference 'ActionMailer::Base.deliveries.size' do
460 471 get :activation_email
461 472 assert_redirected_to '/'
462 473 end
463 474 end
464 475 end
465 476 end
@@ -1,353 +1,356
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class AccountTest < Redmine::IntegrationTest
21 21 fixtures :users, :email_addresses, :roles
22 22
23 23 def test_login
24 24 get "/my/page"
25 25 assert_redirected_to "/login?back_url=http%3A%2F%2Fwww.example.com%2Fmy%2Fpage"
26 26 log_user('jsmith', 'jsmith')
27 27
28 28 get "/my/account"
29 29 assert_response :success
30 30 assert_template "my/account"
31 31 end
32 32
33 33 def test_login_should_set_session_token
34 34 assert_difference 'Token.count' do
35 35 log_user('jsmith', 'jsmith')
36 36
37 37 assert_equal 2, session[:user_id]
38 38 assert_not_nil session[:tk]
39 39 end
40 40 end
41 41
42 42 def test_autologin
43 43 user = User.find(1)
44 44 Token.delete_all
45 45
46 46 with_settings :autologin => '7' do
47 47 assert_difference 'Token.count', 2 do
48 48 # User logs in with 'autologin' checked
49 49 post '/login', :username => user.login, :password => 'admin', :autologin => 1
50 50 assert_redirected_to '/my/page'
51 51 end
52 52 token = Token.where(:action => 'autologin').order(:id => :desc).first
53 53 assert_not_nil token
54 54 assert_equal user, token.user
55 55 assert_equal 'autologin', token.action
56 56 assert_equal user.id, session[:user_id]
57 57 assert_equal token.value, cookies['autologin']
58 58
59 59 # Session is cleared
60 60 reset!
61 61 User.current = nil
62 62 # Clears user's last login timestamp
63 63 user.update_attribute :last_login_on, nil
64 64 assert_nil user.reload.last_login_on
65 65
66 66 # User comes back with user's autologin cookie
67 67 cookies[:autologin] = token.value
68 68 get '/my/page'
69 69 assert_response :success
70 70 assert_template 'my/page'
71 71 assert_equal user.id, session[:user_id]
72 72 assert_not_nil user.reload.last_login_on
73 73 end
74 74 end
75 75
76 76 def test_autologin_should_use_autologin_cookie_name
77 77 Token.delete_all
78 78 Redmine::Configuration.stubs(:[]).with('autologin_cookie_name').returns('custom_autologin')
79 79 Redmine::Configuration.stubs(:[]).with('autologin_cookie_path').returns('/')
80 80 Redmine::Configuration.stubs(:[]).with('autologin_cookie_secure').returns(false)
81 81 Redmine::Configuration.stubs(:[]).with('sudo_mode_timeout').returns(15)
82 82
83 83 with_settings :autologin => '7' do
84 84 assert_difference 'Token.count', 2 do
85 85 post '/login', :username => 'admin', :password => 'admin', :autologin => 1
86 86 assert_response 302
87 87 end
88 88 assert cookies['custom_autologin'].present?
89 89 token = cookies['custom_autologin']
90 90
91 91 # Session is cleared
92 92 reset!
93 93 cookies['custom_autologin'] = token
94 94 get '/my/page'
95 95 assert_response :success
96 96
97 97 assert_difference 'Token.count', -2 do
98 98 post '/logout'
99 99 end
100 100 assert cookies['custom_autologin'].blank?
101 101 end
102 102 end
103 103
104 104 def test_lost_password
105 105 Token.delete_all
106 106
107 107 get "/account/lost_password"
108 108 assert_response :success
109 109 assert_template "account/lost_password"
110 110 assert_select 'input[name=mail]'
111 111
112 112 post "/account/lost_password", :mail => 'jSmith@somenet.foo'
113 113 assert_redirected_to "/login"
114 114
115 115 token = Token.first
116 116 assert_equal 'recovery', token.action
117 117 assert_equal 'jsmith@somenet.foo', token.user.mail
118 118 assert !token.expired?
119 119
120 120 get "/account/lost_password", :token => token.value
121 assert_redirected_to '/account/lost_password'
122
123 follow_redirect!
121 124 assert_response :success
122 125 assert_template "account/password_recovery"
123 126 assert_select 'input[type=hidden][name=token][value=?]', token.value
124 127 assert_select 'input[name=new_password]'
125 128 assert_select 'input[name=new_password_confirmation]'
126 129
127 130 post "/account/lost_password",
128 131 :token => token.value, :new_password => 'newpass123',
129 132 :new_password_confirmation => 'newpass123'
130 133 assert_redirected_to "/login"
131 134 assert_equal 'Password was successfully updated.', flash[:notice]
132 135
133 136 log_user('jsmith', 'newpass123')
134 137 assert_equal false, Token.exists?(token.id), "Password recovery token was not deleted"
135 138 end
136 139
137 140 def test_user_with_must_change_passwd_should_be_forced_to_change_its_password
138 141 User.find_by_login('jsmith').update_attribute :must_change_passwd, true
139 142
140 143 post '/login', :username => 'jsmith', :password => 'jsmith'
141 144 assert_redirected_to '/my/page'
142 145 follow_redirect!
143 146 assert_redirected_to '/my/password'
144 147
145 148 get '/issues'
146 149 assert_redirected_to '/my/password'
147 150 end
148 151
149 152 def test_flash_message_should_use_user_language_when_redirecting_user_for_password_change
150 153 user = User.find_by_login('jsmith')
151 154 user.must_change_passwd = true
152 155 user.language = 'it'
153 156 user.save!
154 157
155 158 post '/login', :username => 'jsmith', :password => 'jsmith'
156 159 assert_redirected_to '/my/page'
157 160 follow_redirect!
158 161 assert_redirected_to '/my/password'
159 162 follow_redirect!
160 163
161 164 assert_select 'div.error', :text => /richiesto che sia cambiata/
162 165 end
163 166
164 167 def test_user_with_must_change_passwd_should_be_able_to_change_its_password
165 168 User.find_by_login('jsmith').update_attribute :must_change_passwd, true
166 169
167 170 post '/login', :username => 'jsmith', :password => 'jsmith'
168 171 assert_redirected_to '/my/page'
169 172 follow_redirect!
170 173 assert_redirected_to '/my/password'
171 174 follow_redirect!
172 175 assert_response :success
173 176 post '/my/password', :password => 'jsmith', :new_password => 'newpassword', :new_password_confirmation => 'newpassword'
174 177 assert_redirected_to '/my/account'
175 178 follow_redirect!
176 179 assert_response :success
177 180
178 181 assert_equal false, User.find_by_login('jsmith').must_change_passwd?
179 182 end
180 183
181 184 def test_user_with_expired_password_should_be_forced_to_change_its_password
182 185 User.find_by_login('jsmith').update_attribute :passwd_changed_on, 14.days.ago
183 186
184 187 with_settings :password_max_age => 7 do
185 188 post '/login', :username => 'jsmith', :password => 'jsmith'
186 189 assert_redirected_to '/my/page'
187 190 follow_redirect!
188 191 assert_redirected_to '/my/password'
189 192
190 193 get '/issues'
191 194 assert_redirected_to '/my/password'
192 195 end
193 196 end
194 197
195 198 def test_user_with_expired_password_should_be_able_to_change_its_password
196 199 User.find_by_login('jsmith').update_attribute :passwd_changed_on, 14.days.ago
197 200
198 201 with_settings :password_max_age => 7 do
199 202 post '/login', :username => 'jsmith', :password => 'jsmith'
200 203 assert_redirected_to '/my/page'
201 204 follow_redirect!
202 205 assert_redirected_to '/my/password'
203 206 follow_redirect!
204 207 assert_response :success
205 208 post '/my/password', :password => 'jsmith', :new_password => 'newpassword', :new_password_confirmation => 'newpassword'
206 209 assert_redirected_to '/my/account'
207 210 follow_redirect!
208 211 assert_response :success
209 212
210 213 assert_equal false, User.find_by_login('jsmith').must_change_passwd?
211 214 end
212 215
213 216 end
214 217
215 218 def test_register_with_automatic_activation
216 219 Setting.self_registration = '3'
217 220
218 221 get '/account/register'
219 222 assert_response :success
220 223 assert_template 'account/register'
221 224
222 225 post '/account/register',
223 226 :user => {:login => "newuser", :language => "en",
224 227 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
225 228 :password => "newpass123", :password_confirmation => "newpass123"}
226 229 assert_redirected_to '/my/account'
227 230 follow_redirect!
228 231 assert_response :success
229 232 assert_template 'my/account'
230 233
231 234 user = User.find_by_login('newuser')
232 235 assert_not_nil user
233 236 assert user.active?
234 237 assert_not_nil user.last_login_on
235 238 end
236 239
237 240 def test_register_with_manual_activation
238 241 Setting.self_registration = '2'
239 242
240 243 post '/account/register',
241 244 :user => {:login => "newuser", :language => "en",
242 245 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
243 246 :password => "newpass123", :password_confirmation => "newpass123"}
244 247 assert_redirected_to '/login'
245 248 assert !User.find_by_login('newuser').active?
246 249 end
247 250
248 251 def test_register_with_email_activation
249 252 Setting.self_registration = '1'
250 253 Token.delete_all
251 254
252 255 post '/account/register',
253 256 :user => {:login => "newuser", :language => "en",
254 257 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
255 258 :password => "newpass123", :password_confirmation => "newpass123"}
256 259 assert_redirected_to '/login'
257 260 assert !User.find_by_login('newuser').active?
258 261
259 262 token = Token.first
260 263 assert_equal 'register', token.action
261 264 assert_equal 'newuser@foo.bar', token.user.mail
262 265 assert !token.expired?
263 266
264 267 get '/account/activate', :token => token.value
265 268 assert_redirected_to '/login'
266 269 log_user('newuser', 'newpass123')
267 270 end
268 271
269 272 def test_onthefly_registration
270 273 # disable registration
271 274 Setting.self_registration = '0'
272 275 AuthSource.expects(:authenticate).returns(
273 276 {:login => 'foo', :firstname => 'Foo', :lastname => 'Smith',
274 277 :mail => 'foo@bar.com', :auth_source_id => 66})
275 278
276 279 post '/login', :username => 'foo', :password => 'bar'
277 280 assert_redirected_to '/my/page'
278 281
279 282 user = User.find_by_login('foo')
280 283 assert user.is_a?(User)
281 284 assert_equal 66, user.auth_source_id
282 285 assert user.hashed_password.blank?
283 286 end
284 287
285 288 def test_onthefly_registration_with_invalid_attributes
286 289 # disable registration
287 290 Setting.self_registration = '0'
288 291 AuthSource.expects(:authenticate).returns(
289 292 {:login => 'foo', :lastname => 'Smith', :auth_source_id => 66})
290 293
291 294 post '/login', :username => 'foo', :password => 'bar'
292 295 assert_response :success
293 296 assert_template 'account/register'
294 297 assert_select 'input[name=?][value=""]', 'user[firstname]'
295 298 assert_select 'input[name=?][value=Smith]', 'user[lastname]'
296 299 assert_select 'input[name=?]', 'user[login]', 0
297 300 assert_select 'input[name=?]', 'user[password]', 0
298 301
299 302 post '/account/register',
300 303 :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
301 304 assert_redirected_to '/my/account'
302 305
303 306 user = User.find_by_login('foo')
304 307 assert user.is_a?(User)
305 308 assert_equal 66, user.auth_source_id
306 309 assert user.hashed_password.blank?
307 310 end
308 311
309 312 def test_registered_user_should_be_able_to_get_a_new_activation_email
310 313 Token.delete_all
311 314
312 315 with_settings :self_registration => '1', :default_language => 'en' do
313 316 # register a new account
314 317 assert_difference 'User.count' do
315 318 assert_difference 'Token.count' do
316 319 post '/account/register',
317 320 :user => {:login => "newuser", :language => "en",
318 321 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
319 322 :password => "newpass123", :password_confirmation => "newpass123"}
320 323 end
321 324 end
322 325 user = User.order('id desc').first
323 326 assert_equal User::STATUS_REGISTERED, user.status
324 327 reset!
325 328
326 329 # try to use "lost password"
327 330 assert_no_difference 'ActionMailer::Base.deliveries.size' do
328 331 post '/account/lost_password', :mail => 'newuser@foo.bar'
329 332 end
330 333 assert_redirected_to '/account/lost_password'
331 334 follow_redirect!
332 335 assert_response :success
333 336 assert_select 'div.flash', :text => /new activation email/
334 337 assert_select 'div.flash a[href="/account/activation_email"]'
335 338
336 339 # request a new action activation email
337 340 assert_difference 'ActionMailer::Base.deliveries.size' do
338 341 get '/account/activation_email'
339 342 end
340 343 assert_redirected_to '/login'
341 344 token = Token.order('id desc').first
342 345 activation_path = "/account/activate?token=#{token.value}"
343 346 assert_include activation_path, mail_body(ActionMailer::Base.deliveries.last)
344 347
345 348 # activate the account
346 349 get activation_path
347 350 assert_redirected_to '/login'
348 351
349 352 post '/login', :username => 'newuser', :password => 'newpass123'
350 353 assert_redirected_to '/my/page'
351 354 end
352 355 end
353 356 end
General Comments 0
You need to be logged in to leave comments. Login now