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>2020-05-20 17:34:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-20 17:34:42 +0300
commit9f46488805e86b1bc341ea1620b866016c2ce5ed (patch)
treef9748c7e287041e37d6da49e0a29c9511dc34768 /app/graphql/mutations
parentdfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff)
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'app/graphql/mutations')
-rw-r--r--app/graphql/mutations/alert_management/base.rb40
-rw-r--r--app/graphql/mutations/alert_management/create_alert_issue.rb30
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb35
-rw-r--r--app/graphql/mutations/base_mutation.rb2
-rw-r--r--app/graphql/mutations/branches/create.rb51
-rw-r--r--app/graphql/mutations/design_management/base.rb23
-rw-r--r--app/graphql/mutations/design_management/delete.rb66
-rw-r--r--app/graphql/mutations/design_management/upload.rb38
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/create.rb106
-rw-r--r--app/graphql/mutations/snippets/base.rb2
-rw-r--r--app/graphql/mutations/snippets/create.rb9
11 files changed, 401 insertions, 1 deletions
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
new file mode 100644
index 00000000000..ca2057d4845
--- /dev/null
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ class Base < BaseMutation
+ include Mutations::ResolvesProject
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: "The project the alert to mutate is in"
+
+ argument :iid, GraphQL::STRING_TYPE,
+ required: true,
+ description: "The iid of the alert to mutate"
+
+ field :alert,
+ Types::AlertManagement::AlertType,
+ null: true,
+ description: "The alert after mutation"
+
+ field :issue,
+ Types::IssueType,
+ null: true,
+ description: "The issue created after mutation"
+
+ authorize :update_alert_management_alert
+
+ private
+
+ def find_object(project_path:, iid:)
+ project = resolve_project(full_path: project_path)
+
+ return unless project
+
+ resolver = Resolvers::AlertManagementAlertResolver.single.new(object: project, context: context, field: nil)
+ resolver.resolve(iid: iid)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/alert_management/create_alert_issue.rb b/app/graphql/mutations/alert_management/create_alert_issue.rb
new file mode 100644
index 00000000000..adb048a4479
--- /dev/null
+++ b/app/graphql/mutations/alert_management/create_alert_issue.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ class CreateAlertIssue < Base
+ graphql_name 'CreateAlertIssue'
+
+ def resolve(args)
+ alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
+ result = create_alert_issue(alert, current_user)
+
+ prepare_response(alert, result)
+ end
+
+ private
+
+ def create_alert_issue(alert, user)
+ ::AlertManagement::CreateAlertIssueService.new(alert, user).execute
+ end
+
+ def prepare_response(alert, result)
+ {
+ alert: alert,
+ issue: result.payload[:issue],
+ errors: Array(result.message)
+ }
+ 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
new file mode 100644
index 00000000000..e73a591378a
--- /dev/null
+++ b/app/graphql/mutations/alert_management/update_alert_status.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Mutations
+ module AlertManagement
+ class UpdateAlertStatus < Base
+ graphql_name 'UpdateAlertStatus'
+
+ argument :status, Types::AlertManagement::StatusEnum,
+ 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])
+
+ prepare_response(result)
+ end
+
+ private
+
+ def update_status(alert, status)
+ ::AlertManagement::UpdateAlertStatusService
+ .new(alert, current_user, status)
+ .execute
+ end
+
+ def prepare_response(result)
+ {
+ alert: result.payload[:alert],
+ errors: result.error? ? [result.message] : []
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb
index 623f7c27584..30510cfab50 100644
--- a/app/graphql/mutations/base_mutation.rb
+++ b/app/graphql/mutations/base_mutation.rb
@@ -9,7 +9,7 @@ module Mutations
field :errors, [GraphQL::STRING_TYPE],
null: false,
- description: "Reasons why the mutation failed."
+ description: "Errors encountered during execution of the mutation."
def current_user
context[:current_user]
diff --git a/app/graphql/mutations/branches/create.rb b/app/graphql/mutations/branches/create.rb
new file mode 100644
index 00000000000..127d5447d0a
--- /dev/null
+++ b/app/graphql/mutations/branches/create.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Branches
+ class Create < BaseMutation
+ include Mutations::ResolvesProject
+
+ graphql_name 'CreateBranch'
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: 'Project full path the branch is associated with'
+
+ argument :name, GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Name of the branch'
+
+ argument :ref,
+ GraphQL::STRING_TYPE,
+ required: true,
+ description: 'Branch name or commit SHA to create branch from'
+
+ field :branch,
+ Types::BranchType,
+ null: true,
+ description: 'Branch after mutation'
+
+ authorize :push_code
+
+ def resolve(project_path:, name:, ref:)
+ project = authorized_find!(full_path: project_path)
+
+ context.scoped_set!(:branch_project, project)
+
+ result = ::Branches::CreateService.new(project, current_user)
+ .execute(name, ref)
+
+ {
+ branch: (result[:branch] if result[:status] == :success),
+ 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/design_management/base.rb b/app/graphql/mutations/design_management/base.rb
new file mode 100644
index 00000000000..918e5709b94
--- /dev/null
+++ b/app/graphql/mutations/design_management/base.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Mutations
+ module DesignManagement
+ class Base < ::Mutations::BaseMutation
+ include Mutations::ResolvesIssuable
+
+ argument :project_path, GraphQL::ID_TYPE,
+ required: true,
+ description: "The project where the issue is to upload designs for"
+
+ argument :iid, GraphQL::ID_TYPE,
+ required: true,
+ description: "The iid of the issue to modify designs for"
+
+ private
+
+ def find_object(project_path:, iid:)
+ resolve_issuable(type: :issue, parent_path: project_path, iid: iid)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/design_management/delete.rb b/app/graphql/mutations/design_management/delete.rb
new file mode 100644
index 00000000000..d2ef2c9bcca
--- /dev/null
+++ b/app/graphql/mutations/design_management/delete.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Mutations
+ module DesignManagement
+ class Delete < Base
+ Errors = ::Gitlab::Graphql::Errors
+
+ graphql_name "DesignManagementDelete"
+
+ argument :filenames, [GraphQL::STRING_TYPE],
+ required: true,
+ description: "The filenames of the designs to delete",
+ prepare: ->(names, _ctx) do
+ names.presence || (raise Errors::ArgumentError, 'no filenames')
+ end
+
+ field :version, Types::DesignManagement::VersionType,
+ null: true, # null on error
+ description: 'The new version in which the designs are deleted'
+
+ authorize :destroy_design
+
+ def resolve(project_path:, iid:, filenames:)
+ issue = authorized_find!(project_path: project_path, iid: iid)
+ project = issue.project
+ designs = resolve_designs(issue, filenames)
+
+ result = ::DesignManagement::DeleteDesignsService
+ .new(project, current_user, issue: issue, designs: designs)
+ .execute
+
+ {
+ version: result[:version],
+ errors: Array.wrap(result[:message])
+ }
+ end
+
+ private
+
+ # Here we check that:
+ # * we find exactly as many designs as filenames
+ def resolve_designs(issue, filenames)
+ designs = issue.design_collection.designs_by_filename(filenames)
+
+ validate_all_were_found!(designs, filenames)
+
+ designs
+ end
+
+ def validate_all_were_found!(designs, filenames)
+ found_filenames = designs.map(&:filename)
+ missing = filenames.difference(found_filenames)
+
+ if missing.present?
+ raise Errors::ArgumentError, <<~MSG
+ Not all the designs you named currently exist.
+ The following filenames were not found:
+ #{missing.join(', ')}
+
+ They may have already been deleted.
+ MSG
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/design_management/upload.rb b/app/graphql/mutations/design_management/upload.rb
new file mode 100644
index 00000000000..1ed7f8e49e6
--- /dev/null
+++ b/app/graphql/mutations/design_management/upload.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Mutations
+ module DesignManagement
+ class Upload < Base
+ graphql_name "DesignManagementUpload"
+
+ argument :files, [ApolloUploadServer::Upload],
+ required: true,
+ description: "The files to upload"
+
+ authorize :create_design
+
+ field :designs, [Types::DesignManagement::DesignType],
+ null: false,
+ description: "The designs that were uploaded by the mutation"
+
+ field :skipped_designs, [Types::DesignManagement::DesignType],
+ null: false,
+ description: "Any designs that were skipped from the upload due to there " \
+ "being no change to their content since their last version"
+
+ def resolve(project_path:, iid:, files:)
+ issue = authorized_find!(project_path: project_path, iid: iid)
+ project = issue.project
+
+ result = ::DesignManagement::SaveDesignsService.new(project, current_user, issue: issue, files: files)
+ .execute
+
+ {
+ designs: Array.wrap(result[:designs]),
+ skipped_designs: Array.wrap(result[:skipped_designs]),
+ errors: Array.wrap(result[:message])
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/create.rb b/app/graphql/mutations/metrics/dashboard/annotations/create.rb
new file mode 100644
index 00000000000..f99688aeac6
--- /dev/null
+++ b/app/graphql/mutations/metrics/dashboard/annotations/create.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Metrics
+ module Dashboard
+ module Annotations
+ class Create < BaseMutation
+ graphql_name 'CreateAnnotation'
+
+ ANNOTATION_SOURCE_ARGUMENT_ERROR = 'Either a cluster or environment global id is required'
+ INVALID_ANNOTATION_SOURCE_ERROR = 'Invalid cluster or environment id'
+
+ authorize :create_metrics_dashboard_annotation
+
+ field :annotation,
+ Types::Metrics::Dashboards::AnnotationType,
+ null: true,
+ description: 'The created annotation'
+
+ argument :environment_id,
+ GraphQL::ID_TYPE,
+ required: false,
+ description: 'The global id of the environment to add an annotation to'
+
+ argument :cluster_id,
+ GraphQL::ID_TYPE,
+ required: false,
+ description: 'The global id of the cluster to add an annotation to'
+
+ argument :starting_at, Types::TimeType,
+ required: true,
+ description: 'Timestamp indicating starting moment to which the annotation relates'
+
+ argument :ending_at, Types::TimeType,
+ required: false,
+ description: 'Timestamp indicating ending moment to which the annotation relates'
+
+ argument :dashboard_path,
+ GraphQL::STRING_TYPE,
+ required: true,
+ description: 'The path to a file defining the dashboard on which the annotation should be added'
+
+ argument :description,
+ GraphQL::STRING_TYPE,
+ required: true,
+ description: 'The description of the annotation'
+
+ AnnotationSource = Struct.new(:object, keyword_init: true) do
+ def type_keys
+ { 'Clusters::Cluster' => :cluster, 'Environment' => :environment }
+ end
+
+ def klass
+ object.class.name
+ end
+
+ def type
+ raise Gitlab::Graphql::Errors::ArgumentError, INVALID_ANNOTATION_SOURCE_ERROR unless type_keys[klass]
+
+ type_keys[klass]
+ end
+ end
+
+ def resolve(args)
+ annotation_response = ::Metrics::Dashboard::Annotations::CreateService.new(context[:current_user], annotation_create_params(args)).execute
+
+ annotation = annotation_response[:annotation]
+
+ {
+ annotation: annotation.valid? ? annotation : nil,
+ errors: errors_on_object(annotation)
+ }
+ end
+
+ private
+
+ def ready?(**args)
+ # Raise error if both cluster_id and environment_id are present or neither is present
+ unless args[:cluster_id].present? ^ args[:environment_id].present?
+ raise Gitlab::Graphql::Errors::ArgumentError, ANNOTATION_SOURCE_ARGUMENT_ERROR
+ end
+
+ super(args)
+ end
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id)
+ end
+
+ def annotation_create_params(args)
+ annotation_source = AnnotationSource.new(object: annotation_source(args))
+
+ args[annotation_source.type] = annotation_source.object
+
+ args
+ end
+
+ def annotation_source(args)
+ annotation_source_id = args[:cluster_id] || args[:environment_id]
+ authorized_find!(id: annotation_source_id)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/snippets/base.rb b/app/graphql/mutations/snippets/base.rb
index 9dc6d49774e..c8cc721b2e0 100644
--- a/app/graphql/mutations/snippets/base.rb
+++ b/app/graphql/mutations/snippets/base.rb
@@ -15,6 +15,8 @@ module Mutations
end
def authorized_resource?(snippet)
+ return false if snippet.nil?
+
Ability.allowed?(context[:current_user], ability_for(snippet), snippet)
end
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index 266a123de82..6fc223fbee7 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -36,6 +36,10 @@ module Mutations
required: false,
description: 'The project full path the snippet is associated with'
+ argument :uploaded_files, [GraphQL::STRING_TYPE],
+ required: false,
+ description: 'The paths to files uploaded in the snippet description'
+
def resolve(args)
project_path = args.delete(:project_path)
@@ -45,9 +49,14 @@ module Mutations
raise_resource_not_available_error!
end
+ # We need to rename `uploaded_files` into `files` because
+ # it's the expected key param
+ args[:files] = args.delete(:uploaded_files)
+
service_response = ::Snippets::CreateService.new(project,
context[:current_user],
args).execute
+
snippet = service_response.payload[:snippet]
{