From 41fe97390ceddf945f3d967b8fdb3de4c66b7dea Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Fri, 18 Mar 2022 20:02:30 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-9-stable-ee --- app/graphql/mutations/ci/pipeline/retry.rb | 5 +- app/graphql/mutations/ci/runner/delete.rb | 11 +--- app/graphql/mutations/ci/runner/update.rb | 2 +- .../ci/runners_registration_token/reset.rb | 13 ++--- .../concerns/mutations/spam_protection.rb | 26 ++------- app/graphql/mutations/notes/base.rb | 6 ++ app/graphql/mutations/notes/create/note.rb | 9 ++- app/graphql/mutations/notes/update/base.rb | 6 -- app/graphql/mutations/saved_replies/base.rb | 39 +++++++++++++ app/graphql/mutations/saved_replies/create.rb | 26 +++++++++ app/graphql/mutations/saved_replies/update.rb | 31 +++++++++++ app/graphql/mutations/work_items/create.rb | 2 +- .../mutations/work_items/create_from_task.rb | 64 ++++++++++++++++++++++ app/graphql/mutations/work_items/delete.rb | 2 +- app/graphql/mutations/work_items/update.rb | 2 +- 15 files changed, 194 insertions(+), 50 deletions(-) create mode 100644 app/graphql/mutations/saved_replies/base.rb create mode 100644 app/graphql/mutations/saved_replies/create.rb create mode 100644 app/graphql/mutations/saved_replies/update.rb create mode 100644 app/graphql/mutations/work_items/create_from_task.rb (limited to 'app/graphql/mutations') diff --git a/app/graphql/mutations/ci/pipeline/retry.rb b/app/graphql/mutations/ci/pipeline/retry.rb index ee93f99703e..895397a96ab 100644 --- a/app/graphql/mutations/ci/pipeline/retry.rb +++ b/app/graphql/mutations/ci/pipeline/retry.rb @@ -17,10 +17,11 @@ module Mutations pipeline = authorized_find!(id: id) project = pipeline.project - ::Ci::RetryPipelineService.new(project, current_user).execute(pipeline) + service_response = ::Ci::RetryPipelineService.new(project, current_user).execute(pipeline) + { pipeline: pipeline, - errors: errors_on_object(pipeline) + errors: errors_on_object(pipeline) + service_response.errors } end end diff --git a/app/graphql/mutations/ci/runner/delete.rb b/app/graphql/mutations/ci/runner/delete.rb index 21c3d55881c..1713ec0bf6d 100644 --- a/app/graphql/mutations/ci/runner/delete.rb +++ b/app/graphql/mutations/ci/runner/delete.rb @@ -17,20 +17,11 @@ module Mutations def resolve(id:, **runner_attrs) runner = authorized_find!(id) - error = authenticate_delete_runner!(runner) - return { errors: [error] } if error - - ::Ci::UnregisterRunnerService.new(runner).execute + ::Ci::Runners::UnregisterRunnerService.new(runner, current_user).execute { errors: runner.errors.full_messages } end - def authenticate_delete_runner!(runner) - return if current_user.can_admin_all_resources? - - "Runner #{runner.to_global_id} associated with more than one project" if runner.runner_projects.count > 1 - end - def find_object(id) # TODO: remove this line when the compatibility layer is removed # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 diff --git a/app/graphql/mutations/ci/runner/update.rb b/app/graphql/mutations/ci/runner/update.rb index e6123b4283a..3432840f60f 100644 --- a/app/graphql/mutations/ci/runner/update.rb +++ b/app/graphql/mutations/ci/runner/update.rb @@ -53,7 +53,7 @@ module Mutations def resolve(id:, **runner_attrs) runner = authorized_find!(id) - unless ::Ci::UpdateRunnerService.new(runner).update(runner_attrs) + unless ::Ci::Runners::UpdateRunnerService.new(runner).update(runner_attrs) return { runner: nil, errors: runner.errors.full_messages } end diff --git a/app/graphql/mutations/ci/runners_registration_token/reset.rb b/app/graphql/mutations/ci/runners_registration_token/reset.rb index 7976e8fb70d..29ef7aa2e81 100644 --- a/app/graphql/mutations/ci/runners_registration_token/reset.rb +++ b/app/graphql/mutations/ci/runners_registration_token/reset.rb @@ -45,20 +45,19 @@ module Mutations def reset_token(type:, **args) id = args[:id] + scope = nil case type when 'instance_type' raise Gitlab::Graphql::Errors::ArgumentError, "id must not be specified for '#{type}' scope" if id.present? - authorize!(:global) - - ApplicationSetting.current.reset_runners_registration_token! - ApplicationSetting.current_without_cache.runners_registration_token + scope = ApplicationSetting.current + authorize!(scope) when 'group_type', 'project_type' - project_or_group = authorized_find!(type: type, id: id) - project_or_group.reset_runners_token! - project_or_group.runners_token + scope = authorized_find!(type: type, id: id) end + + ::Ci::Runners::ResetRegistrationTokenService.new(scope, current_user).execute if scope end end end diff --git a/app/graphql/mutations/concerns/mutations/spam_protection.rb b/app/graphql/mutations/concerns/mutations/spam_protection.rb index 341067710b2..e61f66c02a5 100644 --- a/app/graphql/mutations/concerns/mutations/spam_protection.rb +++ b/app/graphql/mutations/concerns/mutations/spam_protection.rb @@ -16,30 +16,16 @@ module Mutations private - def spam_action_response(object) - fields = spam_action_response_fields(object) - - # If the SpamActionService detected something as spam, - # this is non-recoverable and the needs_captcha_response - # should not be considered - kind = if fields[:spam] - :spam - elsif fields[:needs_captcha_response] - :needs_captcha_response - end - - [kind, fields] - end - def check_spam_action_response!(object) - kind, fields = spam_action_response(object) + fields = spam_action_response_fields(object) - case kind - when :needs_captcha_response + if fields[:spam] + # If the SpamActionService detected something as spam, this is non-recoverable and the + # needs_captcha_response and other CAPTCHA-related fields should not be returned + raise SpamDisallowedError.new(SPAM_DISALLOWED_MESSAGE, extensions: { spam: true }) + elsif fields[:needs_captcha_response] fields.delete :spam raise NeedsCaptchaResponseError.new(NEEDS_CAPTCHA_RESPONSE_MESSAGE, extensions: fields) - when :spam - raise SpamDisallowedError.new(SPAM_DISALLOWED_MESSAGE, extensions: { spam: true }) else nil end diff --git a/app/graphql/mutations/notes/base.rb b/app/graphql/mutations/notes/base.rb index d6c8121eee7..65bb9e4644c 100644 --- a/app/graphql/mutations/notes/base.rb +++ b/app/graphql/mutations/notes/base.rb @@ -3,6 +3,12 @@ module Mutations module Notes class Base < BaseMutation + QUICK_ACTION_ONLY_WARNING = <<~NB + If the body of the Note contains only quick actions, + the Note will be destroyed during an update, and no Note will be + returned. + NB + field :note, Types::Notes::NoteType, null: true, diff --git a/app/graphql/mutations/notes/create/note.rb b/app/graphql/mutations/notes/create/note.rb index 5a5d62a8c20..1cfc11c6b11 100644 --- a/app/graphql/mutations/notes/create/note.rb +++ b/app/graphql/mutations/notes/create/note.rb @@ -5,12 +5,18 @@ module Mutations module Create class Note < Base graphql_name 'CreateNote' + description "Creates a Note.\n#{QUICK_ACTION_ONLY_WARNING}" argument :discussion_id, ::Types::GlobalIDType[::Discussion], required: false, description: 'Global ID of the discussion this note is in reply to.' + argument :merge_request_diff_head_sha, + GraphQL::Types::String, + required: false, + description: 'SHA of the head commit which is used to ensure that the merge request has not been updated since the request was sent.' + private def create_note_params(noteable, args) @@ -28,7 +34,8 @@ module Mutations end super(noteable, args).merge({ - in_reply_to_discussion_id: discussion_id + in_reply_to_discussion_id: discussion_id, + merge_request_diff_head_sha: args[:merge_request_diff_head_sha] }) end diff --git a/app/graphql/mutations/notes/update/base.rb b/app/graphql/mutations/notes/update/base.rb index 2dfa7b815a1..4c6df2776cc 100644 --- a/app/graphql/mutations/notes/update/base.rb +++ b/app/graphql/mutations/notes/update/base.rb @@ -6,12 +6,6 @@ module Mutations # This is a Base class for the Note update mutations and is not # mounted as a GraphQL mutation itself. class Base < Mutations::Notes::Base - QUICK_ACTION_ONLY_WARNING = <<~NB - If the body of the Note contains only quick actions, - the Note will be destroyed during the update, and no Note will be - returned. - NB - authorize :admin_note argument :id, diff --git a/app/graphql/mutations/saved_replies/base.rb b/app/graphql/mutations/saved_replies/base.rb new file mode 100644 index 00000000000..468263b0f9d --- /dev/null +++ b/app/graphql/mutations/saved_replies/base.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Mutations + module SavedReplies + class Base < BaseMutation + field :saved_reply, Types::SavedReplyType, + null: true, + description: 'Updated saved reply.' + + private + + def present_result(result) + if result.success? + { + saved_reply: result[:saved_reply], + errors: [] + } + else + { + saved_reply: nil, + errors: result.message + } + end + end + + def feature_enabled? + Feature.enabled?(:saved_replies, current_user, default_enabled: :yaml) + end + + def find_object(id) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Users::SavedReply].coerce_isolated_input(id) + + GitlabSchema.find_by_gid(id) + end + end + end +end diff --git a/app/graphql/mutations/saved_replies/create.rb b/app/graphql/mutations/saved_replies/create.rb new file mode 100644 index 00000000000..d97461a1c2a --- /dev/null +++ b/app/graphql/mutations/saved_replies/create.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Mutations + module SavedReplies + class Create < Base + graphql_name 'SavedReplyCreate' + + authorize :create_saved_replies + + argument :name, GraphQL::Types::String, + required: true, + description: copy_field_description(Types::SavedReplyType, :name) + + argument :content, GraphQL::Types::String, + required: true, + description: copy_field_description(Types::SavedReplyType, :content) + + def resolve(name:, content:) + raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled? + + result = ::Users::SavedReplies::CreateService.new(current_user: current_user, name: name, content: content).execute + present_result(result) + end + end + end +end diff --git a/app/graphql/mutations/saved_replies/update.rb b/app/graphql/mutations/saved_replies/update.rb new file mode 100644 index 00000000000..bacc6ceb39e --- /dev/null +++ b/app/graphql/mutations/saved_replies/update.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Mutations + module SavedReplies + class Update < Base + graphql_name 'SavedReplyUpdate' + + authorize :update_saved_replies + + argument :id, Types::GlobalIDType[::Users::SavedReply], + required: true, + description: copy_field_description(Types::SavedReplyType, :id) + + argument :name, GraphQL::Types::String, + required: true, + description: copy_field_description(Types::SavedReplyType, :name) + + argument :content, GraphQL::Types::String, + required: true, + description: copy_field_description(Types::SavedReplyType, :content) + + def resolve(id:, name:, content:) + raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled? + + saved_reply = authorized_find!(id) + result = ::Users::SavedReplies::UpdateService.new(current_user: current_user, saved_reply: saved_reply, name: name, content: content).execute + present_result(result) + end + end + end +end diff --git a/app/graphql/mutations/work_items/create.rb b/app/graphql/mutations/work_items/create.rb index 81454db62b1..48f0f470988 100644 --- a/app/graphql/mutations/work_items/create.rb +++ b/app/graphql/mutations/work_items/create.rb @@ -33,7 +33,7 @@ module Mutations def resolve(project_path:, **attributes) project = authorized_find!(project_path) - unless Feature.enabled?(:work_items, project) + unless Feature.enabled?(:work_items, project, default_enabled: :yaml) return { errors: ['`work_items` feature flag disabled for this project'] } end diff --git a/app/graphql/mutations/work_items/create_from_task.rb b/app/graphql/mutations/work_items/create_from_task.rb new file mode 100644 index 00000000000..16d1e646167 --- /dev/null +++ b/app/graphql/mutations/work_items/create_from_task.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Mutations + module WorkItems + class CreateFromTask < BaseMutation + graphql_name 'WorkItemCreateFromTask' + + include Mutations::SpamProtection + + description "Creates a work item from a task in another work item's description." \ + " Available only when feature flag `work_items` is enabled. This feature is experimental and is subject to change without notice." + + authorize :update_work_item + + argument :id, ::Types::GlobalIDType[::WorkItem], + required: true, + description: 'Global ID of the work item.' + argument :work_item_data, ::Types::WorkItems::ConvertTaskInputType, + required: true, + description: 'Arguments necessary to convert a task into a work item.', + prepare: ->(attributes, _ctx) { attributes.to_h } + + field :work_item, Types::WorkItemType, + null: true, + description: 'Updated work item.' + + field :new_work_item, Types::WorkItemType, + null: true, + description: 'New work item created from task.' + + def resolve(id:, work_item_data:) + work_item = authorized_find!(id: id) + + unless Feature.enabled?(:work_items, work_item.project, default_enabled: :yaml) + return { errors: ['`work_items` feature flag disabled for this project'] } + end + + spam_params = ::Spam::SpamParams.new_from_request(request: context[:request]) + + result = ::WorkItems::CreateFromTaskService.new( + work_item: work_item, + current_user: current_user, + work_item_params: work_item_data, + spam_params: spam_params + ).execute + + check_spam_action_response!(result[:work_item]) if result[:work_item] + + response = { errors: result.errors } + response.merge!(work_item: work_item, new_work_item: result[:work_item]) if result.success? + + response + end + + private + + def find_object(id:) + # TODO: Remove coercion when working on https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::WorkItem].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) + end + end + end +end diff --git a/app/graphql/mutations/work_items/delete.rb b/app/graphql/mutations/work_items/delete.rb index 71792a802c0..f32354878ec 100644 --- a/app/graphql/mutations/work_items/delete.rb +++ b/app/graphql/mutations/work_items/delete.rb @@ -20,7 +20,7 @@ module Mutations def resolve(id:) work_item = authorized_find!(id: id) - unless Feature.enabled?(:work_items, work_item.project) + unless Feature.enabled?(:work_items, work_item.project, default_enabled: :yaml) return { errors: ['`work_items` feature flag disabled for this project'] } end diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb index 3ab9ba2d502..2700cbdb709 100644 --- a/app/graphql/mutations/work_items/update.rb +++ b/app/graphql/mutations/work_items/update.rb @@ -28,7 +28,7 @@ module Mutations def resolve(id:, **attributes) work_item = authorized_find!(id: id) - unless Feature.enabled?(:work_items, work_item.project) + unless Feature.enabled?(:work_items, work_item.project, default_enabled: :yaml) return { errors: ['`work_items` feature flag disabled for this project'] } end -- cgit v1.2.3