diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb index 01b741b5a986a9b7024333e8044abb700558ed2c..0bd0f251c1a3f601aec9da51c5b6a76582fb983f 100644 --- a/app/graphql/types/group_type.rb +++ b/app/graphql/types/group_type.rb @@ -62,6 +62,10 @@ class GroupType < NamespaceType null: true, description: 'Indicates if a group has email notifications disabled.' + field :max_access_level, Types::AccessLevelType, + null: false, + description: 'The maximum access level of the current user in the group.' + field :mentions_disabled, type: GraphQL::Types::Boolean, null: true, @@ -375,6 +379,16 @@ def group_members_count end end + def max_access_level + return Gitlab::Access::NO_ACCESS if current_user.nil? + + BatchLoader::GraphQL.for(object.id).batch do |group_ids, loader| + current_user.max_member_access_for_group_ids(group_ids).each do |group_id, max_access_level| + loader.call(group_id, max_access_level) + end + end + end + private def group diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 7f49c717c786acf25eb9a7ef90e18232310bff11..aacd67e269eed1b9a6e44d2514385243a5656980 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -110,6 +110,10 @@ class ProjectType < BaseObject null: true, description: 'Indicates if the project has Large File Storage (LFS) enabled.' + field :max_access_level, Types::AccessLevelType, + null: false, + description: 'The maximum access level of the current user in the project.' + field :merge_requests_ff_only_enabled, GraphQL::Types::Boolean, null: true, description: 'Indicates if no merge commits should be created and all merges should instead be ' \ @@ -823,6 +827,16 @@ def statistics_details_paths } end + def max_access_level + return Gitlab::Access::NO_ACCESS if current_user.nil? + + BatchLoader::GraphQL.for(object.id).batch do |project_ids, loader| + current_user.max_member_access_for_project_ids(project_ids).each do |project_id, max_access_level| + loader.call(project_id, max_access_level) + end + end + end + private def project diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index ab52f1ceb2a8c39dac54a6d891a6c681ad9ec196..0271e5bca7be13b7153ab506a9ba8d4b036eaf86 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -19444,6 +19444,7 @@ GPG signature for a signed commit. | <a id="groupid"></a>`id` | [`ID!`](#id) | ID of the namespace. | | <a id="groupistemporarystorageincreaseenabled"></a>`isTemporaryStorageIncreaseEnabled` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 16.7. Feature removal, will be completely removed in 17.0. | | <a id="grouplfsenabled"></a>`lfsEnabled` | [`Boolean`](#boolean) | Indicates if Large File Storage (LFS) is enabled for namespace. | +| <a id="groupmaxaccesslevel"></a>`maxAccessLevel` | [`AccessLevel!`](#accesslevel) | The maximum access level of the current user in the group. | | <a id="groupmentionsdisabled"></a>`mentionsDisabled` | [`Boolean`](#boolean) | Indicates if a group is disabled from getting mentioned. | | <a id="groupname"></a>`name` | [`String!`](#string) | Name of the namespace. | | <a id="grouppackagesettings"></a>`packageSettings` | [`PackageSettings`](#packagesettings) | Package settings for the namespace. | @@ -24407,6 +24408,7 @@ Represents vulnerability finding of a security report on the pipeline. | <a id="projectlanguages"></a>`languages` | [`[RepositoryLanguage!]`](#repositorylanguage) | Programming languages used in the project. | | <a id="projectlastactivityat"></a>`lastActivityAt` | [`Time`](#time) | Timestamp of the project last activity. | | <a id="projectlfsenabled"></a>`lfsEnabled` | [`Boolean`](#boolean) | Indicates if the project has Large File Storage (LFS) enabled. | +| <a id="projectmaxaccesslevel"></a>`maxAccessLevel` | [`AccessLevel!`](#accesslevel) | The maximum access level of the current user in the project. | | <a id="projectmergecommittemplate"></a>`mergeCommitTemplate` | [`String`](#string) | Template used to create merge commit message in merge requests. | | <a id="projectmergerequestsaccesslevel"></a>`mergeRequestsAccessLevel` | [`ProjectFeatureAccess`](#projectfeatureaccess) | Access level required for merge requests access. | | <a id="projectmergerequestsdisablecommittersapproval"></a>`mergeRequestsDisableCommittersApproval` | [`Boolean!`](#boolean) | Indicates that committers of the given merge request cannot approve. | diff --git a/spec/graphql/resolvers/concerns/resolves_groups_spec.rb b/spec/graphql/resolvers/concerns/resolves_groups_spec.rb index 72e86d54deaa88fb5a5bb72a8167077e17825809..06a6b8d9ada82e2d3308e10582676fe4a4497746 100644 --- a/spec/graphql/resolvers/concerns/resolves_groups_spec.rb +++ b/spec/graphql/resolvers/concerns/resolves_groups_spec.rb @@ -26,15 +26,16 @@ <<~FIELDS containerRepositoriesCount customEmoji { nodes { id } } - fullPath - groupMembersCount - path dependencyProxyBlobCount dependencyProxyBlobs { nodes { fileName } } dependencyProxyImageCount dependencyProxyImageTtlPolicy { enabled } dependencyProxySetting { enabled } descendantGroupsCount + fullPath + groupMembersCount + maxAccessLevel { integerValue } + path projectsCount FIELDS end diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb index 51a9476f449f8962032ca7b90e28317194d3809c..7231a1e0357dbe7019c5f3dd3b0a3b25f8e2a1f8 100644 --- a/spec/graphql/types/group_type_spec.rb +++ b/spec/graphql/types/group_type_spec.rb @@ -22,7 +22,7 @@ mentions_disabled parent boards milestones group_members merge_requests container_repositories container_repositories_count packages dependency_proxy_setting dependency_proxy_manifests - dependency_proxy_blobs dependency_proxy_image_count + dependency_proxy_blobs dependency_proxy_image_count max_access_level dependency_proxy_blob_count dependency_proxy_total_size dependency_proxy_total_size_in_bytes dependency_proxy_image_prefix dependency_proxy_image_ttl_policy shared_runners_setting timelogs organization_state_counts organizations diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index 36d72140006717296f5215c3341be010b9336df5..f6e178f5b28b522448d426b269f75e70f03ebdf9 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -34,7 +34,7 @@ incident_management_timeline_event incident_management_timeline_events container_expiration_policy service_desk_enabled service_desk_address issue_status_counts terraform_states alert_management_integrations - container_repositories container_repositories_count + container_repositories container_repositories_count max_access_level pipeline_analytics squash_read_only sast_ci_configuration cluster_agent cluster_agents agent_configurations ci_access_authorized_agents user_access_authorized_agents ci_template timelogs merge_commit_template squash_commit_template work_item_types diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb index 1dcbc44c587f3639809331271bbeba4fe17ae64d..1b3b153ebe08b90ded512e3430961329c4373814 100644 --- a/spec/requests/api/graphql/group_query_spec.rb +++ b/spec/requests/api/graphql/group_query_spec.rb @@ -217,5 +217,33 @@ def group_query(group) expect(graphql_data['group']).to be_nil end end + + describe 'maxAccessLevel' do + let(:current_user) { user1 } + + it 'returns access level of the current user in the group' do + private_group.add_owner(user1) + + post_graphql(group_query(private_group), current_user: current_user) + + expect(graphql_data_at(:group, :maxAccessLevel, :integerValue)).to eq(Gitlab::Access::OWNER) + end + + shared_examples 'public group in which the user has no membership' do + it 'returns no access' do + post_graphql(group_query(public_group), current_user: current_user) + + expect(graphql_data_at(:group, :maxAccessLevel, :integerValue)).to eq(Gitlab::Access::NO_ACCESS) + end + end + + it_behaves_like 'public group in which the user has no membership' + + context 'when the user is not authenticated' do + let(:current_user) { nil } + + it_behaves_like 'public group in which the user has no membership' + end + end end end diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb index 2d9c6367676c2ce629445bc514b003e55c2d3b00..0c72f34efeeddb7e336a3f9a73fbabe10a83e555 100644 --- a/spec/requests/api/graphql/project_query_spec.rb +++ b/spec/requests/api/graphql/project_query_spec.rb @@ -401,4 +401,34 @@ end end end + + describe 'maxAccessLevel' do + let(:project_fields) { 'maxAccessLevel { integerValue }' } + + it 'returns access level of the current user in the project' do + project.add_developer(current_user) + + post_graphql(query, current_user: current_user) + + expect(graphql_data_at(:project, :maxAccessLevel, :integerValue)).to eq(Gitlab::Access::DEVELOPER) + end + + shared_examples 'public project in which the user has no membership' do + it 'returns no access' do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + + post_graphql(query, current_user: current_user) + + expect(graphql_data_at(:project, :maxAccessLevel, :integerValue)).to eq(Gitlab::Access::NO_ACCESS) + end + end + + it_behaves_like 'public project in which the user has no membership' + + context 'when the user is not authenticated' do + let(:current_user) { nil } + + it_behaves_like 'public project in which the user has no membership' + end + end end