Commit ff0dc69b authored by Jose Ivan Vargas's avatar Jose Ivan Vargas Committed by Fabio Pitino

Add CIJobToken project allow list field for GraphQL

parent 3e71e0b2
# frozen_string_literal: true
module Resolvers
module Ci
class JobTokenScopeResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
authorize :admin_project
description 'Container for resources that can be accessed by a CI job token from the current project. Null if job token scope setting is disabled.'
type ::Types::Ci::JobTokenScopeType, null: true
def resolve
authorize!(object)
return unless object.ci_job_token_scope_enabled?
::Ci::JobToken::Scope.new(object)
end
end
end
end
# frozen_string_literal: true
module Types
# rubocop: disable Graphql/AuthorizeTypes
# Authorization is in the resolver based on the parent project
module Ci
class JobTokenScopeType < BaseObject
graphql_name 'CiJobTokenScopeType'
field :projects, Types::ProjectType.connection_type, null: false,
description: 'Allow list of projects that can be accessed by CI Job tokens created by this project.',
method: :all_projects
end
end
# rubocop: enable Graphql/AuthorizeTypes
end
...@@ -346,6 +346,10 @@ module Types ...@@ -346,6 +346,10 @@ module Types
description: 'Find a single CI/CD template by name.', description: 'Find a single CI/CD template by name.',
resolver: Resolvers::Ci::TemplateResolver resolver: Resolvers::Ci::TemplateResolver
field :ci_job_token_scope, Types::Ci::JobTokenScopeType, null: true,
description: 'The CI Job Tokens scope of access.',
resolver: Resolvers::Ci::JobTokenScopeResolver
def label(title:) def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args| BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder LabelsFinder
......
...@@ -7608,6 +7608,14 @@ Represents the total number of issues and their weights for a particular day. ...@@ -7608,6 +7608,14 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cijobartifactdownloadpath"></a>`downloadPath` | [`String`](#string) | URL for downloading the artifact's file. | | <a id="cijobartifactdownloadpath"></a>`downloadPath` | [`String`](#string) | URL for downloading the artifact's file. |
| <a id="cijobartifactfiletype"></a>`fileType` | [`JobArtifactFileType`](#jobartifactfiletype) | File type of the artifact. | | <a id="cijobartifactfiletype"></a>`fileType` | [`JobArtifactFileType`](#jobartifactfiletype) | File type of the artifact. |
### `CiJobTokenScopeType`
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="cijobtokenscopetypeprojects"></a>`projects` | [`ProjectConnection!`](#projectconnection) | Allow list of projects that can be accessed by CI Job tokens created by this project. (see [Connections](#connections)) |
### `CiRunner` ### `CiRunner`
#### Fields #### Fields
...@@ -11156,6 +11164,7 @@ Represents vulnerability finding of a security report on the pipeline. ...@@ -11156,6 +11164,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectautoclosereferencedissues"></a>`autocloseReferencedIssues` | [`Boolean`](#boolean) | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically. | | <a id="projectautoclosereferencedissues"></a>`autocloseReferencedIssues` | [`Boolean`](#boolean) | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically. |
| <a id="projectavatarurl"></a>`avatarUrl` | [`String`](#string) | URL to avatar image file of the project. | | <a id="projectavatarurl"></a>`avatarUrl` | [`String`](#string) | URL to avatar image file of the project. |
| <a id="projectcicdsettings"></a>`ciCdSettings` | [`ProjectCiCdSetting`](#projectcicdsetting) | CI/CD settings for the project. | | <a id="projectcicdsettings"></a>`ciCdSettings` | [`ProjectCiCdSetting`](#projectcicdsetting) | CI/CD settings for the project. |
| <a id="projectcijobtokenscope"></a>`ciJobTokenScope` | [`CiJobTokenScopeType`](#cijobtokenscopetype) | The CI Job Tokens scope of access. |
| <a id="projectclusteragents"></a>`clusterAgents` | [`ClusterAgentConnection`](#clusteragentconnection) | Cluster agents associated with the project. (see [Connections](#connections)) | | <a id="projectclusteragents"></a>`clusterAgents` | [`ClusterAgentConnection`](#clusteragentconnection) | Cluster agents associated with the project. (see [Connections](#connections)) |
| <a id="projectcodecoveragesummary"></a>`codeCoverageSummary` | [`CodeCoverageSummary`](#codecoveragesummary) | Code coverage summary associated with the project. | | <a id="projectcodecoveragesummary"></a>`codeCoverageSummary` | [`CodeCoverageSummary`](#codecoveragesummary) | Code coverage summary associated with the project. |
| <a id="projectcomplianceframeworks"></a>`complianceFrameworks` | [`ComplianceFrameworkConnection`](#complianceframeworkconnection) | Compliance frameworks associated with the project. (see [Connections](#connections)) | | <a id="projectcomplianceframeworks"></a>`complianceFrameworks` | [`ComplianceFrameworkConnection`](#complianceframeworkconnection) | Compliance frameworks associated with the project. (see [Connections](#connections)) |
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Ci::JobTokenScopeResolver do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
specify do
expect(described_class).to have_nullable_graphql_type(::Types::Ci::JobTokenScopeType)
end
subject(:resolve_scope) { resolve(described_class, ctx: { current_user: current_user }, obj: project) }
describe '#resolve' do
context 'with access to scope' do
before do
project.add_user(current_user, :maintainer)
end
it 'returns nil when scope is not enabled' do
allow(project).to receive(:ci_job_token_scope_enabled?).and_return(false)
expect(resolve_scope).to eq(nil)
end
it 'returns the same project in the allow list of projects for the Ci Job Token' do
expect(resolve_scope.all_projects).to contain_exactly(project)
end
context 'when another projects gets added to the allow list' do
let!(:link) { create(:ci_job_token_project_scope_link, source_project: project) }
it 'returns both projects' do
expect(resolve_scope.all_projects).to contain_exactly(project, link.target_project)
end
end
end
context 'without access to scope' do
before do
project.add_user(current_user, :developer)
end
it 'raises error' do
expect do
resolve_scope
end.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['CiJobTokenScopeType'] do
specify { expect(described_class.graphql_name).to eq('CiJobTokenScopeType') }
it 'has the correct fields' do
expected_fields = [:projects]
expect(described_class).to have_graphql_fields(*expected_fields)
end
describe 'query' do
let_it_be(:project) { create(:project) }
let_it_be(:current_user) { create(:user) }
let(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
ciJobTokenScope {
projects {
nodes {
path
}
}
}
}
}
)
end
subject { GitlabSchema.execute(query, context: { current_user: current_user }).as_json }
let(:projects_field) { subject.dig('data', 'project', 'ciJobTokenScope', 'projects', 'nodes') }
let(:returned_project_paths) { projects_field.map { |project| project['path']} }
context 'with access to scope' do
before do
project.add_user(current_user, :maintainer)
end
context 'when multiple projects in the allow list' do
let!(:link) { create(:ci_job_token_project_scope_link, source_project: project) }
context 'when linked projects are readable' do
before do
link.target_project.add_user(current_user, :developer)
end
it 'returns readable projects in scope' do
expect(returned_project_paths).to contain_exactly(project.path, link.target_project.path)
end
end
context 'when linked project is not readable' do
it 'returns readable projects in scope' do
expect(returned_project_paths).to contain_exactly(project.path)
end
end
end
end
end
end
...@@ -387,4 +387,11 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -387,4 +387,11 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::Ci::TemplateType) } it { is_expected.to have_graphql_type(Types::Ci::TemplateType) }
it { is_expected.to have_graphql_arguments(:name) } it { is_expected.to have_graphql_arguments(:name) }
end end
describe 'ci_job_token_scope field' do
subject { described_class.fields['ciJobTokenScope'] }
it { is_expected.to have_graphql_type(Types::Ci::JobTokenScopeType) }
it { is_expected.to have_graphql_resolver(Resolvers::Ci::JobTokenScopeResolver) }
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