@@ -0,0 +1,10 | |||
|
1 | class AddTokensUpdatedOn < ActiveRecord::Migration | |
|
2 | def self.up | |
|
3 | add_column :tokens, :updated_on, :timestamp | |
|
4 | Token.update_all("updated_on = created_on") | |
|
5 | end | |
|
6 | ||
|
7 | def self.down | |
|
8 | remove_column :tokens, :updated_on | |
|
9 | end | |
|
10 | end |
@@ -0,0 +1,97 | |||
|
1 | # Redmine - project management software | |
|
2 | # Copyright (C) 2006-2015 Jean-Philippe Lang | |
|
3 | # | |
|
4 | # This program is free software; you can redistribute it and/or | |
|
5 | # modify it under the terms of the GNU General Public License | |
|
6 | # as published by the Free Software Foundation; either version 2 | |
|
7 | # of the License, or (at your option) any later version. | |
|
8 | # | |
|
9 | # This program is distributed in the hope that it will be useful, | |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
12 | # GNU General Public License for more details. | |
|
13 | # | |
|
14 | # You should have received a copy of the GNU General Public License | |
|
15 | # along with this program; if not, write to the Free Software | |
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
|
17 | ||
|
18 | require File.expand_path('../../test_helper', __FILE__) | |
|
19 | ||
|
20 | class SessionsTest < Redmine::IntegrationTest | |
|
21 | fixtures :users, :email_addresses, :roles | |
|
22 | ||
|
23 | def setup | |
|
24 | Rails.application.config.redmine_verify_sessions = true | |
|
25 | end | |
|
26 | ||
|
27 | def teardown | |
|
28 | Rails.application.config.redmine_verify_sessions = false | |
|
29 | end | |
|
30 | ||
|
31 | def test_change_password_kills_sessions | |
|
32 | log_user('jsmith', 'jsmith') | |
|
33 | ||
|
34 | jsmith = User.find(2) | |
|
35 | jsmith.password = "somenewpassword" | |
|
36 | jsmith.save! | |
|
37 | ||
|
38 | get '/my/account' | |
|
39 | assert_response 302 | |
|
40 | assert flash[:error].match(/Your session has expired/) | |
|
41 | end | |
|
42 | ||
|
43 | def test_lock_user_kills_sessions | |
|
44 | log_user('jsmith', 'jsmith') | |
|
45 | ||
|
46 | jsmith = User.find(2) | |
|
47 | assert jsmith.lock! | |
|
48 | assert jsmith.activate! | |
|
49 | ||
|
50 | get '/my/account' | |
|
51 | assert_response 302 | |
|
52 | assert flash[:error].match(/Your session has expired/) | |
|
53 | end | |
|
54 | ||
|
55 | def test_update_user_does_not_kill_sessions | |
|
56 | log_user('jsmith', 'jsmith') | |
|
57 | ||
|
58 | jsmith = User.find(2) | |
|
59 | jsmith.firstname = 'Robert' | |
|
60 | jsmith.save! | |
|
61 | ||
|
62 | get '/my/account' | |
|
63 | assert_response 200 | |
|
64 | end | |
|
65 | ||
|
66 | def test_change_password_generates_a_new_token_for_current_session | |
|
67 | log_user('jsmith', 'jsmith') | |
|
68 | assert_not_nil token = session[:tk] | |
|
69 | ||
|
70 | get '/my/password' | |
|
71 | assert_response 200 | |
|
72 | post '/my/password', :password => 'jsmith', | |
|
73 | :new_password => 'secret123', | |
|
74 | :new_password_confirmation => 'secret123' | |
|
75 | assert_response 302 | |
|
76 | assert_not_equal token, session[:tk] | |
|
77 | ||
|
78 | get '/my/account' | |
|
79 | assert_response 200 | |
|
80 | end | |
|
81 | ||
|
82 | def test_simultaneous_sessions_should_be_valid | |
|
83 | first = open_session do |session| | |
|
84 | session.post "/login", :username => 'jsmith', :password => 'jsmith' | |
|
85 | end | |
|
86 | other = open_session do |session| | |
|
87 | session.post "/login", :username => 'jsmith', :password => 'jsmith' | |
|
88 | end | |
|
89 | ||
|
90 | first.get '/my/account' | |
|
91 | assert_equal 200, first.response.response_code | |
|
92 | first.post '/logout' | |
|
93 | ||
|
94 | other.get '/my/account' | |
|
95 | assert_equal 200, other.response.response_code | |
|
96 | end | |
|
97 | end |
@@ -51,7 +51,7 class ApplicationController < ActionController::Base | |||
|
51 | 51 | end |
|
52 | 52 | end |
|
53 | 53 | |
|
54 |
before_filter :session_expiration, :user_setup |
|
|
54 | before_filter :session_expiration, :user_setup, :check_if_login_required, :check_password_change, :set_localization | |
|
55 | 55 | |
|
56 | 56 | rescue_from ::Unauthorized, :with => :deny_access |
|
57 | 57 | rescue_from ::ActionView::MissingTemplate, :with => :missing_template |
@@ -63,36 +63,23 class ApplicationController < ActionController::Base | |||
|
63 | 63 | include Redmine::SudoMode::Controller |
|
64 | 64 | |
|
65 | 65 | def session_expiration |
|
66 | if session[:user_id] | |
|
66 | if session[:user_id] && Rails.application.config.redmine_verify_sessions != false | |
|
67 | 67 | if session_expired? && !try_to_autologin |
|
68 | 68 | set_localization(User.active.find_by_id(session[:user_id])) |
|
69 | 69 | self.logged_user = nil |
|
70 | 70 | flash[:error] = l(:error_session_expired) |
|
71 | 71 | require_login |
|
72 | else | |
|
73 | session[:atime] = Time.now.utc.to_i | |
|
74 | 72 | end |
|
75 | 73 | end |
|
76 | 74 | end |
|
77 | 75 | |
|
78 | 76 | def session_expired? |
|
79 | if Setting.session_lifetime? | |
|
80 | unless session[:ctime] && (Time.now.utc.to_i - session[:ctime].to_i <= Setting.session_lifetime.to_i * 60) | |
|
81 | return true | |
|
82 | end | |
|
83 | end | |
|
84 | if Setting.session_timeout? | |
|
85 | unless session[:atime] && (Time.now.utc.to_i - session[:atime].to_i <= Setting.session_timeout.to_i * 60) | |
|
86 | return true | |
|
87 | end | |
|
88 | end | |
|
89 | false | |
|
77 | ! User.verify_session_token(session[:user_id], session[:tk]) | |
|
90 | 78 | end |
|
91 | 79 | |
|
92 | 80 | def start_user_session(user) |
|
93 | 81 | session[:user_id] = user.id |
|
94 | session[:ctime] = Time.now.utc.to_i | |
|
95 | session[:atime] = Time.now.utc.to_i | |
|
82 | session[:tk] = user.generate_session_token | |
|
96 | 83 | if user.must_change_password? |
|
97 | 84 | session[:pwd] = '1' |
|
98 | 85 | end |
@@ -149,18 +136,6 class ApplicationController < ActionController::Base | |||
|
149 | 136 | user |
|
150 | 137 | end |
|
151 | 138 | |
|
152 | def force_logout_if_password_changed | |
|
153 | passwd_changed_on = User.current.passwd_changed_on || Time.at(0) | |
|
154 | # Make sure we force logout only for web browser sessions, not API calls | |
|
155 | # if the password was changed after the session creation. | |
|
156 | if session[:user_id] && passwd_changed_on.utc.to_i > session[:ctime].to_i | |
|
157 | reset_session | |
|
158 | set_localization | |
|
159 | flash[:error] = l(:error_session_expired) | |
|
160 | redirect_to signin_url | |
|
161 | end | |
|
162 | end | |
|
163 | ||
|
164 | 139 | def autologin_cookie_name |
|
165 | 140 | Redmine::Configuration['autologin_cookie_name'].presence || 'autologin' |
|
166 | 141 | end |
@@ -193,6 +168,7 class ApplicationController < ActionController::Base | |||
|
193 | 168 | if User.current.logged? |
|
194 | 169 | cookies.delete(autologin_cookie_name) |
|
195 | 170 | Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) |
|
171 | Token.delete_all(["user_id = ? AND action = ? AND value = ?", User.current.id, 'session', session[:tk]]) | |
|
196 | 172 | self.logged_user = nil |
|
197 | 173 | end |
|
198 | 174 | end |
@@ -103,9 +103,8 class MyController < ApplicationController | |||
|
103 | 103 | @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] |
|
104 | 104 | @user.must_change_passwd = false |
|
105 | 105 | if @user.save |
|
106 | # Reset the session creation time to not log out this session on next | |
|
107 | # request due to ApplicationController#force_logout_if_password_changed | |
|
108 | session[:ctime] = User.current.passwd_changed_on.utc.to_i | |
|
106 | # The session token was destroyed by the password change, generate a new one | |
|
107 | session[:tk] = @user.generate_session_token | |
|
109 | 108 | flash[:notice] = l(:notice_account_password_updated) |
|
110 | 109 | redirect_to my_account_path |
|
111 | 110 | end |
@@ -36,7 +36,7 class Token < ActiveRecord::Base | |||
|
36 | 36 | |
|
37 | 37 | # Delete all expired tokens |
|
38 | 38 | def self.destroy_expired |
|
39 | Token.where("action NOT IN (?) AND created_on < ?", ['feeds', 'api'], Time.now - validity_time).delete_all | |
|
39 | Token.where("action NOT IN (?) AND created_on < ?", ['feeds', 'api', 'session'], Time.now - validity_time).delete_all | |
|
40 | 40 | end |
|
41 | 41 | |
|
42 | 42 | # Returns the active user who owns the key for the given action |
@@ -79,7 +79,15 class Token < ActiveRecord::Base | |||
|
79 | 79 | # Removes obsolete tokens (same user and action) |
|
80 | 80 | def delete_previous_tokens |
|
81 | 81 | if user |
|
82 |
Token.where(:user_id => user.id, :action => action) |
|
|
82 | scope = Token.where(:user_id => user.id, :action => action) | |
|
83 | if action == 'session' | |
|
84 | ids = scope.order(:updated_on => :desc).offset(9).ids | |
|
85 | if ids.any? | |
|
86 | Token.delete(ids) | |
|
87 | end | |
|
88 | else | |
|
89 | scope.delete_all | |
|
90 | end | |
|
83 | 91 | end |
|
84 | 92 | end |
|
85 | 93 | end |
@@ -394,6 +394,26 class User < Principal | |||
|
394 | 394 | api_token.value |
|
395 | 395 | end |
|
396 | 396 | |
|
397 | # Generates a new session token and returns its value | |
|
398 | def generate_session_token | |
|
399 | token = Token.create!(:user_id => id, :action => 'session') | |
|
400 | token.value | |
|
401 | end | |
|
402 | ||
|
403 | # Returns true if token is a valid session token for the user whose id is user_id | |
|
404 | def self.verify_session_token(user_id, token) | |
|
405 | return false if user_id.blank? || token.blank? | |
|
406 | ||
|
407 | scope = Token.where(:user_id => user_id, :value => token.to_s, :action => 'session') | |
|
408 | if Setting.session_lifetime? | |
|
409 | scope = scope.where("created_on > ?", Setting.session_lifetime.to_i.minutes.ago) | |
|
410 | end | |
|
411 | if Setting.session_timeout? | |
|
412 | scope = scope.where("updated_on > ?", Setting.session_timeout.to_i.minutes.ago) | |
|
413 | end | |
|
414 | scope.update_all(:updated_on => Time.now) == 1 | |
|
415 | end | |
|
416 | ||
|
397 | 417 | # Return an array of project ids for which the user has explicitly turned mail notifications on |
|
398 | 418 | def notified_projects_ids |
|
399 | 419 | @notified_projects_ids ||= memberships.select {|m| m.mail_notification?}.collect(&:project_id) |
@@ -764,8 +784,8 class User < Principal | |||
|
764 | 784 | # This helps to keep the account secure in case the associated email account |
|
765 | 785 | # was compromised. |
|
766 | 786 | def destroy_tokens |
|
767 | if hashed_password_changed? | |
|
768 | tokens = ['recovery', 'autologin'] | |
|
787 | if hashed_password_changed? || (status_changed? && !active?) | |
|
788 | tokens = ['recovery', 'autologin', 'session'] | |
|
769 | 789 | Token.where(:user_id => id, :action => tokens).delete_all |
|
770 | 790 | end |
|
771 | 791 | end |
@@ -26,6 +26,9 Rails.application.configure do | |||
|
26 | 26 | # Disable request forgery protection in test environment. |
|
27 | 27 | config.action_controller.allow_forgery_protection = false |
|
28 | 28 | |
|
29 | # Disable sessions verifications in test environment. | |
|
30 | config.redmine_verify_sessions = false | |
|
31 | ||
|
29 | 32 | # Print deprecation notices to stderr and the Rails logger. |
|
30 | 33 | config.active_support.deprecation = [:stderr, :log] |
|
31 | 34 |
@@ -185,18 +185,6 class MyControllerTest < ActionController::TestCase | |||
|
185 | 185 | assert User.try_to_login('jsmith', 'secret123') |
|
186 | 186 | end |
|
187 | 187 | |
|
188 | def test_change_password_kills_other_sessions | |
|
189 | @request.session[:ctime] = (Time.now - 30.minutes).utc.to_i | |
|
190 | ||
|
191 | jsmith = User.find(2) | |
|
192 | jsmith.passwd_changed_on = Time.now | |
|
193 | jsmith.save! | |
|
194 | ||
|
195 | get 'account' | |
|
196 | assert_response 302 | |
|
197 | assert flash[:error].match(/Your session has expired/) | |
|
198 | end | |
|
199 | ||
|
200 | 188 | def test_change_password_should_redirect_if_user_cannot_change_its_password |
|
201 | 189 | User.find(2).update_attribute(:auth_source_id, 1) |
|
202 | 190 |
@@ -17,95 +17,99 | |||
|
17 | 17 | |
|
18 | 18 | require File.expand_path('../../test_helper', __FILE__) |
|
19 | 19 | |
|
20 |
class Session |
|
|
21 | tests AccountController | |
|
20 | class SessionsControllerTest < ActionController::TestCase | |
|
21 | include Redmine::I18n | |
|
22 | tests WelcomeController | |
|
22 | 23 | |
|
23 | fixtures :users | |
|
24 | fixtures :users, :email_addresses | |
|
24 | 25 | |
|
25 | def test_login_should_set_session_timestamps | |
|
26 | post :login, :username => 'jsmith', :password => 'jsmith' | |
|
27 | assert_response 302 | |
|
28 | assert_equal 2, session[:user_id] | |
|
29 | assert_not_nil session[:ctime] | |
|
30 | assert_not_nil session[:atime] | |
|
26 | def setup | |
|
27 | Rails.application.config.redmine_verify_sessions = true | |
|
31 | 28 | end |
|
32 | end | |
|
33 | 29 | |
|
34 | class SessionsTest < ActionController::TestCase | |
|
35 | include Redmine::I18n | |
|
36 | tests WelcomeController | |
|
30 | def teardown | |
|
31 | Rails.application.config.redmine_verify_sessions = false | |
|
32 | end | |
|
37 | 33 | |
|
38 | fixtures :users, :email_addresses | |
|
34 | def test_session_token_should_be_updated | |
|
35 | created = 10.hours.ago | |
|
36 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
39 | 37 | |
|
40 | def test_atime_from_user_session_should_be_updated | |
|
41 | created = 2.hours.ago.utc.to_i | |
|
42 | get :index, {}, {:user_id => 2, :ctime => created, :atime => created} | |
|
38 | get :index, {}, {:user_id => 2, :tk => token.value} | |
|
43 | 39 | assert_response :success |
|
44 | assert_equal created, session[:ctime] | |
|
45 |
assert_ |
|
|
46 | assert session[:atime] > created | |
|
40 | token.reload | |
|
41 | assert_equal created, token.created_on | |
|
42 | assert_not_equal created, token.updated_on | |
|
43 | assert token.updated_on > created | |
|
47 | 44 | end |
|
48 | 45 | |
|
49 | 46 | def test_user_session_should_not_be_reset_if_lifetime_and_timeout_disabled |
|
47 | created = 2.years.ago | |
|
48 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
49 | ||
|
50 | 50 | with_settings :session_lifetime => '0', :session_timeout => '0' do |
|
51 | get :index, {}, {:user_id => 2} | |
|
51 | get :index, {}, {:user_id => 2, :tk => token.value} | |
|
52 | 52 | assert_response :success |
|
53 | 53 | end |
|
54 | 54 | end |
|
55 | 55 | |
|
56 |
def test_user_session_without_ |
|
|
57 | with_settings :session_lifetime => '720' do | |
|
58 | get :index, {}, {:user_id => 2} | |
|
59 | assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F' | |
|
60 | end | |
|
56 | def test_user_session_without_token_should_be_reset | |
|
57 | get :index, {}, {:user_id => 2} | |
|
58 | assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F' | |
|
61 | 59 | end |
|
62 | 60 | |
|
63 |
def test_user_session |
|
|
61 | def test_expired_user_session_should_be_reset_if_lifetime_enabled | |
|
62 | created = 2.days.ago | |
|
63 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
64 | ||
|
64 | 65 | with_settings :session_timeout => '720' do |
|
65 |
get :index, {}, {:user_id => 2, : |
|
|
66 | get :index, {}, {:user_id => 2, :tk => token.value} | |
|
66 | 67 | assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F' |
|
67 | 68 | end |
|
68 | 69 | end |
|
69 | 70 | |
|
70 |
def test_user_session |
|
|
71 | def test_valid_user_session_should_not_be_reset_if_lifetime_enabled | |
|
72 | created = 3.hours.ago | |
|
73 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
74 | ||
|
71 | 75 | with_settings :session_timeout => '720' do |
|
72 |
get :index, {}, {:user_id => 2, : |
|
|
76 | get :index, {}, {:user_id => 2, :tk => token.value} | |
|
73 | 77 | assert_response :success |
|
74 | 78 | end |
|
75 | 79 | end |
|
76 | 80 | |
|
77 |
def test_user_session |
|
|
78 | with_settings :session_timeout => '60' do | |
|
79 | get :index, {}, {:user_id => 2} | |
|
80 | assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F' | |
|
81 | end | |
|
82 | end | |
|
81 | def test_expired_user_session_should_be_reset_if_timeout_enabled | |
|
82 | created = 4.hours.ago | |
|
83 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
83 | 84 | |
|
84 | def test_user_session_with_expired_atime_should_be_reset_if_timeout_enabled | |
|
85 | 85 | with_settings :session_timeout => '60' do |
|
86 |
get :index, {}, {:user_id => 2, : |
|
|
86 | get :index, {}, {:user_id => 2, :tk => token.value} | |
|
87 | 87 | assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F' |
|
88 | 88 | end |
|
89 | 89 | end |
|
90 | 90 | |
|
91 |
def test_user_session |
|
|
91 | def test_valid_user_session_should_not_be_reset_if_timeout_enabled | |
|
92 | created = 10.minutes.ago | |
|
93 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
94 | ||
|
92 | 95 | with_settings :session_timeout => '60' do |
|
93 |
get :index, {}, {:user_id => 2, : |
|
|
96 | get :index, {}, {:user_id => 2, :tk => token.value} | |
|
94 | 97 | assert_response :success |
|
95 | 98 | end |
|
96 | 99 | end |
|
97 | 100 | |
|
98 | 101 | def test_expired_user_session_should_be_restarted_if_autologin |
|
102 | created = 2.hours.ago | |
|
103 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
104 | ||
|
99 | 105 | with_settings :session_lifetime => '720', :session_timeout => '60', :autologin => 7 do |
|
100 | token = Token.create!(:user_id => 2, :action => 'autologin', :created_on => 1.day.ago) | |
|
101 | @request.cookies['autologin'] = token.value | |
|
102 | created = 2.hours.ago.utc.to_i | |
|
106 | autologin_token = Token.create!(:user_id => 2, :action => 'autologin', :created_on => 1.day.ago) | |
|
107 | @request.cookies['autologin'] = autologin_token.value | |
|
103 | 108 | |
|
104 |
get :index, {}, {:user_id => 2, : |
|
|
109 | get :index, {}, {:user_id => 2, :tk => token.value} | |
|
105 | 110 | assert_equal 2, session[:user_id] |
|
106 | 111 | assert_response :success |
|
107 |
assert_not_equal |
|
|
108 | assert session[:ctime] >= created | |
|
112 | assert_not_equal token.value, session[:tk] | |
|
109 | 113 | end |
|
110 | 114 | end |
|
111 | 115 | |
@@ -114,9 +118,11 class SessionsTest < ActionController::TestCase | |||
|
114 | 118 | user = User.find(2) |
|
115 | 119 | user.language = 'fr' |
|
116 | 120 | user.save! |
|
121 | created = 4.hours.ago | |
|
122 | token = Token.create!(:user_id => 2, :action => 'session', :created_on => created, :updated_on => created) | |
|
117 | 123 | |
|
118 | 124 | with_settings :session_timeout => '60' do |
|
119 |
get :index, {}, {:user_id => user.id, : |
|
|
125 | get :index, {}, {:user_id => user.id, :tk => token.value} | |
|
120 | 126 | assert_redirected_to 'http://test.host/login?back_url=http%3A%2F%2Ftest.host%2F' |
|
121 | 127 | assert_include "Veuillez vous reconnecter", flash[:error] |
|
122 | 128 | assert_equal :fr, current_language |
@@ -30,35 +30,47 class AccountTest < Redmine::IntegrationTest | |||
|
30 | 30 | assert_template "my/account" |
|
31 | 31 | end |
|
32 | 32 | |
|
33 | def test_login_should_set_session_token | |
|
34 | assert_difference 'Token.count' do | |
|
35 | log_user('jsmith', 'jsmith') | |
|
36 | ||
|
37 | assert_equal 2, session[:user_id] | |
|
38 | assert_not_nil session[:tk] | |
|
39 | end | |
|
40 | end | |
|
41 | ||
|
33 | 42 | def test_autologin |
|
34 | 43 | user = User.find(1) |
|
35 | Setting.autologin = "7" | |
|
36 | 44 | Token.delete_all |
|
37 | 45 | |
|
38 | # User logs in with 'autologin' checked | |
|
39 | post '/login', :username => user.login, :password => 'admin', :autologin => 1 | |
|
40 | assert_redirected_to '/my/page' | |
|
41 | token = Token.first | |
|
42 | assert_not_nil token | |
|
43 | assert_equal user, token.user | |
|
44 | assert_equal 'autologin', token.action | |
|
45 | assert_equal user.id, session[:user_id] | |
|
46 | assert_equal token.value, cookies['autologin'] | |
|
47 | ||
|
48 | # Session is cleared | |
|
49 | reset! | |
|
50 | User.current = nil | |
|
51 | # Clears user's last login timestamp | |
|
52 | user.update_attribute :last_login_on, nil | |
|
53 | assert_nil user.reload.last_login_on | |
|
54 | ||
|
55 | # User comes back with user's autologin cookie | |
|
56 | cookies[:autologin] = token.value | |
|
57 | get '/my/page' | |
|
58 | assert_response :success | |
|
59 | assert_template 'my/page' | |
|
60 | assert_equal user.id, session[:user_id] | |
|
61 | assert_not_nil user.reload.last_login_on | |
|
46 | with_settings :autologin => '7' do | |
|
47 | assert_difference 'Token.count', 2 do | |
|
48 | # User logs in with 'autologin' checked | |
|
49 | post '/login', :username => user.login, :password => 'admin', :autologin => 1 | |
|
50 | assert_redirected_to '/my/page' | |
|
51 | end | |
|
52 | token = Token.where(:action => 'autologin').order(:id => :desc).first | |
|
53 | assert_not_nil token | |
|
54 | assert_equal user, token.user | |
|
55 | assert_equal 'autologin', token.action | |
|
56 | assert_equal user.id, session[:user_id] | |
|
57 | assert_equal token.value, cookies['autologin'] | |
|
58 | ||
|
59 | # Session is cleared | |
|
60 | reset! | |
|
61 | User.current = nil | |
|
62 | # Clears user's last login timestamp | |
|
63 | user.update_attribute :last_login_on, nil | |
|
64 | assert_nil user.reload.last_login_on | |
|
65 | ||
|
66 | # User comes back with user's autologin cookie | |
|
67 | cookies[:autologin] = token.value | |
|
68 | get '/my/page' | |
|
69 | assert_response :success | |
|
70 | assert_template 'my/page' | |
|
71 | assert_equal user.id, session[:user_id] | |
|
72 | assert_not_nil user.reload.last_login_on | |
|
73 | end | |
|
62 | 74 | end |
|
63 | 75 | |
|
64 | 76 | def test_autologin_should_use_autologin_cookie_name |
@@ -69,7 +81,7 class AccountTest < Redmine::IntegrationTest | |||
|
69 | 81 | Redmine::Configuration.stubs(:[]).with('sudo_mode_timeout').returns(15) |
|
70 | 82 | |
|
71 | 83 | with_settings :autologin => '7' do |
|
72 | assert_difference 'Token.count' do | |
|
84 | assert_difference 'Token.count', 2 do | |
|
73 | 85 | post '/login', :username => 'admin', :password => 'admin', :autologin => 1 |
|
74 | 86 | assert_response 302 |
|
75 | 87 | end |
@@ -82,7 +94,7 class AccountTest < Redmine::IntegrationTest | |||
|
82 | 94 | get '/my/page' |
|
83 | 95 | assert_response :success |
|
84 | 96 | |
|
85 |
assert_difference 'Token.count', - |
|
|
97 | assert_difference 'Token.count', -2 do | |
|
86 | 98 | post '/logout' |
|
87 | 99 | end |
|
88 | 100 | assert cookies['custom_autologin'].blank? |
@@ -119,7 +131,7 class AccountTest < Redmine::IntegrationTest | |||
|
119 | 131 | assert_equal 'Password was successfully updated.', flash[:notice] |
|
120 | 132 | |
|
121 | 133 | log_user('jsmith', 'newpass123') |
|
122 | assert_equal 0, Token.count | |
|
134 | assert_equal false, Token.exists?(token.id), "Password recovery token was not deleted" | |
|
123 | 135 | end |
|
124 | 136 | |
|
125 | 137 | def test_user_with_must_change_passwd_should_be_forced_to_change_its_password |
@@ -36,6 +36,19 class TokenTest < ActiveSupport::TestCase | |||
|
36 | 36 | assert Token.exists?(t2.id) |
|
37 | 37 | end |
|
38 | 38 | |
|
39 | def test_create_session_token_should_keep_last_10_tokens | |
|
40 | Token.delete_all | |
|
41 | user = User.find(1) | |
|
42 | ||
|
43 | assert_difference 'Token.count', 10 do | |
|
44 | 10.times { Token.create!(:user => user, :action => 'session') } | |
|
45 | end | |
|
46 | ||
|
47 | assert_no_difference 'Token.count' do | |
|
48 | Token.create!(:user => user, :action => 'session') | |
|
49 | end | |
|
50 | end | |
|
51 | ||
|
39 | 52 | def test_destroy_expired_should_not_destroy_feeds_and_api_tokens |
|
40 | 53 | Token.delete_all |
|
41 | 54 |
General Comments 0
You need to be logged in to leave comments.
Login now