Commit 5f961f65 authored by peterhegman's avatar peterhegman

Add "Enterprise" badge to users that are provisioned via SAML/SCIM

Add an "Enterprise" badge to group members that are provisioned via
SAML/SCIM

Changelog: added
EE: true
parent c61122f9
......@@ -175,6 +175,10 @@ We recommend users do this prior to turning on sync, because while synchronizati
New users and existing users on subsequent visits can access the group through the identify provider's dashboard or by visiting links directly.
GitLab users that were created with a SCIM identity will be displayed with an **Enterprise** badge in the **Members** view.
![Enterprise badge for users created with a SCIM identity](img/member_enterprise_badge_v14_0.png)
For role information, please see the [Group SAML page](index.md#user-access-and-management)
### Blocking access
......
......@@ -32,6 +32,11 @@ export const generateBadges = ({ member, isCurrentUser, canManageMembers }) => [
text: __('LDAP'),
variant: 'info',
},
{
show: member.provisionedByThisGroup,
text: __('Enterprise'),
variant: 'info',
},
];
export const canOverride = (member) => member.canOverride && isDirectMember(member);
......@@ -81,6 +81,10 @@ module EE
end
end
def provisioned_by_this_group?
user&.user_detail&.provisioned_by_group_id == source_id
end
private
override :access_level_inclusion
......@@ -152,9 +156,5 @@ module EE
def send_welcome_email?
!provisioned_by_this_group?
end
def provisioned_by_this_group?
user.user_detail.provisioned_by_group_id == source_id
end
end
end
......@@ -11,6 +11,7 @@ module EE
ActiveRecord::Associations::Preloader.new.preload(members, user: { group_saml_identities: :saml_provider })
ActiveRecord::Associations::Preloader.new.preload(members, user: { oncall_participants: { rotation: :schedule } })
ActiveRecord::Associations::Preloader.new.preload(members, user: :oncall_schedules)
ActiveRecord::Associations::Preloader.new.preload(members, user: :user_detail)
end
end
end
......@@ -33,5 +33,9 @@ module EE
errors.add(:user, _('is not in the group enforcing Group Managed Account'))
end
end
def provisioned_by_this_group?
false
end
end
end
......@@ -18,6 +18,8 @@ module EE
end
expose :override, as: :is_overridden
expose :provisioned_by_this_group?, as: :provisioned_by_this_group
end
private
......
......@@ -8,14 +8,16 @@
"group_sso",
"group_managed_account",
"can_override",
"is_overridden"
"is_overridden",
"provisioned_by_this_group"
],
"properties": {
"using_license": { "type": ["boolean", "null"] },
"group_sso": { "type": ["boolean", "null"] },
"group_managed_account": { "type": ["boolean", "null"] },
"can_override": { "type": ["boolean"] },
"is_overridden": { "type": ["boolean"] }
"is_overridden": { "type": ["boolean"] },
"provisioned_by_this_group": { "type": ["boolean"] }
}
}
]
......
......@@ -22,11 +22,12 @@ describe('Members Utils', () => {
});
it.each`
member | expected
${{ ...memberMock, usingLicense: true }} | ${{ show: true, text: 'Is using seat', variant: 'neutral' }}
${{ ...memberMock, groupSso: true }} | ${{ show: true, text: 'SAML', variant: 'info' }}
${{ ...memberMock, groupManagedAccount: true }} | ${{ show: true, text: 'Managed Account', variant: 'info' }}
${{ ...memberMock, canOverride: true }} | ${{ show: true, text: 'LDAP', variant: 'info' }}
member | expected
${{ ...memberMock, usingLicense: true }} | ${{ show: true, text: 'Is using seat', variant: 'neutral' }}
${{ ...memberMock, groupSso: true }} | ${{ show: true, text: 'SAML', variant: 'info' }}
${{ ...memberMock, groupManagedAccount: true }} | ${{ show: true, text: 'Managed Account', variant: 'info' }}
${{ ...memberMock, canOverride: true }} | ${{ show: true, text: 'LDAP', variant: 'info' }}
${{ ...memberMock, provisionedByThisGroup: true }} | ${{ show: true, text: 'Enterprise', variant: 'info' }}
`('returns expected output for "$expected.text" badge', ({ member, expected }) => {
expect(
generateBadges({ member, isCurrentUser: true, canManageMembers: true }),
......
......@@ -400,6 +400,32 @@ RSpec.describe GroupMember do
end
end
describe '#provisioned_by_this_group?' do
let_it_be(:group) { create(:group) }
let(:user) { build(:user) }
let(:member) { build(:group_member, group: group, user: user) }
let(:invited) { build(:group_member, :invited, group: group, user: user) }
subject { member.provisioned_by_this_group? }
context 'when user is provisioned by the group' do
let!(:user_detail) { build(:user_detail, user: user, provisioned_by_group_id: group.id) }
it { is_expected.to eq(true) }
end
context 'when user is not provisioned by the group' do
it { is_expected.to eq(false) }
end
context 'when member does not have a related user (invited member)' do
it 'returns `false`' do
expect(invited.provisioned_by_this_group?).to eq(false)
end
end
end
def webhook_data(group_member, event)
{
headers: { 'Content-Type' => 'application/json', 'User-Agent' => "GitLab/#{Gitlab::VERSION}", 'X-Gitlab-Event' => 'Member Hook' },
......
......@@ -88,4 +88,12 @@ RSpec.describe ProjectMember do
end
end
end
describe '#provisioned_by_this_group?' do
let_it_be(:member) { build(:project_member) }
subject { member.provisioned_by_this_group? }
it { is_expected.to eq(false) }
end
end
......@@ -37,6 +37,12 @@ RSpec.describe MemberEntity do
expect(entity_hash[:can_override]).to be(true)
end
it 'correctly exposes `provisioned_by_this_group`' do
allow(member).to receive(:provisioned_by_this_group?).and_return(true)
expect(entity_hash[:provisioned_by_this_group]).to be(true)
end
end
context 'group member' do
......
......@@ -12382,6 +12382,9 @@ msgstr ""
msgid "Enter your password to approve"
msgstr ""
msgid "Enterprise"
msgstr ""
msgid "Environment"
msgstr ""
......
......@@ -30,6 +30,7 @@ export const member = {
usingLicense: false,
groupSso: false,
groupManagedAccount: false,
provisionedByThisGroup: false,
validRoles: {
Guest: 10,
Reporter: 20,
......
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