blob: bc1e6c47109566b3a40123db99c19a81767bc9ef (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# frozen_string_literal: true
require 'spec_helper'
require 'active_model'
class TwoFactorBackupablePbkdf2Double
extend ::ActiveModel::Callbacks
include ::ActiveModel::Validations::Callbacks
extend ::Devise::Models
# stub out the ::ActiveRecord::Encryption::EncryptableRecord API
attr_accessor :otp_secret
def self.encrypts(*attrs)
nil
end
define_model_callbacks :update
devise :two_factor_backupable, otp_number_of_backup_codes: 10
devise :two_factor_backupable_pbkdf2
attr_accessor :otp_backup_codes
end
module Gitlab
class FIPS
def enabled?
end
end
end
RSpec.describe ::Devise::Models::TwoFactorBackupablePbkdf2 do
subject { TwoFactorBackupablePbkdf2Double.new }
describe '#generate_otp_backup_codes_pbkdf2!' do
context 'with no existing recovery codes' do
before do
@plaintext_codes = subject.generate_otp_backup_codes_pbkdf2!
end
it 'generates the correct number of new recovery codes' do
expect(subject.otp_backup_codes.length).to eq(subject.class.otp_number_of_backup_codes)
end
it 'generates recovery codes of the correct length' do
@plaintext_codes.each do |code|
expect(code.length).to eq(subject.class.otp_backup_code_length)
end
end
it 'generates distinct recovery codes' do
expect(@plaintext_codes.uniq).to contain_exactly(*@plaintext_codes)
end
it 'stores the codes as pbkdf2 hashes' do
subject.otp_backup_codes.each do |code|
expect(code.start_with?("$pbkdf2-sha512$")).to be_truthy
end
end
end
end
describe '#invalidate_otp_backup_code_pdkdf2!' do
before do
@plaintext_codes = subject.generate_otp_backup_codes_pbkdf2!
end
context 'given an invalid recovery code' do
it 'returns false' do
expect(subject.invalidate_otp_backup_code_pdkdf2!('password')).to be false
end
end
context 'given a valid recovery code' do
it 'returns true' do
@plaintext_codes.each do |code|
expect(subject.invalidate_otp_backup_code_pdkdf2!(code)).to be true
end
end
it 'invalidates that recovery code' do
code = @plaintext_codes.sample
subject.invalidate_otp_backup_code_pdkdf2!(code)
expect(subject.invalidate_otp_backup_code_pdkdf2!(code)).to be false
end
it 'does not invalidate the other recovery codes' do
code = @plaintext_codes.sample
subject.invalidate_otp_backup_code_pdkdf2!(code)
@plaintext_codes.delete(code)
@plaintext_codes.each do |code|
expect(subject.invalidate_otp_backup_code_pdkdf2!(code)).to be true
end
end
end
end
end
|