From 45432cba9f524c99015c90b6b6aa381fe2b04984 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sat, 1 Aug 2026 18:38:42 +0200 Subject: Require a second factor for elevation, not for holding admin --- test/controllers/users_controller_test.rb | 12 ++++++++++++ test/models/user_otp_test.rb | 32 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) (limited to 'test') diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index 2dd0759a..0c517647 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -273,4 +273,16 @@ class UsersControllerTest < ActionController::TestCase assert_not user.reload.is_admin? end + + test "clearing the factor closes an open elevation window" do + login_as :aaron + elevate_session! + get :new, params: { :locale => "de" } + assert_response :success + + users(:aaron).update_column(:otp_secret, nil) + + get :new, params: { :locale => "de" } + assert_redirected_to new_elevation_path + end end diff --git a/test/models/user_otp_test.rb b/test/models/user_otp_test.rb index 81f25575..2044ac18 100644 --- a/test/models/user_otp_test.rb +++ b/test/models/user_otp_test.rb @@ -74,6 +74,38 @@ class UserOtpTest < ActiveSupport::TestCase assert_equal @user.login, action.metadata["target_login"] end + test "an admin without a factor can start enrollment" do + admin = users(:aaron) + assert admin.is_admin? + assert_not admin.otp_enrolled? + + uri = admin.begin_otp_enrollment! + + assert admin.reload.otp_pending_secret.present? + assert uri.present? + end + + test "an admin disabling their factor keeps the role" do + admin = users(:aaron) + admin.update_column(:otp_secret, ROTP::Base32.random) + + admin.disable_otp!(:actor => admin) + + assert_not admin.reload.otp_enrolled? + assert admin.is_admin? + end + + test "a fellow admin can reset an admin's factor" do + admin = users(:aaron) + admin.update_column(:otp_secret, ROTP::Base32.random) + actor = users(:redella) + + admin.disable_otp!(:actor => actor) + + assert_not admin.reload.otp_enrolled? + assert_equal "otp_reset", NodeAction.last.action + end + private def enroll!(user) -- cgit v1.3