##// END OF EJS Templates
Merged r16287 to r16289 (#24416)....
Jean-Philippe Lang -
r15917:a170c3d93c95
parent child
Show More
@@ -1,359 +1,367
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 flash[:notice] = l(:notice_account_password_updated)
77 85 redirect_to signin_path
78 86 return
79 87 end
80 88 end
81 89 render :template => "account/password_recovery"
82 90 return
83 91 else
84 92 if request.post?
85 93 email = params[:mail].to_s
86 94 user = User.find_by_mail(email)
87 95 # user not found
88 96 unless user
89 97 flash.now[:error] = l(:notice_account_unknown_email)
90 98 return
91 99 end
92 100 unless user.active?
93 101 handle_inactive_user(user, lost_password_path)
94 102 return
95 103 end
96 104 # user cannot change its password
97 105 unless user.change_password_allowed?
98 106 flash.now[:error] = l(:notice_can_t_change_password)
99 107 return
100 108 end
101 109 # create a new token for password recovery
102 110 token = Token.new(:user => user, :action => "recovery")
103 111 if token.save
104 112 # Don't use the param to send the email
105 113 recipent = user.mails.detect {|e| email.casecmp(e) == 0} || user.mail
106 114 Mailer.lost_password(token, recipent).deliver
107 115 flash[:notice] = l(:notice_account_lost_email_sent)
108 116 redirect_to signin_path
109 117 return
110 118 end
111 119 end
112 120 end
113 121 end
114 122
115 123 # User self-registration
116 124 def register
117 125 (redirect_to(home_url); return) unless Setting.self_registration? || session[:auth_source_registration]
118 126 if request.get?
119 127 session[:auth_source_registration] = nil
120 128 @user = User.new(:language => current_language.to_s)
121 129 else
122 130 user_params = params[:user] || {}
123 131 @user = User.new
124 132 @user.safe_attributes = user_params
125 133 @user.admin = false
126 134 @user.register
127 135 if session[:auth_source_registration]
128 136 @user.activate
129 137 @user.login = session[:auth_source_registration][:login]
130 138 @user.auth_source_id = session[:auth_source_registration][:auth_source_id]
131 139 if @user.save
132 140 session[:auth_source_registration] = nil
133 141 self.logged_user = @user
134 142 flash[:notice] = l(:notice_account_activated)
135 143 redirect_to my_account_path
136 144 end
137 145 else
138 146 @user.login = params[:user][:login]
139 147 unless user_params[:identity_url].present? && user_params[:password].blank? && user_params[:password_confirmation].blank?
140 148 @user.password, @user.password_confirmation = user_params[:password], user_params[:password_confirmation]
141 149 end
142 150
143 151 case Setting.self_registration
144 152 when '1'
145 153 register_by_email_activation(@user)
146 154 when '3'
147 155 register_automatically(@user)
148 156 else
149 157 register_manually_by_administrator(@user)
150 158 end
151 159 end
152 160 end
153 161 end
154 162
155 163 # Token based account activation
156 164 def activate
157 165 (redirect_to(home_url); return) unless Setting.self_registration? && params[:token].present?
158 166 token = Token.find_token('register', params[:token].to_s)
159 167 (redirect_to(home_url); return) unless token and !token.expired?
160 168 user = token.user
161 169 (redirect_to(home_url); return) unless user.registered?
162 170 user.activate
163 171 if user.save
164 172 token.destroy
165 173 flash[:notice] = l(:notice_account_activated)
166 174 end
167 175 redirect_to signin_path
168 176 end
169 177
170 178 # Sends a new account activation email
171 179 def activation_email
172 180 if session[:registered_user_id] && Setting.self_registration == '1'
173 181 user_id = session.delete(:registered_user_id).to_i
174 182 user = User.find_by_id(user_id)
175 183 if user && user.registered?
176 184 register_by_email_activation(user)
177 185 return
178 186 end
179 187 end
180 188 redirect_to(home_url)
181 189 end
182 190
183 191 private
184 192
185 193 def authenticate_user
186 194 if Setting.openid? && using_open_id?
187 195 open_id_authenticate(params[:openid_url])
188 196 else
189 197 password_authentication
190 198 end
191 199 end
192 200
193 201 def password_authentication
194 202 user = User.try_to_login(params[:username], params[:password], false)
195 203
196 204 if user.nil?
197 205 invalid_credentials
198 206 elsif user.new_record?
199 207 onthefly_creation_failed(user, {:login => user.login, :auth_source_id => user.auth_source_id })
200 208 else
201 209 # Valid user
202 210 if user.active?
203 211 successful_authentication(user)
204 212 update_sudo_timestamp! # activate Sudo Mode
205 213 else
206 214 handle_inactive_user(user)
207 215 end
208 216 end
209 217 end
210 218
211 219 def open_id_authenticate(openid_url)
212 220 back_url = signin_url(:autologin => params[:autologin])
213 221 authenticate_with_open_id(
214 222 openid_url, :required => [:nickname, :fullname, :email],
215 223 :return_to => back_url, :method => :post
216 224 ) do |result, identity_url, registration|
217 225 if result.successful?
218 226 user = User.find_or_initialize_by_identity_url(identity_url)
219 227 if user.new_record?
220 228 # Self-registration off
221 229 (redirect_to(home_url); return) unless Setting.self_registration?
222 230 # Create on the fly
223 231 user.login = registration['nickname'] unless registration['nickname'].nil?
224 232 user.mail = registration['email'] unless registration['email'].nil?
225 233 user.firstname, user.lastname = registration['fullname'].split(' ') unless registration['fullname'].nil?
226 234 user.random_password
227 235 user.register
228 236 case Setting.self_registration
229 237 when '1'
230 238 register_by_email_activation(user) do
231 239 onthefly_creation_failed(user)
232 240 end
233 241 when '3'
234 242 register_automatically(user) do
235 243 onthefly_creation_failed(user)
236 244 end
237 245 else
238 246 register_manually_by_administrator(user) do
239 247 onthefly_creation_failed(user)
240 248 end
241 249 end
242 250 else
243 251 # Existing record
244 252 if user.active?
245 253 successful_authentication(user)
246 254 else
247 255 handle_inactive_user(user)
248 256 end
249 257 end
250 258 end
251 259 end
252 260 end
253 261
254 262 def successful_authentication(user)
255 263 logger.info "Successful authentication for '#{user.login}' from #{request.remote_ip} at #{Time.now.utc}"
256 264 # Valid user
257 265 self.logged_user = user
258 266 # generate a key and set cookie if autologin
259 267 if params[:autologin] && Setting.autologin?
260 268 set_autologin_cookie(user)
261 269 end
262 270 call_hook(:controller_account_success_authentication_after, {:user => user })
263 271 redirect_back_or_default my_page_path
264 272 end
265 273
266 274 def set_autologin_cookie(user)
267 275 token = Token.create(:user => user, :action => 'autologin')
268 276 secure = Redmine::Configuration['autologin_cookie_secure']
269 277 if secure.nil?
270 278 secure = request.ssl?
271 279 end
272 280 cookie_options = {
273 281 :value => token.value,
274 282 :expires => 1.year.from_now,
275 283 :path => (Redmine::Configuration['autologin_cookie_path'] || RedmineApp::Application.config.relative_url_root || '/'),
276 284 :secure => secure,
277 285 :httponly => true
278 286 }
279 287 cookies[autologin_cookie_name] = cookie_options
280 288 end
281 289
282 290 # Onthefly creation failed, display the registration form to fill/fix attributes
283 291 def onthefly_creation_failed(user, auth_source_options = { })
284 292 @user = user
285 293 session[:auth_source_registration] = auth_source_options unless auth_source_options.empty?
286 294 render :action => 'register'
287 295 end
288 296
289 297 def invalid_credentials
290 298 logger.warn "Failed login for '#{params[:username]}' from #{request.remote_ip} at #{Time.now.utc}"
291 299 flash.now[:error] = l(:notice_account_invalid_creditentials)
292 300 end
293 301
294 302 # Register a user for email activation.
295 303 #
296 304 # Pass a block for behavior when a user fails to save
297 305 def register_by_email_activation(user, &block)
298 306 token = Token.new(:user => user, :action => "register")
299 307 if user.save and token.save
300 308 Mailer.register(token).deliver
301 309 flash[:notice] = l(:notice_account_register_done, :email => ERB::Util.h(user.mail))
302 310 redirect_to signin_path
303 311 else
304 312 yield if block_given?
305 313 end
306 314 end
307 315
308 316 # Automatically register a user
309 317 #
310 318 # Pass a block for behavior when a user fails to save
311 319 def register_automatically(user, &block)
312 320 # Automatic activation
313 321 user.activate
314 322 user.last_login_on = Time.now
315 323 if user.save
316 324 self.logged_user = user
317 325 flash[:notice] = l(:notice_account_activated)
318 326 redirect_to my_account_path
319 327 else
320 328 yield if block_given?
321 329 end
322 330 end
323 331
324 332 # Manual activation by the administrator
325 333 #
326 334 # Pass a block for behavior when a user fails to save
327 335 def register_manually_by_administrator(user, &block)
328 336 if user.save
329 337 # Sends an email to the administrators
330 338 Mailer.account_activation_request(user).deliver
331 339 account_pending(user)
332 340 else
333 341 yield if block_given?
334 342 end
335 343 end
336 344
337 345 def handle_inactive_user(user, redirect_path=signin_path)
338 346 if user.registered?
339 347 account_pending(user, redirect_path)
340 348 else
341 349 account_locked(user, redirect_path)
342 350 end
343 351 end
344 352
345 353 def account_pending(user, redirect_path=signin_path)
346 354 if Setting.self_registration == '1'
347 355 flash[:error] = l(:notice_account_not_activated_yet, :url => activation_email_path)
348 356 session[:registered_user_id] = user.id
349 357 else
350 358 flash[:error] = l(:notice_account_pending)
351 359 end
352 360 redirect_to redirect_path
353 361 end
354 362
355 363 def account_locked(user, redirect_path=signin_path)
356 364 flash[:error] = l(:notice_account_locked)
357 365 redirect_to redirect_path
358 366 end
359 367 end
@@ -1,434 +1,445
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 # See integration/account_test.rb for the full test
251 251 def test_post_register_with_registration_on
252 252 with_settings :self_registration => '3' do
253 253 assert_difference 'User.count' do
254 254 post :register, :user => {
255 255 :login => 'register',
256 256 :password => 'secret123',
257 257 :password_confirmation => 'secret123',
258 258 :firstname => 'John',
259 259 :lastname => 'Doe',
260 260 :mail => 'register@example.com'
261 261 }
262 262 assert_redirected_to '/my/account'
263 263 end
264 264 user = User.order('id DESC').first
265 265 assert_equal 'register', user.login
266 266 assert_equal 'John', user.firstname
267 267 assert_equal 'Doe', user.lastname
268 268 assert_equal 'register@example.com', user.mail
269 269 assert user.check_password?('secret123')
270 270 assert user.active?
271 271 end
272 272 end
273 273
274 274 def test_post_register_with_registration_off_should_redirect
275 275 with_settings :self_registration => '0' do
276 276 assert_no_difference 'User.count' do
277 277 post :register, :user => {
278 278 :login => 'register',
279 279 :password => 'test',
280 280 :password_confirmation => 'test',
281 281 :firstname => 'John',
282 282 :lastname => 'Doe',
283 283 :mail => 'register@example.com'
284 284 }
285 285 assert_redirected_to '/'
286 286 end
287 287 end
288 288 end
289 289
290 290 def test_get_lost_password_should_display_lost_password_form
291 291 get :lost_password
292 292 assert_response :success
293 293 assert_select 'input[name=mail]'
294 294 end
295 295
296 296 def test_lost_password_for_active_user_should_create_a_token
297 297 Token.delete_all
298 298 ActionMailer::Base.deliveries.clear
299 299 assert_difference 'ActionMailer::Base.deliveries.size' do
300 300 assert_difference 'Token.count' do
301 301 with_settings :host_name => 'mydomain.foo', :protocol => 'http' do
302 302 post :lost_password, :mail => 'JSmith@somenet.foo'
303 303 assert_redirected_to '/login'
304 304 end
305 305 end
306 306 end
307 307
308 308 token = Token.order('id DESC').first
309 309 assert_equal User.find(2), token.user
310 310 assert_equal 'recovery', token.action
311 311
312 312 assert_select_email do
313 313 assert_select "a[href=?]", "http://mydomain.foo/account/lost_password?token=#{token.value}"
314 314 end
315 315 end
316 316
317 317 def test_lost_password_using_additional_email_address_should_send_email_to_the_address
318 318 EmailAddress.create!(:user_id => 2, :address => 'anotherAddress@foo.bar')
319 319 Token.delete_all
320 320
321 321 assert_difference 'ActionMailer::Base.deliveries.size' do
322 322 assert_difference 'Token.count' do
323 323 post :lost_password, :mail => 'ANOTHERaddress@foo.bar'
324 324 assert_redirected_to '/login'
325 325 end
326 326 end
327 327 mail = ActionMailer::Base.deliveries.last
328 328 assert_equal ['anotherAddress@foo.bar'], mail.bcc
329 329 end
330 330
331 331 def test_lost_password_for_unknown_user_should_fail
332 332 Token.delete_all
333 333 assert_no_difference 'Token.count' do
334 334 post :lost_password, :mail => 'invalid@somenet.foo'
335 335 assert_response :success
336 336 end
337 337 end
338 338
339 339 def test_lost_password_for_non_active_user_should_fail
340 340 Token.delete_all
341 341 assert User.find(2).lock!
342 342
343 343 assert_no_difference 'Token.count' do
344 344 post :lost_password, :mail => 'JSmith@somenet.foo'
345 345 assert_redirected_to '/account/lost_password'
346 346 end
347 347 end
348 348
349 349 def test_lost_password_for_user_who_cannot_change_password_should_fail
350 350 User.any_instance.stubs(:change_password_allowed?).returns(false)
351 351
352 352 assert_no_difference 'Token.count' do
353 353 post :lost_password, :mail => 'JSmith@somenet.foo'
354 354 assert_response :success
355 355 end
356 356 end
357 357
358 def test_get_lost_password_with_token_should_display_the_password_recovery_form
358 def test_get_lost_password_with_token_should_redirect_with_token_in_session
359 359 user = User.find(2)
360 360 token = Token.create!(:action => 'recovery', :user => user)
361 361
362 362 get :lost_password, :token => token.value
363 assert_redirected_to '/account/lost_password'
364
365 assert_equal token.value, request.session[:password_recovery_token]
366 end
367
368 def test_get_lost_password_with_token_in_session_should_display_the_password_recovery_form
369 user = User.find(2)
370 token = Token.create!(:action => 'recovery', :user => user)
371 request.session[:password_recovery_token] = token.value
372
373 get :lost_password
363 374 assert_response :success
364 375 assert_template 'password_recovery'
365 376
366 377 assert_select 'input[type=hidden][name=token][value=?]', token.value
367 378 end
368 379
369 380 def test_get_lost_password_with_invalid_token_should_redirect
370 381 get :lost_password, :token => "abcdef"
371 382 assert_redirected_to '/'
372 383 end
373 384
374 385 def test_post_lost_password_with_token_should_change_the_user_password
375 386 user = User.find(2)
376 387 token = Token.create!(:action => 'recovery', :user => user)
377 388
378 389 post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
379 390 assert_redirected_to '/login'
380 391 user.reload
381 392 assert user.check_password?('newpass123')
382 393 assert_nil Token.find_by_id(token.id), "Token was not deleted"
383 394 end
384 395
385 396 def test_post_lost_password_with_token_for_non_active_user_should_fail
386 397 user = User.find(2)
387 398 token = Token.create!(:action => 'recovery', :user => user)
388 399 user.lock!
389 400
390 401 post :lost_password, :token => token.value, :new_password => 'newpass123', :new_password_confirmation => 'newpass123'
391 402 assert_redirected_to '/'
392 403 assert ! user.check_password?('newpass123')
393 404 end
394 405
395 406 def test_post_lost_password_with_token_and_password_confirmation_failure_should_redisplay_the_form
396 407 user = User.find(2)
397 408 token = Token.create!(:action => 'recovery', :user => user)
398 409
399 410 post :lost_password, :token => token.value, :new_password => 'newpass', :new_password_confirmation => 'wrongpass'
400 411 assert_response :success
401 412 assert_template 'password_recovery'
402 413 assert_not_nil Token.find_by_id(token.id), "Token was deleted"
403 414
404 415 assert_select 'input[type=hidden][name=token][value=?]', token.value
405 416 end
406 417
407 418 def test_post_lost_password_with_invalid_token_should_redirect
408 419 post :lost_password, :token => "abcdef", :new_password => 'newpass', :new_password_confirmation => 'newpass'
409 420 assert_redirected_to '/'
410 421 end
411 422
412 423 def test_activation_email_should_send_an_activation_email
413 424 User.find(2).update_attribute :status, User::STATUS_REGISTERED
414 425 @request.session[:registered_user_id] = 2
415 426
416 427 with_settings :self_registration => '1' do
417 428 assert_difference 'ActionMailer::Base.deliveries.size' do
418 429 get :activation_email
419 430 assert_redirected_to '/login'
420 431 end
421 432 end
422 433 end
423 434
424 435 def test_activation_email_without_session_data_should_fail
425 436 User.find(2).update_attribute :status, User::STATUS_REGISTERED
426 437
427 438 with_settings :self_registration => '1' do
428 439 assert_no_difference 'ActionMailer::Base.deliveries.size' do
429 440 get :activation_email
430 441 assert_redirected_to '/'
431 442 end
432 443 end
433 444 end
434 445 end
@@ -1,338 +1,341
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_user_with_must_change_passwd_should_be_able_to_change_its_password
150 153 User.find_by_login('jsmith').update_attribute :must_change_passwd, true
151 154
152 155 post '/login', :username => 'jsmith', :password => 'jsmith'
153 156 assert_redirected_to '/my/page'
154 157 follow_redirect!
155 158 assert_redirected_to '/my/password'
156 159 follow_redirect!
157 160 assert_response :success
158 161 post '/my/password', :password => 'jsmith', :new_password => 'newpassword', :new_password_confirmation => 'newpassword'
159 162 assert_redirected_to '/my/account'
160 163 follow_redirect!
161 164 assert_response :success
162 165
163 166 assert_equal false, User.find_by_login('jsmith').must_change_passwd?
164 167 end
165 168
166 169 def test_user_with_expired_password_should_be_forced_to_change_its_password
167 170 User.find_by_login('jsmith').update_attribute :passwd_changed_on, 14.days.ago
168 171
169 172 with_settings :password_max_age => 7 do
170 173 post '/login', :username => 'jsmith', :password => 'jsmith'
171 174 assert_redirected_to '/my/page'
172 175 follow_redirect!
173 176 assert_redirected_to '/my/password'
174 177
175 178 get '/issues'
176 179 assert_redirected_to '/my/password'
177 180 end
178 181 end
179 182
180 183 def test_user_with_expired_password_should_be_able_to_change_its_password
181 184 User.find_by_login('jsmith').update_attribute :passwd_changed_on, 14.days.ago
182 185
183 186 with_settings :password_max_age => 7 do
184 187 post '/login', :username => 'jsmith', :password => 'jsmith'
185 188 assert_redirected_to '/my/page'
186 189 follow_redirect!
187 190 assert_redirected_to '/my/password'
188 191 follow_redirect!
189 192 assert_response :success
190 193 post '/my/password', :password => 'jsmith', :new_password => 'newpassword', :new_password_confirmation => 'newpassword'
191 194 assert_redirected_to '/my/account'
192 195 follow_redirect!
193 196 assert_response :success
194 197
195 198 assert_equal false, User.find_by_login('jsmith').must_change_passwd?
196 199 end
197 200
198 201 end
199 202
200 203 def test_register_with_automatic_activation
201 204 Setting.self_registration = '3'
202 205
203 206 get '/account/register'
204 207 assert_response :success
205 208 assert_template 'account/register'
206 209
207 210 post '/account/register',
208 211 :user => {:login => "newuser", :language => "en",
209 212 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
210 213 :password => "newpass123", :password_confirmation => "newpass123"}
211 214 assert_redirected_to '/my/account'
212 215 follow_redirect!
213 216 assert_response :success
214 217 assert_template 'my/account'
215 218
216 219 user = User.find_by_login('newuser')
217 220 assert_not_nil user
218 221 assert user.active?
219 222 assert_not_nil user.last_login_on
220 223 end
221 224
222 225 def test_register_with_manual_activation
223 226 Setting.self_registration = '2'
224 227
225 228 post '/account/register',
226 229 :user => {:login => "newuser", :language => "en",
227 230 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
228 231 :password => "newpass123", :password_confirmation => "newpass123"}
229 232 assert_redirected_to '/login'
230 233 assert !User.find_by_login('newuser').active?
231 234 end
232 235
233 236 def test_register_with_email_activation
234 237 Setting.self_registration = '1'
235 238 Token.delete_all
236 239
237 240 post '/account/register',
238 241 :user => {:login => "newuser", :language => "en",
239 242 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
240 243 :password => "newpass123", :password_confirmation => "newpass123"}
241 244 assert_redirected_to '/login'
242 245 assert !User.find_by_login('newuser').active?
243 246
244 247 token = Token.first
245 248 assert_equal 'register', token.action
246 249 assert_equal 'newuser@foo.bar', token.user.mail
247 250 assert !token.expired?
248 251
249 252 get '/account/activate', :token => token.value
250 253 assert_redirected_to '/login'
251 254 log_user('newuser', 'newpass123')
252 255 end
253 256
254 257 def test_onthefly_registration
255 258 # disable registration
256 259 Setting.self_registration = '0'
257 260 AuthSource.expects(:authenticate).returns(
258 261 {:login => 'foo', :firstname => 'Foo', :lastname => 'Smith',
259 262 :mail => 'foo@bar.com', :auth_source_id => 66})
260 263
261 264 post '/login', :username => 'foo', :password => 'bar'
262 265 assert_redirected_to '/my/page'
263 266
264 267 user = User.find_by_login('foo')
265 268 assert user.is_a?(User)
266 269 assert_equal 66, user.auth_source_id
267 270 assert user.hashed_password.blank?
268 271 end
269 272
270 273 def test_onthefly_registration_with_invalid_attributes
271 274 # disable registration
272 275 Setting.self_registration = '0'
273 276 AuthSource.expects(:authenticate).returns(
274 277 {:login => 'foo', :lastname => 'Smith', :auth_source_id => 66})
275 278
276 279 post '/login', :username => 'foo', :password => 'bar'
277 280 assert_response :success
278 281 assert_template 'account/register'
279 282 assert_select 'input[name=?][value=""]', 'user[firstname]'
280 283 assert_select 'input[name=?][value=Smith]', 'user[lastname]'
281 284 assert_select 'input[name=?]', 'user[login]', 0
282 285 assert_select 'input[name=?]', 'user[password]', 0
283 286
284 287 post '/account/register',
285 288 :user => {:firstname => 'Foo', :lastname => 'Smith', :mail => 'foo@bar.com'}
286 289 assert_redirected_to '/my/account'
287 290
288 291 user = User.find_by_login('foo')
289 292 assert user.is_a?(User)
290 293 assert_equal 66, user.auth_source_id
291 294 assert user.hashed_password.blank?
292 295 end
293 296
294 297 def test_registered_user_should_be_able_to_get_a_new_activation_email
295 298 Token.delete_all
296 299
297 300 with_settings :self_registration => '1', :default_language => 'en' do
298 301 # register a new account
299 302 assert_difference 'User.count' do
300 303 assert_difference 'Token.count' do
301 304 post '/account/register',
302 305 :user => {:login => "newuser", :language => "en",
303 306 :firstname => "New", :lastname => "User", :mail => "newuser@foo.bar",
304 307 :password => "newpass123", :password_confirmation => "newpass123"}
305 308 end
306 309 end
307 310 user = User.order('id desc').first
308 311 assert_equal User::STATUS_REGISTERED, user.status
309 312 reset!
310 313
311 314 # try to use "lost password"
312 315 assert_no_difference 'ActionMailer::Base.deliveries.size' do
313 316 post '/account/lost_password', :mail => 'newuser@foo.bar'
314 317 end
315 318 assert_redirected_to '/account/lost_password'
316 319 follow_redirect!
317 320 assert_response :success
318 321 assert_select 'div.flash', :text => /new activation email/
319 322 assert_select 'div.flash a[href="/account/activation_email"]'
320 323
321 324 # request a new action activation email
322 325 assert_difference 'ActionMailer::Base.deliveries.size' do
323 326 get '/account/activation_email'
324 327 end
325 328 assert_redirected_to '/login'
326 329 token = Token.order('id desc').first
327 330 activation_path = "/account/activate?token=#{token.value}"
328 331 assert_include activation_path, mail_body(ActionMailer::Base.deliveries.last)
329 332
330 333 # activate the account
331 334 get activation_path
332 335 assert_redirected_to '/login'
333 336
334 337 post '/login', :username => 'newuser', :password => 'newpass123'
335 338 assert_redirected_to '/my/page'
336 339 end
337 340 end
338 341 end
General Comments 0
You need to be logged in to leave comments. Login now