diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 6aae76d335a0889fdbfd218559c748b41d394bf3..f8d415038aea728aebdbddcd8eebbed9b99f5603 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -27561,6 +27561,7 @@ Which group, user or role is allowed to approve deployments to the environment. | <a id="protectedenvironmentapprovalruleforsummaryaccesslevel"></a>`accessLevel` | [`AccessLevel`](#accesslevel) | Role details. Present if it's role specific access control. | | <a id="protectedenvironmentapprovalruleforsummaryapprovals"></a>`approvals` | [`[DeploymentApproval!]`](#deploymentapproval) | Current approvals of the deployment. | | <a id="protectedenvironmentapprovalruleforsummaryapprovedcount"></a>`approvedCount` | [`Int`](#int) | Approved count. | +| <a id="protectedenvironmentapprovalruleforsummarycanapprove"></a>`canApprove` | [`Boolean`](#boolean) | Indicates whether a user is authorized to approve. | | <a id="protectedenvironmentapprovalruleforsummarygroup"></a>`group` | [`Group`](#group) | Group details. Present if it's group specific access control. | | <a id="protectedenvironmentapprovalruleforsummarypendingapprovalcount"></a>`pendingApprovalCount` | [`Int`](#int) | Pending approval count. | | <a id="protectedenvironmentapprovalruleforsummaryrequiredapprovals"></a>`requiredApprovals` | [`Int`](#int) | Number of required approvals. | diff --git a/ee/app/graphql/types/protected_environments/approval_rule_for_summary_type.rb b/ee/app/graphql/types/protected_environments/approval_rule_for_summary_type.rb index be01e9bc8cd05f856c95bcbed26de337a6595638..5ad74e7da8f748a6af0efa39e449087d96857dbf 100644 --- a/ee/app/graphql/types/protected_environments/approval_rule_for_summary_type.rb +++ b/ee/app/graphql/types/protected_environments/approval_rule_for_summary_type.rb @@ -24,6 +24,14 @@ class ApprovalRuleForSummaryType < ApprovalRuleType type: [::Types::Deployments::ApprovalType], description: 'Current approvals of the deployment.', method: :approvals_for_summary + + field :can_approve, + type: GraphQL::Types::Boolean, + description: 'Indicates whether a user is authorized to approve.' + + def can_approve + object.check_access(current_user) + end end # rubocop:enable Graphql/AuthorizeTypes end diff --git a/ee/spec/graphql/types/protected_environments/approval_rule_for_summary_type_spec.rb b/ee/spec/graphql/types/protected_environments/approval_rule_for_summary_type_spec.rb index 70ad98f755e10018d348461a525d97ccafdd7cf4..eb166c6db8ff602b9ebbc9c2a0ecf9667331b334 100644 --- a/ee/spec/graphql/types/protected_environments/approval_rule_for_summary_type_spec.rb +++ b/ee/spec/graphql/types/protected_environments/approval_rule_for_summary_type_spec.rb @@ -2,14 +2,50 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['ProtectedEnvironmentApprovalRuleForSummary'] do +RSpec.describe GitlabSchema.types['ProtectedEnvironmentApprovalRuleForSummary'], + feature_category: :deployment_management do specify { expect(described_class.graphql_name).to eq('ProtectedEnvironmentApprovalRuleForSummary') } it 'includes the expected fields' do expected_fields = %w[ - approved_count pending_approval_count required_approvals status approvals + approvals + approved_count + can_approve + pending_approval_count + required_approvals + status ] expect(described_class).to include_graphql_fields(*expected_fields) end + + describe '#can_approve' do + include_context 'with an approval rule and approver' + + subject(:result) do + described_class.send( + :new, approval_rule, { current_user: user_being_checked } + ).can_approve + end + + context 'when user can approve' do + let_it_be(:user_being_checked) { approver } + + it { is_expected.to eq(true) } + end + + context 'when user cannot approve' do + include_context 'with a non approver' + + let_it_be(:user_being_checked) { non_approver } + + it { is_expected.to eq(false) } + end + + context 'when user is nil' do + let_it_be(:user_being_checked) { nil } + + it { is_expected.to eq(false) } + end + end end diff --git a/ee/spec/models/protected_environments/approval_rule_spec.rb b/ee/spec/models/protected_environments/approval_rule_spec.rb index 36a23c752343e12d3c59b295e9f7f27a0e12ed11..852cc5fc1d446d1778436dd03313636a80a4b2e1 100644 --- a/ee/spec/models/protected_environments/approval_rule_spec.rb +++ b/ee/spec/models/protected_environments/approval_rule_spec.rb @@ -1,21 +1,9 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe ProtectedEnvironments::ApprovalRule do - let_it_be(:project) { create(:project, :repository) } - let_it_be(:environment) { create(:environment, project: project) } - let_it_be(:approver) { create(:user) } - - let!(:protected_environment) { create(:protected_environment, project: project, name: environment.name) } - - let!(:approval_rule) do - create( - :protected_environment_approval_rule, - protected_environment: protected_environment, - user: approver, - required_approvals: 1 - ) - end +RSpec.describe ProtectedEnvironments::ApprovalRule, + feature_category: :deployment_management do + include_context 'with an approval rule and approver' describe 'associations' do it { is_expected.to have_many(:deployment_approvals).class_name('Deployments::Approval').inverse_of(:approval_rule) } diff --git a/spec/support/shared_contexts/models/protected_environments/approval_rule.rb b/spec/support/shared_contexts/models/protected_environments/approval_rule.rb new file mode 100644 index 0000000000000000000000000000000000000000..76f4d4380da661375ce8348a951f483dc75fd59f --- /dev/null +++ b/spec/support/shared_contexts/models/protected_environments/approval_rule.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +RSpec.shared_context 'with an approval rule and approver' do + let_it_be(:project) { create(:project, :repository) } + let_it_be(:environment) { create(:environment, project: project) } + let_it_be(:approver) { create(:user) } + + let!(:protected_environment) do + create( + :protected_environment, + project: project, + name: environment.name + ) + end + + let!(:approval_rule) do + create( + :protected_environment_approval_rule, + protected_environment: protected_environment, + user: approver, + required_approvals: 1 + ) + end +end + +RSpec.shared_context 'with a non approver' do + let_it_be(:non_approver) { create(:user) } +end