2019-07-31 22:56:46 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-10-24 18:46:33 +05:30
|
|
|
require 'spec_helper'
|
|
|
|
|
2021-03-11 19:13:27 +05:30
|
|
|
RSpec.describe InvitesController do
|
2020-07-28 23:09:34 +05:30
|
|
|
let_it_be(:user) { create(:user) }
|
2021-04-29 21:17:54 +05:30
|
|
|
let_it_be(:member, reload: true) { create(:project_member, :invited, invite_email: user.email) }
|
2021-09-30 23:02:18 +05:30
|
|
|
|
2020-11-24 15:15:51 +05:30
|
|
|
let(:raw_invite_token) { member.raw_invite_token }
|
2020-07-28 23:09:34 +05:30
|
|
|
let(:project_members) { member.source.users }
|
2020-11-24 15:15:51 +05:30
|
|
|
let(:md5_member_global_id) { Digest::MD5.hexdigest(member.to_global_id.to_s) }
|
2021-06-08 01:23:25 +05:30
|
|
|
let(:extra_params) { {} }
|
|
|
|
let(:params) { { id: raw_invite_token }.merge(extra_params) }
|
2015-10-24 18:46:33 +05:30
|
|
|
|
2021-01-03 14:25:43 +05:30
|
|
|
shared_examples 'invalid token' do
|
|
|
|
context 'when invite token is not valid' do
|
2021-06-08 01:23:25 +05:30
|
|
|
let(:raw_invite_token) { '_bogus_token_' }
|
2021-01-03 14:25:43 +05:30
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
it 'redirects to root' do
|
2021-01-03 14:25:43 +05:30
|
|
|
request
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
expect(response).to redirect_to(root_path)
|
|
|
|
expect(controller).to set_flash[:alert].to('The invitation can not be found with the provided invite token.')
|
2021-01-03 14:25:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-08-04 16:29:09 +05:30
|
|
|
shared_examples 'invite email match enforcement' do |error_status:, flash_alert: nil|
|
|
|
|
it 'accepts user if invite email matches signed in user' do
|
|
|
|
expect do
|
|
|
|
request
|
|
|
|
end.to change { project_members.include?(user) }.from(false).to(true)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:found)
|
|
|
|
expect(flash[:notice]).to include 'You have been granted'
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'accepts invite if invite email matches confirmed secondary email' do
|
|
|
|
secondary_email = create(:email, :confirmed, user: user)
|
|
|
|
member.update!(invite_email: secondary_email.email)
|
|
|
|
|
|
|
|
expect do
|
|
|
|
request
|
|
|
|
end.to change { project_members.include?(user) }.from(false).to(true)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:found)
|
|
|
|
expect(flash[:notice]).to include 'You have been granted'
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not accept if invite email matches unconfirmed secondary email' do
|
|
|
|
secondary_email = create(:email, user: user)
|
|
|
|
member.update!(invite_email: secondary_email.email)
|
|
|
|
|
|
|
|
expect do
|
|
|
|
request
|
|
|
|
end.not_to change { project_members.include?(user) }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(error_status)
|
|
|
|
expect(flash[:alert]).to eq(flash_alert)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not accept if invite email does not match signed in user' do
|
|
|
|
member.update!(invite_email: 'bogus@email.com')
|
|
|
|
|
|
|
|
expect do
|
|
|
|
request
|
|
|
|
end.not_to change { project_members.include?(user) }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(error_status)
|
|
|
|
expect(flash[:alert]).to eq(flash_alert)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
describe 'GET #show', :snowplow do
|
2020-11-24 15:15:51 +05:30
|
|
|
subject(:request) { get :show, params: params }
|
|
|
|
|
2021-08-04 16:29:09 +05:30
|
|
|
context 'when logged in' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'invite email match enforcement', error_status: :ok
|
|
|
|
it_behaves_like 'invalid token'
|
|
|
|
end
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
context 'when it is an initial invite email' do
|
2021-06-08 01:23:25 +05:30
|
|
|
let(:extra_params) { { invite_type: 'initial_email' } }
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
it 'tracks the initial join click from email' do
|
2021-06-08 01:23:25 +05:30
|
|
|
request
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
expect_snowplow_event(
|
|
|
|
category: described_class.name,
|
|
|
|
action: 'join_clicked',
|
|
|
|
label: 'invite_email',
|
|
|
|
property: member.id.to_s
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
context 'when member does not exist' do
|
|
|
|
let(:raw_invite_token) { '_bogus_token_' }
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
it 'does not track join click' do
|
2021-06-08 01:23:25 +05:30
|
|
|
request
|
2021-10-27 15:23:28 +05:30
|
|
|
|
|
|
|
expect_no_snowplow_event(
|
|
|
|
category: described_class.name,
|
|
|
|
action: 'join_clicked',
|
|
|
|
label: 'invite_email'
|
|
|
|
)
|
2021-06-08 01:23:25 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-10-27 15:23:28 +05:30
|
|
|
context 'when it is not an initial email' do
|
|
|
|
it 'does not track the join click' do
|
2021-06-08 01:23:25 +05:30
|
|
|
request
|
2021-10-27 15:23:28 +05:30
|
|
|
|
|
|
|
expect_no_snowplow_event(
|
|
|
|
category: described_class.name,
|
|
|
|
action: 'join_clicked',
|
|
|
|
label: 'invite_email'
|
|
|
|
)
|
|
|
|
end
|
2021-06-08 01:23:25 +05:30
|
|
|
end
|
|
|
|
|
2020-11-24 15:15:51 +05:30
|
|
|
context 'when not logged in' do
|
2021-06-08 01:23:25 +05:30
|
|
|
context 'when invite token belongs to a valid member' do
|
2021-04-29 21:17:54 +05:30
|
|
|
context 'when instance allows sign up' do
|
|
|
|
it 'indicates an account can be created in notice' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(flash[:notice]).to include('or create an account')
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user exists with the invited email' do
|
|
|
|
it 'is redirected to a new session with invite email param' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user exists with the invited email as secondary email' do
|
|
|
|
before do
|
|
|
|
member.update!(invite_email: secondary_email.email)
|
|
|
|
end
|
|
|
|
|
2022-07-29 17:44:30 +05:30
|
|
|
context 'when secondary email is confirmed' do
|
|
|
|
let(:secondary_email) { create(:email, :confirmed, user: user, email: 'foo@example.com') }
|
2021-04-29 21:17:54 +05:30
|
|
|
|
2022-07-29 17:44:30 +05:30
|
|
|
it 'is redirected to a new session with invite email param' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when secondary email is unconfirmed' do
|
|
|
|
let(:secondary_email) { create(:email, user: user, email: 'foo@example.com') }
|
|
|
|
|
|
|
|
it 'is redirected to a new registration with invite email param and flash message', :aggregate_failures do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(response).to redirect_to(new_user_registration_path(invite_email: member.invite_email))
|
|
|
|
expect(flash[:notice]).to eq 'To accept this invitation, create an account or sign in.'
|
|
|
|
end
|
2021-04-29 21:17:54 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user does not exist with the invited email' do
|
|
|
|
before do
|
|
|
|
member.update!(invite_email: 'bogus_email@example.com')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'indicates an account can be created in notice' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(flash[:notice]).to include('create an account or sign in')
|
|
|
|
end
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
it 'is redirected to a new registration with invite email param and flash message', :aggregate_failures do
|
|
|
|
request
|
2021-06-08 01:23:25 +05:30
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
expect(response).to redirect_to(new_user_registration_path(invite_email: member.invite_email))
|
|
|
|
expect(flash[:notice]).to eq 'To accept this invitation, create an account or sign in.'
|
2021-06-08 01:23:25 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
it 'sets session keys for auto email confirmation on sign up' do
|
2021-04-29 21:17:54 +05:30
|
|
|
request
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
expect(session[:invite_email]).to eq(member.invite_email)
|
|
|
|
end
|
|
|
|
|
2023-06-20 00:43:36 +05:30
|
|
|
context 'with stored location for user' do
|
|
|
|
it 'stores the correct path for user' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(controller.stored_location_for(:user)).to eq(activity_project_path(member.source))
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with relative root' do
|
|
|
|
before do
|
|
|
|
stub_default_url_options(script_name: '/gitlab')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'stores the correct path for user' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(controller.stored_location_for(:user)).to eq(activity_project_path(member.source))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
context 'when it is part of our invite email experiment' do
|
|
|
|
let(:extra_params) { { invite_type: 'initial_email' } }
|
|
|
|
|
|
|
|
it 'sets session key for invite acceptance tracking on sign-up' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(session[:originating_member_id]).to eq(member.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when it is not part of our invite email experiment' do
|
|
|
|
it 'does not set the session key for invite acceptance tracking on sign-up' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(session[:originating_member_id]).to be_nil
|
|
|
|
end
|
2021-04-29 21:17:54 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when instance does not allow sign up' do
|
|
|
|
before do
|
|
|
|
stub_application_setting(allow_signup?: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not indicate an account can be created in notice' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(flash[:notice]).not_to include('or create an account')
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user exists with the invited email' do
|
|
|
|
it 'is redirected to a new session with invite email param' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user does not exist with the invited email' do
|
|
|
|
before do
|
|
|
|
member.update!(invite_email: 'bogus_email@example.com')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is redirected to a new session with invite email param' do
|
|
|
|
request
|
2020-11-24 15:15:51 +05:30
|
|
|
|
2021-04-29 21:17:54 +05:30
|
|
|
expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
|
|
|
|
end
|
|
|
|
end
|
2020-11-24 15:15:51 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-06-08 01:23:25 +05:30
|
|
|
context 'when invite token does not belong to a valid member' do
|
2020-11-24 15:15:51 +05:30
|
|
|
let(:params) { { id: '_bogus_token_' } }
|
|
|
|
|
|
|
|
it 'is redirected to a new session' do
|
|
|
|
request
|
|
|
|
|
|
|
|
expect(response).to redirect_to(new_user_session_path)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'POST #accept' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:request) { post :accept, params: params }
|
|
|
|
|
2021-08-04 16:29:09 +05:30
|
|
|
it_behaves_like 'invite email match enforcement', error_status: :redirect, flash_alert: 'The invitation could not be accepted.'
|
2021-01-03 14:25:43 +05:30
|
|
|
it_behaves_like 'invalid token'
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'POST #decline for link in UI' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:request) { post :decline, params: params }
|
|
|
|
|
|
|
|
it_behaves_like 'invalid token'
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'GET #decline for link in email' do
|
|
|
|
before do
|
|
|
|
sign_in(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:request) { get :decline, params: params }
|
|
|
|
|
|
|
|
it_behaves_like 'invalid token'
|
2020-07-28 23:09:34 +05:30
|
|
|
end
|
2015-10-24 18:46:33 +05:30
|
|
|
end
|