summaryrefslogtreecommitdiff
path: root/test/controllers
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-24 13:52:56 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-24 13:52:56 +0200
commitfefec929c59c72dc93e4be30e8f23cd8c5258b0a (patch)
treee35d2e050a9052384e52a5ccb623d8dd193c2370 /test/controllers
parentcd36a46bbb5679ded1653f65bf4e8a74ae55100c (diff)
Add self-service TOTP enrollment UI and witnessed admin reset
Diffstat (limited to 'test/controllers')
-rw-r--r--test/controllers/otp_enrollments_controller_test.rb41
-rw-r--r--test/controllers/users_controller_test.rb14
2 files changed, 54 insertions, 1 deletions
diff --git a/test/controllers/otp_enrollments_controller_test.rb b/test/controllers/otp_enrollments_controller_test.rb
new file mode 100644
index 00000000..3bfab8e3
--- /dev/null
+++ b/test/controllers/otp_enrollments_controller_test.rb
@@ -0,0 +1,41 @@
1require "test_helper"
2
3class OtpEnrollmentsControllerTest < ActionController::TestCase
4 include AuthenticatedTestHelper
5 fixtures :users
6
7 def setup
8 login_as :quentin
9 @user = users(:quentin)
10 User.authenticate("quentin", "monkey") # ensure digest is migrated
11 end
12
13 test "create requires the current password" do
14 post :create, params: { :current_password => "wrong" }
15 assert_nil @user.reload.otp_pending_secret
16 end
17
18 test "create with the password begins enrollment" do
19 post :create, params: { :current_password => "monkey" }
20 assert @user.reload.otp_pending_secret.present?
21 assert_redirected_to otp_enrollment_path
22 end
23
24 test "update with the first code completes enrollment" do
25 @user.begin_otp_enrollment!
26 code = ROTP::TOTP.new(@user.reload.otp_pending_secret).now
27 put :update, params: { :code => code }
28 assert @user.reload.otp_enrolled?
29 end
30
31 test "destroy needs password and a current code" do
32 @user.update!(:otp_secret => ROTP::Base32.random)
33
34 delete :destroy, params: { :current_password => "monkey", :code => "000000" }
35 assert @user.reload.otp_enrolled?
36
37 code = ROTP::TOTP.new(@user.otp_secret).now
38 delete :destroy, params: { :current_password => "monkey", :code => code }
39 assert_not @user.reload.otp_enrolled?
40 end
41end
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
index 58f8a86b..946b5414 100644
--- a/test/controllers/users_controller_test.rb
+++ b/test/controllers/users_controller_test.rb
@@ -182,5 +182,17 @@ class UsersControllerTest < ActionController::TestCase
182 assert_equal false, user.is_admin? 182 assert_equal false, user.is_admin?
183 end 183 end
184 184
185 185 test "reset_otp is admin-only and witnessed" do
186 user = users(:quentin)
187 user.update!(:otp_secret => ROTP::Base32.random)
188
189 login_as :quentin
190 put :reset_otp, params: { :id => user.id }
191 assert user.reload.otp_enrolled?, "non-admin must be refused"
192
193 login_as :aaron
194 put :reset_otp, params: { :id => user.id }
195 assert_not user.reload.otp_enrolled?
196 assert_equal "otp_reset", NodeAction.last.action
197 end
186end 198end