mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 04:11:12 +08:00
FEATURE: Second factor backup
This commit is contained in:

committed by
Joffrey JAFFEUX

parent
c73f98c289
commit
ec3e6a81a4
@ -1,10 +1,13 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe SecondFactorManager do
|
||||
let(:user_second_factor) { Fabricate(:user_second_factor) }
|
||||
let(:user) { user_second_factor.user }
|
||||
let(:user_second_factor_totp) { Fabricate(:user_second_factor_totp) }
|
||||
let(:user) { user_second_factor_totp.user }
|
||||
let(:another_user) { Fabricate(:user) }
|
||||
|
||||
let(:user_second_factor_backup) { Fabricate(:user_second_factor_backup) }
|
||||
let(:user_backup) { user_second_factor_backup.user }
|
||||
|
||||
describe '#totp' do
|
||||
it 'should return the right data' do
|
||||
totp = nil
|
||||
@ -14,7 +17,7 @@ RSpec.describe SecondFactorManager do
|
||||
end.to change { UserSecondFactor.count }.by(1)
|
||||
|
||||
expect(totp.issuer).to eq(SiteSetting.title)
|
||||
expect(totp.secret).to eq(another_user.reload.user_second_factor.data)
|
||||
expect(totp.secret).to eq(another_user.reload.user_second_factors.totp.data)
|
||||
end
|
||||
end
|
||||
|
||||
@ -37,7 +40,7 @@ RSpec.describe SecondFactorManager do
|
||||
describe '#totp_provisioning_uri' do
|
||||
it 'should return the right uri' do
|
||||
expect(user.totp_provisioning_uri).to eq(
|
||||
"otpauth://totp/#{SiteSetting.title}:#{user.email}?secret=#{user_second_factor.data}&issuer=#{SiteSetting.title}"
|
||||
"otpauth://totp/#{SiteSetting.title}:#{user.email}?secret=#{user_second_factor_totp.data}&issuer=#{SiteSetting.title}"
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -45,12 +48,12 @@ RSpec.describe SecondFactorManager do
|
||||
describe '#authenticate_totp' do
|
||||
it 'should be able to authenticate a token' do
|
||||
freeze_time do
|
||||
expect(user.user_second_factor.last_used).to eq(nil)
|
||||
expect(user.user_second_factors.totp.last_used).to eq(nil)
|
||||
|
||||
token = user.totp.now
|
||||
|
||||
expect(user.authenticate_totp(token)).to eq(true)
|
||||
expect(user.user_second_factor.last_used).to eq(DateTime.now)
|
||||
expect(user.user_second_factors.totp.last_used).to eq(DateTime.now)
|
||||
expect(user.authenticate_totp(token)).to eq(false)
|
||||
end
|
||||
end
|
||||
@ -58,14 +61,14 @@ RSpec.describe SecondFactorManager do
|
||||
describe 'when token is blank' do
|
||||
it 'should be false' do
|
||||
expect(user.authenticate_totp(nil)).to eq(false)
|
||||
expect(user.user_second_factor.last_used).to eq(nil)
|
||||
expect(user.user_second_factors.totp.last_used).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when token is invalid' do
|
||||
it 'should be false' do
|
||||
expect(user.authenticate_totp('111111')).to eq(false)
|
||||
expect(user.user_second_factor.last_used).to eq(nil)
|
||||
expect(user.user_second_factors.totp.last_used).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -79,7 +82,7 @@ RSpec.describe SecondFactorManager do
|
||||
|
||||
describe "when user's second factor record is disabled" do
|
||||
it 'should return false' do
|
||||
user.user_second_factor.update!(enabled: false)
|
||||
user.user_second_factors.totp.update!(enabled: false)
|
||||
expect(user.totp_enabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
@ -107,4 +110,85 @@ RSpec.describe SecondFactorManager do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'backup codes' do
|
||||
describe '#generate_backup_codes' do
|
||||
it 'should generate and store 10 backup codes' do
|
||||
backup_codes = user.generate_backup_codes
|
||||
|
||||
expect(backup_codes.length).to be 10
|
||||
expect(user_backup.user_second_factors.backup_codes).to be_present
|
||||
expect(user_backup.user_second_factors.backup_codes.pluck(:method).uniq[0]).to eq(UserSecondFactor.methods[:backup_codes])
|
||||
expect(user_backup.user_second_factors.backup_codes.pluck(:enabled).uniq[0]).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create_backup_codes' do
|
||||
it 'should create 10 backup code records' do
|
||||
raw_codes = Array.new(10) { SecureRandom.hex(8) }
|
||||
backup_codes = another_user.create_backup_codes(raw_codes)
|
||||
|
||||
expect(another_user.user_second_factors.backup_codes.length).to be 10
|
||||
end
|
||||
end
|
||||
|
||||
describe '#authenticate_backup_code' do
|
||||
it 'should be able to authenticate a backup code' do
|
||||
backup_code = "iAmValidBackupCode"
|
||||
|
||||
expect(user_backup.authenticate_backup_code(backup_code)).to eq(true)
|
||||
expect(user_backup.authenticate_backup_code(backup_code)).to eq(false)
|
||||
end
|
||||
|
||||
describe 'when code is blank' do
|
||||
it 'should be false' do
|
||||
expect(user_backup.authenticate_backup_code(nil)).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when code is invalid' do
|
||||
it 'should be false' do
|
||||
expect(user_backup.authenticate_backup_code("notValidBackupCode")).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#backup_codes_enabled?' do
|
||||
describe 'when user does not have a second factor backup enabled' do
|
||||
it 'should return false' do
|
||||
expect(another_user.backup_codes_enabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when user's second factor backup codes have been used" do
|
||||
it 'should return false' do
|
||||
user_backup.user_second_factors.backup_codes.update_all(enabled: false)
|
||||
expect(user_backup.backup_codes_enabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when user's second factor code is available" do
|
||||
it 'should return true' do
|
||||
expect(user_backup.backup_codes_enabled?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when SSO is enabled' do
|
||||
it 'should return false' do
|
||||
SiteSetting.sso_url = 'http://someurl.com'
|
||||
SiteSetting.enable_sso = true
|
||||
|
||||
expect(user_backup.backup_codes_enabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when local login is disabled' do
|
||||
it 'should return false' do
|
||||
SiteSetting.enable_local_logins = false
|
||||
|
||||
expect(user_backup.backup_codes_enabled?).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user