123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- require 'rotp'
- RSpec.describe Auth::TwoFactor::AuthenticationMethod, current_user_id: 1 do
- subject(:instance) { described_class.new(user) }
- let(:user) { create(:user) }
- shared_examples 'responding to provided instance method' do |method|
- it "responds to '.#{method}'" do
- expect(instance).to respond_to(method)
- end
- end
- shared_examples "raising 'NotImplemented' error for base methods" do |method, args = []|
- it "raises 'NotImplemented' error for '.#{method}'" do
- expect { instance.method(method).call(*args) }.to raise_error(NotImplementedError)
- end
- end
- shared_examples 'returning expected value' do |method, value, args = [], assertion: 'be'|
- it "returns expected value for '.#{method}'", if: assertion == 'eq' do
- expect(instance.method(method).call(*args)).to eq(value)
- end
- it "returns expected value for '.#{method}'", if: assertion == 'be' do
- expect(instance.method(method).call(*args)).to be(value)
- end
- end
- it_behaves_like 'responding to provided instance method', :verify
- it_behaves_like 'responding to provided instance method', :available?
- it_behaves_like 'responding to provided instance method', :enabled?
- it_behaves_like 'responding to provided instance method', :method_name
- it_behaves_like 'responding to provided instance method', :related_setting_name
- it_behaves_like 'responding to provided instance method', :initiate_configuration
- it_behaves_like 'responding to provided instance method', :create_user_config
- it_behaves_like 'responding to provided instance method', :destroy_user_config
- it_behaves_like "raising 'NotImplemented' error for base methods", :verify, [ nil, nil ]
- it_behaves_like "raising 'NotImplemented' error for base methods", :initiate_configuration
- it_behaves_like 'returning expected value', :available?, true
- it_behaves_like 'returning expected value', :enabled?, nil
- it_behaves_like 'returning expected value', :method_name, 'authentication_method', assertion: 'eq'
- it_behaves_like 'returning expected value', :related_setting_name, 'two_factor_authentication_method_authentication_method', assertion: 'eq'
- describe '#create_user_config' do
- let(:secret) { ROTP::Base32.random_base32 }
- let(:data) do
- {
- secret: secret,
- provisioning_uri: ROTP::TOTP.new(secret, issuer: 'Zammad CI').provisioning_uri(user.login),
- }
- end
- it 'saves two factor configuration for the user' do
- instance.create_user_config(data)
- expect(user.two_factor_preferences).to include(User::TwoFactorPreference)
- end
- context 'with existing configuration' do
- let!(:two_factor_pref) { create(:user_two_factor_preference, :security_keys, method: 'authentication_method', user: user) }
- let(:data) do
- {
- 'credentials' => [
- *two_factor_pref.configuration[:credentials],
- {
- 'external_id' => Faker::Alphanumeric.alpha(number: 70),
- 'public_key' => Faker::Alphanumeric.alpha(number: 128),
- 'nickname' => Faker::Lorem.unique.word,
- 'sign_count' => '0',
- 'created_at' => Time.zone.now,
- },
- ]
- }
- end
- it 'updates two factor configuration for the user' do
- instance.create_user_config(data)
- expect(two_factor_pref.reload.configuration).to eq(data)
- end
- end
- end
- describe '#update_user_config' do
- let!(:two_factor_pref) { create(:user_two_factor_preference, :authenticator_app, method: 'authentication_method', user: user) }
- let(:secret) { ROTP::Base32.random_base32 }
- let(:data) do
- {
- 'code' => two_factor_pref.configuration[:code],
- 'secret' => secret,
- 'provisioning_uri' => ROTP::TOTP.new(secret, issuer: 'Zammad CI').provisioning_uri(user.login),
- }
- end
- it 'updates two factor configuration for the user' do
- instance.update_user_config(data)
- expect(two_factor_pref.reload.configuration).to eq(data)
- end
- end
- describe '#destroy_user_config' do
- before { create(:user_two_factor_preference, :authenticator_app, method: 'authentication_method', user: user) }
- it 'removes two factor configuration for the user' do
- instance.destroy_user_config
- expect(user.reload.two_factor_preferences).to be_empty
- end
- context 'with existing recovery codes' do
- it 'deletes recovery code', :aggregate_failures do
- instance.destroy_user_config
- expect(user.reload.two_factor_preferences.authentication_methods).to be_empty
- expect(user.reload.two_factor_preferences.recovery_codes).to be_nil
- end
- end
- end
- end
|