@@ -0,0 +1,9 | |||
|
1 | class AddUsersMustChangePasswd < ActiveRecord::Migration | |
|
2 | def up | |
|
3 | add_column :users, :must_change_passwd, :boolean, :default => false, :null => false | |
|
4 | end | |
|
5 | ||
|
6 | def down | |
|
7 | remove_column :users, :must_change_passwd | |
|
8 | end | |
|
9 | end |
@@ -20,7 +20,7 class AccountController < ApplicationController | |||
|
20 | 20 | include CustomFieldsHelper |
|
21 | 21 | |
|
22 | 22 | # prevents login action to be filtered by check_if_login_required application scope filter |
|
23 | skip_before_filter :check_if_login_required | |
|
23 | skip_before_filter :check_if_login_required, :check_password_change | |
|
24 | 24 | |
|
25 | 25 | # Login request and validation |
|
26 | 26 | def login |
@@ -38,7 +38,7 class ApplicationController < ActionController::Base | |||
|
38 | 38 | cookies.delete(autologin_cookie_name) |
|
39 | 39 | end |
|
40 | 40 | |
|
41 | before_filter :session_expiration, :user_setup, :check_if_login_required, :set_localization | |
|
41 | before_filter :session_expiration, :user_setup, :check_if_login_required, :check_password_change, :set_localization | |
|
42 | 42 | |
|
43 | 43 | rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token |
|
44 | 44 | rescue_from ::Unauthorized, :with => :deny_access |
@@ -78,6 +78,9 class ApplicationController < ActionController::Base | |||
|
78 | 78 | session[:user_id] = user.id |
|
79 | 79 | session[:ctime] = Time.now.utc.to_i |
|
80 | 80 | session[:atime] = Time.now.utc.to_i |
|
81 | if user.must_change_password? | |
|
82 | session[:pwd] = '1' | |
|
83 | end | |
|
81 | 84 | end |
|
82 | 85 | |
|
83 | 86 | def user_setup |
@@ -112,6 +115,10 class ApplicationController < ActionController::Base | |||
|
112 | 115 | authenticate_with_http_basic do |username, password| |
|
113 | 116 | user = User.try_to_login(username, password) || User.find_by_api_key(username) |
|
114 | 117 | end |
|
118 | if user && user.must_change_password? | |
|
119 | render_error :message => 'You must change your password', :status => 403 | |
|
120 | return | |
|
121 | end | |
|
115 | 122 | end |
|
116 | 123 | # Switch user if requested by an admin user |
|
117 | 124 | if user && user.admin? && (username = api_switch_user_from_request) |
@@ -170,6 +177,16 class ApplicationController < ActionController::Base | |||
|
170 | 177 | require_login if Setting.login_required? |
|
171 | 178 | end |
|
172 | 179 | |
|
180 | def check_password_change | |
|
181 | if session[:pwd] | |
|
182 | if User.current.must_change_password? | |
|
183 | redirect_to my_password_path | |
|
184 | else | |
|
185 | session.delete(:pwd) | |
|
186 | end | |
|
187 | end | |
|
188 | end | |
|
189 | ||
|
173 | 190 | def set_localization |
|
174 | 191 | lang = nil |
|
175 | 192 | if User.current.logged? |
@@ -17,6 +17,8 | |||
|
17 | 17 | |
|
18 | 18 | class MyController < ApplicationController |
|
19 | 19 | before_filter :require_login |
|
20 | # let user change his password when he has to | |
|
21 | skip_before_filter :check_password_change, :only => :password | |
|
20 | 22 | |
|
21 | 23 | helper :issues |
|
22 | 24 | helper :users |
@@ -90,14 +92,17 class MyController < ApplicationController | |||
|
90 | 92 | return |
|
91 | 93 | end |
|
92 | 94 | if request.post? |
|
93 | if @user.check_password?(params[:password]) | |
|
95 | if !@user.check_password?(params[:password]) | |
|
96 | flash.now[:error] = l(:notice_account_wrong_password) | |
|
97 | elsif params[:password] == params[:new_password] | |
|
98 | flash.now[:error] = 'Your new password must be different from your current password' | |
|
99 | else | |
|
94 | 100 | @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] |
|
101 | @user.must_change_passwd = false | |
|
95 | 102 | if @user.save |
|
96 | 103 | flash[:notice] = l(:notice_account_password_updated) |
|
97 | 104 | redirect_to my_account_path |
|
98 | 105 | end |
|
99 | else | |
|
100 | flash[:error] = l(:notice_account_wrong_password) | |
|
101 | 106 | end |
|
102 | 107 | end |
|
103 | 108 | end |
@@ -280,6 +280,10 class User < Principal | |||
|
280 | 280 | return auth_source.allow_password_changes? |
|
281 | 281 | end |
|
282 | 282 | |
|
283 | def must_change_password? | |
|
284 | must_change_passwd? && change_password_allowed? | |
|
285 | end | |
|
286 | ||
|
283 | 287 | def generate_password? |
|
284 | 288 | generate_password == '1' || generate_password == true |
|
285 | 289 | end |
@@ -568,6 +572,7 class User < Principal | |||
|
568 | 572 | safe_attributes 'status', |
|
569 | 573 | 'auth_source_id', |
|
570 | 574 | 'generate_password', |
|
575 | 'must_change_passwd', | |
|
571 | 576 | :if => lambda {|user, current_user| current_user.admin?} |
|
572 | 577 | |
|
573 | 578 | safe_attributes 'group_ids', |
@@ -17,6 +17,10 | |||
|
17 | 17 | <%= submit_tag l(:button_apply) %> |
|
18 | 18 | <% end %> |
|
19 | 19 | |
|
20 | <% unless @user.must_change_passwd? %> | |
|
20 | 21 | <% content_for :sidebar do %> |
|
21 | 22 | <%= render :partial => 'sidebar' %> |
|
22 | 23 | <% end %> |
|
24 | <% end %> | |
|
25 | ||
|
26 | <%= javascript_tag "$('#password').focus();" %> |
@@ -28,10 +28,11 | |||
|
28 | 28 | <p><%= f.select :auth_source_id, ([[l(:label_internal), ""]] + @auth_sources.collect { |a| [a.name, a.id] }), {}, :onchange => "if (this.value=='') {$('#password_fields').show();} else {$('#password_fields').hide();}" %></p> |
|
29 | 29 | <% end %> |
|
30 | 30 | <div id="password_fields" style="<%= 'display:none;' if @user.auth_source %>"> |
|
31 | <p><%= f.check_box :generate_password %></p> | |
|
32 | 31 | <p><%= f.password_field :password, :required => true, :size => 25 %> |
|
33 | 32 | <em class="info"><%= l(:text_caracters_minimum, :count => Setting.password_min_length) %></em></p> |
|
34 | 33 | <p><%= f.password_field :password_confirmation, :required => true, :size => 25 %></p> |
|
34 | <p><%= f.check_box :generate_password %></p> | |
|
35 | <p><%= f.check_box :must_change_passwd %></p> | |
|
35 | 36 | </div> |
|
36 | 37 | </fieldset> |
|
37 | 38 | </div> |
@@ -335,6 +335,7 en: | |||
|
335 | 335 | field_private_notes: Private notes |
|
336 | 336 | field_inherit_members: Inherit members |
|
337 | 337 | field_generate_password: Generate password |
|
338 | field_must_change_passwd: Must change password at next logon | |
|
338 | 339 | |
|
339 | 340 | setting_app_title: Application title |
|
340 | 341 | setting_app_subtitle: Application subtitle |
@@ -335,6 +335,7 fr: | |||
|
335 | 335 | field_private_notes: Notes privées |
|
336 | 336 | field_inherit_members: Hériter les membres |
|
337 | 337 | field_generate_password: Générer un mot de passe |
|
338 | field_must_change_passwd: Doit changer de mot de passe à la prochaine connexion | |
|
338 | 339 | |
|
339 | 340 | setting_app_title: Titre de l'application |
|
340 | 341 | setting_app_subtitle: Sous-titre de l'application |
@@ -128,6 +128,35 class AccountTest < ActionController::IntegrationTest | |||
|
128 | 128 | assert_equal 0, Token.count |
|
129 | 129 | end |
|
130 | 130 | |
|
131 | def test_user_with_must_change_passwd_should_be_forced_to_change_its_password | |
|
132 | User.find_by_login('jsmith').update_attribute :must_change_passwd, true | |
|
133 | ||
|
134 | post '/login', :username => 'jsmith', :password => 'jsmith' | |
|
135 | assert_redirected_to '/my/page' | |
|
136 | follow_redirect! | |
|
137 | assert_redirected_to '/my/password' | |
|
138 | ||
|
139 | get '/issues' | |
|
140 | assert_redirected_to '/my/password' | |
|
141 | end | |
|
142 | ||
|
143 | def test_user_with_must_change_passwd_should_be_able_to_change_its_password | |
|
144 | User.find_by_login('jsmith').update_attribute :must_change_passwd, true | |
|
145 | ||
|
146 | post '/login', :username => 'jsmith', :password => 'jsmith' | |
|
147 | assert_redirected_to '/my/page' | |
|
148 | follow_redirect! | |
|
149 | assert_redirected_to '/my/password' | |
|
150 | follow_redirect! | |
|
151 | assert_response :success | |
|
152 | post '/my/password', :password => 'jsmith', :new_password => 'newpassword', :new_password_confirmation => 'newpassword' | |
|
153 | assert_redirected_to '/my/account' | |
|
154 | follow_redirect! | |
|
155 | assert_response :success | |
|
156 | ||
|
157 | assert_equal false, User.find_by_login('jsmith').must_change_passwd? | |
|
158 | end | |
|
159 | ||
|
131 | 160 | def test_register_with_automatic_activation |
|
132 | 161 | Setting.self_registration = '3' |
|
133 | 162 |
General Comments 0
You need to be logged in to leave comments.
Login now