login_spec.rb 5.47 KB
Newer Older
1 2
require 'spec_helper'

3
feature 'Login', feature: true do
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
  describe 'initial login after setup' do
    it 'allows the initial admin to create a password' do
      # This behavior is dependent on there only being one user
      User.delete_all

      user = create(:admin, password_automatically_set: true)

      visit root_path
      expect(current_path).to eq edit_user_password_path
      expect(page).to have_content('Please create a password for your new account.')

      fill_in 'user_password',              with: 'password'
      fill_in 'user_password_confirmation', with: 'password'
      click_button 'Change your password'

      expect(current_path).to eq new_user_session_path
      expect(page).to have_content(I18n.t('devise.passwords.updated_not_active'))

      fill_in 'user_login',    with: user.username
      fill_in 'user_password', with: 'password'
      click_button 'Sign in'

      expect(current_path).to eq root_path
    end
  end

30
  describe 'with two-factor authentication' do
31
    context 'with valid username/password' do
32 33
      let(:user) { create(:user, :two_factor) }

34 35 36 37 38 39
      before do
        login_with(user)
        expect(page).to have_content('Two-factor Authentication')
      end

      def enter_code(code)
40
        fill_in 'Two-factor Authentication code', with: code
41 42 43
        click_button 'Verify code'
      end

44 45 46 47 48
      it 'does not show a "You are already signed in." error message' do
        enter_code(user.current_otp)
        expect(page).not_to have_content('You are already signed in.')
      end

49 50 51 52 53 54 55 56 57 58
      context 'using one-time code' do
        it 'allows login with valid code' do
          enter_code(user.current_otp)
          expect(current_path).to eq root_path
        end

        it 'blocks login with invalid code' do
          enter_code('foo')
          expect(page).to have_content('Invalid two-factor code')
        end
59 60 61 62 63 64 65 66

        it 'allows login with invalid code, then valid code' do
          enter_code('foo')
          expect(page).to have_content('Invalid two-factor code')

          enter_code(user.current_otp)
          expect(current_path).to eq root_path
        end
67 68 69 70 71 72
      end

      context 'using backup code' do
        let(:codes) { user.generate_otp_backup_codes! }

        before do
73
          expect(codes.size).to eq 10
74

75
          # Ensure the generated codes get saved
76 77 78 79 80 81 82 83 84 85
          user.save
        end

        context 'with valid code' do
          it 'allows login' do
            enter_code(codes.sample)
            expect(current_path).to eq root_path
          end

          it 'invalidates the used code' do
86 87
            expect { enter_code(codes.sample) }.
              to change { user.reload.otp_backup_codes.size }.by(-1)
88 89 90 91 92 93 94
          end
        end

        context 'with invalid code' do
          it 'blocks login' do
            code = codes.sample
            expect(user.invalidate_otp_backup_code!(code)).to eq true
95

96
            user.save!
97
            expect(user.reload.otp_backup_codes.size).to eq 9
98 99

            enter_code(code)
100
            expect(page).to have_content('Invalid two-factor code.')
101 102 103 104 105 106
          end
        end
      end
    end
  end

107
  describe 'without two-factor authentication' do
108 109
    let(:user) { create(:user) }

110 111 112 113
    it 'allows basic login' do
      login_with(user)
      expect(current_path).to eq root_path
    end
114 115 116 117 118 119 120 121 122 123

    it 'does not show a "You are already signed in." error message' do
      login_with(user)
      expect(page).not_to have_content('You are already signed in.')
    end

    it 'blocks invalid login' do
      user = create(:user, password: 'not-the-default')

      login_with(user)
124
      expect(page).to have_content('Invalid login or password.')
125
    end
126
  end
127 128 129 130 131 132 133 134 135 136 137 138 139 140

  describe 'with required two-factor authentication enabled' do
    let(:user) { create(:user) }
    before(:each) { stub_application_setting(require_two_factor_authentication: true) }

    context 'with grace period defined' do
      before(:each) do
        stub_application_setting(two_factor_grace_period: 48)
        login_with(user)
      end

      context 'within the grace period' do
        it 'redirects to two-factor configuration page' do
          expect(current_path).to eq new_profile_two_factor_auth_path
141
          expect(page).to have_content('You must enable Two-factor Authentication for your account before')
142 143
        end

144
        it 'disallows skipping two-factor configuration' do
145 146 147 148 149 150 151 152 153 154 155 156
          expect(current_path).to eq new_profile_two_factor_auth_path

          click_link 'Configure it later'
          expect(current_path).to eq root_path
        end
      end

      context 'after the grace period' do
        let(:user) { create(:user, otp_grace_period_started_at: 9999.hours.ago) }

        it 'redirects to two-factor configuration page' do
          expect(current_path).to eq new_profile_two_factor_auth_path
157
          expect(page).to have_content('You must enable Two-factor Authentication for your account.')
158 159
        end

160
        it 'disallows skipping two-factor configuration' do
161 162 163 164 165 166 167 168 169 170 171 172 173 174
          expect(current_path).to eq new_profile_two_factor_auth_path
          expect(page).not_to have_link('Configure it later')
        end
      end
    end

    context 'without grace pariod defined' do
      before(:each) do
        stub_application_setting(two_factor_grace_period: 0)
        login_with(user)
      end

      it 'redirects to two-factor configuration page' do
        expect(current_path).to eq new_profile_two_factor_auth_path
175
        expect(page).to have_content('You must enable Two-factor Authentication for your account.')
176 177 178
      end
    end
  end
179
end