Merge upstream tag 'v3.5.2'

This commit is contained in:
Mike Barnes 2022-05-23 19:28:18 +10:00
commit d161ca885c
2205 changed files with 91260 additions and 41616 deletions

View file

@ -32,6 +32,52 @@ describe Auth::ConfirmationsController, type: :controller do
end
end
context 'when user is unconfirmed and unapproved' do
let!(:user) { Fabricate(:user, confirmation_token: 'foobar', confirmed_at: nil, approved: false) }
before do
allow(BootstrapTimelineWorker).to receive(:perform_async)
@request.env['devise.mapping'] = Devise.mappings[:user]
get :show, params: { confirmation_token: 'foobar' }
end
it 'redirects to login' do
expect(response).to redirect_to(new_user_session_path)
end
end
context 'when user is already confirmed' do
let!(:user) { Fabricate(:user) }
before do
allow(BootstrapTimelineWorker).to receive(:perform_async)
@request.env['devise.mapping'] = Devise.mappings[:user]
sign_in(user, scope: :user)
get :show, params: { confirmation_token: 'foobar' }
end
it 'redirects to root path' do
expect(response).to redirect_to(root_path)
end
end
context 'when user is already confirmed but unapproved' do
let!(:user) { Fabricate(:user, approved: false) }
before do
allow(BootstrapTimelineWorker).to receive(:perform_async)
@request.env['devise.mapping'] = Devise.mappings[:user]
user.approved = false
user.save!
sign_in(user, scope: :user)
get :show, params: { confirmation_token: 'foobar' }
end
it 'redirects to settings' do
expect(response).to redirect_to(edit_user_registration_path)
end
end
context 'when user is updating email' do
let!(:user) { Fabricate(:user, confirmation_token: 'foobar', unconfirmed_email: 'new-email@example.com') }

View file

@ -228,7 +228,7 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
end
it 'does nothing if user already exists' do
Fabricate(:user, account: Fabricate(:account, username: 'test'))
Fabricate(:account, username: 'test')
subject
end

View file

@ -37,8 +37,11 @@ RSpec.describe Auth::SessionsController, type: :controller do
end
context 'with a suspended user' do
before do
user.account.suspend!
end
it 'redirects to home after sign out' do
Fabricate(:account, user: user, suspended: true)
sign_in(user, scope: :user)
delete :destroy
@ -69,7 +72,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
end
it 'shows a login error' do
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email'))
end
it "doesn't log the user in" do
@ -78,8 +81,8 @@ RSpec.describe Auth::SessionsController, type: :controller do
end
context 'using a valid email and existing user' do
let(:user) do
account = Fabricate.build(:account, username: 'pam_user1')
let!(:user) do
account = Fabricate.build(:account, username: 'pam_user1', user: nil)
account.save!(validate: false)
user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account, external: true)
user
@ -136,7 +139,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
end
it 'shows a login error' do
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: I18n.t('activerecord.attributes.user.email'))
end
it "doesn't log the user in" do
@ -222,22 +225,6 @@ RSpec.describe Auth::SessionsController, type: :controller do
end
end
context 'using email and password after an unfinished log-in attempt with a sign-in token challenge' do
let!(:other_user) do
Fabricate(:user, email: 'z@y.com', password: 'abcdefgh', otp_required_for_login: false, current_sign_in_at: 1.month.ago)
end
before do
post :create, params: { user: { email: other_user.email, password: other_user.password } }
post :create, params: { user: { email: user.email, password: user.password } }
end
it 'renders two factor authentication page' do
expect(controller).to render_template("two_factor")
expect(controller).to render_template(partial: "_otp_authentication_form")
end
end
context 'using upcase email and password' do
before do
post :create, params: { user: { email: user.email.upcase, password: user.password } }
@ -398,124 +385,33 @@ RSpec.describe Auth::SessionsController, type: :controller do
end
end
end
end
context 'when 2FA is disabled and IP is unfamiliar' do
let!(:user) { Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', current_sign_in_at: 3.weeks.ago, current_sign_in_ip: '0.0.0.0') }
describe 'GET #webauthn_options' do
context 'with WebAuthn and OTP enabled as second factor' do
let(:domain) { "#{Rails.configuration.x.use_https ? 'https' : 'http' }://#{Rails.configuration.x.web_domain}" }
let(:fake_client) { WebAuthn::FakeClient.new(domain) }
let!(:user) do
Fabricate(:user, email: 'x@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32))
end
before do
request.remote_ip = '10.10.10.10'
request.user_agent = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0'
allow(UserMailer).to receive(:sign_in_token).and_return(double('email', deliver_later!: nil))
user.update(webauthn_id: WebAuthn.generate_user_id)
public_key_credential = WebAuthn::Credential.from_create(fake_client.create)
user.webauthn_credentials.create(
nickname: 'SecurityKeyNickname',
external_id: public_key_credential.id,
public_key: public_key_credential.public_key,
sign_count: '1000'
)
post :create, params: { user: { email: user.email, password: user.password } }
end
context 'using email and password' do
before do
post :create, params: { user: { email: user.email, password: user.password } }
end
it 'renders sign in token authentication page' do
expect(controller).to render_template("sign_in_token")
end
it 'generates sign in token' do
expect(user.reload.sign_in_token).to_not be_nil
end
it 'sends sign in token e-mail' do
expect(UserMailer).to have_received(:sign_in_token)
end
end
context 'using email and password after an unfinished log-in attempt to a 2FA-protected account' do
let!(:other_user) do
Fabricate(:user, email: 'z@y.com', password: 'abcdefgh', otp_required_for_login: true, otp_secret: User.generate_otp_secret(32))
end
before do
post :create, params: { user: { email: other_user.email, password: other_user.password } }
post :create, params: { user: { email: user.email, password: user.password } }
end
it 'renders sign in token authentication page' do
expect(controller).to render_template("sign_in_token")
end
it 'generates sign in token' do
expect(user.reload.sign_in_token).to_not be_nil
end
it 'sends sign in token e-mail' do
expect(UserMailer).to have_received(:sign_in_token)
end
end
context 'using email and password after an unfinished log-in attempt with a sign-in token challenge' do
let!(:other_user) do
Fabricate(:user, email: 'z@y.com', password: 'abcdefgh', otp_required_for_login: false, current_sign_in_at: 1.month.ago)
end
before do
post :create, params: { user: { email: other_user.email, password: other_user.password } }
post :create, params: { user: { email: user.email, password: user.password } }
end
it 'renders sign in token authentication page' do
expect(controller).to render_template("sign_in_token")
end
it 'generates sign in token' do
expect(user.reload.sign_in_token).to_not be_nil
end
it 'sends sign in token e-mail' do
expect(UserMailer).to have_received(:sign_in_token).with(user, any_args)
end
end
context 'using a valid sign in token' do
before do
user.generate_sign_in_token && user.save
post :create, params: { user: { sign_in_token_attempt: user.sign_in_token } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end
it 'redirects to home' do
expect(response).to redirect_to(root_path)
end
it 'logs the user in' do
expect(controller.current_user).to eq user
end
end
context 'using a valid sign in token, attempting to leverage previous half-login to bypass password auth' do
let!(:other_user) do
Fabricate(:user, email: 'z@y.com', password: 'abcdefgh', otp_required_for_login: false, current_sign_in_at: 1.month.ago)
end
before do
user.generate_sign_in_token && user.save
post :create, params: { user: { email: other_user.email, password: other_user.password } }
post :create, params: { user: { email: user.email, sign_in_token_attempt: user.sign_in_token } }, session: { attempt_user_updated_at: user.updated_at.to_s }
end
it "doesn't log the user in" do
expect(controller.current_user).to be_nil
end
end
context 'using an invalid sign in token' do
before do
post :create, params: { user: { sign_in_token_attempt: 'wrongotp' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end
it 'shows a login error' do
expect(flash[:alert]).to match I18n.t('users.invalid_sign_in_token')
end
it "doesn't log the user in" do
expect(controller.current_user).to be_nil
end
it 'returns http success' do
get :webauthn_options
expect(response).to have_http_status :ok
end
end
end