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:
Diffstat (limited to 'app/graphql/mutations')
-rw-r--r--app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb6
-rw-r--r--app/graphql/mutations/alert_management/base.rb8
-rw-r--r--app/graphql/mutations/alert_management/http_integration/create.rb41
-rw-r--r--app/graphql/mutations/alert_management/http_integration/destroy.rb24
-rw-r--r--app/graphql/mutations/alert_management/http_integration/http_integration_base.rb29
-rw-r--r--app/graphql/mutations/alert_management/http_integration/reset_token.rb25
-rw-r--r--app/graphql/mutations/alert_management/http_integration/update.rb33
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/create.rb50
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb42
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb27
-rw-r--r--app/graphql/mutations/alert_management/prometheus_integration/update.rb35
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb6
-rw-r--r--app/graphql/mutations/boards/create.rb37
-rw-r--r--app/graphql/mutations/boards/lists/update.rb2
-rw-r--r--app/graphql/mutations/commits/create.rb10
-rw-r--r--app/graphql/mutations/concerns/mutations/package_eventable.rb14
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb43
-rw-r--r--app/graphql/mutations/container_repositories/destroy.rb45
-rw-r--r--app/graphql/mutations/custom_emoji/create.rb50
-rw-r--r--app/graphql/mutations/labels/create.rb43
-rw-r--r--app/graphql/mutations/merge_requests/set_labels.rb15
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/delete.rb3
-rw-r--r--app/graphql/mutations/notes/reposition_image_diff_note.rb65
-rw-r--r--app/graphql/mutations/notes/update/image_diff_note.rb5
-rw-r--r--app/graphql/mutations/releases/base.rb19
-rw-r--r--app/graphql/mutations/releases/create.rb68
-rw-r--r--app/graphql/mutations/snippets/destroy.rb3
-rw-r--r--app/graphql/mutations/snippets/mark_as_spam.rb3
-rw-r--r--app/graphql/mutations/snippets/update.rb3
-rw-r--r--app/graphql/mutations/terraform/state/base.rb22
-rw-r--r--app/graphql/mutations/terraform/state/delete.rb18
-rw-r--r--app/graphql/mutations/terraform/state/lock.rb29
-rw-r--r--app/graphql/mutations/terraform/state/unlock.rb18
-rw-r--r--app/graphql/mutations/todos/base.rb10
-rw-r--r--app/graphql/mutations/todos/create.rb39
-rw-r--r--app/graphql/mutations/todos/mark_all_done.rb4
-rw-r--r--app/graphql/mutations/todos/restore_many.rb8
37 files changed, 816 insertions, 86 deletions
diff --git a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
index a3a421f8938..17f9b5b5637 100644
--- a/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
+++ b/app/graphql/mutations/admin/sidekiq_queues/delete_jobs.rb
@@ -33,9 +33,9 @@ module Mutations
super
end
- def resolve(args)
+ def resolve(queue_name:, **args)
{
- result: Gitlab::SidekiqQueue.new(args[:queue_name]).drop_jobs!(args, timeout: 30),
+ result: Gitlab::SidekiqQueue.new(queue_name).drop_jobs!(args, timeout: 30),
errors: []
}
rescue Gitlab::SidekiqQueue::NoMetadataError
@@ -44,7 +44,7 @@ module Mutations
errors: ['No metadata provided']
}
rescue Gitlab::SidekiqQueue::InvalidQueueError
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, "Queue #{args[:queue_name]} not found"
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable, "Queue #{queue_name} not found"
end
end
end
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
index 0ccfcf34180..81d5ee95f06 100644
--- a/app/graphql/mutations/alert_management/base.rb
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -4,7 +4,6 @@ module Mutations
module AlertManagement
class Base < BaseMutation
include Gitlab::Utils::UsageData
- include ResolvesProject
argument :project_path, GraphQL::ID_TYPE,
required: true,
@@ -33,13 +32,12 @@ module Mutations
private
- def find_object(project_path:, iid:)
- project = resolve_project(full_path: project_path)
+ def find_object(project_path:, **args)
+ project = Project.find_by_full_path(project_path)
return unless project
- resolver = Resolvers::AlertManagement::AlertResolver.single.new(object: project, context: context, field: nil)
- resolver.resolve(iid: iid)
+ ::AlertManagement::AlertsFinder.new(current_user, project, args).execute.first
end
end
end
diff --git a/app/graphql/mutations/alert_management/http_integration/create.rb b/app/graphql/mutations/alert_management/http_integration/create.rb
new file mode 100644
index 00000000000..ddb75e66bb4
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/create.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class Create < HttpIntegrationBase
+ include ResolvesProject
+
+ graphql_name 'HttpIntegrationCreate'
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'The project to create the integration in'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'The name of the integration'
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: true,
+ description: 'Whether the integration is receiving alerts'
+
+ def resolve(args)
+ project = authorized_find!(full_path: args[:project_path])
+
+ response ::AlertManagement::HttpIntegrations::CreateService.new(
+ project,
+ current_user,
+ args.slice(:name, :active)
+ ).execute
+ end
+
+ private
+
+ def find_object(full_path:)
+ resolve_project(full_path: full_path)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/http_integration/destroy.rb b/app/graphql/mutations/alert_management/http_integration/destroy.rb
new file mode 100644
index 00000000000..0f478760aab
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/destroy.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class Destroy < HttpIntegrationBase
+ graphql_name 'HttpIntegrationDestroy'
+
+ argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
+ required: true,
+ description: "The id of the integration to remove"
+
+ def resolve(id:)
+ integration = authorized_find!(id: id)
+
+ response ::AlertManagement::HttpIntegrations::DestroyService.new(
+ integration,
+ current_user
+ ).execute
+ end
+ 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
new file mode 100644
index 00000000000..d328eabf244
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/http_integration_base.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class HttpIntegrationBase < BaseMutation
+ field :integration,
+ Types::AlertManagement::HttpIntegrationType,
+ null: true,
+ description: "The HTTP integration"
+
+ authorize :admin_operations
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_class: ::AlertManagement::HttpIntegration)
+ end
+
+ def response(result)
+ {
+ integration: result.payload[:integration],
+ errors: result.errors
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/http_integration/reset_token.rb b/app/graphql/mutations/alert_management/http_integration/reset_token.rb
new file mode 100644
index 00000000000..eefab156825
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/reset_token.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class ResetToken < HttpIntegrationBase
+ graphql_name 'HttpIntegrationResetToken'
+
+ argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ def resolve(id:)
+ integration = authorized_find!(id: id)
+
+ response ::AlertManagement::HttpIntegrations::UpdateService.new(
+ integration,
+ current_user,
+ regenerate_token: true
+ ).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/http_integration/update.rb b/app/graphql/mutations/alert_management/http_integration/update.rb
new file mode 100644
index 00000000000..309c45b04ac
--- /dev/null
+++ b/app/graphql/mutations/alert_management/http_integration/update.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module HttpIntegration
+ class Update < HttpIntegrationBase
+ graphql_name 'HttpIntegrationUpdate'
+
+ argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: false,
+ description: "The name of the integration"
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: "Whether the integration is receiving alerts"
+
+ def resolve(args)
+ integration = authorized_find!(id: args[:id])
+
+ response ::AlertManagement::HttpIntegrations::UpdateService.new(
+ integration,
+ current_user,
+ args.slice(:name, :active)
+ ).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/create.rb b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
new file mode 100644
index 00000000000..935ec53795c
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/create.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class Create < PrometheusIntegrationBase
+ include ResolvesProject
+
+ graphql_name 'PrometheusIntegrationCreate'
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'The project to create the integration in'
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: true,
+ description: 'Whether the integration is receiving alerts'
+
+ argument :api_url, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Endpoint at which prometheus can be queried'
+
+ def resolve(args)
+ project = authorized_find!(full_path: args[:project_path])
+
+ return integration_exists if project.prometheus_service
+
+ result = ::Projects::Operations::UpdateService.new(
+ project,
+ current_user,
+ **integration_attributes(args),
+ **token_attributes
+ ).execute
+
+ response(project.prometheus_service, result)
+ end
+
+ 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
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
new file mode 100644
index 00000000000..6b690ac239a
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/prometheus_integration_base.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class PrometheusIntegrationBase < BaseMutation
+ field :integration,
+ Types::AlertManagement::PrometheusIntegrationType,
+ null: true,
+ description: "The newly created integration"
+
+ authorize :admin_project
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_class: ::PrometheusService)
+ end
+
+ def response(integration, result)
+ {
+ integration: integration,
+ errors: Array(result[:message])
+ }
+ end
+
+ def integration_attributes(args)
+ {
+ prometheus_integration_attributes: {
+ manual_configuration: args[:active],
+ api_url: args[:api_url]
+ }.compact
+ }
+ end
+
+ def token_attributes
+ { alerting_setting_attributes: { regenerate_token: true } }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
new file mode 100644
index 00000000000..745ac51f6e3
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/reset_token.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class ResetToken < PrometheusIntegrationBase
+ graphql_name 'PrometheusIntegrationResetToken'
+
+ argument :id, Types::GlobalIDType[::PrometheusService],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ def resolve(id:)
+ integration = authorized_find!(id: id)
+
+ result = ::Projects::Operations::UpdateService.new(
+ integration.project,
+ current_user,
+ token_attributes
+ ).execute
+
+ response integration, result
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/prometheus_integration/update.rb b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
new file mode 100644
index 00000000000..1f0dea119c5
--- /dev/null
+++ b/app/graphql/mutations/alert_management/prometheus_integration/update.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ module PrometheusIntegration
+ class Update < PrometheusIntegrationBase
+ graphql_name 'PrometheusIntegrationUpdate'
+
+ argument :id, Types::GlobalIDType[::PrometheusService],
+ required: true,
+ description: "The id of the integration to mutate"
+
+ argument :active, GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: "Whether the integration is receiving alerts"
+
+ argument :api_url, GraphQL::STRING_TYPE,
+ required: false,
+ description: "Endpoint at which prometheus can be queried"
+
+ def resolve(args)
+ integration = authorized_find!(id: args[:id])
+
+ result = ::Projects::Operations::UpdateService.new(
+ integration.project,
+ current_user,
+ integration_attributes(args)
+ ).execute
+
+ response integration.reset, result
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb
index 1e14bae048a..74185dca529 100644
--- a/app/graphql/mutations/alert_management/update_alert_status.rb
+++ b/app/graphql/mutations/alert_management/update_alert_status.rb
@@ -9,9 +9,9 @@ module Mutations
required: true,
description: 'The status to set the alert'
- def resolve(args)
- alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
- result = update_status(alert, args[:status])
+ def resolve(project_path:, iid:, status:)
+ alert = authorized_find!(project_path: project_path, iid: iid)
+ result = update_status(alert, status)
track_usage_event(:incident_management_alert_status_changed, current_user.id)
diff --git a/app/graphql/mutations/boards/create.rb b/app/graphql/mutations/boards/create.rb
index e381205242e..ebbd19930ec 100644
--- a/app/graphql/mutations/boards/create.rb
+++ b/app/graphql/mutations/boards/create.rb
@@ -3,8 +3,7 @@
module Mutations
module Boards
class Create < ::Mutations::BaseMutation
- include Mutations::ResolvesGroup
- include ResolvesProject
+ include Mutations::ResolvesResourceParent
graphql_name 'CreateBoard'
@@ -13,12 +12,6 @@ module Mutations
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,
@@ -28,7 +21,7 @@ module Mutations
required: false,
description: 'The ID of the user to be assigned to the board.'
argument :milestone_id,
- GraphQL::ID_TYPE,
+ Types::GlobalIDType[Milestone],
required: false,
description: 'The ID of the milestone to be assigned to the board.'
argument :weight,
@@ -36,17 +29,14 @@ module Mutations
required: false,
description: 'The weight of the board.'
argument :label_ids,
- [GraphQL::ID_TYPE],
+ [Types::GlobalIDType[Label]],
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)
+ board_parent = authorized_resource_parent_find!(args)
response = ::Boards::CreateService.new(board_parent, current_user, args).execute
{
@@ -54,25 +44,6 @@ module Mutations
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/update.rb b/app/graphql/mutations/boards/lists/update.rb
index 7efed3058b3..14502b5174f 100644
--- a/app/graphql/mutations/boards/lists/update.rb
+++ b/app/graphql/mutations/boards/lists/update.rb
@@ -6,7 +6,7 @@ module Mutations
class Update < BaseMutation
graphql_name 'UpdateBoardList'
- argument :list_id, GraphQL::ID_TYPE,
+ argument :list_id, Types::GlobalIDType[List],
required: true,
loads: Types::BoardListType,
description: 'Global ID of the list.'
diff --git a/app/graphql/mutations/commits/create.rb b/app/graphql/mutations/commits/create.rb
index 9ed1bb819c8..2b9107350fd 100644
--- a/app/graphql/mutations/commits/create.rb
+++ b/app/graphql/mutations/commits/create.rb
@@ -13,7 +13,11 @@ module Mutations
argument :branch, GraphQL::STRING_TYPE,
required: true,
- description: 'Name of the branch'
+ description: 'Name of the branch to commit into, it can be a new branch'
+
+ argument :start_branch, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'If on a new branch, name of the original branch'
argument :message,
GraphQL::STRING_TYPE,
@@ -32,13 +36,13 @@ module Mutations
authorize :push_code
- def resolve(project_path:, branch:, message:, actions:)
+ def resolve(project_path:, branch:, message:, actions:, **args)
project = authorized_find!(full_path: project_path)
attributes = {
commit_message: message,
branch_name: branch,
- start_branch: branch,
+ start_branch: args[:start_branch] || branch,
actions: actions.map { |action| action.to_h }
}
diff --git a/app/graphql/mutations/concerns/mutations/package_eventable.rb b/app/graphql/mutations/concerns/mutations/package_eventable.rb
new file mode 100644
index 00000000000..86fd7b9a88a
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/package_eventable.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Mutations
+ module PackageEventable
+ extend ActiveSupport::Concern
+
+ private
+
+ def track_event(event, scope)
+ ::Packages::CreateEventService.new(nil, current_user, event_name: event, scope: scope).execute
+ ::Gitlab::Tracking.event(event.to_s, scope.to_s)
+ 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
new file mode 100644
index 00000000000..04a9abf9529
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/resolves_resource_parent.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Mutations
+ module ResolvesResourceParent
+ extend ActiveSupport::Concern
+ include Mutations::ResolvesGroup
+ include ResolvesProject
+
+ included do
+ argument :project_path, GraphQL::ID_TYPE,
+ required: false,
+ description: 'The project full path the resource is associated with'
+
+ argument :group_path, GraphQL::ID_TYPE,
+ required: false,
+ description: 'The group full path the resource is associated with'
+ end
+
+ def ready?(**args)
+ unless args[:project_path].present? ^ args[:group_path].present?
+ raise Gitlab::Graphql::Errors::ArgumentError,
+ 'Exactly one of group_path or project_path arguments is required'
+ end
+
+ super
+ end
+
+ private
+
+ def authorized_resource_parent_find!(args)
+ authorized_find!(project_path: args.delete(:project_path),
+ group_path: args.delete(:group_path))
+ end
+
+ def find_object(project_path: nil, group_path: nil)
+ if group_path.present?
+ resolve_group(full_path: group_path)
+ else
+ resolve_project(full_path: project_path)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/container_repositories/destroy.rb b/app/graphql/mutations/container_repositories/destroy.rb
new file mode 100644
index 00000000000..8312193147f
--- /dev/null
+++ b/app/graphql/mutations/container_repositories/destroy.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Mutations
+ module ContainerRepositories
+ class Destroy < Mutations::BaseMutation
+ include ::Mutations::PackageEventable
+
+ graphql_name 'DestroyContainerRepository'
+
+ authorize :destroy_container_image
+
+ argument :id,
+ ::Types::GlobalIDType[::ContainerRepository],
+ required: true,
+ description: 'ID of the container repository.'
+
+ field :container_repository,
+ Types::ContainerRepositoryType,
+ null: false,
+ description: 'The container repository policy after scheduling the deletion.'
+
+ def resolve(id:)
+ container_repository = authorized_find!(id: id)
+
+ container_repository.delete_scheduled!
+ DeleteContainerRepositoryWorker.perform_async(current_user.id, container_repository.id)
+ track_event(:delete_repository, :container)
+
+ {
+ container_repository: container_repository,
+ errors: []
+ }
+ end
+
+ 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 = ::Types::GlobalIDType[::ContainerRepository].coerce_isolated_input(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/custom_emoji/create.rb b/app/graphql/mutations/custom_emoji/create.rb
new file mode 100644
index 00000000000..d912a29d12e
--- /dev/null
+++ b/app/graphql/mutations/custom_emoji/create.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Mutations
+ module CustomEmoji
+ class Create < BaseMutation
+ include Mutations::ResolvesGroup
+
+ graphql_name 'CreateCustomEmoji'
+
+ authorize :create_custom_emoji
+
+ field :custom_emoji,
+ Types::CustomEmojiType,
+ null: true,
+ description: 'The new custom emoji'
+
+ argument :group_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'Namespace full path the emoji is associated with'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Name of the emoji'
+
+ argument :url, GraphQL::STRING_TYPE,
+ required: true,
+ as: :file,
+ description: 'Location of the emoji file'
+
+ def resolve(group_path:, **args)
+ group = authorized_find!(group_path: group_path)
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911#note_444682238
+ args[:external] = true
+
+ custom_emoji = group.custom_emoji.create(args)
+
+ {
+ custom_emoji: custom_emoji.valid? ? custom_emoji : nil,
+ errors: errors_on_object(custom_emoji)
+ }
+ end
+
+ private
+
+ def find_object(group_path:)
+ resolve_group(full_path: group_path)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/labels/create.rb b/app/graphql/mutations/labels/create.rb
new file mode 100644
index 00000000000..cb03651618e
--- /dev/null
+++ b/app/graphql/mutations/labels/create.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Labels
+ class Create < BaseMutation
+ include Mutations::ResolvesResourceParent
+
+ graphql_name 'LabelCreate'
+
+ field :label,
+ Types::LabelType,
+ null: true,
+ description: 'The label after mutation'
+
+ argument :title, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Title of the label'
+
+ argument :description, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Description of the label'
+
+ argument :color, GraphQL::STRING_TYPE,
+ required: false,
+ default_value: Label::DEFAULT_COLOR,
+ description: "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords"
+
+ authorize :admin_label
+
+ def resolve(args)
+ parent = authorized_resource_parent_find!(args)
+ parent_key = parent.is_a?(Project) ? :project : :group
+
+ label = ::Labels::CreateService.new(args).execute(parent_key => parent)
+
+ {
+ label: label.persisted? ? label : nil,
+ errors: errors_on_object(label)
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/set_labels.rb b/app/graphql/mutations/merge_requests/set_labels.rb
index c1e45808593..712c68c9425 100644
--- a/app/graphql/mutations/merge_requests/set_labels.rb
+++ b/app/graphql/mutations/merge_requests/set_labels.rb
@@ -6,7 +6,7 @@ module Mutations
graphql_name 'MergeRequestSetLabels'
argument :label_ids,
- [GraphQL::ID_TYPE],
+ [::Types::GlobalIDType[Label]],
required: true,
description: <<~DESC
The Label IDs to set. Replaces existing labels by default.
@@ -23,10 +23,11 @@ module Mutations
merge_request = authorized_find!(project_path: project_path, iid: iid)
project = merge_request.project
- label_ids = label_ids
- .map { |gid| GlobalID.parse(gid) }
- .select(&method(:label_descendant?))
- .map(&:model_id) # MergeRequests::UpdateService expects integers
+ # TODO: remove this line when the compatibility layer is removed:
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
+ label_ids = label_ids.map { |id| ::Types::GlobalIDType[::Label].coerce_isolated_input(id) }
+ # MergeRequests::UpdateService expects integers
+ label_ids = label_ids.compact.map(&:model_id)
attribute_name = case operation_mode
when Types::MutationOperationModeEnum.enum[:append]
@@ -45,10 +46,6 @@ module Mutations
errors: errors_on_object(merge_request)
}
end
-
- def label_descendant?(gid)
- gid&.model_class&.ancestors&.include?(Label)
- end
end
end
end
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
index 6e183e78d9b..d6731dfcafd 100644
--- a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
+++ b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
@@ -9,8 +9,7 @@ module Mutations
authorize :delete_metrics_dashboard_annotation
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Metrics::Dashboard::Annotation],
required: true,
description: 'The global ID of the annotation to delete'
diff --git a/app/graphql/mutations/notes/reposition_image_diff_note.rb b/app/graphql/mutations/notes/reposition_image_diff_note.rb
new file mode 100644
index 00000000000..0d88bcd9a30
--- /dev/null
+++ b/app/graphql/mutations/notes/reposition_image_diff_note.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Notes
+ # This mutation differs from the update note mutations as it checks the
+ # `reposition_note` permission, and doesn't allow updating a note's `body`.
+ class RepositionImageDiffNote < Mutations::Notes::Base
+ graphql_name 'RepositionImageDiffNote'
+
+ description 'Repositions a DiffNote on an image (a `Note` where the `position.positionType` is `"image"`)'
+
+ authorize :reposition_note
+
+ argument :id,
+ Types::GlobalIDType[DiffNote],
+ loads: Types::Notes::NoteType,
+ as: :note,
+ required: true,
+ description: 'The global id of the DiffNote to update'
+
+ argument :position,
+ Types::Notes::UpdateDiffImagePositionInputType,
+ required: true,
+ description: copy_field_description(Types::Notes::NoteType, :position)
+
+ def resolve(note:, position:)
+ authorize!(note)
+
+ pre_update_checks!(note, position)
+
+ updated_note = ::Notes::UpdateService.new(
+ note.project,
+ current_user,
+ note_params(note.position, position)
+ ).execute(note)
+
+ {
+ note: updated_note.reset,
+ errors: errors_on_object(updated_note)
+ }
+ end
+
+ private
+
+ # An ImageDiffNote does not exist as a class itself, but is instead
+ # just a `DiffNote` with a particular kind of `Gitlab::Diff::Position`.
+ # In addition to accepting a `DiffNote` Global ID we also need to
+ # perform this check.
+ def pre_update_checks!(note, position)
+ unless note.position&.on_image?
+ raise Gitlab::Graphql::Errors::ResourceNotAvailable,
+ 'Resource is not an ImageDiffNote'
+ end
+ end
+
+ def note_params(old_position, new_position)
+ position = old_position.to_h.merge(new_position)
+
+ {
+ position: Gitlab::Diff::Position.new(position)
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/notes/update/image_diff_note.rb b/app/graphql/mutations/notes/update/image_diff_note.rb
index ef70a8d2bf4..f4533cd9edb 100644
--- a/app/graphql/mutations/notes/update/image_diff_note.rb
+++ b/app/graphql/mutations/notes/update/image_diff_note.rb
@@ -47,12 +47,11 @@ module Mutations
end
def position_params(note, args)
- new_position = args[:position]&.to_h&.compact
- return unless new_position
+ return unless args[:position]
original_position = note.position.to_h
- Gitlab::Diff::Position.new(original_position.merge(new_position))
+ Gitlab::Diff::Position.new(original_position.merge(args[:position]))
end
end
end
diff --git a/app/graphql/mutations/releases/base.rb b/app/graphql/mutations/releases/base.rb
new file mode 100644
index 00000000000..d53cfbe6a11
--- /dev/null
+++ b/app/graphql/mutations/releases/base.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Releases
+ class Base < BaseMutation
+ include ResolvesProject
+
+ 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
new file mode 100644
index 00000000000..57c1541c368
--- /dev/null
+++ b/app/graphql/mutations/releases/create.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Releases
+ class Create < Base
+ graphql_name 'ReleaseCreate'
+
+ field :release,
+ Types::ReleaseType,
+ null: true,
+ description: 'The release after mutation'
+
+ argument :tag_name, GraphQL::STRING_TYPE,
+ required: true, as: :tag,
+ description: 'Name of the tag to associate with the release'
+
+ argument :ref, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'The commit SHA or branch name to use if creating a new tag'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Name of the release'
+
+ argument :description, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Description (also known as "release notes") of the release'
+
+ argument :released_at, Types::TimeType,
+ required: false,
+ description: 'The date when the release will be/was ready. Defaults to the current time.'
+
+ argument :milestones, [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'The title of each milestone the release is associated with. GitLab Premium customers can specify group milestones.'
+
+ argument :assets, Types::ReleaseAssetsInputType,
+ required: false,
+ description: 'Assets associated to the release'
+
+ authorize :create_release
+
+ def resolve(project_path:, milestones: nil, assets: nil, **scalars)
+ project = authorized_find!(full_path: project_path)
+
+ params = {
+ **scalars,
+ milestones: milestones.presence || [],
+ assets: assets.to_h
+ }.with_indifferent_access
+
+ result = ::Releases::CreateService.new(project, current_user, params).execute
+
+ if result[:status] == :success
+ {
+ release: result[:release],
+ errors: []
+ }
+ else
+ {
+ release: nil,
+ errors: [result[:message]]
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/destroy.rb b/app/graphql/mutations/snippets/destroy.rb
index dc9a1e82575..4915d7dd77a 100644
--- a/app/graphql/mutations/snippets/destroy.rb
+++ b/app/graphql/mutations/snippets/destroy.rb
@@ -7,8 +7,7 @@ module Mutations
ERROR_MSG = 'Error deleting the snippet'
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
description: 'The global id of the snippet to destroy'
diff --git a/app/graphql/mutations/snippets/mark_as_spam.rb b/app/graphql/mutations/snippets/mark_as_spam.rb
index 8cfbbae7c08..d6b96c699c0 100644
--- a/app/graphql/mutations/snippets/mark_as_spam.rb
+++ b/app/graphql/mutations/snippets/mark_as_spam.rb
@@ -5,8 +5,7 @@ module Mutations
class MarkAsSpam < Base
graphql_name 'MarkAsSpamSnippet'
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
description: 'The global id of the snippet to update'
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 74266880806..bcaa807e4c1 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -7,8 +7,7 @@ module Mutations
graphql_name 'UpdateSnippet'
- argument :id,
- GraphQL::ID_TYPE,
+ argument :id, ::Types::GlobalIDType[::Snippet],
required: true,
description: 'The global id of the snippet to update'
diff --git a/app/graphql/mutations/terraform/state/base.rb b/app/graphql/mutations/terraform/state/base.rb
new file mode 100644
index 00000000000..b1721c784b1
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/base.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Base < BaseMutation
+ authorize :admin_terraform_state
+
+ argument :id,
+ Types::GlobalIDType[::Terraform::State],
+ required: true,
+ description: 'Global ID of the Terraform state'
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/terraform/state/delete.rb b/app/graphql/mutations/terraform/state/delete.rb
new file mode 100644
index 00000000000..f08219cb395
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/delete.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Delete < Base
+ graphql_name 'TerraformStateDelete'
+
+ def resolve(id:)
+ state = authorized_find!(id: id)
+ state.destroy
+
+ { errors: errors_on_object(state) }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/terraform/state/lock.rb b/app/graphql/mutations/terraform/state/lock.rb
new file mode 100644
index 00000000000..d22c8de2560
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/lock.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Lock < Base
+ graphql_name 'TerraformStateLock'
+
+ def resolve(id:)
+ state = authorized_find!(id: id)
+
+ if state.locked?
+ state.errors.add(:base, 'state is already locked')
+ else
+ state.update(lock_xid: lock_xid, locked_by_user: current_user, locked_at: Time.current)
+ end
+
+ { errors: errors_on_object(state) }
+ end
+
+ private
+
+ def lock_xid
+ SecureRandom.uuid
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/terraform/state/unlock.rb b/app/graphql/mutations/terraform/state/unlock.rb
new file mode 100644
index 00000000000..0818dbd7fb3
--- /dev/null
+++ b/app/graphql/mutations/terraform/state/unlock.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Terraform
+ module State
+ class Unlock < Base
+ graphql_name 'TerraformStateUnlock'
+
+ def resolve(id:)
+ state = authorized_find!(id: id)
+ state.update(lock_xid: nil, locked_by_user: nil, locked_at: nil)
+
+ { errors: errors_on_object(state) }
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/todos/base.rb b/app/graphql/mutations/todos/base.rb
index 6db863796bc..4dab3bbc3f4 100644
--- a/app/graphql/mutations/todos/base.rb
+++ b/app/graphql/mutations/todos/base.rb
@@ -11,16 +11,6 @@ module Mutations
id = ::Types::GlobalIDType[::Todo].coerce_isolated_input(id)
GitlabSchema.find_by_gid(id)
end
-
- def map_to_global_ids(ids)
- return [] if ids.blank?
-
- ids.map { |id| to_global_id(id) }
- end
-
- def to_global_id(id)
- Gitlab::GlobalId.as_global_id(id, model_name: Todo.name).to_s
- end
end
end
end
diff --git a/app/graphql/mutations/todos/create.rb b/app/graphql/mutations/todos/create.rb
new file mode 100644
index 00000000000..53c88696fdd
--- /dev/null
+++ b/app/graphql/mutations/todos/create.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Todos
+ class Create < ::Mutations::Todos::Base
+ graphql_name 'TodoCreate'
+
+ authorize :create_todo
+
+ argument :target_id,
+ Types::GlobalIDType[Todoable],
+ required: true,
+ description: "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported"
+
+ field :todo, Types::TodoType,
+ null: true,
+ description: 'The to-do created'
+
+ def resolve(target_id:)
+ id = ::Types::GlobalIDType[Todoable].coerce_isolated_input(target_id)
+ target = authorized_find!(id)
+
+ todo = TodoService.new.mark_todo(target, current_user)&.first
+ errors = errors_on_object(todo) if todo
+
+ {
+ todo: todo,
+ errors: errors
+ }
+ end
+
+ private
+
+ def find_object(id)
+ GitlabSchema.find_by_gid(id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/todos/mark_all_done.rb b/app/graphql/mutations/todos/mark_all_done.rb
index 8b53658ddd5..97bbbeeaa2f 100644
--- a/app/graphql/mutations/todos/mark_all_done.rb
+++ b/app/graphql/mutations/todos/mark_all_done.rb
@@ -8,7 +8,7 @@ module Mutations
authorize :update_user
field :updated_ids,
- [GraphQL::ID_TYPE],
+ [::Types::GlobalIDType[::Todo]],
null: false,
deprecated: { reason: 'Use todos', milestone: '13.2' },
description: 'Ids of the updated todos'
@@ -23,7 +23,7 @@ module Mutations
updated_ids = mark_all_todos_done
{
- updated_ids: map_to_global_ids(updated_ids),
+ updated_ids: updated_ids,
todos: Todo.id_in(updated_ids),
errors: []
}
diff --git a/app/graphql/mutations/todos/restore_many.rb b/app/graphql/mutations/todos/restore_many.rb
index ea5f5414134..9e0a95c48ec 100644
--- a/app/graphql/mutations/todos/restore_many.rb
+++ b/app/graphql/mutations/todos/restore_many.rb
@@ -12,7 +12,7 @@ module Mutations
required: true,
description: 'The global ids of the todos to restore (a maximum of 50 is supported at once)'
- field :updated_ids, [GraphQL::ID_TYPE],
+ field :updated_ids, [::Types::GlobalIDType[Todo]],
null: false,
description: 'The ids of the updated todo items',
deprecated: { reason: 'Use todos', milestone: '13.2' }
@@ -28,7 +28,7 @@ module Mutations
updated_ids = restore(todos)
{
- updated_ids: gids_of(updated_ids),
+ updated_ids: updated_ids,
todos: Todo.id_in(updated_ids),
errors: errors_on_objects(todos)
}
@@ -36,10 +36,6 @@ module Mutations
private
- def gids_of(ids)
- 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|
# TODO: remove this line when the compatibility layer is removed