summaryrefslogtreecommitdiff
path: root/app/services/issuable_base_service.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/issuable_base_service.rb')
-rw-r--r--app/services/issuable_base_service.rb74
1 files changed, 65 insertions, 9 deletions
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 094b31b4ad6..add53bc6267 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -29,32 +29,48 @@ class IssuableBaseService < BaseService
params.delete(:label_ids)
params.delete(:assignee_ids)
params.delete(:assignee_id)
+ params.delete(:add_assignee_ids)
+ params.delete(:remove_assignee_ids)
params.delete(:due_date)
params.delete(:canonical_issue_id)
params.delete(:project)
params.delete(:discussion_locked)
end
- filter_assignee(issuable)
+ filter_assignees(issuable)
filter_milestone
filter_labels
end
- def filter_assignee(issuable)
- return if params[:assignee_ids].blank?
+ def filter_assignees(issuable)
+ filter_assignees_with_key(issuable, :assignee_ids, :assignees)
+ filter_assignees_with_key(issuable, :add_assignee_ids, :add_assignees)
+ filter_assignees_with_key(issuable, :remove_assignee_ids, :remove_assignees)
+ end
+
+ def filter_assignees_with_key(issuable, id_key, key)
+ if params[key] && params[id_key].blank?
+ params[id_key] = params[key].map(&:id)
+ end
+
+ return if params[id_key].blank?
+
+ filter_assignees_using_checks(issuable, id_key)
+ end
+ def filter_assignees_using_checks(issuable, id_key)
unless issuable.allows_multiple_assignees?
- params[:assignee_ids] = params[:assignee_ids].first(1)
+ params[id_key] = params[id_key].first(1)
end
- assignee_ids = params[:assignee_ids].select { |assignee_id| user_can_read?(issuable, assignee_id) }
+ assignee_ids = params[id_key].select { |assignee_id| user_can_read?(issuable, assignee_id) }
- if params[:assignee_ids].map(&:to_s) == [IssuableFinder::Params::NONE]
- params[:assignee_ids] = []
+ if params[id_key].map(&:to_s) == [IssuableFinder::Params::NONE]
+ params[id_key] = []
elsif assignee_ids.any?
- params[:assignee_ids] = assignee_ids
+ params[id_key] = assignee_ids
else
- params.delete(:assignee_ids)
+ params.delete(id_key)
end
end
@@ -116,6 +132,15 @@ class IssuableBaseService < BaseService
new_label_ids.uniq
end
+ def process_assignee_ids(attributes, existing_assignee_ids: nil, extra_assignee_ids: [])
+ process = Issuable::ProcessAssignees.new(assignee_ids: attributes.delete(:assignee_ids),
+ add_assignee_ids: attributes.delete(:add_assignee_ids),
+ remove_assignee_ids: attributes.delete(:remove_assignee_ids),
+ existing_assignee_ids: existing_assignee_ids,
+ extra_assignee_ids: extra_assignee_ids)
+ process.execute
+ end
+
def handle_quick_actions(issuable)
merge_quick_actions_into_params!(issuable)
end
@@ -145,6 +170,10 @@ class IssuableBaseService < BaseService
params[:author] ||= current_user
params[:label_ids] = process_label_ids(params, extra_label_ids: issuable.label_ids.to_a)
+ if issuable.respond_to?(:assignee_ids)
+ params[:assignee_ids] = process_assignee_ids(params, extra_assignee_ids: issuable.assignee_ids.to_a)
+ end
+
issuable.assign_attributes(params)
before_create(issuable)
@@ -191,6 +220,7 @@ class IssuableBaseService < BaseService
old_associations = associations_before_update(issuable)
assign_requested_labels(issuable)
+ assign_requested_assignees(issuable)
if issuable.changed? || params.present?
issuable.assign_attributes(params)
@@ -354,6 +384,16 @@ class IssuableBaseService < BaseService
issuable.touch
end
+ def assign_requested_assignees(issuable)
+ return if issuable.is_a?(Epic)
+
+ assignee_ids = process_assignee_ids(params, existing_assignee_ids: issuable.assignee_ids)
+ if ids_changing?(issuable.assignee_ids, assignee_ids)
+ params[:assignee_ids] = assignee_ids
+ issuable.touch
+ end
+ end
+
# Arrays of ids are used, but we should really use sets of ids, so
# let's have an helper to properly check if some ids are changing
def ids_changing?(old_array, new_array)
@@ -384,6 +424,20 @@ class IssuableBaseService < BaseService
associations
end
+ def handle_move_between_ids(issuable_position)
+ return unless params[:move_between_ids]
+
+ after_id, before_id = params.delete(:move_between_ids)
+ positioning_scope_id = params.delete(positioning_scope_key)
+
+ issuable_before = issuable_for_positioning(before_id, positioning_scope_id)
+ issuable_after = issuable_for_positioning(after_id, positioning_scope_id)
+
+ raise ActiveRecord::RecordNotFound unless issuable_before || issuable_after
+
+ issuable_position.move_between(issuable_before, issuable_after)
+ end
+
def has_changes?(issuable, old_labels: [], old_assignees: [], old_reviewers: [])
valid_attrs = [:title, :description, :assignee_ids, :reviewer_ids, :milestone_id, :target_branch]
@@ -429,6 +483,8 @@ class IssuableBaseService < BaseService
# we need to check this because milestone from milestone_id param is displayed on "new" page
# where private project milestone could leak without this check
def ensure_milestone_available(issuable)
+ return unless issuable.supports_milestone? && issuable.milestone_id.present?
+
issuable.milestone_id = nil unless issuable.milestone_available?
end