diff options
author | Oswaldo Ferreira <oswaldo@gitlab.com> | 2017-06-07 23:05:08 +0300 |
---|---|---|
committer | Oswaldo Ferreira <oswaldo@gitlab.com> | 2017-06-14 03:07:02 +0300 |
commit | 521813f246e31ebe4a406bb340c9df5c55dfa63a (patch) | |
tree | 68e73bea195f93fde107f97df68f0605663a03f9 /app/services | |
parent | 113666a8d5cd4ba891774738af8a11ed04e4db92 (diff) |
Add related issues backend
Diffstat (limited to 'app/services')
-rw-r--r-- | app/services/issue_links/create_service.rb | 47 | ||||
-rw-r--r-- | app/services/issue_links/destroy_service.rb | 28 | ||||
-rw-r--r-- | app/services/issue_links/list_service.rb | 58 | ||||
-rw-r--r-- | app/services/system_note_service.rb | 32 |
4 files changed, 165 insertions, 0 deletions
diff --git a/app/services/issue_links/create_service.rb b/app/services/issue_links/create_service.rb new file mode 100644 index 00000000000..5f938e61280 --- /dev/null +++ b/app/services/issue_links/create_service.rb @@ -0,0 +1,47 @@ +module IssueLinks + class CreateService < BaseService + def initialize(issue, user, params) + @issue, @current_user, @params = issue, user, params.dup + end + + def execute + if referenced_issues.blank? + return error('No Issue found for given reference', 401) + end + + create_issue_links + success + end + + private + + def create_issue_links + referenced_issues.each do |referenced_issue| + create_notes(referenced_issue) if relate_issues(referenced_issue) + end + end + + def relate_issues(referenced_issue) + IssueLink.create(source: @issue, target: referenced_issue) + end + + def create_notes(referenced_issue) + SystemNoteService.relate_issue(@issue, referenced_issue, current_user) + SystemNoteService.relate_issue(referenced_issue, @issue, current_user) + end + + def referenced_issues + @referenced_issues ||= begin + issue_references = params[:issue_references] + text = issue_references.join(' ') + + extractor = Gitlab::ReferenceExtractor.new(@issue.project, @current_user) + extractor.analyze(text) + + extractor.issues.select do |issue| + can?(current_user, :admin_issue_link, issue) + end + end + end + end +end diff --git a/app/services/issue_links/destroy_service.rb b/app/services/issue_links/destroy_service.rb new file mode 100644 index 00000000000..0b08d869c9f --- /dev/null +++ b/app/services/issue_links/destroy_service.rb @@ -0,0 +1,28 @@ +module IssueLinks + class DestroyService < BaseService + def initialize(issue_link, user) + @issue_link = issue_link + @current_user = user + @issue = issue_link.source + @referenced_issue = issue_link.target + end + + def execute + remove_relation + create_notes + + success(message: 'Relation was removed') + end + + private + + def remove_relation + @issue_link.destroy! + end + + def create_notes + SystemNoteService.unrelate_issue(@issue, @referenced_issue, current_user) + SystemNoteService.unrelate_issue(@referenced_issue, @issue, current_user) + end + end +end diff --git a/app/services/issue_links/list_service.rb b/app/services/issue_links/list_service.rb new file mode 100644 index 00000000000..609b125c31d --- /dev/null +++ b/app/services/issue_links/list_service.rb @@ -0,0 +1,58 @@ +module IssueLinks + class ListService + include Gitlab::Routing + + def initialize(issue, user) + @issue, @current_user, @project = issue, user, issue.project + end + + def execute + issues.map do |referenced_issue| + { + id: referenced_issue.id, + title: referenced_issue.title, + state: referenced_issue.state, + reference: referenced_issue.to_reference(@project), + path: namespace_project_issue_path(referenced_issue.project.namespace, referenced_issue.project, referenced_issue.iid), + destroy_relation_path: destroy_relation_path(referenced_issue) + } + end + end + + private + + def issues + related_issues = Issue + .select(['issues.*', 'issue_links.id AS issue_links_id']) + .joins("INNER JOIN issue_links ON + (issue_links.source_id = issues.id AND issue_links.target_id = #{@issue.id}) + OR + (issue_links.target_id = issues.id AND issue_links.source_id = #{@issue.id})") + .preload(project: :namespace) + .reorder('issue_links_id') + + Ability.issues_readable_by_user(related_issues, @current_user) + end + + def destroy_relation_path(issue) + # Make sure the user can admin both the current issue AND the + # referenced issue projects in order to return the removal link. + if can_destroy_issue_link_on_current_project? && can_destroy_issue_link?(issue.project) + namespace_project_issue_link_path(@project.namespace, + @issue.project, + @issue.iid, + issue.issue_links_id) + end + end + + def can_destroy_issue_link_on_current_project? + return @can_destroy_on_current_project if defined?(@can_destroy_on_current_project) + + @can_destroy_on_current_project = can_destroy_issue_link?(@project) + end + + def can_destroy_issue_link?(project) + Ability.allowed?(@current_user, :admin_issue_link, project) + end + end +end diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 01d572e5efd..ac47f42c6c1 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -552,6 +552,38 @@ module SystemNoteService create_note(NoteSummary.new(noteable, project, author, body, action: 'moved')) end + # + # noteable - Noteable object + # noteable_ref - Referenced noteable object + # user - User performing reference + # + # Example Note text: + # + # "marked this issue as related to gitlab-ce#9001" + # + # Returns the created Note object + def relate_issue(noteable, noteable_ref, user) + body = "marked this issue as related to #{noteable_ref.to_reference(noteable.project)}" + + create_note(NoteSummary.new(noteable, noteable.project, user, body, action: 'relate')) + end + + # + # noteable - Noteable object + # noteable_ref - Referenced noteable object + # user - User performing reference + # + # Example Note text: + # + # "removed the relation with gitlab-ce#9001" + # + # Returns the created Note object + def unrelate_issue(noteable, noteable_ref, user) + body = "removed the relation with #{noteable_ref.to_reference(noteable.project)}" + + create_note(NoteSummary.new(noteable, noteable.project, user, body, action: 'unrelate')) + end + # Called when the merge request is approved by user # # noteable - Noteable object |