recovery_codes_spec.rb 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Auth::TwoFactor::RecoveryCodes, current_user_id: 1 do
  4. subject(:instance) { described_class.new(user) }
  5. let(:user) { create(:user) }
  6. shared_examples 'responding to provided instance method' do |method|
  7. it "responds to '.#{method}'" do
  8. expect(instance).to respond_to(method)
  9. end
  10. end
  11. it_behaves_like 'responding to provided instance method', :verify
  12. it_behaves_like 'responding to provided instance method', :generate
  13. it_behaves_like 'responding to provided instance method', :exists?
  14. it_behaves_like 'responding to provided instance method', :enabled?
  15. it_behaves_like 'responding to provided instance method', :method_name
  16. it_behaves_like 'responding to provided instance method', :related_setting_name
  17. it_behaves_like 'responding to provided instance method', :create_user_config
  18. it_behaves_like 'responding to provided instance method', :destroy_user_config
  19. describe '#verify' do
  20. let(:current_codes) { instance.generate }
  21. let(:current_hashed_codes) { user.reload.two_factor_preferences.recovery_codes.configuration[:codes] }
  22. let(:code) { current_codes.first }
  23. before do
  24. current_codes
  25. current_hashed_codes
  26. end
  27. context 'when code is correct' do
  28. it 'returns true' do
  29. expect(instance.verify(code)[:verified]).to be(true)
  30. end
  31. it 'removes code from list' do
  32. verify_result = instance.verify(code)
  33. expect(verify_result['codes']).not_to include(code)
  34. end
  35. end
  36. context 'when code is incorrect' do
  37. let(:code) { 'incorrect' }
  38. before do
  39. current_codes
  40. current_hashed_codes
  41. end
  42. it 'returns false' do
  43. expect(instance.verify(code)[:verified]).to be(false)
  44. end
  45. it 'current code list is untouched' do
  46. instance.verify(code)
  47. expect(user.reload.two_factor_preferences.recovery_codes.configuration[:codes]).to eq(current_hashed_codes)
  48. end
  49. end
  50. end
  51. describe '#generate' do
  52. it 'codes will be generated' do
  53. expect(instance.generate.length).to eq(described_class.const_get(:NUMBER_OF_CODES))
  54. end
  55. it 'codes have the correct length' do
  56. expect(instance.generate.first.length).to eq(described_class.const_get(:CODE_LENGTH))
  57. end
  58. it 'codes are saved in two factor preferences' do
  59. instance.generate
  60. expect(user.reload.two_factor_preferences.recovery_codes.configuration[:codes].length).to eq(described_class.const_get(:NUMBER_OF_CODES))
  61. end
  62. context 'when codes already exist' do
  63. let(:current_codes) { instance.generate }
  64. let(:current_hashed_codes) { user.reload.two_factor_preferences.recovery_codes.configuration[:codes] }
  65. before do
  66. current_codes
  67. current_hashed_codes
  68. end
  69. it 'codes are saved in two factor preferences' do
  70. instance.generate
  71. expect(user.reload.two_factor_preferences.recovery_codes.configuration[:codes]).not_to be(current_hashed_codes)
  72. end
  73. end
  74. end
  75. describe '#exists?' do
  76. let(:two_factor_pref_recovery_codes) do
  77. create(:user_two_factor_preference, :authenticator_app,
  78. user: user,
  79. method: 'recovery_codes',
  80. configuration: {})
  81. end
  82. context 'when recovery codes are present' do
  83. before { two_factor_pref_recovery_codes }
  84. it 'returns true' do
  85. expect(instance.exists?).to be(true)
  86. end
  87. end
  88. context 'when recovery codes are not present' do
  89. it 'returns false' do
  90. expect(instance.exists?).to be(false)
  91. end
  92. end
  93. end
  94. end