Commit f8b652b9 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch...

Merge branch '321706-fix-error-message-inviting-to-disallowed-email-address-when-restrict-membership-by-domain-is' into 'master'

Change modal error message for restricted emails

See merge request gitlab-org/gitlab!61425
parents 19fb82e8 670a84b6
...@@ -11,9 +11,10 @@ import { ...@@ -11,9 +11,10 @@ import {
GlFormInput, GlFormInput,
GlFormCheckboxGroup, GlFormCheckboxGroup,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { partition, isString } from 'lodash'; import { partition, isString, unescape } from 'lodash';
import Api from '~/api'; import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking'; import ExperimentTracking from '~/experimentation/experiment_tracking';
import { sanitize } from '~/lib/dompurify';
import { BV_SHOW_MODAL } from '~/lib/utils/constants'; import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import { import {
...@@ -293,7 +294,7 @@ export default { ...@@ -293,7 +294,7 @@ export default {
}; };
}, },
conditionallyShowToastSuccess(response) { conditionallyShowToastSuccess(response) {
const message = responseMessageFromSuccess(response); const message = this.unescapeMsg(responseMessageFromSuccess(response));
if (message === '') { if (message === '') {
this.showToastMessageSuccess(); this.showToastMessageSuccess();
...@@ -309,13 +310,17 @@ export default { ...@@ -309,13 +310,17 @@ export default {
this.closeModal(); this.closeModal();
}, },
showInvalidFeedbackMessage(response) { showInvalidFeedbackMessage(response) {
const message = this.unescapeMsg(responseMessageFromError(response));
this.isLoading = false; this.isLoading = false;
this.invalidFeedbackMessage = this.invalidFeedbackMessage = message || this.$options.labels.invalidFeedbackMessageDefault;
responseMessageFromError(response) || this.$options.labels.invalidFeedbackMessageDefault;
}, },
handleMembersTokenSelectClear() { handleMembersTokenSelectClear() {
this.invalidFeedbackMessage = ''; this.invalidFeedbackMessage = '';
}, },
unescapeMsg(message) {
return unescape(sanitize(message, { ALLOWED_TAGS: [] }));
},
}, },
labels: { labels: {
members: { members: {
......
...@@ -18,7 +18,10 @@ function responseMessageStringForMultiple(message) { ...@@ -18,7 +18,10 @@ function responseMessageStringForMultiple(message) {
return message.includes(':'); return message.includes(':');
} }
function responseMessageStringFirstPart(message) { function responseMessageStringFirstPart(message) {
return message.split(' and ')[0]; const firstPart = message.split(':')[1];
const firstMsg = firstPart.split(/ and [\w-]*$/)[0].trim();
return firstMsg;
} }
export function responseMessageFromError(response) { export function responseMessageFromError(response) {
......
...@@ -7,15 +7,49 @@ module RestrictedSignup ...@@ -7,15 +7,49 @@ module RestrictedSignup
def validate_admin_signup_restrictions(email) def validate_admin_signup_restrictions(email)
return if allowed_domain?(email) return if allowed_domain?(email)
error_type = fetch_error_type(email)
return unless error_type.present?
[
signup_email_invalid_message,
error_message[created_by_key][error_type]
].join(' ')
end
def fetch_error_type(email)
if allowlist_present? if allowlist_present?
return _('domain is not authorized for sign-up.') :allowlist
elsif denied_domain?(email) elsif denied_domain?(email)
return _('is not from an allowed domain.') :denylist
elsif restricted_email?(email) elsif restricted_email?(email)
return _('is not allowed. Try again with a different email address, or contact your GitLab admin.') :restricted
end
end
def error_message
{
admin: {
allowlist: html_escape_once(_("Go to the 'Admin area > Sign-up restrictions', and check 'Allowed domains for sign-ups'.")).html_safe,
denylist: html_escape_once(_("Go to the 'Admin area > Sign-up restrictions', and check the 'Domain denylist'.")).html_safe,
restricted: html_escape_once(_("Go to the 'Admin area > Sign-up restrictions', and check 'Email restrictions for sign-ups'.")).html_safe,
group_setting: html_escape_once(_("Go to the group’s 'Settings > General' page, and check 'Restrict membership by email domain'.")).html_safe
},
nonadmin: {
allowlist: error_nonadmin,
denylist: error_nonadmin,
restricted: error_nonadmin,
group_setting: error_nonadmin
}
}
end
def error_nonadmin
_("Check with your administrator.")
end end
nil def created_by_key
created_by&.can_admin_all_resources? ? :admin : :nonadmin
end end
def denied_domain?(email) def denied_domain?(email)
......
...@@ -448,6 +448,14 @@ class Member < ApplicationRecord ...@@ -448,6 +448,14 @@ class Member < ApplicationRecord
errors.add(:user, error) if error errors.add(:user, error) if error
end end
def signup_email_invalid_message
if source_type == 'Project'
_("is not allowed for this project.")
else
_("is not allowed for this group.")
end
end
def update_highest_role? def update_highest_role?
return unless user_id.present? return unless user_id.present?
......
...@@ -2102,6 +2102,10 @@ class User < ApplicationRecord ...@@ -2102,6 +2102,10 @@ class User < ApplicationRecord
errors.add(:email, error) if error errors.add(:email, error) if error
end end
def signup_email_invalid_message
_('is not allowed for sign-up.')
end
def check_username_format def check_username_format
return if username.blank? || Mime::EXTENSION_LOOKUP.keys.none? { |type| username.end_with?(".#{type}") } return if username.blank? || Mime::EXTENSION_LOOKUP.keys.none? { |type| username.end_with?(".#{type}") }
......
...@@ -10,6 +10,9 @@ en: ...@@ -10,6 +10,9 @@ en:
target: Target issue target: Target issue
group: group:
path: Group URL path: Group URL
member:
user: "The member's email address"
invite_email: "The member's email address"
project/error_tracking_setting: project/error_tracking_setting:
token: "Auth Token" token: "Auth Token"
project: "Project" project: "Project"
......
...@@ -103,8 +103,11 @@ module EE ...@@ -103,8 +103,11 @@ module EE
end end
def email_does_not_match_any_allowed_domains(email) def email_does_not_match_any_allowed_domains(email)
n_("email does not match the allowed domain of %{email_domains}", "email does not match the allowed domains: %{email_domains}", group_allowed_email_domains.size) % msg_1 = signup_email_invalid_message
{ email_domains: group_allowed_email_domains.map(&:domain).join(', ') }
msg_2 = error_message[created_by_key][:group_setting]
[msg_1, msg_2].join(' ')
end end
def matches_at_least_one_group_allowed_email_domain?(email) def matches_at_least_one_group_allowed_email_domain?(email)
......
...@@ -189,7 +189,7 @@ RSpec.describe Groups::GroupMembersController do ...@@ -189,7 +189,7 @@ RSpec.describe Groups::GroupMembersController do
post :request_access, params: { group_id: group } post :request_access, params: { group_id: group }
expect(controller).to set_flash.to "Your request for access could not be processed: "\ expect(controller).to set_flash.to "Your request for access could not be processed: "\
"User email 'unverified@gitlab.com' is not a verified email." "The member's email address email 'unverified@gitlab.com' is not a verified email."
expect(response).to redirect_to(group_path(group)) expect(response).to redirect_to(group_path(group))
expect(group.requesters.exists?(user_id: requesting_user)).to be_falsey expect(group.requesters.exists?(user_id: requesting_user)).to be_falsey
expect(group.users).not_to include requesting_user expect(group.users).not_to include requesting_user
......
...@@ -12,7 +12,7 @@ RSpec.describe GroupMember do ...@@ -12,7 +12,7 @@ RSpec.describe GroupMember do
let(:source) { group } let(:source) { group }
let(:nested_source) { create(:group, parent: group) } let(:nested_source) { create(:group, parent: group) }
it_behaves_like 'member group domain validations' it_behaves_like 'member group domain validations', 'group'
end end
describe 'access level inclusion' do describe 'access level inclusion' do
......
...@@ -95,7 +95,7 @@ RSpec.describe ProjectMember do ...@@ -95,7 +95,7 @@ RSpec.describe ProjectMember do
let(:subgroup) { create(:group, parent: group) } let(:subgroup) { create(:group, parent: group) }
let(:nested_source) { create(:project, namespace: subgroup) } let(:nested_source) { create(:project, namespace: subgroup) }
it_behaves_like 'member group domain validations' it_behaves_like 'member group domain validations', 'project'
it 'does not validate personal projects' do it 'does not validate personal projects' do
unconfirmed_gitlab_user = create(:user, :unconfirmed, email: 'unverified@gitlab.com') unconfirmed_gitlab_user = create(:user, :unconfirmed, email: 'unverified@gitlab.com')
......
...@@ -21,40 +21,37 @@ RSpec.describe API::Invitations, 'EE Invitations' do ...@@ -21,40 +21,37 @@ RSpec.describe API::Invitations, 'EE Invitations' do
end end
end end
shared_examples 'admin signup restrictions email error' do shared_examples 'admin signup restrictions email error - denylist' do |message, code|
context 'when restricted by admin signup restriction - denylist' do
before do before do
stub_application_setting(domain_denylist_enabled: true) stub_application_setting(domain_denylist_enabled: true)
stub_application_setting(domain_denylist: ['example.org']) stub_application_setting(domain_denylist: ['example.org'])
end end
# this response code should be changed to 4xx: https://gitlab.com/gitlab-org/gitlab/-/issues/321706 it_behaves_like 'restricted email error', message, code
it_behaves_like 'restricted email error', 'User is not from an allowed domain.', :created
end end
context 'when restricted by admin signup restriction - allowlist' do shared_examples 'admin signup restrictions email error - allowlist' do |message, code|
before do before do
stub_application_setting(domain_allowlist: ['example.com']) stub_application_setting(domain_allowlist: ['example.com'])
end end
# this response code should be changed to 4xx: https://gitlab.com/gitlab-org/gitlab/-/issues/321706 it_behaves_like 'restricted email error', message, code
it_behaves_like 'restricted email error', 'User domain is not authorized for sign-up.', :created
end end
context 'when restricted by admin signup restriction - email restrictions' do shared_examples 'admin signup restrictions email error - email restrictions' do |message, code|
before do before do
stub_application_setting(email_restrictions_enabled: true) stub_application_setting(email_restrictions_enabled: true)
stub_application_setting(email_restrictions: '([\+]|\b(\w*example.org\w*)\b)') stub_application_setting(email_restrictions: '([\+]|\b(\w*example.org\w*)\b)')
end end
# this response code should be changed to 4xx: https://gitlab.com/gitlab-org/gitlab/-/issues/321706 it_behaves_like 'restricted email error', message, code
it_behaves_like 'restricted email error', 'User is not allowed. Try again with a different email address, or contact your GitLab admin.', :created
end
end end
describe 'POST /groups/:id/invitations' do describe 'POST /groups/:id/invitations' do
it_behaves_like 'admin signup restrictions email error - denylist', "The member's email address is not allowed for this group. Go to the &#39;Admin area &gt; Sign-up restrictions&#39;, and check the &#39;Domain denylist&#39;.", :created
context 'when the group is restricted by admin signup restrictions' do context 'when the group is restricted by admin signup restrictions' do
it_behaves_like 'admin signup restrictions email error' it_behaves_like 'admin signup restrictions email error - allowlist', "The member's email address is not allowed for this group. Go to the &#39;Admin area &gt; Sign-up restrictions&#39;, and check &#39;Allowed domains for sign-ups&#39;.", :created
it_behaves_like 'admin signup restrictions email error - email restrictions', "The member's email address is not allowed for this group. Go to the &#39;Admin area &gt; Sign-up restrictions&#39;, and check &#39;Email restrictions for sign-ups&#39;.", :created
end end
context 'when the group is restricted by group signup restriction - allowed domains for signup' do context 'when the group is restricted by group signup restriction - allowed domains for signup' do
...@@ -63,8 +60,7 @@ RSpec.describe API::Invitations, 'EE Invitations' do ...@@ -63,8 +60,7 @@ RSpec.describe API::Invitations, 'EE Invitations' do
create(:allowed_email_domain, group: group, domain: 'example.com') create(:allowed_email_domain, group: group, domain: 'example.com')
end end
# this response code should be changed to 4xx: https://gitlab.com/gitlab-org/gitlab/-/issues/321706 it_behaves_like 'restricted email error', "The member's email address is not allowed for this group. Go to the group’s &#39;Settings &gt; General&#39; page, and check &#39;Restrict membership by email domain&#39;.", :success
it_behaves_like 'restricted email error', "Invite email email does not match the allowed domain of example.com", :success
end end
end end
...@@ -74,7 +70,11 @@ RSpec.describe API::Invitations, 'EE Invitations' do ...@@ -74,7 +70,11 @@ RSpec.describe API::Invitations, 'EE Invitations' do
let(:url) { "/projects/#{project.id}/invitations" } let(:url) { "/projects/#{project.id}/invitations" }
context 'when the project is restricted by admin signup restrictions' do context 'when the project is restricted by admin signup restrictions' do
it_behaves_like 'admin signup restrictions email error' it_behaves_like 'admin signup restrictions email error - denylist', "The member's email address is not allowed for this project. Go to the &#39;Admin area &gt; Sign-up restrictions&#39;, and check the &#39;Domain denylist&#39;.", :created
context 'when the group is restricted by admin signup restrictions' do
it_behaves_like 'admin signup restrictions email error - allowlist', "The member's email address is not allowed for this project. Go to the &#39;Admin area &gt; Sign-up restrictions&#39;, and check &#39;Allowed domains for sign-ups&#39;.", :created
it_behaves_like 'admin signup restrictions email error - email restrictions', "The member's email address is not allowed for this project. Go to the &#39;Admin area &gt; Sign-up restrictions&#39;, and check &#39;Email restrictions for sign-ups&#39;.", :created
end
end end
end end
end end
...@@ -53,7 +53,7 @@ RSpec.describe Groups::GroupMembersController do ...@@ -53,7 +53,7 @@ RSpec.describe Groups::GroupMembersController do
it 'returns error message' do it 'returns error message' do
subject subject
expect(json_response).to eq({ 'message' => "User email does not match the allowed domain of gitlab.com" }) expect(json_response['message']).to eq("The member's email address is not allowed for this group. Check with your administrator.")
end end
end end
end end
......
...@@ -53,7 +53,7 @@ RSpec.shared_examples 'member validations' do ...@@ -53,7 +53,7 @@ RSpec.shared_examples 'member validations' do
end end
end end
RSpec.shared_examples 'member group domain validations' do RSpec.shared_examples 'member group domain validations' do |source_type|
context 'validates group domain limitations' do context 'validates group domain limitations' do
let(:group) { create(:group) } let(:group) { create(:group) }
let(:gitlab_user) { create(:user, email: 'test@gitlab.com') } let(:gitlab_user) { create(:user, email: 'test@gitlab.com') }
...@@ -77,11 +77,20 @@ RSpec.shared_examples 'member group domain validations' do ...@@ -77,11 +77,20 @@ RSpec.shared_examples 'member group domain validations' do
expect(build(member_type, source: source, user: acme_user)).to be_valid expect(build(member_type, source: source, user: acme_user)).to be_valid
end end
it 'shows proper error message' do it 'shows proper error message when not invited by admin' do
member = build(member_type, source: source, user: gmail_user) member = build(member_type, source: source, user: gmail_user)
allow(member).to receive_message_chain(:created_by, :can_admin_all_resources?).and_return(false)
expect(member).to be_invalid expect(member).to be_invalid
expect(member.errors[:user]).to include("email does not match the allowed domains: gitlab.com, acme.com") expect(member.errors[:user]).to include("is not allowed for this #{source_type}. Check with your administrator.")
end
it 'shows proper error message when invited by admin' do
member = build(member_type, source: source, user: gmail_user)
allow(member).to receive_message_chain(:created_by, :can_admin_all_resources?).and_return(true)
expect(member).to be_invalid
expect(member.errors[:user]).to include("is not allowed for this #{source_type}. Go to the group’s &#39;Settings &gt; General&#39; page, and check &#39;Restrict membership by email domain&#39;.")
end end
it 'shows proper error message for single domain limitation' do it 'shows proper error message for single domain limitation' do
...@@ -89,7 +98,7 @@ RSpec.shared_examples 'member group domain validations' do ...@@ -89,7 +98,7 @@ RSpec.shared_examples 'member group domain validations' do
member = build(member_type, source: source, user: gmail_user) member = build(member_type, source: source, user: gmail_user)
expect(member).to be_invalid expect(member).to be_invalid
expect(member.errors[:user]).to include("email does not match the allowed domain of gitlab.com") expect(member.errors[:user]).to include("is not allowed for this #{source_type}. Check with your administrator.")
end end
it 'invited email must match at least one of the allowed domain emails' do it 'invited email must match at least one of the allowed domain emails' do
......
...@@ -6546,6 +6546,9 @@ msgstr "" ...@@ -6546,6 +6546,9 @@ msgstr ""
msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background." msgid "Check the elasticsearch.log file to debug why the migration was halted and make any changes before retrying the migration. When you fix the cause of the failure, click \"Retry migration\", and the migration will be scheduled to be retried in the background."
msgstr "" msgstr ""
msgid "Check with your administrator."
msgstr ""
msgid "Check your Docker images for known vulnerabilities." msgid "Check your Docker images for known vulnerabilities."
msgstr "" msgstr ""
...@@ -15820,9 +15823,21 @@ msgstr "" ...@@ -15820,9 +15823,21 @@ msgstr ""
msgid "Go to snippets" msgid "Go to snippets"
msgstr "" msgstr ""
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Allowed domains for sign-ups'."
msgstr ""
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Email restrictions for sign-ups'."
msgstr ""
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check the 'Domain denylist'."
msgstr ""
msgid "Go to the activity feed" msgid "Go to the activity feed"
msgstr "" msgstr ""
msgid "Go to the group’s 'Settings &gt; General' page, and check 'Restrict membership by email domain'."
msgstr ""
msgid "Go to the milestone list" msgid "Go to the milestone list"
msgstr "" msgstr ""
...@@ -40025,9 +40040,6 @@ msgstr "" ...@@ -40025,9 +40040,6 @@ msgstr ""
msgid "does not have a supported extension. Only %{extension_list} are supported" msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr "" msgstr ""
msgid "domain is not authorized for sign-up."
msgstr ""
msgid "download it" msgid "download it"
msgstr "" msgstr ""
...@@ -40045,11 +40057,6 @@ msgstr "" ...@@ -40045,11 +40057,6 @@ msgstr ""
msgid "email '%{email}' is not a verified email." msgid "email '%{email}' is not a verified email."
msgstr "" msgstr ""
msgid "email does not match the allowed domain of %{email_domains}"
msgid_plural "email does not match the allowed domains: %{email_domains}"
msgstr[0] ""
msgstr[1] ""
msgid "enabled" msgid "enabled"
msgstr "" msgstr ""
...@@ -40263,16 +40270,19 @@ msgstr "" ...@@ -40263,16 +40270,19 @@ msgstr ""
msgid "is not a valid X509 certificate." msgid "is not a valid X509 certificate."
msgstr "" msgstr ""
msgid "is not allowed since the group is not top-level group." msgid "is not allowed for sign-up."
msgstr "" msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin." msgid "is not allowed for this group."
msgstr "" msgstr ""
msgid "is not allowed. We do not currently support project-level iterations" msgid "is not allowed for this project."
msgstr "" msgstr ""
msgid "is not from an allowed domain." msgid "is not allowed since the group is not top-level group."
msgstr ""
msgid "is not allowed. We do not currently support project-level iterations"
msgstr "" msgstr ""
msgid "is not in the group enforcing Group Managed Account" msgid "is not in the group enforcing Group Managed Account"
......
...@@ -242,7 +242,7 @@ describe('InviteMembersModal', () => { ...@@ -242,7 +242,7 @@ describe('InviteMembersModal', () => {
}; };
const expectedEmailRestrictedError = const expectedEmailRestrictedError =
"email 'email@example.com' does not match the allowed domains: example1.org"; "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.";
const expectedSyntaxError = 'email contains an invalid email address'; const expectedSyntaxError = 'email contains an invalid email address';
it('calls the API with the expected focus data when an areas_of_focus checkbox is clicked', () => { it('calls the API with the expected focus data when an areas_of_focus checkbox is clicked', () => {
...@@ -421,7 +421,7 @@ describe('InviteMembersModal', () => { ...@@ -421,7 +421,7 @@ describe('InviteMembersModal', () => {
await waitForPromises(); await waitForPromises();
expect(membersFormGroupInvalidFeedback()).toBe( expect(membersFormGroupInvalidFeedback()).toBe(
"root: User email 'admin@example.com' does not match the allowed domain of example2.com", "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.",
); );
expect(findMembersSelect().props('validationState')).toBe(false); expect(findMembersSelect().props('validationState')).toBe(false);
}); });
......
...@@ -9,7 +9,7 @@ const INVITATIONS_API_ERROR_EMAIL_INVALID = { ...@@ -9,7 +9,7 @@ const INVITATIONS_API_ERROR_EMAIL_INVALID = {
const INVITATIONS_API_EMAIL_RESTRICTED = { const INVITATIONS_API_EMAIL_RESTRICTED = {
message: { message: {
'email@example.com': 'email@example.com':
"Invite email 'email@example.com' does not match the allowed domains: example1.org", "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.",
}, },
status: 'error', status: 'error',
}; };
...@@ -17,9 +17,9 @@ const INVITATIONS_API_EMAIL_RESTRICTED = { ...@@ -17,9 +17,9 @@ const INVITATIONS_API_EMAIL_RESTRICTED = {
const INVITATIONS_API_MULTIPLE_EMAIL_RESTRICTED = { const INVITATIONS_API_MULTIPLE_EMAIL_RESTRICTED = {
message: { message: {
'email@example.com': 'email@example.com':
"Invite email email 'email@example.com' does not match the allowed domains: example1.org", "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.",
'email4@example.com': 'email4@example.com':
"Invite email email 'email4@example.com' does not match the allowed domains: example1.org", "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check the Domain denylist.",
}, },
status: 'error', status: 'error',
}; };
...@@ -36,7 +36,11 @@ const MEMBERS_API_MEMBER_ALREADY_EXISTS = { ...@@ -36,7 +36,11 @@ const MEMBERS_API_MEMBER_ALREADY_EXISTS = {
}; };
const MEMBERS_API_SINGLE_USER_RESTRICTED = { const MEMBERS_API_SINGLE_USER_RESTRICTED = {
message: { user: ["email 'email@example.com' does not match the allowed domains: example1.org"] }, message: {
user: [
"The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.",
],
},
}; };
const MEMBERS_API_SINGLE_USER_ACCESS_LEVEL = { const MEMBERS_API_SINGLE_USER_ACCESS_LEVEL = {
...@@ -49,7 +53,7 @@ const MEMBERS_API_SINGLE_USER_ACCESS_LEVEL = { ...@@ -49,7 +53,7 @@ const MEMBERS_API_SINGLE_USER_ACCESS_LEVEL = {
const MEMBERS_API_MULTIPLE_USERS_RESTRICTED = { const MEMBERS_API_MULTIPLE_USERS_RESTRICTED = {
message: message:
"root: User email 'admin@example.com' does not match the allowed domain of example2.com and user18: User email 'user18@example.org' does not match the allowed domain of example2.com", "root: The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups. and user18: The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check the Domain denylist. and john_doe31: The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Email restrictions for sign-ups.",
status: 'error', status: 'error',
}; };
......
...@@ -2,18 +2,20 @@ import { ...@@ -2,18 +2,20 @@ import {
responseMessageFromSuccess, responseMessageFromSuccess,
responseMessageFromError, responseMessageFromError,
} from '~/invite_members/utils/response_message_parser'; } from '~/invite_members/utils/response_message_parser';
import { membersApiResponse, invitationsApiResponse } from '../mock_data/api_responses';
describe('Response message parser', () => { describe('Response message parser', () => {
const expectedMessage = 'expected display message'; const expectedMessage = 'expected display and message.';
describe('parse message from successful response', () => { describe('parse message from successful response', () => {
const exampleKeyedMsg = { 'email@example.com': expectedMessage }; const exampleKeyedMsg = { 'email@example.com': expectedMessage };
const exampleFirstPartMultiple = 'username1: expected display and message.';
const exampleUserMsgMultiple = const exampleUserMsgMultiple =
' and username1: id not found and username2: email is restricted'; ' and username2: id not found and restricted email. and username3: email is restricted.';
it.each([ it.each([
[[{ data: { message: expectedMessage } }]], [[{ data: { message: expectedMessage } }]],
[[{ data: { message: expectedMessage + exampleUserMsgMultiple } }]], [[{ data: { message: exampleFirstPartMultiple + exampleUserMsgMultiple } }]],
[[{ data: { error: expectedMessage } }]], [[{ data: { error: expectedMessage } }]],
[[{ data: { message: [expectedMessage] } }]], [[{ data: { message: [expectedMessage] } }]],
[[{ data: { message: exampleKeyedMsg } }]], [[{ data: { message: exampleKeyedMsg } }]],
...@@ -33,4 +35,24 @@ describe('Response message parser', () => { ...@@ -33,4 +35,24 @@ describe('Response message parser', () => {
expect(responseMessageFromError(errorResponse)).toBe(expectedMessage); expect(responseMessageFromError(errorResponse)).toBe(expectedMessage);
}); });
}); });
describe('displaying only the first error when a response has messages for multiple users', () => {
const expected =
"The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.";
it.each([
[[{ data: membersApiResponse.MULTIPLE_USERS_RESTRICTED }]],
[[{ data: invitationsApiResponse.MULTIPLE_EMAIL_RESTRICTED }]],
[[{ data: invitationsApiResponse.EMAIL_RESTRICTED }]],
])(`returns "${expectedMessage}" from success response: %j`, (restrictedResponse) => {
expect(responseMessageFromSuccess(restrictedResponse)).toBe(expected);
});
it.each([[{ response: { data: membersApiResponse.SINGLE_USER_RESTRICTED } }]])(
`returns "${expectedMessage}" from error response: %j`,
(singleRestrictedResponse) => {
expect(responseMessageFromError(singleRestrictedResponse)).toBe(expected);
},
);
});
}); });
...@@ -65,6 +65,8 @@ RSpec.describe Member do ...@@ -65,6 +65,8 @@ RSpec.describe Member do
end end
context 'with admin signup restrictions' do context 'with admin signup restrictions' do
let(:expected_message) { _('is not allowed for this group. Check with your administrator.') }
context 'when allowed domains for signup is enabled' do context 'when allowed domains for signup is enabled' do
before do before do
stub_application_setting(domain_allowlist: ['example.com']) stub_application_setting(domain_allowlist: ['example.com'])
...@@ -74,7 +76,7 @@ RSpec.describe Member do ...@@ -74,7 +76,7 @@ RSpec.describe Member do
member = build(:group_member, :invited, invite_email: 'info@gitlab.com') member = build(:group_member, :invited, invite_email: 'info@gitlab.com')
expect(member).not_to be_valid expect(member).not_to be_valid
expect(member.errors.messages[:user].first).to eq(_('domain is not authorized for sign-up.')) expect(member.errors.messages[:user].first).to eq(expected_message)
end end
end end
...@@ -88,7 +90,7 @@ RSpec.describe Member do ...@@ -88,7 +90,7 @@ RSpec.describe Member do
member = build(:group_member, :invited, invite_email: 'denylist@example.org') member = build(:group_member, :invited, invite_email: 'denylist@example.org')
expect(member).not_to be_valid expect(member).not_to be_valid
expect(member.errors.messages[:user].first).to eq(_('is not from an allowed domain.')) expect(member.errors.messages[:user].first).to eq(expected_message)
end end
end end
...@@ -102,7 +104,7 @@ RSpec.describe Member do ...@@ -102,7 +104,7 @@ RSpec.describe Member do
member = build(:group_member, :invited, invite_email: 'info@gitlab.com') member = build(:group_member, :invited, invite_email: 'info@gitlab.com')
expect(member).not_to be_valid expect(member).not_to be_valid
expect(member.errors.messages[:user].first).to eq(_('is not allowed. Try again with a different email address, or contact your GitLab admin.')) expect(member.errors.messages[:user].first).to eq(expected_message)
end end
end end
end end
......
...@@ -494,6 +494,8 @@ RSpec.describe User do ...@@ -494,6 +494,8 @@ RSpec.describe User do
end end
describe 'email' do describe 'email' do
let(:expected_error) { _('is not allowed for sign-up. Check with your administrator.') }
context 'when no signup domains allowed' do context 'when no signup domains allowed' do
before do before do
stub_application_setting(domain_allowlist: []) stub_application_setting(domain_allowlist: [])
...@@ -537,7 +539,7 @@ RSpec.describe User do ...@@ -537,7 +539,7 @@ RSpec.describe User do
it 'rejects example@test.com' do it 'rejects example@test.com' do
user = build(:user, email: "example@test.com") user = build(:user, email: "example@test.com")
expect(user).to be_invalid expect(user).to be_invalid
expect(user.errors.messages[:email].first).to eq(_('domain is not authorized for sign-up.')) expect(user.errors.messages[:email].first).to eq(expected_error)
end end
end end
...@@ -554,13 +556,13 @@ RSpec.describe User do ...@@ -554,13 +556,13 @@ RSpec.describe User do
it 'rejects info@test.example.com' do it 'rejects info@test.example.com' do
user = build(:user, email: "info@test.example.com") user = build(:user, email: "info@test.example.com")
expect(user).to be_invalid expect(user).to be_invalid
expect(user.errors.messages[:email].first).to eq(_('domain is not authorized for sign-up.')) expect(user.errors.messages[:email].first).to eq(expected_error)
end end
it 'rejects example@test.com' do it 'rejects example@test.com' do
user = build(:user, email: "example@test.com") user = build(:user, email: "example@test.com")
expect(user).to be_invalid expect(user).to be_invalid
expect(user.errors.messages[:email].first).to eq(_('domain is not authorized for sign-up.')) expect(user.errors.messages[:email].first).to eq(expected_error)
end end
it 'accepts example@test.com when added by another user' do it 'accepts example@test.com when added by another user' do
...@@ -598,7 +600,7 @@ RSpec.describe User do ...@@ -598,7 +600,7 @@ RSpec.describe User do
it 'rejects info@example.com' do it 'rejects info@example.com' do
user = build(:user, email: 'info@example.com') user = build(:user, email: 'info@example.com')
expect(user).not_to be_valid expect(user).not_to be_valid
expect(user.errors.messages[:email].first).to eq(_('is not from an allowed domain.')) expect(user.errors.messages[:email].first).to eq(expected_error)
end end
it 'accepts info@example.com when added by another user' do it 'accepts info@example.com when added by another user' do
...@@ -632,7 +634,7 @@ RSpec.describe User do ...@@ -632,7 +634,7 @@ RSpec.describe User do
it 'rejects info@example.com' do it 'rejects info@example.com' do
user = build(:user, email: 'info@example.com') user = build(:user, email: 'info@example.com')
expect(user).not_to be_valid expect(user).not_to be_valid
expect(user.errors.messages[:email].first).to eq(_('domain is not authorized for sign-up.')) expect(user.errors.messages[:email].first).to eq(expected_error)
end end
end end
end end
...@@ -673,7 +675,7 @@ RSpec.describe User do ...@@ -673,7 +675,7 @@ RSpec.describe User do
user = build(:user, email: 'info@gitlab.com') user = build(:user, email: 'info@gitlab.com')
expect(user).not_to be_valid expect(user).not_to be_valid
expect(user.errors.messages[:email].first).to eq(_('is not allowed. Try again with a different email address, or contact your GitLab admin.')) expect(user.errors.messages[:email].first).to eq(expected_error)
end end
it 'does accept a valid email address' do it 'does accept a valid email address' do
......
...@@ -80,7 +80,7 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_ ...@@ -80,7 +80,7 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
it 'does not add a member' do it 'does not add a member' do
expect(execute_service[:status]).to eq(:error) expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to eq('Invite email has already been taken') expect(execute_service[:message]).to eq("The member's email address has already been taken")
expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false) expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end end
end end
......
...@@ -150,7 +150,7 @@ RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_ ...@@ -150,7 +150,7 @@ RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_
expect_to_create_members(count: 1) expect_to_create_members(count: 1)
expect(result[:status]).to eq(:error) expect(result[:status]).to eq(:error)
expect(result[:message][invited_member.invite_email]) expect(result[:message][invited_member.invite_email])
.to eq("Invite email has already been taken") .to eq("The member's email address has already been taken")
expect(project.users).to include project_user expect(project.users).to include project_user
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment