diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-08-04 05:40:54 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-08-04 05:40:54 +0200 |
| commit | 974062f16169f6d07f2289564be6d72610b8770e (patch) | |
| tree | b18f297a9d4326a3ce36f5192fbc4992fcb28e7d /test | |
| parent | be2cdea85177ac016e56dcce6cbe6015d754adf5 (diff) | |
Witness every promotion and demotion made through the roles form
Diffstat (limited to 'test')
| -rw-r--r-- | test/controllers/users_controller_test.rb | 46 | ||||
| -rw-r--r-- | test/models/user_test.rb | 66 |
2 files changed, 112 insertions, 0 deletions
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index 69c535f5..aeff9bc7 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb | |||
| @@ -357,4 +357,50 @@ class UsersControllerTest < ActionController::TestCase | |||
| 357 | assert_redirected_to new_elevation_path | 357 | assert_redirected_to new_elevation_path |
| 358 | assert_equal ["admin", "redaktion"], users(:aaron).reload.roles.sort | 358 | assert_equal ["admin", "redaktion"], users(:aaron).reload.roles.sort |
| 359 | end | 359 | end |
| 360 | |||
| 361 | test "promoting through the roles form leaves a log entry" do | ||
| 362 | login_as :aaron | ||
| 363 | elevate_session! | ||
| 364 | target = users(:redella) | ||
| 365 | target.update_column(:otp_secret, ROTP::Base32.random) | ||
| 366 | |||
| 367 | assert_difference -> { NodeAction.where(:action => "admin_grant").count }, 1 do | ||
| 368 | put :update, params: { :locale => "de", :id => target.id, | ||
| 369 | :user => { :roles => ["", "redaktion", "admin"] } } | ||
| 370 | end | ||
| 371 | |||
| 372 | assert_redirected_to user_path(target) | ||
| 373 | assert_equal %w[admin redaktion], target.reload.roles.sort | ||
| 374 | end | ||
| 375 | |||
| 376 | test "a refused promotion re-renders with an error and changes nothing" do | ||
| 377 | login_as :aaron | ||
| 378 | elevate_session! | ||
| 379 | target = users(:quentin) | ||
| 380 | |||
| 381 | assert_no_difference -> { NodeAction.count } do | ||
| 382 | put :update, params: { :locale => "de", :id => target.id, | ||
| 383 | :user => { :roles => ["", "admin"] } } | ||
| 384 | end | ||
| 385 | |||
| 386 | assert_response :success | ||
| 387 | assert_empty target.reload.roles | ||
| 388 | assert_not_nil flash[:error] | ||
| 389 | assert_nil flash[:notice] | ||
| 390 | end | ||
| 391 | |||
| 392 | test "a validation failure leaves no promotion behind" do | ||
| 393 | login_as :aaron | ||
| 394 | elevate_session! | ||
| 395 | target = users(:redella) | ||
| 396 | target.update_column(:otp_secret, ROTP::Base32.random) | ||
| 397 | |||
| 398 | assert_no_difference -> { NodeAction.count } do | ||
| 399 | put :update, params: { :locale => "de", :id => target.id, | ||
| 400 | :user => { :email => "", :roles => ["", "redaktion", "admin"] } } | ||
| 401 | end | ||
| 402 | |||
| 403 | assert_response :success | ||
| 404 | assert_equal %w[redaktion], target.reload.roles | ||
| 405 | end | ||
| 360 | end | 406 | end |
diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 62552ee7..5ccc53a9 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb | |||
| @@ -6,6 +6,11 @@ class UserTest < ActiveSupport::TestCase | |||
| 6 | include AuthenticatedTestHelper | 6 | include AuthenticatedTestHelper |
| 7 | fixtures :users | 7 | fixtures :users |
| 8 | 8 | ||
| 9 | def role_entries | ||
| 10 | NodeAction.where(:action => %w[admin_grant admin_revoke redaktion_grant | ||
| 11 | redaktion_revoke user_deactivate user_reactivate]) | ||
| 12 | end | ||
| 13 | |||
| 9 | def test_should_create_user | 14 | def test_should_create_user |
| 10 | assert_difference 'User.count' do | 15 | assert_difference 'User.count' do |
| 11 | user = create_user | 16 | user = create_user |
| @@ -187,6 +192,67 @@ class UserTest < ActiveSupport::TestCase | |||
| 187 | redella.update_column(:last_login_at, nil) | 192 | redella.update_column(:last_login_at, nil) |
| 188 | assert_equal :never, redella.staleness_tier(now) | 193 | assert_equal :never, redella.staleness_tier(now) |
| 189 | end | 194 | end |
| 195 | |||
| 196 | test "granting a role through update_roles! is witnessed" do | ||
| 197 | target = users(:redella) | ||
| 198 | target.update_column(:otp_secret, ROTP::Base32.random) | ||
| 199 | |||
| 200 | assert_difference -> { role_entries.count }, 1 do | ||
| 201 | assert_empty target.update_roles!(%w[redaktion admin], :actor => users(:aaron)) | ||
| 202 | end | ||
| 203 | |||
| 204 | assert_equal %w[admin redaktion], target.reload.roles.sort | ||
| 205 | entry = role_entries.order(:id).last | ||
| 206 | assert_equal "admin_grant", entry.action | ||
| 207 | assert_equal users(:aaron).id, entry.user_id | ||
| 208 | assert_equal "redella", entry.metadata["target_login"] | ||
| 209 | end | ||
| 210 | |||
| 211 | test "a refused grant applies nothing at all" do | ||
| 212 | target = users(:quentin) | ||
| 213 | assert_not target.otp_enrolled? | ||
| 214 | |||
| 215 | assert_no_difference -> { role_entries.count } do | ||
| 216 | refusals = target.update_roles!(%w[redaktion admin], :actor => users(:aaron)) | ||
| 217 | assert_includes refusals, :admin_needs_otp | ||
| 218 | assert_includes refusals, :redaktion_needs_otp | ||
| 219 | end | ||
| 220 | |||
| 221 | assert_empty target.reload.roles, "a refusal must leave the stored set untouched" | ||
| 222 | end | ||
| 223 | |||
| 224 | test "nobody demotes themselves through update_roles!" do | ||
| 225 | actor = users(:aaron) | ||
| 226 | |||
| 227 | refusals = actor.update_roles!([], :actor => actor) | ||
| 228 | |||
| 229 | assert_includes refusals, :admin_not_self | ||
| 230 | assert_includes refusals, :redaktion_not_self | ||
| 231 | assert_equal %w[admin redaktion], actor.reload.roles.sort | ||
| 232 | end | ||
| 233 | |||
| 234 | test "marking an account alumni through update_roles! is witnessed as a deactivation" do | ||
| 235 | target = users(:redella) | ||
| 236 | |||
| 237 | assert_difference -> { role_entries.where(:action => "user_deactivate").count }, 1 do | ||
| 238 | assert_empty target.update_roles!(%w[redaktion alumni], :actor => users(:aaron)) | ||
| 239 | end | ||
| 240 | |||
| 241 | assert target.reload.alumni? | ||
| 242 | assert target.redaktion?, "deactivate! preserves the other roles" | ||
| 243 | end | ||
| 244 | |||
| 245 | test "revoking and granting in one submission apply in the right order" do | ||
| 246 | target = users(:redella) | ||
| 247 | target.update_column(:otp_secret, ROTP::Base32.random) | ||
| 248 | |||
| 249 | assert_empty target.update_roles!(%w[admin], :actor => users(:aaron)) | ||
| 250 | |||
| 251 | assert_equal %w[admin], target.reload.roles | ||
| 252 | actions = role_entries.order(:id).last(2).map(&:action) | ||
| 253 | assert_includes actions, "redaktion_revoke" | ||
| 254 | assert_includes actions, "admin_grant" | ||
| 255 | end | ||
| 190 | 256 | ||
| 191 | protected | 257 | protected |
| 192 | def create_user(options = {}) | 258 | def create_user(options = {}) |
