diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml index bf0e8b627fdc5d1e3a5a47ba80b2741e91885ee3..f0fd9026b307872aece7a288ad9ce65c5c920f10 100644 --- a/app/views/groups/_invite_members_modal.html.haml +++ b/app/views/groups/_invite_members_modal.html.haml @@ -1,6 +1,6 @@ - return unless can_admin_group_member?(group) .js-invite-members-modal{ data: { is_project: 'false', - access_levels: GroupMember.access_level_roles.to_json, + access_levels: group.access_level_roles.to_json, reload_page_on_submit: local_assigns.fetch(:reload_page_on_submit, false).to_s, help_link: help_page_url('user/permissions') }.merge(common_invite_modal_dataset(group)).merge(users_filter_data(group)) } diff --git a/ee/lib/ee/api/helpers/members_helpers.rb b/ee/lib/ee/api/helpers/members_helpers.rb index d569d7464aeca0a93b58e01f11a03f9c267818b6..3fe4a88bd27939169226fc00570ba43c4c41a526 100644 --- a/ee/lib/ee/api/helpers/members_helpers.rb +++ b/ee/lib/ee/api/helpers/members_helpers.rb @@ -26,6 +26,15 @@ def member_sort_options end end + class_methods do + extend ::Gitlab::Utils::Override + + override :member_access_levels + def member_access_levels + super + [::Gitlab::Access::MINIMAL_ACCESS] + end + end + # rubocop: disable CodeReuse/ActiveRecord override :retrieve_members def retrieve_members(source, params:, deep: false) diff --git a/ee/spec/lib/ee/api/helpers/members_helpers_spec.rb b/ee/spec/lib/ee/api/helpers/members_helpers_spec.rb index d55a4156b0dbcff0e0d790a9cb67acf5f0209894..e5af422ed1d576f87dfb2ac5716065454016ae5a 100644 --- a/ee/spec/lib/ee/api/helpers/members_helpers_spec.rb +++ b/ee/spec/lib/ee/api/helpers/members_helpers_spec.rb @@ -84,4 +84,12 @@ def can?(user, ability, members_source) end end end + + describe '.member_access_levels' do + it 'return all access levels including minimal access' do + expect(API::Helpers::MembersHelpers.member_access_levels).to eq( + ::Gitlab::Access.all_values + [::Gitlab::Access::MINIMAL_ACCESS] + ) + end + end end diff --git a/ee/spec/models/ee/group_spec.rb b/ee/spec/models/ee/group_spec.rb index 711def1e0e0d23bb86bcd8a83e03dd740eb61084..5f10b026e934fc02acd2554edd511022c2d4760e 100644 --- a/ee/spec/models/ee/group_spec.rb +++ b/ee/spec/models/ee/group_spec.rb @@ -2199,6 +2199,27 @@ def webhook_headers it { is_expected.to match([user.email]) } end + describe "#access_level_roles" do + let(:group) { create(:group) } + + before do + stub_licensed_features(minimal_access_role: true) + end + + it "returns the correct roles" do + expect(group.access_level_roles).to eq( + { + "Minimal Access" => 5, + "Guest" => 10, + "Reporter" => 20, + "Developer" => 30, + "Maintainer" => 40, + "Owner" => 50 + } + ) + end + end + describe 'Releases Stats' do context 'when there are no releases' do describe '#releases_count' do diff --git a/ee/spec/requests/api/invitations_spec.rb b/ee/spec/requests/api/invitations_spec.rb index 0ee1027a18b355bcacf0acd0cfac30d22b3d42c3..4d14c909b6321d46e9a9ebbdcf1cbe1fc3fcb837 100644 --- a/ee/spec/requests/api/invitations_spec.rb +++ b/ee/spec/requests/api/invitations_spec.rb @@ -159,6 +159,37 @@ end end end + + context 'with minimal access level' do + before do + stub_licensed_features(minimal_access_role: true) + end + + context 'when group has no parent' do + it 'return success' do + post api(url, admin), + params: { email: invite_email, + access_level: Member::MINIMAL_ACCESS } + + expect(response).to have_gitlab_http_status(:created) + expect(json_response['status']).to eq("success") + end + end + + context 'when group has parent' do + let(:parent_group) { create(:group) } + let(:group) { create(:group, parent: parent_group) } + + it 'return error' do + post api(url, admin), + params: { email: invite_email, + access_level: Member::MINIMAL_ACCESS } + + expect(json_response['status']).to eq 'error' + expect(json_response['message'][invite_email]).to include('Access level is not included in the list') + end + end + end end describe 'POST /projects/:id/invitations' do diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb index b0ea4388d9bdc67970a8bdc5bb1d01ef851c1ae7..a406a62344ac9ae69f57d733ad5d5dc189b174ed 100644 --- a/lib/api/helpers/members_helpers.rb +++ b/lib/api/helpers/members_helpers.rb @@ -98,6 +98,10 @@ def add_single_member?(user_id) user_id.present? end + def self.member_access_levels + Gitlab::Access.all_values + end + private def member_already_exists?(source, user_id) diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb index ec563e6a5c5058e7280b5f7148056543efbb5751..828f4b419ef333237d0aac188ff6cfd71168b114 100644 --- a/lib/api/invitations.rb +++ b/lib/api/invitations.rb @@ -21,7 +21,7 @@ class Invitations < ::API::Base tags %w[invitations] end params do - requires :access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'A valid access level (defaults: `30`, developer access level)' + requires :access_level, type: Integer, values: ::API::Helpers::MembersHelpers.member_access_levels, desc: 'A valid access level (defaults: `30`, developer access level)' optional :email, type: Array[String], email_or_email_list: true, coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The email address to invite, or multiple emails separated by comma' optional :user_id, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The user ID of the new member or multiple IDs separated by commas.' optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY' diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 4605c086763ba160add8f81aba80ccd92083c58c..9975086ff219be343b4348f19630259d2ea0633f 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -2913,6 +2913,22 @@ def define_cache_expectations(cache_key) end end + describe "#access_level_roles" do + let(:group) { create(:group) } + + it "returns the correct roles" do + expect(group.access_level_roles).to eq( + { + 'Guest' => 10, + 'Reporter' => 20, + 'Developer' => 30, + 'Maintainer' => 40, + 'Owner' => 50 + } + ) + end + end + describe '#membership_locked?' do it 'returns false' do expect(build(:group)).not_to be_membership_locked