Welcome to mirror list, hosted at ThFree Co, Russian Federation.

set_crm_contacts_service.rb « issues « services « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 13fe30b5ac870d0fe04981ddc9a71122b68a414d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# frozen_string_literal: true

module Issues
  class SetCrmContactsService < ::BaseProjectService
    attr_accessor :issue, :errors

    MAX_ADDITIONAL_CONTACTS = 6

    def execute(issue)
      @issue = issue
      @errors = []

      return error_no_permissions unless allowed?
      return error_invalid_params unless valid_params?

      determine_changes if params[:crm_contact_ids]

      return error_too_many if too_many?

      add_contacts if params[:add_crm_contact_ids]
      remove_contacts if params[:remove_crm_contact_ids]

      if issue.valid?
        ServiceResponse.success(payload: issue)
      else
        # The default error isn't very helpful: "Issue customer relations contacts is invalid"
        issue.errors.delete(:issue_customer_relations_contacts)
        issue.errors.add(:issue_customer_relations_contacts, errors.to_sentence)
        ServiceResponse.error(payload: issue, message: issue.errors.full_messages)
      end
    end

    private

    def determine_changes
      existing_contact_ids = issue.issue_customer_relations_contacts.map(&:contact_id)
      params[:add_crm_contact_ids] = params[:crm_contact_ids] - existing_contact_ids
      params[:remove_crm_contact_ids] = existing_contact_ids - params[:crm_contact_ids]
    end

    def add_contacts
      params[:add_crm_contact_ids].uniq.each do |contact_id|
        issue_contact = issue.issue_customer_relations_contacts.create(contact_id: contact_id)

        unless issue_contact.persisted?
          # The validation ensures that the id exists and the user has permission
          errors << "#{contact_id}: The resource that you are attempting to access does not exist or you don't have permission to perform this action"
        end
      end
    end

    def remove_contacts
      issue.issue_customer_relations_contacts
        .where(contact_id: params[:remove_crm_contact_ids]) # rubocop: disable CodeReuse/ActiveRecord
        .delete_all
    end

    def allowed?
      current_user&.can?(:set_issue_crm_contacts, issue)
    end

    def valid_params?
      set_present? ^ add_or_remove_present?
    end

    def set_present?
      params[:crm_contact_ids].present?
    end

    def add_or_remove_present?
      params[:add_crm_contact_ids].present? || params[:remove_crm_contact_ids].present?
    end

    def too_many?
      params[:add_crm_contact_ids] && params[:add_crm_contact_ids].length > MAX_ADDITIONAL_CONTACTS
    end

    def error_no_permissions
      ServiceResponse.error(message: ['You have insufficient permissions to set customer relations contacts for this issue'])
    end

    def error_invalid_params
      ServiceResponse.error(message: ['You cannot combine crm_contact_ids with add_crm_contact_ids or remove_crm_contact_ids'])
    end

    def error_too_many
      ServiceResponse.error(payload: issue, message: ["You can only add up to #{MAX_ADDITIONAL_CONTACTS} contacts at one time"])
    end
  end
end