Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /app/graphql/mutations
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'app/graphql/mutations')
-rw-r--r--app/graphql/mutations/alert_management/base.rb2
-rw-r--r--app/graphql/mutations/alert_management/http_integration/create.rb19
-rw-r--r--app/graphql/mutations/alert_management/http_integration/http_integration_base.rb7
-rw-r--r--app/graphql/mutations/alert_management/http_integration/update.rb4
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/create.rb8
-rw-r--r--app/graphql/mutations/boards/lists/base.rb28
-rw-r--r--app/graphql/mutations/boards/lists/base_create.rb55
-rw-r--r--app/graphql/mutations/boards/lists/create.rb51
-rw-r--r--app/graphql/mutations/branches/create.rb10
-rw-r--r--app/graphql/mutations/commits/create.rb10
-rw-r--r--app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb83
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb4
-rw-r--r--app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb24
-rw-r--r--app/graphql/mutations/container_expiration_policies/update.rb10
-rw-r--r--app/graphql/mutations/discussions/toggle_resolve.rb2
-rw-r--r--app/graphql/mutations/issues/create.rb8
-rw-r--r--app/graphql/mutations/jira_import/import_users.rb16
-rw-r--r--app/graphql/mutations/jira_import/start.rb16
-rw-r--r--app/graphql/mutations/merge_requests/create.rb10
-rw-r--r--app/graphql/mutations/merge_requests/reviewer_rereview.rb27
-rw-r--r--app/graphql/mutations/merge_requests/update.rb11
-rw-r--r--app/graphql/mutations/notes/create/base.rb15
-rw-r--r--app/graphql/mutations/releases/base.rb8
-rw-r--r--app/graphql/mutations/releases/create.rb2
-rw-r--r--app/graphql/mutations/releases/delete.rb2
-rw-r--r--app/graphql/mutations/releases/update.rb2
-rw-r--r--app/graphql/mutations/security/ci_configuration/configure_sast.rb46
-rw-r--r--app/graphql/mutations/snippets/create.rb41
-rw-r--r--app/graphql/mutations/snippets/service_compatibility.rb23
-rw-r--r--app/graphql/mutations/snippets/update.rb48
-rw-r--r--app/graphql/mutations/todos/create.rb2
-rw-r--r--app/graphql/mutations/todos/mark_all_done.rb6
-rw-r--r--app/graphql/mutations/todos/mark_done.rb4
-rw-r--r--app/graphql/mutations/todos/restore.rb4
-rw-r--r--app/graphql/mutations/todos/restore_many.rb10
35 files changed, 377 insertions, 241 deletions
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
index 3a57cb9670d..86908c1449c 100644
--- a/app/graphql/mutations/alert_management/base.rb
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -21,7 +21,7 @@ module Mutations
field :todo,
Types::TodoType,
null: true,
- description: "The todo after mutation."
+ description: "The to-do item after mutation."
field :issue,
Types::IssueType,
diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb
index ff165d7f302..2d7bffb4333 100644
--- a/app/graphql/mutations/alert_management/http_integration/create.rb
+++ b/app/graphql/mutations/alert_management/http_integration/create.rb
@@ -4,7 +4,7 @@ module Mutations
module AlertManagement
module HttpIntegration
class Create < HttpIntegrationBase
- include ResolvesProject
+ include FindsProject
graphql_name 'HttpIntegrationCreate'
@@ -21,27 +21,14 @@ module Mutations
description: 'Whether the integration is receiving alerts.'
def resolve(args)
- @project = authorized_find!(full_path: args[:project_path])
+ project = authorized_find!(args[:project_path])
response ::AlertManagement::HttpIntegrations::CreateService.new(
project,
current_user,
- http_integration_params(args)
+ http_integration_params(project, args)
).execute
end
-
- private
-
- attr_reader :project
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
- # overriden in EE
- def http_integration_params(args)
- args.slice(:name, :active)
- end
end
end
end
diff --git a/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
index 147df982bec..e33b7bb399a 100644
--- a/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
+++ b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
@@ -23,7 +23,14 @@ module Mutations
errors: result.errors
}
end
+
+ # overriden in EE
+ def http_integration_params(_project, args)
+ args.slice(:name, :active)
+ end
end
end
end
end
+
+Mutations::AlertManagement::HttpIntegration::HttpIntegrationBase.prepend_if_ee('::EE::Mutations::AlertManagement::HttpIntegration::HttpIntegrationBase')
diff --git a/app/graphql/mutations/alert_management/http_integration/update.rb b/app/graphql/mutations/alert_management/http_integration/update.rb
index 431fccaa5e5..b1e4ce841ee 100644
--- a/app/graphql/mutations/alert_management/http_integration/update.rb
+++ b/app/graphql/mutations/alert_management/http_integration/update.rb
@@ -24,10 +24,12 @@ module Mutations
response ::AlertManagement::HttpIntegrations::UpdateService.new(
integration,
current_user,
- args.slice(:name, :active)
+ http_integration_params(integration.project, args)
).execute
end
end
end
end
end
+
+Mutations::AlertManagement::HttpIntegration::Update.prepend_if_ee('::EE::Mutations::AlertManagement::HttpIntegration::Update')
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
index c676cde90b4..87e6bc46937 100644
--- a/app/graphql/mutations/alert_management/prometheus_integration/create.rb
+++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
@@ -4,7 +4,7 @@ module Mutations
module AlertManagement
module PrometheusIntegration
class Create < PrometheusIntegrationBase
- include ResolvesProject
+ include FindsProject
graphql_name 'PrometheusIntegrationCreate'
@@ -21,7 +21,7 @@ module Mutations
description: 'Endpoint at which prometheus can be queried.'
def resolve(args)
- project = authorized_find!(full_path: args[:project_path])
+ project = authorized_find!(args[:project_path])
return integration_exists if project.prometheus_service
@@ -37,10 +37,6 @@ module Mutations
private
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
def integration_exists
response(nil, message: _('Multiple Prometheus integrations are not supported'))
end
diff --git a/app/graphql/mutations/boards/lists/base.rb b/app/graphql/mutations/boards/lists/base.rb
deleted file mode 100644
index 34c138bddc9..00000000000
--- a/app/graphql/mutations/boards/lists/base.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module Boards
- module Lists
- class Base < BaseMutation
- include Mutations::ResolvesIssuable
-
- argument :board_id, ::Types::GlobalIDType[::Board],
- required: true,
- description: 'Global ID of the issue board to mutate.'
-
- field :list,
- Types::BoardListType,
- null: true,
- description: 'List of the issue board.'
-
- authorize :admin_list
-
- private
-
- def find_object(id:)
- GitlabSchema.object_from_id(id, expected_type: ::Board)
- end
- end
- end
- end
-end
diff --git a/app/graphql/mutations/boards/lists/base_create.rb b/app/graphql/mutations/boards/lists/base_create.rb
new file mode 100644
index 00000000000..a21c7feece3
--- /dev/null
+++ b/app/graphql/mutations/boards/lists/base_create.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Boards
+ module Lists
+ class BaseCreate < BaseMutation
+ argument :backlog, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'Create the backlog list.'
+
+ argument :label_id, ::Types::GlobalIDType[::Label],
+ required: false,
+ description: 'Global ID of an existing label.'
+
+ def ready?(**args)
+ if args.slice(*mutually_exclusive_args).size != 1
+ arg_str = mutually_exclusive_args.map { |x| x.to_s.camelize(:lower) }.join(' or ')
+ raise Gitlab::Graphql::Errors::ArgumentError, "one and only one of #{arg_str} is required"
+ end
+
+ super
+ end
+
+ def resolve(**args)
+ board = authorized_find!(id: args[:board_id])
+ params = create_list_params(args)
+
+ response = create_list(board, params)
+
+ {
+ list: response.success? ? response.payload[:list] : nil,
+ errors: response.errors
+ }
+ end
+
+ private
+
+ def create_list(board, params)
+ raise NotImplementedError
+ end
+
+ def create_list_params(args)
+ params = args.slice(*mutually_exclusive_args).with_indifferent_access
+ params[:label_id] &&= ::GitlabSchema.parse_gid(params[:label_id], expected_type: ::Label).model_id
+
+ params
+ end
+
+ def mutually_exclusive_args
+ [:backlog, :label_id]
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/boards/lists/create.rb b/app/graphql/mutations/boards/lists/create.rb
index 9eb9a4d4b87..f3aae9ac9c8 100644
--- a/app/graphql/mutations/boards/lists/create.rb
+++ b/app/graphql/mutations/boards/lists/create.rb
@@ -3,59 +3,32 @@
module Mutations
module Boards
module Lists
- class Create < Base
+ class Create < BaseCreate
graphql_name 'BoardListCreate'
- argument :backlog, GraphQL::BOOLEAN_TYPE,
- required: false,
- description: 'Create the backlog list.'
+ argument :board_id, ::Types::GlobalIDType[::Board],
+ required: true,
+ description: 'Global ID of the issue board to mutate.'
- argument :label_id, ::Types::GlobalIDType[::Label],
- required: false,
- description: 'Global ID of an existing label.'
+ field :list,
+ Types::BoardListType,
+ null: true,
+ description: 'Issue list in the issue board.'
- def ready?(**args)
- if args.slice(*mutually_exclusive_args).size != 1
- arg_str = mutually_exclusive_args.map { |x| x.to_s.camelize(:lower) }.join(' or ')
- raise Gitlab::Graphql::Errors::ArgumentError, "one and only one of #{arg_str} is required"
- end
+ authorize :admin_list
- super
- end
-
- def resolve(**args)
- board = authorized_find!(id: args[:board_id])
- params = create_list_params(args)
-
- response = create_list(board, params)
+ private
- {
- list: response.success? ? response.payload[:list] : nil,
- errors: response.errors
- }
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_type: ::Board)
end
- private
-
def create_list(board, params)
create_list_service =
::Boards::Lists::CreateService.new(board.resource_parent, current_user, params)
create_list_service.execute(board)
end
-
- # Overridden in EE
- def create_list_params(args)
- params = args.slice(*mutually_exclusive_args).with_indifferent_access
- params[:label_id] &&= ::GitlabSchema.parse_gid(params[:label_id], expected_type: ::Label).model_id
-
- params
- end
-
- # Overridden in EE
- def mutually_exclusive_args
- [:backlog, :label_id]
- end
end
end
end
diff --git a/app/graphql/mutations/branches/create.rb b/app/graphql/mutations/branches/create.rb
index 9fe9bef5403..6354976f1ea 100644
--- a/app/graphql/mutations/branches/create.rb
+++ b/app/graphql/mutations/branches/create.rb
@@ -3,7 +3,7 @@
module Mutations
module Branches
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'CreateBranch'
@@ -28,7 +28,7 @@ module Mutations
authorize :push_code
def resolve(project_path:, name:, ref:)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
context.scoped_set!(:branch_project, project)
@@ -40,12 +40,6 @@ module Mutations
errors: Array.wrap(result[:message])
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb
index ae14401558b..84933fee5d2 100644
--- a/app/graphql/mutations/commits/create.rb
+++ b/app/graphql/mutations/commits/create.rb
@@ -3,7 +3,7 @@
module Mutations
module Commits
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'CommitCreate'
@@ -37,7 +37,7 @@ module Mutations
authorize :push_code
def resolve(project_path:, branch:, message:, actions:, **args)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
attributes = {
commit_message: message,
@@ -53,12 +53,6 @@ module Mutations
errors: Array.wrap(result[:message])
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
new file mode 100644
index 00000000000..2d4983f0d6e
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/can_mutate_spammable.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Mutations
+ # This concern can be mixed into a mutation to provide support for spam checking,
+ # and optionally support the workflow to allow clients to display and solve CAPTCHAs.
+ module CanMutateSpammable
+ extend ActiveSupport::Concern
+
+ # NOTE: The arguments and fields are intentionally named with 'captcha' instead of 'recaptcha',
+ # so that they can be applied to future alternative CAPTCHA implementations other than
+ # reCAPTCHA (e.g. FriendlyCaptcha) without having to change the names and descriptions in the API.
+ included do
+ argument :captcha_response, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'A valid CAPTCHA response value obtained by using the provided captchaSiteKey with a CAPTCHA API to present a challenge to be solved on the client. Required to resubmit if the previous operation returned "NeedsCaptchaResponse: true".'
+
+ argument :spam_log_id, GraphQL::INT_TYPE,
+ required: false,
+ description: 'The spam log ID which must be passed along with a valid CAPTCHA response for the operation to be completed. Required to resubmit if the previous operation returned "NeedsCaptchaResponse: true".'
+
+ field :spam,
+ GraphQL::BOOLEAN_TYPE,
+ null: true,
+ description: 'Indicates whether the operation was detected as definite spam. There is no option to resubmit the request with a CAPTCHA response.'
+
+ field :needs_captcha_response,
+ GraphQL::BOOLEAN_TYPE,
+ null: true,
+ description: 'Indicates whether the operation was detected as possible spam and not completed. If CAPTCHA is enabled, the request must be resubmitted with a valid CAPTCHA response and spam_log_id included for the operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
+
+ field :spam_log_id,
+ GraphQL::INT_TYPE,
+ null: true,
+ description: 'The spam log ID which must be passed along with a valid CAPTCHA response for an operation to be completed. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
+
+ field :captcha_site_key,
+ GraphQL::STRING_TYPE,
+ null: true,
+ description: 'The CAPTCHA site key which must be used to render a challenge for the user to solve to obtain a valid captchaResponse value. Included only when an operation was not completed because "NeedsCaptchaResponse" is true.'
+ end
+
+ private
+
+ # additional_spam_params -> hash
+ #
+ # Used from a spammable mutation's #resolve method to generate
+ # the required additional spam/recaptcha params which must be merged into the params
+ # passed to the constructor of a service, where they can then be used in the service
+ # to perform spam checking via SpamActionService.
+ #
+ # Also accesses the #context of the mutation's Resolver superclass to obtain the request.
+ #
+ # Example:
+ #
+ # existing_args.merge!(additional_spam_params)
+ def additional_spam_params
+ {
+ api: true,
+ request: context[:request]
+ }
+ end
+
+ # with_spam_action_fields(spammable) { {other_fields: true} } -> hash
+ #
+ # Takes a Spammable and a block as arguments.
+ #
+ # The block passed should be a hash, which the spam action fields will be merged into.
+ def with_spam_action_fields(spammable)
+ spam_action_fields = {
+ spam: spammable.spam?,
+ # NOTE: These fields are intentionally named with 'captcha' instead of 'recaptcha', so
+ # that they can be applied to future alternative CAPTCHA implementations other than
+ # reCAPTCHA (such as FriendlyCaptcha) without having to change the response field name
+ # in the API.
+ needs_captcha_response: spammable.render_recaptcha?,
+ spam_log_id: spammable.spam_log&.id,
+ captcha_site_key: Gitlab::CurrentSettings.recaptcha_site_key
+ }
+
+ yield.merge(spam_action_fields)
+ end
+ end
+end
diff --git a/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb b/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
index e2b3f4b046f..b8ef675c3d4 100644
--- a/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
+++ b/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
@@ -9,11 +9,11 @@ module Mutations
included do
argument :project_path, GraphQL::ID_TYPE,
required: false,
- description: 'The project full path the resource is associated with.'
+ description: 'Full path of the project with which the resource is associated.'
argument :group_path, GraphQL::ID_TYPE,
required: false,
- description: 'The group full path the resource is associated with.'
+ description: 'Full path of the group with which the resource is associated.'
end
def ready?(**args)
diff --git a/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb b/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb
deleted file mode 100644
index e5df8565618..00000000000
--- a/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module SpammableMutationFields
- extend ActiveSupport::Concern
-
- included do
- field :spam,
- GraphQL::BOOLEAN_TYPE,
- null: true,
- description: 'Indicates whether the operation returns a record detected as spam.'
- end
-
- def with_spam_params(&block)
- request = Feature.enabled?(:snippet_spam) ? context[:request] : nil
-
- yield.merge({ api: true, request: request })
- end
-
- def with_spam_fields(spammable, &block)
- { spam: spammable.spam? }.merge!(yield)
- end
- end
-end
diff --git a/app/graphql/mutations/container_expiration_policies/update.rb b/app/graphql/mutations/container_expiration_policies/update.rb
index 37cf2fa6bf3..f61d852bb6c 100644
--- a/app/graphql/mutations/container_expiration_policies/update.rb
+++ b/app/graphql/mutations/container_expiration_policies/update.rb
@@ -3,7 +3,7 @@
module Mutations
module ContainerExpirationPolicies
class Update < Mutations::BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'UpdateContainerExpirationPolicy'
@@ -50,7 +50,7 @@ module Mutations
description: 'The container expiration policy after mutation.'
def resolve(project_path:, **args)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
result = ::ContainerExpirationPolicies::UpdateService
.new(container: project, current_user: current_user, params: args)
@@ -61,12 +61,6 @@ module Mutations
errors: result.errors
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/discussions/toggle_resolve.rb b/app/graphql/mutations/discussions/toggle_resolve.rb
index c9834c946b2..6639252ec67 100644
--- a/app/graphql/mutations/discussions/toggle_resolve.rb
+++ b/app/graphql/mutations/discussions/toggle_resolve.rb
@@ -69,7 +69,7 @@ module Mutations
end
def unresolve!(discussion)
- discussion.unresolve!
+ ::Discussions::UnresolveService.new(discussion, current_user).execute
end
end
end
diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb
index 18b80ff1736..37fddd92832 100644
--- a/app/graphql/mutations/issues/create.rb
+++ b/app/graphql/mutations/issues/create.rb
@@ -3,7 +3,7 @@
module Mutations
module Issues
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'CreateIssue'
authorize :create_issue
@@ -70,7 +70,7 @@ module Mutations
end
def resolve(project_path:, **attributes)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = build_create_issue_params(attributes.merge(author_id: current_user.id))
issue = ::Issues::CreateService.new(project, current_user, params).execute
@@ -98,10 +98,6 @@ module Mutations
def mutually_exclusive_label_args
[:labels, :label_ids]
end
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/jira_import/import_users.rb b/app/graphql/mutations/jira_import/import_users.rb
index 616ef390657..af2bb18161f 100644
--- a/app/graphql/mutations/jira_import/import_users.rb
+++ b/app/graphql/mutations/jira_import/import_users.rb
@@ -3,10 +3,12 @@
module Mutations
module JiraImport
class ImportUsers < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'JiraImportUsers'
+ authorize :admin_project
+
field :jira_users,
[Types::JiraUserType],
null: true,
@@ -20,7 +22,7 @@ module Mutations
description: 'The index of the record the import should started at, default 0 (50 records returned).'
def resolve(project_path:, start_at: 0)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
service_response = ::JiraImport::UsersImporter.new(context[:current_user], project, start_at.to_i).execute
@@ -29,16 +31,6 @@ module Mutations
errors: service_response.errors
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
- def authorized_resource?(project)
- Ability.allowed?(context[:current_user], :admin_project, project)
- end
end
end
end
diff --git a/app/graphql/mutations/jira_import/start.rb b/app/graphql/mutations/jira_import/start.rb
index 3d50ebde13a..e31aaf53a09 100644
--- a/app/graphql/mutations/jira_import/start.rb
+++ b/app/graphql/mutations/jira_import/start.rb
@@ -3,10 +3,12 @@
module Mutations
module JiraImport
class Start < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'JiraImportStart'
+ authorize :admin_project
+
field :jira_import,
Types::JiraImportType,
null: true,
@@ -27,7 +29,7 @@ module Mutations
description: 'The mapping of Jira to GitLab users.'
def resolve(project_path:, jira_project_key:, users_mapping:)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
mapping = users_mapping.to_ary.map { |map| map.to_hash }
service_response = ::JiraImport::StartImportService
@@ -40,16 +42,6 @@ module Mutations
errors: service_response.errors
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
-
- def authorized_resource?(project)
- Ability.allowed?(context[:current_user], :admin_project, project)
- end
end
end
end
diff --git a/app/graphql/mutations/merge_requests/create.rb b/app/graphql/mutations/merge_requests/create.rb
index 64fa8417e50..9ac8f70be95 100644
--- a/app/graphql/mutations/merge_requests/create.rb
+++ b/app/graphql/mutations/merge_requests/create.rb
@@ -3,7 +3,7 @@
module Mutations
module MergeRequests
class Create < BaseMutation
- include ResolvesProject
+ include FindsProject
graphql_name 'MergeRequestCreate'
@@ -39,7 +39,7 @@ module Mutations
authorize :create_merge_request_from
def resolve(project_path:, **attributes)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = attributes.merge(author_id: current_user.id)
merge_request = ::MergeRequests::CreateService.new(project, current_user, params).execute
@@ -49,12 +49,6 @@ module Mutations
errors: errors_on_object(merge_request)
}
end
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/merge_requests/reviewer_rereview.rb b/app/graphql/mutations/merge_requests/reviewer_rereview.rb
new file mode 100644
index 00000000000..f6f4881654e
--- /dev/null
+++ b/app/graphql/mutations/merge_requests/reviewer_rereview.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module MergeRequests
+ class ReviewerRereview < Base
+ graphql_name 'MergeRequestReviewerRereview'
+
+ argument :user_id, ::Types::GlobalIDType[::User],
+ loads: Types::UserType,
+ required: true,
+ description: <<~DESC
+ The user ID for the user that has been requested for a new review.
+ DESC
+
+ def resolve(project_path:, iid:, user:)
+ merge_request = authorized_find!(project_path: project_path, iid: iid)
+
+ result = ::MergeRequests::RequestReviewService.new(merge_request.project, current_user).execute(merge_request, user)
+
+ {
+ merge_request: merge_request,
+ errors: Array(result[:message])
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/update.rb b/app/graphql/mutations/merge_requests/update.rb
index 4721ebab41b..6a94d2f37b2 100644
--- a/app/graphql/mutations/merge_requests/update.rb
+++ b/app/graphql/mutations/merge_requests/update.rb
@@ -19,9 +19,14 @@ module Mutations
required: false,
description: copy_field_description(Types::MergeRequestType, :description)
- def resolve(args)
- merge_request = authorized_find!(**args.slice(:project_path, :iid))
- attributes = args.slice(:title, :description, :target_branch).compact
+ argument :state, ::Types::MergeRequestStateEventEnum,
+ required: false,
+ as: :state_event,
+ description: 'The action to perform to change the state.'
+
+ def resolve(project_path:, iid:, **args)
+ merge_request = authorized_find!(project_path: project_path, iid: iid)
+ attributes = args.compact
::MergeRequests::UpdateService
.new(merge_request.project, current_user, attributes)
diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb
index 2351af01813..a157a5abdf2 100644
--- a/app/graphql/mutations/notes/create/base.rb
+++ b/app/graphql/mutations/notes/create/base.rb
@@ -25,6 +25,7 @@ module Mutations
def resolve(args)
noteable = authorized_find!(id: args[:noteable_id])
+ verify_rate_limit!(current_user)
note = ::Notes::CreateService.new(
noteable.project,
@@ -54,6 +55,20 @@ module Mutations
confidential: args[:confidential]
}
end
+
+ def verify_rate_limit!(current_user)
+ return unless rate_limit_throttled?
+
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable,
+ 'This endpoint has been requested too many times. Try again later.'
+ end
+
+ def rate_limit_throttled?
+ rate_limiter = ::Gitlab::ApplicationRateLimiter
+ allowlist = Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist
+
+ rate_limiter.throttled?(:notes_create, scope: [current_user], users_allowlist: allowlist)
+ end
end
end
end
diff --git a/app/graphql/mutations/releases/base.rb b/app/graphql/mutations/releases/base.rb
index dd1724fe320..610e9cd9cde 100644
--- a/app/graphql/mutations/releases/base.rb
+++ b/app/graphql/mutations/releases/base.rb
@@ -3,17 +3,11 @@
module Mutations
module Releases
class Base < BaseMutation
- include ResolvesProject
+ include FindsProject
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'Full path of the project the release is associated with.'
-
- private
-
- def find_object(full_path:)
- resolve_project(full_path: full_path)
- end
end
end
end
diff --git a/app/graphql/mutations/releases/create.rb b/app/graphql/mutations/releases/create.rb
index 91ac256033e..914c1302094 100644
--- a/app/graphql/mutations/releases/create.rb
+++ b/app/graphql/mutations/releases/create.rb
@@ -41,7 +41,7 @@ module Mutations
authorize :create_release
def resolve(project_path:, assets: nil, **scalars)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = {
**scalars,
diff --git a/app/graphql/mutations/releases/delete.rb b/app/graphql/mutations/releases/delete.rb
index e887b702cce..020c9133b58 100644
--- a/app/graphql/mutations/releases/delete.rb
+++ b/app/graphql/mutations/releases/delete.rb
@@ -17,7 +17,7 @@ module Mutations
authorize :destroy_release
def resolve(project_path:, tag:)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = { tag: tag }.with_indifferent_access
diff --git a/app/graphql/mutations/releases/update.rb b/app/graphql/mutations/releases/update.rb
index dff743254bd..35f2a7b3d4b 100644
--- a/app/graphql/mutations/releases/update.rb
+++ b/app/graphql/mutations/releases/update.rb
@@ -47,7 +47,7 @@ module Mutations
end
def resolve(project_path:, **scalars)
- project = authorized_find!(full_path: project_path)
+ project = authorized_find!(project_path)
params = scalars.with_indifferent_access
diff --git a/app/graphql/mutations/security/ci_configuration/configure_sast.rb b/app/graphql/mutations/security/ci_configuration/configure_sast.rb
new file mode 100644
index 00000000000..e4a3f815396
--- /dev/null
+++ b/app/graphql/mutations/security/ci_configuration/configure_sast.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Security
+ module CiConfiguration
+ class ConfigureSast < BaseMutation
+ include FindsProject
+
+ graphql_name 'ConfigureSast'
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'Full path of the project.'
+
+ argument :configuration, ::Types::CiConfiguration::Sast::InputType,
+ required: true,
+ description: 'SAST CI configuration for the project.'
+
+ field :status, GraphQL::STRING_TYPE, null: false,
+ description: 'Status of creating the commit for the supplied SAST CI configuration.'
+
+ field :success_path, GraphQL::STRING_TYPE, null: true,
+ description: 'Redirect path to use when the response is successful.'
+
+ authorize :push_code
+
+ def resolve(project_path:, configuration:)
+ project = authorized_find!(project_path)
+
+ result = ::Security::CiConfiguration::SastCreateService.new(project, current_user, configuration).execute
+ prepare_response(result)
+ end
+
+ private
+
+ def prepare_response(result)
+ {
+ status: result[:status],
+ success_path: result[:success_path],
+ errors: Array(result[:errors])
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index b4485e28c5a..73eac9f0f3b 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -3,7 +3,8 @@
module Mutations
module Snippets
class Create < BaseMutation
- include SpammableMutationFields
+ include ServiceCompatibility
+ include CanMutateSpammable
authorize :create_snippet
@@ -45,18 +46,17 @@ module Mutations
authorize!(:global)
end
- service_response = ::Snippets::CreateService.new(project,
- current_user,
- create_params(args)).execute
+ process_args_for_params!(args)
- snippet = service_response.payload[:snippet]
+ service_response = ::Snippets::CreateService.new(project, current_user, args).execute
# Only when the user is not an api user and the operation was successful
if !api_user? && service_response.success?
::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
end
- with_spam_fields(snippet) do
+ snippet = service_response.payload[:snippet]
+ with_spam_action_fields(snippet) do
{
snippet: service_response.success? ? snippet : nil,
errors: errors_on_object(snippet)
@@ -70,18 +70,25 @@ module Mutations
Project.find_by_full_path(full_path)
end
- def create_params(args)
- with_spam_params do
- args.tap do |create_args|
- # We need to rename `blob_actions` into `snippet_actions` because
- # it's the expected key param
- create_args[:snippet_actions] = create_args.delete(:blob_actions)&.map(&:to_h)
-
- # We need to rename `uploaded_files` into `files` because
- # it's the expected key param
- create_args[:files] = create_args.delete(:uploaded_files)
- end
+ # process_args_for_params!(args) -> nil
+ #
+ # Modifies/adds/deletes mutation resolve args as necessary to be passed as params to service layer.
+ def process_args_for_params!(args)
+ convert_blob_actions_to_snippet_actions!(args)
+
+ # We need to rename `uploaded_files` into `files` because
+ # it's the expected key param
+ args[:files] = args.delete(:uploaded_files)
+
+ if Feature.enabled?(:snippet_spam)
+ args.merge!(additional_spam_params)
+ else
+ args[:disable_spam_action_service] = true
end
+
+ # Return nil to make it explicit that this method is mutating the args parameter, and that
+ # the return value is not relevant and is not to be used.
+ nil
end
end
end
diff --git a/app/graphql/mutations/snippets/service_compatibility.rb b/app/graphql/mutations/snippets/service_compatibility.rb
new file mode 100644
index 00000000000..0e7ee5d78bf
--- /dev/null
+++ b/app/graphql/mutations/snippets/service_compatibility.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Snippets
+ # Translates graphql mutation field params to be compatible with those expected by the service layer
+ module ServiceCompatibility
+ extend ActiveSupport::Concern
+
+ # convert_blob_actions_to_snippet_actions!(args) -> nil
+ #
+ # Converts the blob_actions mutation argument into the
+ # snippet_actions hash which the service layer expects
+ def convert_blob_actions_to_snippet_actions!(args)
+ # We need to rename `blob_actions` into `snippet_actions` because
+ # it's the expected key param
+ args[:snippet_actions] = args.delete(:blob_actions)&.map(&:to_h)
+
+ # Return nil to make it explicit that this method is mutating the args parameter
+ nil
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 930440fbd35..af8e6f384b7 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -3,7 +3,8 @@
module Mutations
module Snippets
class Update < Base
- include SpammableMutationFields
+ include ServiceCompatibility
+ include CanMutateSpammable
graphql_name 'UpdateSnippet'
@@ -30,19 +31,23 @@ module Mutations
def resolve(id:, **args)
snippet = authorized_find!(id: id)
- result = ::Snippets::UpdateService.new(snippet.project,
- current_user,
- update_params(args)).execute(snippet)
- snippet = result.payload[:snippet]
+ process_args_for_params!(args)
+
+ service_response = ::Snippets::UpdateService.new(snippet.project, current_user, args).execute(snippet)
+
+ # TODO: DRY this up - From here down, this is all duplicated with Mutations::Snippets::Create#resolve, except for
+ # `snippet.reset`, which is required in order to return the object in its non-dirty, unmodified, database state
+ # See issue here: https://gitlab.com/gitlab-org/gitlab/-/issues/300250
# Only when the user is not an api user and the operation was successful
- if !api_user? && result.success?
+ if !api_user? && service_response.success?
::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
end
- with_spam_fields(snippet) do
+ snippet = service_response.payload[:snippet]
+ with_spam_action_fields(snippet) do
{
- snippet: result.success? ? snippet : snippet.reset,
+ snippet: service_response.success? ? snippet : snippet.reset,
errors: errors_on_object(snippet)
}
end
@@ -50,18 +55,25 @@ module Mutations
private
- def ability_name
- 'update'
- end
+ # process_args_for_params!(args) -> nil
+ #
+ # Modifies/adds/deletes mutation resolve args as necessary to be passed as params to service layer.
+ def process_args_for_params!(args)
+ convert_blob_actions_to_snippet_actions!(args)
- def update_params(args)
- with_spam_params do
- args.tap do |update_args|
- # We need to rename `blob_actions` into `snippet_actions` because
- # it's the expected key param
- update_args[:snippet_actions] = update_args.delete(:blob_actions)&.map(&:to_h)
- end
+ if Feature.enabled?(:snippet_spam)
+ args.merge!(additional_spam_params)
+ else
+ args[:disable_spam_action_service] = true
end
+
+ # Return nil to make it explicit that this method is mutating the args parameter, and that
+ # the return value is not relevant and is not to be used.
+ nil
+ end
+
+ def ability_name
+ 'update'
end
end
end
diff --git a/app/graphql/mutations/todos/create.rb b/app/graphql/mutations/todos/create.rb
index 814f7ec4fc4..b6250b0228c 100644
--- a/app/graphql/mutations/todos/create.rb
+++ b/app/graphql/mutations/todos/create.rb
@@ -14,7 +14,7 @@ module Mutations
field :todo, Types::TodoType,
null: true,
- description: 'The to-do created.'
+ description: 'The to-do item created.'
def resolve(target_id:)
id = ::Types::GlobalIDType[Todoable].coerce_isolated_input(target_id)
diff --git a/app/graphql/mutations/todos/mark_all_done.rb b/app/graphql/mutations/todos/mark_all_done.rb
index c8359953567..22a5893d4ec 100644
--- a/app/graphql/mutations/todos/mark_all_done.rb
+++ b/app/graphql/mutations/todos/mark_all_done.rb
@@ -10,12 +10,12 @@ module Mutations
field :updated_ids,
[::Types::GlobalIDType[::Todo]],
null: false,
- deprecated: { reason: 'Use todos', milestone: '13.2' },
- description: 'Ids of the updated todos.'
+ deprecated: { reason: 'Use to-do items', milestone: '13.2' },
+ description: 'IDs of the updated to-do items.'
field :todos, [::Types::TodoType],
null: false,
- description: 'Updated todos.'
+ description: 'Updated to-do items.'
def resolve
authorize!(current_user)
diff --git a/app/graphql/mutations/todos/mark_done.rb b/app/graphql/mutations/todos/mark_done.rb
index 95144abb040..a78cc91da68 100644
--- a/app/graphql/mutations/todos/mark_done.rb
+++ b/app/graphql/mutations/todos/mark_done.rb
@@ -10,11 +10,11 @@ module Mutations
argument :id,
::Types::GlobalIDType[::Todo],
required: true,
- description: 'The global ID of the todo to mark as done.'
+ description: 'The global ID of the to-do item to mark as done.'
field :todo, Types::TodoType,
null: false,
- description: 'The requested todo.'
+ description: 'The requested to-do item.'
def resolve(id:)
todo = authorized_find!(id: id)
diff --git a/app/graphql/mutations/todos/restore.rb b/app/graphql/mutations/todos/restore.rb
index e496627aec2..70c33c439c4 100644
--- a/app/graphql/mutations/todos/restore.rb
+++ b/app/graphql/mutations/todos/restore.rb
@@ -10,11 +10,11 @@ module Mutations
argument :id,
::Types::GlobalIDType[::Todo],
required: true,
- description: 'The global ID of the todo to restore.'
+ description: 'The global ID of the to-do item to restore.'
field :todo, Types::TodoType,
null: false,
- description: 'The requested todo.'
+ description: 'The requested to-do item.'
def resolve(id:)
todo = authorized_find!(id: id)
diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb
index 9263c1d9afe..dc02ffadada 100644
--- a/app/graphql/mutations/todos/restore_many.rb
+++ b/app/graphql/mutations/todos/restore_many.rb
@@ -10,16 +10,16 @@ module Mutations
argument :ids,
[::Types::GlobalIDType[::Todo]],
required: true,
- description: 'The global IDs of the todos to restore (a maximum of 50 is supported at once).'
+ description: 'The global IDs of the to-do items to restore (a maximum of 50 is supported at once).'
field :updated_ids, [::Types::GlobalIDType[Todo]],
null: false,
- description: 'The IDs of the updated todo items.',
- deprecated: { reason: 'Use todos', milestone: '13.2' }
+ description: 'The IDs of the updated to-do items.',
+ deprecated: { reason: 'Use to-do items', milestone: '13.2' }
field :todos, [::Types::TodoType],
null: false,
- description: 'Updated todos.'
+ description: 'Updated to-do items.'
def resolve(ids:)
check_update_amount_limit!(ids)
@@ -46,7 +46,7 @@ module Mutations
end
def raise_too_many_todos_requested_error
- raise Gitlab::Graphql::Errors::ArgumentError, 'Too many todos requested.'
+ raise Gitlab::Graphql::Errors::ArgumentError, 'Too many to-do items requested.'
end
def check_update_amount_limit!(ids)