diff options
Diffstat (limited to 'app/graphql/mutations')
27 files changed, 436 insertions, 110 deletions
diff --git a/app/graphql/mutations/award_emojis/base.rb b/app/graphql/mutations/award_emojis/base.rb index 583744c3884..df6b883529e 100644 --- a/app/graphql/mutations/award_emojis/base.rb +++ b/app/graphql/mutations/award_emojis/base.rb @@ -6,7 +6,7 @@ module Mutations authorize :award_emoji argument :awardable_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Awardable], required: true, description: 'The global id of the awardable resource' @@ -23,7 +23,10 @@ module Mutations private def find_object(id:) - GitlabSchema.object_from_id(id) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Awardable].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) end # Called by mutations methods after performing an authorization check diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb index 577f10545b3..ac5ddc5bd4c 100644 --- a/app/graphql/mutations/base_mutation.rb +++ b/app/graphql/mutations/base_mutation.rb @@ -4,6 +4,7 @@ module Mutations class BaseMutation < GraphQL::Schema::RelayClassicMutation prepend Gitlab::Graphql::Authorize::AuthorizeResource prepend Gitlab::Graphql::CopyFieldDescription + prepend ::Gitlab::Graphql::GlobalIDCompatibility ERROR_MESSAGE = 'You cannot perform write operations on a read-only instance' diff --git a/app/graphql/mutations/boards/create.rb b/app/graphql/mutations/boards/create.rb new file mode 100644 index 00000000000..e381205242e --- /dev/null +++ b/app/graphql/mutations/boards/create.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +module Mutations + module Boards + class Create < ::Mutations::BaseMutation + include Mutations::ResolvesGroup + include ResolvesProject + + graphql_name 'CreateBoard' + + field :board, + Types::BoardType, + null: true, + description: 'The board after mutation.' + + argument :project_path, GraphQL::ID_TYPE, + required: false, + description: 'The project full path the board is associated with.' + argument :group_path, GraphQL::ID_TYPE, + required: false, + description: 'The group full path the board is associated with.' + argument :name, + GraphQL::STRING_TYPE, + required: false, + description: 'The board name.' + argument :assignee_id, + GraphQL::STRING_TYPE, + required: false, + description: 'The ID of the user to be assigned to the board.' + argument :milestone_id, + GraphQL::ID_TYPE, + required: false, + description: 'The ID of the milestone to be assigned to the board.' + argument :weight, + GraphQL::BOOLEAN_TYPE, + required: false, + description: 'The weight of the board.' + argument :label_ids, + [GraphQL::ID_TYPE], + required: false, + description: 'The IDs of labels to be added to the board.' + + authorize :admin_board + + def resolve(args) + group_path = args.delete(:group_path) + project_path = args.delete(:project_path) + + board_parent = authorized_find!(group_path: group_path, project_path: project_path) + response = ::Boards::CreateService.new(board_parent, current_user, args).execute + + { + board: response.payload, + errors: response.errors + } + end + + def ready?(**args) + if args.values_at(:project_path, :group_path).compact.blank? + raise Gitlab::Graphql::Errors::ArgumentError, + 'group_path or project_path arguments are required' + end + + super + end + + private + + def find_object(group_path: nil, project_path: nil) + if group_path + resolve_group(full_path: group_path) + else + resolve_project(full_path: project_path) + end + end + end + end +end diff --git a/app/graphql/mutations/boards/lists/destroy.rb b/app/graphql/mutations/boards/lists/destroy.rb new file mode 100644 index 00000000000..61ffae7c047 --- /dev/null +++ b/app/graphql/mutations/boards/lists/destroy.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Mutations + module Boards + module Lists + class Destroy < ::Mutations::BaseMutation + graphql_name 'DestroyBoardList' + + field :list, + Types::BoardListType, + null: true, + description: 'The list after mutation.' + + argument :list_id, ::Types::GlobalIDType[::List], + required: true, + loads: Types::BoardListType, + description: 'Global ID of the list to destroy. Only label lists are accepted.' + + def resolve(list:) + raise_resource_not_available_error! unless can_admin_list?(list) + + response = ::Boards::Lists::DestroyService.new(list.board.resource_parent, current_user) + .execute(list) + + { + list: response.success? ? nil : list, + errors: response.errors + } + end + + private + + def can_admin_list?(list) + return false unless list.present? + + Ability.allowed?(current_user, :admin_list, list.board) + end + end + end + end +end diff --git a/app/graphql/mutations/ci/base.rb b/app/graphql/mutations/ci/base.rb index 09df4487a50..aaece2a3021 100644 --- a/app/graphql/mutations/ci/base.rb +++ b/app/graphql/mutations/ci/base.rb @@ -3,13 +3,18 @@ module Mutations module Ci class Base < BaseMutation - argument :id, ::Types::GlobalIDType[::Ci::Pipeline], + PipelineID = ::Types::GlobalIDType[::Ci::Pipeline] + + argument :id, PipelineID, required: true, description: 'The id of the pipeline to mutate' private def find_object(id:) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = PipelineID.coerce_isolated_input(id) GlobalID::Locator.locate(id) end end diff --git a/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb b/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb new file mode 100644 index 00000000000..7aef55f8011 --- /dev/null +++ b/app/graphql/mutations/concerns/mutations/spammable_mutation_fields.rb @@ -0,0 +1,24 @@ +# 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/design_management/move.rb b/app/graphql/mutations/design_management/move.rb index 6126af8b68b..aed4cfec0fd 100644 --- a/app/graphql/mutations/design_management/move.rb +++ b/app/graphql/mutations/design_management/move.rb @@ -21,7 +21,7 @@ module Mutations description: "The current state of the collection" def resolve(**args) - service = ::DesignManagement::MoveDesignsService.new(current_user, parameters(args)) + service = ::DesignManagement::MoveDesignsService.new(current_user, parameters(**args)) { design_collection: service.collection, errors: service.execute.errors } end @@ -29,11 +29,18 @@ module Mutations private def parameters(**args) - args.transform_values { |id| GitlabSchema.find_by_gid(id) }.transform_values(&:sync).tap do |hash| + args.transform_values { |id| find_design(id) }.transform_values(&:sync).tap do |hash| hash.each { |k, design| not_found(args[k]) unless current_user.can?(:read_design, design) } end end + def find_design(id) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = DesignID.coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) + end + def not_found(gid) raise Gitlab::Graphql::Errors::ResourceNotAvailable, "Resource not available: #{gid}" end diff --git a/app/graphql/mutations/discussions/toggle_resolve.rb b/app/graphql/mutations/discussions/toggle_resolve.rb index 41fd22c6b55..4492da74706 100644 --- a/app/graphql/mutations/discussions/toggle_resolve.rb +++ b/app/graphql/mutations/discussions/toggle_resolve.rb @@ -8,7 +8,7 @@ module Mutations description 'Toggles the resolved state of a discussion' argument :id, - GraphQL::ID_TYPE, + Types::GlobalIDType[Discussion], required: true, description: 'The global id of the discussion' @@ -54,7 +54,10 @@ module Mutations end def find_object(id:) - GitlabSchema.object_from_id(id, expected_type: ::Discussion) + # TODO: remove explicit coercion once compatibility layer has been removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = Types::GlobalIDType[Discussion].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) end def resolve!(discussion) diff --git a/app/graphql/mutations/issues/common_mutation_arguments.rb b/app/graphql/mutations/issues/common_mutation_arguments.rb new file mode 100644 index 00000000000..4b5b246281f --- /dev/null +++ b/app/graphql/mutations/issues/common_mutation_arguments.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Mutations + module Issues + module CommonMutationArguments + extend ActiveSupport::Concern + + included do + argument :description, GraphQL::STRING_TYPE, + required: false, + description: copy_field_description(Types::IssueType, :description) + + argument :due_date, GraphQL::Types::ISO8601Date, + required: false, + description: copy_field_description(Types::IssueType, :due_date) + + argument :confidential, GraphQL::BOOLEAN_TYPE, + required: false, + description: copy_field_description(Types::IssueType, :confidential) + + argument :locked, GraphQL::BOOLEAN_TYPE, + as: :discussion_locked, + required: false, + description: copy_field_description(Types::IssueType, :discussion_locked) + end + end + end +end diff --git a/app/graphql/mutations/issues/create.rb b/app/graphql/mutations/issues/create.rb new file mode 100644 index 00000000000..1454916bc77 --- /dev/null +++ b/app/graphql/mutations/issues/create.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +module Mutations + module Issues + class Create < BaseMutation + include ResolvesProject + graphql_name 'CreateIssue' + + authorize :create_issue + + include CommonMutationArguments + + argument :project_path, GraphQL::ID_TYPE, + required: true, + description: 'Project full path the issue is associated with' + + argument :iid, GraphQL::INT_TYPE, + required: false, + description: 'The IID (internal ID) of a project issue. Only admins and project owners can modify' + + argument :title, GraphQL::STRING_TYPE, + required: true, + description: copy_field_description(Types::IssueType, :title) + + argument :milestone_id, ::Types::GlobalIDType[::Milestone], + required: false, + description: 'The ID of the milestone to assign to the issue. On update milestone will be removed if set to null' + + argument :labels, [GraphQL::STRING_TYPE], + required: false, + description: copy_field_description(Types::IssueType, :labels) + + argument :label_ids, [::Types::GlobalIDType[::Label]], + required: false, + description: 'The IDs of labels to be added to the issue' + + argument :created_at, Types::TimeType, + required: false, + description: 'Timestamp when the issue was created. Available only for admins and project owners' + + argument :merge_request_to_resolve_discussions_of, ::Types::GlobalIDType[::MergeRequest], + required: false, + description: 'The IID of a merge request for which to resolve discussions' + + argument :discussion_to_resolve, GraphQL::STRING_TYPE, + required: false, + description: 'The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`' + + argument :assignee_ids, [::Types::GlobalIDType[::User]], + required: false, + description: 'The array of user IDs to assign to the issue' + + field :issue, + Types::IssueType, + null: true, + description: 'The issue after mutation' + + def ready?(**args) + if args.slice(*mutually_exclusive_label_args).size > 1 + arg_str = mutually_exclusive_label_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 + + if args[:discussion_to_resolve].present? && args[:merge_request_to_resolve_discussions_of].blank? + raise Gitlab::Graphql::Errors::ArgumentError, + 'to resolve a discussion please also provide `merge_request_to_resolve_discussions_of` parameter' + end + + super + end + + def resolve(project_path:, **attributes) + project = authorized_find!(full_path: project_path) + params = build_create_issue_params(attributes.merge(author_id: current_user.id)) + + issue = ::Issues::CreateService.new(project, current_user, params).execute + + if issue.spam? + issue.errors.add(:base, 'Spam detected.') + end + + { + issue: issue.valid? ? issue : nil, + errors: errors_on_object(issue) + } + end + + private + + def build_create_issue_params(params) + params[:milestone_id] &&= params[:milestone_id]&.model_id + params[:assignee_ids] &&= params[:assignee_ids].map { |assignee_id| assignee_id&.model_id } + params[:label_ids] &&= params[:label_ids].map { |label_id| label_id&.model_id } + + params + end + + def mutually_exclusive_label_args + [:labels, :label_ids] + end + + def find_object(full_path:) + resolve_project(full_path: full_path) + end + end + end +end + +Mutations::Issues::Create.prepend_if_ee('::EE::Mutations::Issues::Create') diff --git a/app/graphql/mutations/issues/move.rb b/app/graphql/mutations/issues/move.rb new file mode 100644 index 00000000000..e6971c9df8c --- /dev/null +++ b/app/graphql/mutations/issues/move.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Mutations + module Issues + class Move < Base + graphql_name 'IssueMove' + + argument :target_project_path, + GraphQL::ID_TYPE, + required: true, + description: 'The project to move the issue to' + + def resolve(project_path:, iid:, target_project_path:) + Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/267762') + + issue = authorized_find!(project_path: project_path, iid: iid) + source_project = issue.project + target_project = resolve_project(full_path: target_project_path).sync + + begin + moved_issue = ::Issues::MoveService.new(source_project, current_user).execute(issue, target_project) + rescue ::Issues::MoveService::MoveError => error + errors = error.message + end + + { + issue: moved_issue, + errors: Array.wrap(errors) + } + end + end + end +end diff --git a/app/graphql/mutations/issues/update.rb b/app/graphql/mutations/issues/update.rb index cc03d32731b..9b216b31f9b 100644 --- a/app/graphql/mutations/issues/update.rb +++ b/app/graphql/mutations/issues/update.rb @@ -5,46 +5,27 @@ module Mutations class Update < Base graphql_name 'UpdateIssue' - argument :title, - GraphQL::STRING_TYPE, - required: false, - description: copy_field_description(Types::IssueType, :title) + include CommonMutationArguments - argument :description, - GraphQL::STRING_TYPE, - required: false, - description: copy_field_description(Types::IssueType, :description) - - argument :due_date, - Types::TimeType, - required: false, - description: copy_field_description(Types::IssueType, :due_date) - - argument :confidential, - GraphQL::BOOLEAN_TYPE, + argument :title, GraphQL::STRING_TYPE, required: false, - description: copy_field_description(Types::IssueType, :confidential) + description: copy_field_description(Types::IssueType, :title) - argument :locked, - GraphQL::BOOLEAN_TYPE, - as: :discussion_locked, + argument :milestone_id, GraphQL::ID_TYPE, required: false, - description: copy_field_description(Types::IssueType, :discussion_locked) + description: 'The ID of the milestone to assign to the issue. On update milestone will be removed if set to null' - argument :add_label_ids, - [GraphQL::ID_TYPE], + argument :add_label_ids, [GraphQL::ID_TYPE], required: false, - description: 'The IDs of labels to be added to the issue.' + description: 'The IDs of labels to be added to the issue' - argument :remove_label_ids, - [GraphQL::ID_TYPE], + argument :remove_label_ids, [GraphQL::ID_TYPE], required: false, - description: 'The IDs of labels to be removed from the issue.' + description: 'The IDs of labels to be removed from the issue' - argument :milestone_id, - GraphQL::ID_TYPE, - required: false, - description: 'The ID of the milestone to be assigned, milestone will be removed if set to null.' + argument :state_event, Types::IssueStateEventEnum, + description: 'Close or reopen an issue', + required: false def resolve(project_path:, iid:, **args) issue = authorized_find!(project_path: project_path, iid: iid) diff --git a/app/graphql/mutations/merge_requests/set_milestone.rb b/app/graphql/mutations/merge_requests/set_milestone.rb index b3412dd9ed2..abcb1bda1f3 100644 --- a/app/graphql/mutations/merge_requests/set_milestone.rb +++ b/app/graphql/mutations/merge_requests/set_milestone.rb @@ -6,7 +6,7 @@ module Mutations graphql_name 'MergeRequestSetMilestone' argument :milestone_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Milestone], required: false, loads: Types::MilestoneType, description: <<~DESC diff --git a/app/graphql/mutations/metrics/dashboard/annotations/create.rb b/app/graphql/mutations/metrics/dashboard/annotations/create.rb index f99688aeac6..b064f55825f 100644 --- a/app/graphql/mutations/metrics/dashboard/annotations/create.rb +++ b/app/graphql/mutations/metrics/dashboard/annotations/create.rb @@ -18,12 +18,12 @@ module Mutations description: 'The created annotation' argument :environment_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Environment], required: false, description: 'The global id of the environment to add an annotation to' argument :cluster_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Clusters::Cluster], required: false, description: 'The global id of the cluster to add an annotation to' @@ -80,11 +80,11 @@ module Mutations raise Gitlab::Graphql::Errors::ArgumentError, ANNOTATION_SOURCE_ARGUMENT_ERROR end - super(args) + super(**args) end def find_object(id:) - GitlabSchema.object_from_id(id) + GitlabSchema.find_by_gid(id) end def annotation_create_params(args) @@ -96,7 +96,16 @@ module Mutations end def annotation_source(args) - annotation_source_id = args[:cluster_id] || args[:environment_id] + # TODO: remove these lines when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + annotation_source_id = if args[:cluster_id] + ::Types::GlobalIDType[::Clusters::Cluster].coerce_isolated_input(args[:cluster_id]) + else + ::Types::GlobalIDType[::Environment].coerce_isolated_input(args[:environment_id]) + end + + # TODO: uncomment following line once lines above are removed + # annotation_source_id = args[:cluster_id] || args[:environment_id] authorized_find!(id: annotation_source_id) end end diff --git a/app/graphql/mutations/notes/base.rb b/app/graphql/mutations/notes/base.rb index 31dabc0a660..f2678211335 100644 --- a/app/graphql/mutations/notes/base.rb +++ b/app/graphql/mutations/notes/base.rb @@ -11,21 +11,10 @@ module Mutations private def find_object(id:) - GitlabSchema.object_from_id(id) - end - - def check_object_is_noteable!(object) - unless object.is_a?(Noteable) - raise Gitlab::Graphql::Errors::ResourceNotAvailable, - 'Cannot add notes to this resource' - end - end - - def check_object_is_note!(object) - unless object.is_a?(Note) - raise Gitlab::Graphql::Errors::ResourceNotAvailable, - 'Resource is not a note' - end + # TODO: remove explicit coercion once compatibility layer has been removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Note].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) end end end diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb index f081eac368e..3cfdaf84760 100644 --- a/app/graphql/mutations/notes/create/base.rb +++ b/app/graphql/mutations/notes/create/base.rb @@ -9,7 +9,7 @@ module Mutations authorize :create_note argument :noteable_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Noteable], required: true, description: 'The global id of the resource to add a note to' @@ -26,8 +26,6 @@ module Mutations def resolve(args) noteable = authorized_find!(id: args[:noteable_id]) - check_object_is_noteable!(noteable) - note = ::Notes::CreateService.new( noteable.project, current_user, @@ -42,6 +40,13 @@ module Mutations private + def find_object(id:) + # TODO: remove explicit coercion once compatibility layer has been removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Noteable].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) + end + def create_note_params(noteable, args) { noteable: noteable, diff --git a/app/graphql/mutations/notes/create/note.rb b/app/graphql/mutations/notes/create/note.rb index 5236e48026e..e97037171f7 100644 --- a/app/graphql/mutations/notes/create/note.rb +++ b/app/graphql/mutations/notes/create/note.rb @@ -7,7 +7,7 @@ module Mutations graphql_name 'CreateNote' argument :discussion_id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Discussion], required: false, description: 'The global id of the discussion this note is in reply to' @@ -17,7 +17,11 @@ module Mutations discussion_id = nil if args[:discussion_id] - discussion = GitlabSchema.object_from_id(args[:discussion_id]) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + discussion_gid = ::Types::GlobalIDType[::Discussion].coerce_isolated_input(args[:discussion_id]) + discussion = GitlabSchema.find_by_gid(discussion_gid) + authorize_discussion!(discussion) discussion_id = discussion.id diff --git a/app/graphql/mutations/notes/destroy.rb b/app/graphql/mutations/notes/destroy.rb index a81322bc9b7..63e5eeb5ecf 100644 --- a/app/graphql/mutations/notes/destroy.rb +++ b/app/graphql/mutations/notes/destroy.rb @@ -8,15 +8,13 @@ module Mutations authorize :admin_note argument :id, - GraphQL::ID_TYPE, - required: true, - description: 'The global id of the note to destroy' + ::Types::GlobalIDType[::Note], + required: true, + description: 'The global id of the note to destroy' def resolve(id:) note = authorized_find!(id: id) - check_object_is_note!(note) - ::Notes::DestroyService.new(note.project, current_user).execute(note) { diff --git a/app/graphql/mutations/notes/update/base.rb b/app/graphql/mutations/notes/update/base.rb index 8a2a78a29ec..1d5738ada77 100644 --- a/app/graphql/mutations/notes/update/base.rb +++ b/app/graphql/mutations/notes/update/base.rb @@ -9,7 +9,7 @@ module Mutations authorize :admin_note argument :id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Note], required: true, description: 'The global id of the note to update' diff --git a/app/graphql/mutations/notes/update/image_diff_note.rb b/app/graphql/mutations/notes/update/image_diff_note.rb index 7aad3af1e04..ef70a8d2bf4 100644 --- a/app/graphql/mutations/notes/update/image_diff_note.rb +++ b/app/graphql/mutations/notes/update/image_diff_note.rb @@ -28,12 +28,12 @@ module Mutations 'body or position arguments are required' end - super(args) + super(**args) end private - def pre_update_checks!(note, args) + def pre_update_checks!(note, _args) unless note.is_a?(DiffNote) && note.position.on_image? raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Resource is not an ImageDiffNote' diff --git a/app/graphql/mutations/notes/update/note.rb b/app/graphql/mutations/notes/update/note.rb index ca97dad6ded..73b9b9bc49a 100644 --- a/app/graphql/mutations/notes/update/note.rb +++ b/app/graphql/mutations/notes/update/note.rb @@ -18,8 +18,8 @@ module Mutations private - def pre_update_checks!(note, _args) - check_object_is_note!(note) + def pre_update_checks!(_note, _args) + # no-op end end end diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb index a8aeb15afcd..37c0f80310c 100644 --- a/app/graphql/mutations/snippets/create.rb +++ b/app/graphql/mutations/snippets/create.rb @@ -3,6 +3,7 @@ module Mutations module Snippets class Create < BaseMutation + include SpammableMutationFields include ResolvesProject graphql_name 'CreateSnippet' @@ -56,10 +57,12 @@ module Mutations ::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user) end - { - snippet: service_response.success? ? snippet : nil, - errors: errors_on_object(snippet) - } + with_spam_fields(snippet) do + { + snippet: service_response.success? ? snippet : nil, + errors: errors_on_object(snippet) + } + end end private @@ -81,14 +84,16 @@ module Mutations end def create_params(args) - 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) + 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 end end end diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb index d0db5fa2eb9..74266880806 100644 --- a/app/graphql/mutations/snippets/update.rb +++ b/app/graphql/mutations/snippets/update.rb @@ -3,6 +3,8 @@ module Mutations module Snippets class Update < Base + include SpammableMutationFields + graphql_name 'UpdateSnippet' argument :id, @@ -39,10 +41,12 @@ module Mutations ::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user) end - { - snippet: result.success? ? snippet : snippet.reset, - errors: errors_on_object(snippet) - } + with_spam_fields(snippet) do + { + snippet: result.success? ? snippet : snippet.reset, + errors: errors_on_object(snippet) + } + end end private @@ -52,10 +56,12 @@ module Mutations end def update_params(args) - 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) + 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 end end end diff --git a/app/graphql/mutations/todos/base.rb b/app/graphql/mutations/todos/base.rb index 2a72019fbac..6db863796bc 100644 --- a/app/graphql/mutations/todos/base.rb +++ b/app/graphql/mutations/todos/base.rb @@ -6,7 +6,10 @@ module Mutations private def find_object(id:) - GitlabSchema.object_from_id(id) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + id = ::Types::GlobalIDType[::Todo].coerce_isolated_input(id) + GitlabSchema.find_by_gid(id) end def map_to_global_ids(ids) @@ -16,7 +19,7 @@ module Mutations end def to_global_id(id) - ::URI::GID.build(app: GlobalID.app, model_name: Todo.name, model_id: id, params: nil).to_s + Gitlab::GlobalId.as_global_id(id, model_name: Todo.name).to_s end end end diff --git a/app/graphql/mutations/todos/mark_done.rb b/app/graphql/mutations/todos/mark_done.rb index 748e02d8782..3d73022f266 100644 --- a/app/graphql/mutations/todos/mark_done.rb +++ b/app/graphql/mutations/todos/mark_done.rb @@ -8,7 +8,7 @@ module Mutations authorize :update_todo argument :id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Todo], required: true, description: 'The global id of the todo to mark as done' diff --git a/app/graphql/mutations/todos/restore.rb b/app/graphql/mutations/todos/restore.rb index a0a1772db0a..7c8f92d32f5 100644 --- a/app/graphql/mutations/todos/restore.rb +++ b/app/graphql/mutations/todos/restore.rb @@ -8,7 +8,7 @@ module Mutations authorize :update_todo argument :id, - GraphQL::ID_TYPE, + ::Types::GlobalIDType[::Todo], required: true, description: 'The global id of the todo to restore' diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb index c5e2750768c..ea5f5414134 100644 --- a/app/graphql/mutations/todos/restore_many.rb +++ b/app/graphql/mutations/todos/restore_many.rb @@ -8,7 +8,7 @@ module Mutations MAX_UPDATE_AMOUNT = 50 argument :ids, - [GraphQL::ID_TYPE], + [::Types::GlobalIDType[::Todo]], required: true, description: 'The global ids of the todos to restore (a maximum of 50 is supported at once)' @@ -37,24 +37,18 @@ module Mutations private def gids_of(ids) - ids.map { |id| ::URI::GID.build(app: GlobalID.app, model_name: Todo.name, model_id: id, params: nil).to_s } + ids.map { |id| Gitlab::GlobalId.as_global_id(id, model_name: Todo.name).to_s } end def model_ids_of(ids) ids.map do |gid| - parsed_gid = ::URI::GID.parse(gid) - parsed_gid.model_id.to_i if accessible_todo?(parsed_gid) + # TODO: remove this line when the compatibility layer is removed + # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 + gid = ::Types::GlobalIDType[::Todo].coerce_isolated_input(gid) + gid.model_id.to_i end.compact end - def accessible_todo?(gid) - gid.app == GlobalID.app && todo?(gid) - end - - def todo?(gid) - GlobalID.parse(gid)&.model_class&.ancestors&.include?(Todo) - end - def raise_too_many_todos_requested_error raise Gitlab::Graphql::Errors::ArgumentError, 'Too many todos requested.' end |