summaryrefslogtreecommitdiff
path: root/app/services/issuable_links
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 01:45:44 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 01:45:44 +0000
commit85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch)
tree9160f299afd8c80c038f08e1545be119f5e3f1e1 /app/services/issuable_links
parent15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff)
downloadgitlab-ce-85dc423f7090da0a52c73eb66faf22ddb20efff9.tar.gz
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'app/services/issuable_links')
-rw-r--r--app/services/issuable_links/create_service.rb119
-rw-r--r--app/services/issuable_links/destroy_service.rb34
-rw-r--r--app/services/issuable_links/list_service.rb27
3 files changed, 180 insertions, 0 deletions
diff --git a/app/services/issuable_links/create_service.rb b/app/services/issuable_links/create_service.rb
new file mode 100644
index 00000000000..f148c503dcf
--- /dev/null
+++ b/app/services/issuable_links/create_service.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+module IssuableLinks
+ class CreateService < BaseService
+ include IncidentManagement::UsageData
+
+ attr_reader :issuable, :current_user, :params
+
+ def initialize(issuable, user, params)
+ @issuable, @current_user, @params = issuable, user, params.dup
+ end
+
+ def execute
+ # If ALL referenced issues are already assigned to the given epic it renders a conflict status,
+ # otherwise create issue links for the issues which
+ # are still not assigned and return success message.
+ if render_conflict_error?
+ return error(issuables_assigned_message, 409)
+ end
+
+ if render_not_found_error?
+ return error(issuables_not_found_message, 404)
+ end
+
+ @errors = []
+ create_links
+
+ if @errors.present?
+ return error(@errors.join('. '), 422)
+ end
+
+ track_event
+
+ success
+ end
+
+ private
+
+ def render_conflict_error?
+ referenced_issuables.present? && (referenced_issuables - previous_related_issuables).empty?
+ end
+
+ def render_not_found_error?
+ linkable_issuables(referenced_issuables).empty?
+ end
+
+ def create_links
+ objects = linkable_issuables(referenced_issuables)
+ link_issuables(objects)
+ end
+
+ def link_issuables(target_issuables)
+ target_issuables.each do |referenced_object|
+ link = relate_issuables(referenced_object)
+
+ unless link.valid?
+ @errors << _("%{ref} cannot be added: %{error}") % {
+ ref: referenced_object.to_reference,
+ error: link.errors.messages.values.flatten.to_sentence
+ }
+ end
+ end
+ end
+
+ def referenced_issuables
+ @referenced_issuables ||= begin
+ target_issuable = params[:target_issuable]
+
+ if params[:issuable_references].present?
+ extract_references
+ elsif target_issuable
+ [target_issuable]
+ else
+ []
+ end
+ end
+ end
+
+ def extract_references
+ issuable_references = params[:issuable_references]
+ text = issuable_references.join(' ')
+
+ extractor = Gitlab::ReferenceExtractor.new(issuable.project, current_user)
+ extractor.analyze(text, extractor_context)
+
+ references(extractor)
+ end
+
+ def references(extractor)
+ extractor.issues
+ end
+
+ def extractor_context
+ {}
+ end
+
+ def linkable_issuables(objects)
+ raise NotImplementedError
+ end
+
+ def previous_related_issuables
+ raise NotImplementedError
+ end
+
+ def relate_issuables(referenced_object)
+ raise NotImplementedError
+ end
+
+ def issuables_assigned_message
+ 'Issue(s) already assigned'
+ end
+
+ def issuables_not_found_message
+ 'No Issue found for given params'
+ end
+ end
+end
+
+IssuableLinks::CreateService.prepend_if_ee('EE::IssuableLinks::CreateService')
diff --git a/app/services/issuable_links/destroy_service.rb b/app/services/issuable_links/destroy_service.rb
new file mode 100644
index 00000000000..57e1314e0da
--- /dev/null
+++ b/app/services/issuable_links/destroy_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module IssuableLinks
+ class DestroyService < BaseService
+ include IncidentManagement::UsageData
+
+ attr_reader :link, :current_user
+
+ def initialize(link, user)
+ @link = link
+ @current_user = user
+ end
+
+ def execute
+ return error(not_found_message, 404) unless permission_to_remove_relation?
+
+ remove_relation
+ create_notes
+ track_event
+
+ success(message: 'Relation was removed')
+ end
+
+ private
+
+ def remove_relation
+ link.destroy!
+ end
+
+ def not_found_message
+ 'No Issue Link found'
+ end
+ end
+end
diff --git a/app/services/issuable_links/list_service.rb b/app/services/issuable_links/list_service.rb
new file mode 100644
index 00000000000..10a2da7eb03
--- /dev/null
+++ b/app/services/issuable_links/list_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module IssuableLinks
+ class ListService
+ include Gitlab::Routing
+
+ attr_reader :issuable, :current_user
+
+ def initialize(issuable, user)
+ @issuable, @current_user = issuable, user
+ end
+
+ def execute
+ serializer.new(current_user: current_user, issuable: issuable).represent(child_issuables)
+ end
+
+ private
+
+ def serializer
+ raise NotImplementedError
+ end
+
+ def preload_for_collection
+ [{ project: :namespace }, :assignees]
+ end
+ end
+end