summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/application_controller_spec.rb201
-rw-r--r--spec/models/group_spec.rb42
-rw-r--r--spec/models/members/group_member_spec.rb17
-rw-r--r--spec/models/user_spec.rb42
4 files changed, 299 insertions, 3 deletions
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 81cbccd5436..64cfb87da5d 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -100,8 +100,6 @@ describe ApplicationController do
end
describe '#route_not_found' do
- let(:controller) { ApplicationController.new }
-
it 'renders 404 if authenticated' do
allow(controller).to receive(:current_user).and_return(user)
expect(controller).to receive(:not_found)
@@ -115,4 +113,203 @@ describe ApplicationController do
controller.send(:route_not_found)
end
end
+
+ context 'two-factor authentication' do
+ let(:controller) { ApplicationController.new }
+
+ describe '#check_2fa_requirement' do
+ subject { controller.send :check_2fa_requirement }
+
+ it 'does not redirect if 2FA is not required' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(false)
+ expect(controller).not_to receive(:redirect_to)
+
+ subject
+ end
+
+ it 'does not redirect if user is not logged in' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(controller).to receive(:current_user).and_return(nil)
+ expect(controller).not_to receive(:redirect_to)
+
+ subject
+ end
+
+ it 'does not redirect if user has 2FA enabled' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(controller).to receive(:current_user).twice.and_return(user)
+ allow(user).to receive(:two_factor_enabled?).and_return(true)
+ expect(controller).not_to receive(:redirect_to)
+
+ subject
+ end
+
+ it 'does not redirect if 2FA setup can be skipped' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(controller).to receive(:current_user).twice.and_return(user)
+ allow(user).to receive(:two_factor_enabled?).and_return(false)
+ allow(controller).to receive(:skip_two_factor?).and_return(true)
+ expect(controller).not_to receive(:redirect_to)
+
+ subject
+ end
+
+ it 'redirects to 2FA setup otherwise' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(controller).to receive(:current_user).twice.and_return(user)
+ allow(user).to receive(:two_factor_enabled?).and_return(false)
+ allow(controller).to receive(:skip_two_factor?).and_return(false)
+ allow(controller).to receive(:profile_two_factor_auth_path)
+ expect(controller).to receive(:redirect_to)
+
+ subject
+ end
+ end
+
+ describe '#two_factor_authentication_required?' do
+ subject { controller.send :two_factor_authentication_required? }
+
+ it 'returns false if no 2FA requirement is present' do
+ allow(controller).to receive(:current_user).and_return(nil)
+
+ expect(subject).to be_falsey
+ end
+
+ it 'returns true if a 2FA requirement is set in the application settings' do
+ stub_application_setting require_two_factor_authentication: true
+ allow(controller).to receive(:current_user).and_return(nil)
+
+ expect(subject).to be_truthy
+ end
+
+ it 'returns true if a 2FA requirement is set on the user' do
+ user.require_two_factor_authentication = true
+ allow(controller).to receive(:current_user).and_return(user)
+
+ expect(subject).to be_truthy
+ end
+ end
+
+ describe '#two_factor_grace_period' do
+ subject { controller.send :two_factor_grace_period }
+
+ it 'returns the grace period from the application settings' do
+ stub_application_setting two_factor_grace_period: 23
+ allow(controller).to receive(:current_user).and_return(nil)
+
+ expect(subject).to eq 23
+ end
+
+ context 'with a 2FA requirement set on the user' do
+ let(:user) { create :user, require_two_factor_authentication: true, two_factor_grace_period: 23 }
+
+ it 'returns the user grace period if lower than the application grace period' do
+ stub_application_setting two_factor_grace_period: 24
+ allow(controller).to receive(:current_user).and_return(user)
+
+ expect(subject).to eq 23
+ end
+
+ it 'returns the application grace period if lower than the user grace period' do
+ stub_application_setting two_factor_grace_period: 22
+ allow(controller).to receive(:current_user).and_return(user)
+
+ expect(subject).to eq 22
+ end
+ end
+ end
+
+ describe '#two_factor_grace_period_expired?' do
+ subject { controller.send :two_factor_grace_period_expired? }
+
+ before do
+ allow(controller).to receive(:current_user).and_return(user)
+ end
+
+ it 'returns false if the user has not started their grace period yet' do
+ expect(subject).to be_falsey
+ end
+
+ context 'with grace period started' do
+ let(:user) { create :user, otp_grace_period_started_at: 2.hours.ago }
+
+ it 'returns true if the grace period has expired' do
+ allow(controller).to receive(:two_factor_grace_period).and_return(1)
+
+ expect(subject).to be_truthy
+ end
+
+ it 'returns false if the grace period is still active' do
+ allow(controller).to receive(:two_factor_grace_period).and_return(3)
+
+ expect(subject).to be_falsey
+ end
+ end
+ end
+
+ describe '#two_factor_skippable' do
+ subject { controller.send :two_factor_skippable? }
+
+ before do
+ allow(controller).to receive(:current_user).and_return(user)
+ end
+
+ it 'returns false if 2FA is not required' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(false)
+
+ expect(subject).to be_falsey
+ end
+
+ it 'returns false if the user has already enabled 2FA' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(user).to receive(:two_factor_enabled?).and_return(true)
+
+ expect(subject).to be_falsey
+ end
+
+ it 'returns false if the 2FA grace period has expired' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(user).to receive(:two_factor_enabled?).and_return(false)
+ allow(controller).to receive(:two_factor_grace_period_expired?).and_return(true)
+
+ expect(subject).to be_falsey
+ end
+
+ it 'returns true otherwise' do
+ allow(controller).to receive(:two_factor_authentication_required?).and_return(true)
+ allow(user).to receive(:two_factor_enabled?).and_return(false)
+ allow(controller).to receive(:two_factor_grace_period_expired?).and_return(false)
+
+ expect(subject).to be_truthy
+ end
+ end
+
+ describe '#skip_two_factor?' do
+ subject { controller.send :skip_two_factor? }
+
+ it 'returns false if 2FA setup was not skipped' do
+ allow(controller).to receive(:session).and_return({})
+
+ expect(subject).to be_falsey
+ end
+
+ context 'with 2FA setup skipped' do
+ before do
+ allow(controller).to receive(:session).and_return({ skip_tfa: 2.hours.from_now })
+ end
+
+ it 'returns false if the grace period has expired' do
+ Timecop.freeze(3.hours.from_now) do
+ expect(subject).to be_falsey
+ end
+ end
+
+ it 'returns true if the grace period is still active' do
+ Timecop.freeze(1.hour.from_now) do
+ expect(subject).to be_truthy
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 5d87938235a..8ffde6f7fbb 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -55,6 +55,8 @@ describe Group, models: true do
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_id) }
it { is_expected.to validate_presence_of :path }
it { is_expected.not_to validate_presence_of :owner }
+ it { is_expected.to validate_presence_of :two_factor_grace_period }
+ it { is_expected.to validate_numericality_of(:two_factor_grace_period).is_greater_than_or_equal_to(0) }
end
describe '.visible_to_user' do
@@ -315,4 +317,44 @@ describe Group, models: true do
to include(master.id, developer.id)
end
end
+
+ describe '#update_two_factor_requirement' do
+ let(:user) { create(:user) }
+
+ before do
+ group.add_user(user, GroupMember::OWNER)
+ end
+
+ it 'is called when require_two_factor_authentication is changed' do
+ expect_any_instance_of(User).to receive(:update_two_factor_requirement)
+
+ group.update!(require_two_factor_authentication: true)
+ end
+
+ it 'is called when two_factor_grace_period is changed' do
+ expect_any_instance_of(User).to receive(:update_two_factor_requirement)
+
+ group.update!(two_factor_grace_period: 23)
+ end
+
+ it 'is not called when other attributes are changed' do
+ expect_any_instance_of(User).not_to receive(:update_two_factor_requirement)
+
+ group.update!(description: 'foobar')
+ end
+
+ it 'calls #update_two_factor_requirement on each group member' do
+ other_user = create(:user)
+ group.add_user(other_user, GroupMember::OWNER)
+
+ calls = 0
+ allow_any_instance_of(User).to receive(:update_two_factor_requirement) do
+ calls += 1
+ end
+
+ group.update!(require_two_factor_authentication: true, two_factor_grace_period: 23)
+
+ expect(calls).to eq 2
+ end
+ end
end
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index 370aeb9e0a9..024380b7ebb 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -61,7 +61,7 @@ describe GroupMember, models: true do
describe '#after_accept_request' do
it 'calls NotificationService.accept_group_access_request' do
- member = create(:group_member, user: build_stubbed(:user), requested_at: Time.now)
+ member = create(:group_member, user: build(:user), requested_at: Time.now)
expect_any_instance_of(NotificationService).to receive(:new_group_member)
@@ -75,4 +75,19 @@ describe GroupMember, models: true do
it { is_expected.to eq 'Group' }
end
end
+
+ describe '#update_two_factor_requirement' do
+ let(:user) { build :user }
+ let(:group_member) { build :group_member, user: user }
+
+ it 'is called after creation and deletion' do
+ expect(user).to receive(:update_two_factor_requirement)
+
+ group_member.save
+
+ expect(user).to receive(:update_two_factor_requirement)
+
+ group_member.destroy
+ end
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index a9e37be1157..b2f686a1819 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1521,4 +1521,46 @@ describe User, models: true do
end
end
end
+
+ describe '#update_two_factor_requirement' do
+ let(:user) { create :user }
+
+ context 'with 2FA requirement on groups' do
+ let(:group1) { create :group, require_two_factor_authentication: true, two_factor_grace_period: 23 }
+ let(:group2) { create :group, require_two_factor_authentication: true, two_factor_grace_period: 32 }
+
+ before do
+ group1.add_user(user, GroupMember::OWNER)
+ group2.add_user(user, GroupMember::OWNER)
+
+ user.update_two_factor_requirement
+ end
+
+ it 'requires 2FA' do
+ expect(user.require_two_factor_authentication).to be true
+ end
+
+ it 'uses the shortest grace period' do
+ expect(user.two_factor_grace_period).to be 23
+ end
+ end
+
+ context 'without 2FA requirement on groups' do
+ let(:group) { create :group }
+
+ before do
+ group.add_user(user, GroupMember::OWNER)
+
+ user.update_two_factor_requirement
+ end
+
+ it 'does not require 2FA' do
+ expect(user.require_two_factor_authentication).to be false
+ end
+
+ it 'falls back to the default grace period' do
+ expect(user.two_factor_grace_period).to be 48
+ end
+ end
+ end
end