diff options
| -rw-r--r-- | app/controllers/users_controller.rb | 18 | ||||
| -rw-r--r-- | test/controllers/users_controller_test.rb | 55 |
2 files changed, 73 insertions, 0 deletions
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 7932e28b..1bd436e5 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb | |||
| @@ -10,6 +10,7 @@ class UsersController < ApplicationController | |||
| 10 | before_action :require_admin, :only => [:new, :create, :reset_otp, :deactivate, :reactivate] | 10 | before_action :require_admin, :only => [:new, :create, :reset_otp, :deactivate, :reactivate] |
| 11 | before_action :require_elevation, :only => [:new, :create, :reset_otp, :deactivate, :reactivate] | 11 | before_action :require_elevation, :only => [:new, :create, :reset_otp, :deactivate, :reactivate] |
| 12 | before_action :verify_status, :except => [:index, :grant_redaktion, :revoke_redaktion] | 12 | before_action :verify_status, :except => [:index, :grant_redaktion, :revoke_redaktion] |
| 13 | before_action :require_elevation_for_other_accounts, :only => [:edit, :update] | ||
| 13 | 14 | ||
| 14 | layout 'admin' | 15 | layout 'admin' |
| 15 | 16 | ||
| @@ -43,6 +44,11 @@ class UsersController < ApplicationController | |||
| 43 | end | 44 | end |
| 44 | 45 | ||
| 45 | def update | 46 | def update |
| 47 | if roles_change_needs_elevation? | ||
| 48 | session[:elevation_return_to] = request.fullpath | ||
| 49 | return redirect_to new_elevation_path | ||
| 50 | end | ||
| 51 | |||
| 46 | permitted = user_params | 52 | permitted = user_params |
| 47 | 53 | ||
| 48 | if @user.update(permitted) | 54 | if @user.update(permitted) |
| @@ -128,4 +134,16 @@ class UsersController < ApplicationController | |||
| 128 | def deny_user_access | 134 | def deny_user_access |
| 129 | deny_role_access(:admin_required) | 135 | deny_role_access(:admin_required) |
| 130 | end | 136 | end |
| 137 | |||
| 138 | def require_elevation_for_other_accounts | ||
| 139 | return if @user == current_user | ||
| 140 | require_elevation | ||
| 141 | end | ||
| 142 | |||
| 143 | def roles_change_needs_elevation? | ||
| 144 | return false unless params[:user].respond_to?(:key?) && params[:user].key?(:roles) | ||
| 145 | submitted = Array(params[:user][:roles]).reject(&:blank?).sort | ||
| 146 | return false if submitted == @user.roles.sort | ||
| 147 | !(current_user.is_admin? && elevated?) | ||
| 148 | end | ||
| 131 | end | 149 | end |
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index a1812cb7..69c535f5 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb | |||
| @@ -105,6 +105,7 @@ class UsersControllerTest < ActionController::TestCase | |||
| 105 | 105 | ||
| 106 | test "get edit of another user being logged in as admin user" do | 106 | test "get edit of another user being logged in as admin user" do |
| 107 | login_as :aaron | 107 | login_as :aaron |
| 108 | elevate_session! | ||
| 108 | get :edit, params: { :id => User.find_by_login("quentin").id } | 109 | get :edit, params: { :id => User.find_by_login("quentin").id } |
| 109 | assert_response :success | 110 | assert_response :success |
| 110 | end | 111 | end |
| @@ -129,6 +130,7 @@ class UsersControllerTest < ActionController::TestCase | |||
| 129 | test "updating an user when being login in as admin user" do | 130 | test "updating an user when being login in as admin user" do |
| 130 | user = User.find_by_login("quentin") | 131 | user = User.find_by_login("quentin") |
| 131 | login_as :aaron | 132 | login_as :aaron |
| 133 | elevate_session! | ||
| 132 | put :update, params: { :id => user.id, :user => {:login => "random"} } | 134 | put :update, params: { :id => user.id, :user => {:login => "random"} } |
| 133 | assert_redirected_to user_path(user) | 135 | assert_redirected_to user_path(user) |
| 134 | assert_equal "random", user.reload.login | 136 | assert_equal "random", user.reload.login |
| @@ -302,4 +304,57 @@ class UsersControllerTest < ActionController::TestCase | |||
| 302 | assert_equal User.find_by(:login => "newcomer").id, | 304 | assert_equal User.find_by(:login => "newcomer").id, |
| 303 | entry.action_participants.first.subject_id | 305 | entry.action_participants.first.subject_id |
| 304 | end | 306 | end |
| 307 | |||
| 308 | test "editing another account without elevation prompts for a code" do | ||
| 309 | login_as :aaron | ||
| 310 | get :edit, params: { :locale => "de", :id => users(:quentin).id } | ||
| 311 | assert_redirected_to new_elevation_path | ||
| 312 | end | ||
| 313 | |||
| 314 | test "editing your own account needs no elevation" do | ||
| 315 | login_as :aaron | ||
| 316 | get :edit, params: { :locale => "de", :id => users(:aaron).id } | ||
| 317 | assert_response :success | ||
| 318 | end | ||
| 319 | |||
| 320 | test "a role change submitted without elevation is refused, not silently dropped" do | ||
| 321 | login_as :aaron | ||
| 322 | target = users(:quentin) | ||
| 323 | assert_empty target.roles | ||
| 324 | |||
| 325 | put :update, params: { :locale => "de", :id => target.id, | ||
| 326 | :user => { :roles => ["", "redaktion"] } } | ||
| 327 | |||
| 328 | assert_redirected_to new_elevation_path | ||
| 329 | assert_empty target.reload.roles | ||
| 330 | assert_nil flash[:notice] | ||
| 331 | end | ||
| 332 | |||
| 333 | test "a role change with elevation goes through" do | ||
| 334 | login_as :aaron | ||
| 335 | elevate_session! | ||
| 336 | target = users(:redella) | ||
| 337 | target.update_column(:otp_secret, ROTP::Base32.random) | ||
| 338 | |||
| 339 | put :update, params: { :locale => "de", :id => target.id, | ||
| 340 | :user => { :roles => ["", "redaktion", "admin"] } } | ||
| 341 | |||
| 342 | assert_redirected_to user_path(target) | ||
| 343 | assert_equal ["admin", "redaktion"], target.reload.roles.sort | ||
| 344 | end | ||
| 345 | |||
| 346 | test "editing your own account without elevation does not prompt" do | ||
| 347 | login_as :aaron | ||
| 348 | put :update, params: { :locale => "de", :id => users(:aaron).id, | ||
| 349 | :user => { :roles => ["", "admin", "redaktion"] } } | ||
| 350 | assert_redirected_to user_path(users(:aaron)) | ||
| 351 | end | ||
| 352 | |||
| 353 | test "changing your own roles without elevation is refused" do | ||
| 354 | login_as :aaron | ||
| 355 | put :update, params: { :locale => "de", :id => users(:aaron).id, | ||
| 356 | :user => { :roles => [""] } } | ||
| 357 | assert_redirected_to new_elevation_path | ||
| 358 | assert_equal ["admin", "redaktion"], users(:aaron).reload.roles.sort | ||
| 359 | end | ||
| 305 | end | 360 | end |
