DEV: update rake task to disable 2FA for a user (#29052)

- limits security key deletes to second factor keys
- also deletes backup codes (lingering backup codes break login flow entirely)

* Add spec for rake task to disable 2FA for a user
This commit is contained in:
Penar Musaraj 2024-10-15 18:11:29 -04:00 committed by GitHub
parent d04fd3a8ac
commit 80ac3275ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 1 deletions

View File

@ -155,7 +155,13 @@ task "users:disable_2fa", [:username] => [:environment] do |_, args|
username = args[:username]
user = find_user(username)
UserSecondFactor.where(user_id: user.id, method: UserSecondFactor.methods[:totp]).each(&:destroy!)
UserSecurityKey.where(user_id: user.id).destroy_all
UserSecurityKey.where(
user_id: user.id,
factor_type: UserSecurityKey.factor_types[:second_factor],
).destroy_all
UserSecondFactor.where(user_id: user.id, method: UserSecondFactor.methods[:backup_codes]).each(
&:destroy!
)
puts "2FA disabled for #{username}"
end

40
spec/tasks/users_spec.rb Normal file
View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
RSpec.describe "tasks/users" do
before do
Rake::Task.clear
Discourse::Application.load_tasks
end
describe "users:disable_2fa" do
let(:user) { Fabricate(:user) }
it "should remove all 2fa methods for user with given username" do
Fabricate(:user_second_factor_totp, user: user, name: "TOTP", enabled: true)
Fabricate(:user_second_factor_totp, user: user, name: "TOTP2", enabled: true)
Fabricate(
:user_security_key_with_random_credential,
user: user,
name: "YubiKey",
enabled: true,
)
Fabricate(:passkey_with_random_credential, user: user) # This should not be removed
backup_codes = user.generate_backup_codes
expect(backup_codes.length).to be 10
expect(user.user_second_factors.backup_codes).to be_present
expect(user.user_second_factors.totps.count).to eq(2)
expect(user.second_factor_security_keys.count).to eq(1)
stdout = capture_stdout { Rake::Task["users:disable_2fa"].invoke(user.username) }
user.reload
expect(stdout.chomp).to eq("2FA disabled for #{user.username}")
expect(user.user_second_factors.totps.count).to eq(0)
expect(user.second_factor_security_keys.count).to eq(0)
expect(user.user_second_factors.backup_codes.count).to eq(0)
expect(user.passkey_credential_ids.count).to eq(1)
end
end
end