diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb index 35cd44f224fb2d350a344f4cf58944387e6601a8..b14716f618525b63e4d58e7762bce1ccaabdb268 100644 --- a/app/graphql/types/group_type.rb +++ b/app/graphql/types/group_type.rb @@ -31,6 +31,16 @@ class GroupType < NamespaceType null: false, description: 'Path for editing group.' + field :admin_edit_path, GraphQL::Types::String, + null: true, + description: 'Admin path for editing group. Only available to admins.', + authorize: :admin_all_resources + + field :admin_show_path, GraphQL::Types::String, + null: true, + description: 'Admin path of the group. Only available to admins.', + authorize: :admin_all_resources + field :avatar_url, type: GraphQL::Types::String, null: true, @@ -532,6 +542,14 @@ def edit_path ::Gitlab::Routing.url_helpers.edit_group_path(group) end + def admin_show_path + ::Gitlab::Routing.url_helpers.admin_group_path(group) + end + + def admin_edit_path + ::Gitlab::Routing.url_helpers.admin_group_edit_path(group) + end + private def group diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index af10eb05df709b55eb6a578fd9279b209ea8dd7f..a42cee6f5e798e63f9733ffe88dfa7273068f471 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -136,6 +136,16 @@ def self.authorization_scopes null: false, description: 'Path for editing project.' + field :admin_edit_path, GraphQL::Types::String, + null: true, + description: 'Admin path for editing project. Only available to admins.', + authorize: :admin_all_resources + + field :admin_show_path, GraphQL::Types::String, + null: true, + description: 'Admin path of the project. Only available to admins.', + authorize: :admin_all_resources + field :forks_count, GraphQL::Types::Int, null: false, calls_gitaly: true, # 4 times @@ -1143,6 +1153,18 @@ def edit_path ::Gitlab::Routing.url_helpers.edit_project_path(project) end + def admin_show_path + ::Gitlab::Routing.url_helpers.admin_namespace_project_path( + { id: project.to_param, namespace_id: project.namespace.to_param } + ) + end + + def admin_edit_path + ::Gitlab::Routing.url_helpers.edit_admin_namespace_project_path( + { id: project.to_param, namespace_id: project.namespace.to_param } + ) + end + def grafana_integration nil end diff --git a/doc/api/graphql/reference/_index.md b/doc/api/graphql/reference/_index.md index 1fcc7e4f11d1ce3f564aa2860b13bb8dc78f5f39..f6fc331e9c6c4938e0e2f2e524ac86bc66fd9c57 100644 --- a/doc/api/graphql/reference/_index.md +++ b/doc/api/graphql/reference/_index.md @@ -31563,6 +31563,8 @@ GPG signature for a signed commit. | `actualRepositorySizeLimit` | [`Float`](#float) | Size limit for repositories in the namespace in bytes. This limit only applies to namespaces under Project limit enforcement. | | `actualSizeLimit` | [`Float`](#float) | The actual storage size limit (in bytes) based on the enforcement type of either repository or namespace. This limit is agnostic of enforcement type. | | `additionalPurchasedStorageSize` | [`Float`](#float) | Additional storage purchased for the root namespace in bytes. | +| `adminEditPath` | [`String`](#string) | Admin path for editing group. Only available to admins. | +| `adminShowPath` | [`String`](#string) | Admin path of the group. Only available to admins. | | `aiUsageData` {{< icon name="warning-solid" >}} | [`AiUsageData`](#aiusagedata) | **Introduced** in GitLab 17.5. **Status**: Experiment. AI-related data. | | `allowStaleRunnerPruning` | [`Boolean!`](#boolean) | Indicates whether to regularly prune stale group runners. Defaults to false. | | `amazonS3Configurations` | [`AmazonS3ConfigurationTypeConnection`](#amazons3configurationtypeconnection) | Amazon S3 configurations that receive audit events belonging to the group. (see [Connections](#connections)) | @@ -39986,6 +39988,8 @@ Project-level settings for product analytics provider. | Name | Type | Description | | ---- | ---- | ----------- | | `actualRepositorySizeLimit` | [`Float`](#float) | Size limit for the repository in bytes. | +| `adminEditPath` | [`String`](#string) | Admin path for editing project. Only available to admins. | +| `adminShowPath` | [`String`](#string) | Admin path of the project. Only available to admins. | | `agentConfigurations` | [`AgentConfigurationConnection`](#agentconfigurationconnection) | Agent configurations defined by the project. (see [Connections](#connections)) | | `aiAgents` {{< icon name="warning-solid" >}} | [`AiAgentConnection`](#aiagentconnection) | **Introduced** in GitLab 16.9. **Status**: Experiment. Ai Agents for the project. | | `aiUsageData` {{< icon name="warning-solid" >}} | [`AiUsageData`](#aiusagedata) | **Introduced** in GitLab 17.5. **Status**: Experiment. AI-related data. | diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb index 22a81a1a1bcbb860b50b7dfa25375cb192ef6e5a..73fa8a91b2ce5b8cf515066e6c0e6269c4483fe2 100644 --- a/spec/graphql/types/group_type_spec.rb +++ b/spec/graphql/types/group_type_spec.rb @@ -20,7 +20,8 @@ expected_fields = %w[ id name path full_name full_path description description_html visibility archived is_self_archived lfs_enabled request_access_enabled projects root_storage_statistics - web_url web_path edit_path avatar_url share_with_group_lock project_creation_level + web_url web_path edit_path admin_show_path admin_edit_path avatar_url + share_with_group_lock project_creation_level descendant_groups_count group_members_count projects_count subgroup_creation_level require_two_factor_authentication two_factor_grace_period auto_devops_enabled emails_disabled emails_enabled @@ -562,4 +563,78 @@ def clean_state_query expect(edit_path).to eq("/groups/#{group.full_path}/-/edit") end end + + describe 'admin_show_path' do + let_it_be(:group) { create(:group, :public) } + + let(:query) do + %( + query { + group(fullPath: "#{group.full_path}") { + adminShowPath + } + } + ) + end + + subject(:admin_show_path) do + GitlabSchema + .execute(query, context: { current_user: current_user }) + .as_json + .dig('data', 'group', 'adminShowPath') + end + + context 'when current user is an admin', :enable_admin_mode do + let_it_be(:current_user) { create(:user, :admin) } + + it 'returns admin_show_path field' do + expect(admin_show_path).to eq("/admin/groups/#{group.full_path}") + end + end + + context 'when current user is not an admin' do + let_it_be(:current_user) { create(:user) } + + it 'returns admin_show_path field as null' do + expect(admin_show_path).to be_nil + end + end + end + + describe 'admin_edit_path' do + let_it_be(:group) { create(:group, :public) } + + let(:query) do + %( + query { + group(fullPath: "#{group.full_path}") { + adminEditPath + } + } + ) + end + + subject(:admin_edit_path) do + GitlabSchema + .execute(query, context: { current_user: current_user }) + .as_json + .dig('data', 'group', 'adminEditPath') + end + + context 'when current user is an admin', :enable_admin_mode do + let_it_be(:current_user) { create(:user, :admin) } + + it 'returns admin_edit_path field' do + expect(admin_edit_path).to eq("/admin/groups/#{group.full_path}/edit") + end + end + + context 'when current user is not an admin' do + let_it_be(:current_user) { create(:user) } + + it 'returns admin_edit_path field as null' do + expect(admin_edit_path).to be_nil + end + end + end end diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index 7ae8c477c0a787439038daf87deecb599f241718..b729365a205796028ea87935afadc74e133e01b5 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -21,7 +21,7 @@ expected_fields = %w[ user_permissions id full_path path name_with_namespace name description description_html tag_list topics ssh_url_to_repo - http_url_to_repo web_url web_path edit_path star_count forks_count + http_url_to_repo web_url web_path edit_path admin_show_path admin_edit_path star_count forks_count created_at updated_at last_activity_at archived is_self_archived visibility container_registry_enabled shared_runners_enabled lfs_enabled merge_requests_ff_only_enabled avatar_url @@ -1432,6 +1432,80 @@ end end + describe 'admin_show_path' do + let_it_be(:project) { create(:project, :public) } + + let(:query) do + %( + query { + project(fullPath: "#{project.full_path}") { + adminShowPath + } + } + ) + end + + subject(:admin_show_path) do + GitlabSchema + .execute(query, context: { current_user: current_user }) + .as_json + .dig('data', 'project', 'adminShowPath') + end + + context 'when current user is an admin', :enable_admin_mode do + let_it_be(:current_user) { create(:user, :admin) } + + it 'returns admin_show_path field' do + expect(admin_show_path).to eq("/admin/projects/#{project.full_path}") + end + end + + context 'when current user is not an admin' do + let_it_be(:current_user) { create(:user) } + + it 'returns admin_show_path field as null' do + expect(admin_show_path).to be_nil + end + end + end + + describe 'admin_edit_path' do + let_it_be(:project) { create(:project, :public) } + + let(:query) do + %( + query { + project(fullPath: "#{project.full_path}") { + adminEditPath + } + } + ) + end + + subject(:admin_edit_path) do + GitlabSchema + .execute(query, context: { current_user: current_user }) + .as_json + .dig('data', 'project', 'adminEditPath') + end + + context 'when current user is an admin', :enable_admin_mode do + let_it_be(:current_user) { create(:user, :admin) } + + it 'returns admin_edit_path field' do + expect(admin_edit_path).to eq("/admin/projects/#{project.full_path}/edit") + end + end + + context 'when current user is not an admin' do + let_it_be(:current_user) { create(:user) } + + it 'returns admin_edit_path field as null' do + expect(admin_edit_path).to be_nil + end + end + end + describe 'organization_edit_path' do let_it_be(:user) { create(:user) } let_it_be(:organization) { create(:organization) }