Commit 380cc55a authored by Lee Tickett's avatar Lee Tickett Committed by Pavel Shutsin

Allow issue contacts from parent groups

Changelog: added
parent 82253cc6
......@@ -25,10 +25,10 @@ class CustomerRelations::Contact < ApplicationRecord
validates :description, length: { maximum: 1024 }
validate :validate_email_format
def self.find_ids_by_emails(group_id, emails)
def self.find_ids_by_emails(group, emails)
raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK
where(group_id: group_id, email: emails)
where(group_id: group.self_and_ancestor_ids, email: emails)
.pluck(:id)
end
......
......@@ -6,7 +6,7 @@ class CustomerRelations::IssueContact < ApplicationRecord
belongs_to :issue, optional: false, inverse_of: :customer_relations_contacts
belongs_to :contact, optional: false, inverse_of: :issue_contacts
validate :contact_belongs_to_issue_group
validate :contact_belongs_to_issue_group_or_ancestor
def self.find_contact_ids_by_emails(issue_id, emails)
raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK
......@@ -18,11 +18,11 @@ class CustomerRelations::IssueContact < ApplicationRecord
private
def contact_belongs_to_issue_group
def contact_belongs_to_issue_group_or_ancestor
return unless contact&.group_id
return unless issue&.project&.namespace_id
return if contact.group_id == issue.project.namespace_id
return if issue.project.group&.self_and_ancestor_ids&.include?(contact.group_id)
errors.add(:base, _('The contact does not belong to the same group as the issue'))
errors.add(:base, _('The contact does not belong to the issue group or an ancestor'))
end
end
......@@ -48,7 +48,7 @@ module Issues
end
def add_by_email
contact_ids = ::CustomerRelations::Contact.find_ids_by_emails(project_group.id, params[:add_emails])
contact_ids = ::CustomerRelations::Contact.find_ids_by_emails(project_group, params[:add_emails])
add_by_id(contact_ids)
end
......
......@@ -35313,7 +35313,7 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
msgid "The contact does not belong to the same group as the issue"
msgid "The contact does not belong to the issue group or an ancestor"
msgstr ""
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
......
......@@ -43,20 +43,27 @@ RSpec.describe CustomerRelations::Contact, type: :model do
let_it_be(:other_contacts) { create_list(:contact, 2) }
it 'returns ids of contacts from group' do
contact_ids = described_class.find_ids_by_emails(group.id, group_contacts.pluck(:email))
contact_ids = described_class.find_ids_by_emails(group, group_contacts.pluck(:email))
expect(contact_ids).to match_array(group_contacts.pluck(:id))
end
it 'returns ids of contacts from parent group' do
subgroup = create(:group, parent: group)
contact_ids = described_class.find_ids_by_emails(subgroup, group_contacts.pluck(:email))
expect(contact_ids).to match_array(group_contacts.pluck(:id))
end
it 'does not return ids of contacts from other groups' do
contact_ids = described_class.find_ids_by_emails(group.id, other_contacts.pluck(:email))
contact_ids = described_class.find_ids_by_emails(group, other_contacts.pluck(:email))
expect(contact_ids).to be_empty
end
it 'raises ArgumentError when called with too many emails' do
too_many_emails = described_class::MAX_PLUCK + 1
expect { described_class.find_ids_by_emails(group.id, Array(0..too_many_emails)) }.to raise_error(ArgumentError)
expect { described_class.find_ids_by_emails(group, Array(0..too_many_emails)) }.to raise_error(ArgumentError)
end
end
end
......@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe CustomerRelations::IssueContact do
let_it_be(:issue_contact, reload: true) { create(:issue_customer_relations_contact) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:project) { create(:project, group: subgroup) }
let_it_be(:issue) { create(:issue, project: project) }
subject { issue_contact }
......@@ -33,17 +34,29 @@ RSpec.describe CustomerRelations::IssueContact do
end
it 'builds using the same group', :aggregate_failures do
expect(for_issue.contact.group).to eq(group)
expect(for_issue.contact.group).to eq(subgroup)
expect(for_contact.issue.project.group).to eq(group)
end
end
describe 'validation' do
let(:built) { build(:issue_customer_relations_contact, issue: create(:issue), contact: create(:contact)) }
it 'fails when the contact group does not belong to the issue group or ancestors' do
built = build(:issue_customer_relations_contact, issue: create(:issue), contact: create(:contact))
it 'fails when the contact group does not match the issue group' do
expect(built).not_to be_valid
end
it 'succeeds when the contact group is the same as the issue group' do
built = build(:issue_customer_relations_contact, issue: create(:issue, project: project), contact: create(:contact, group: subgroup))
expect(built).to be_valid
end
it 'succeeds when the contact group is an ancestor of the issue group' do
built = build(:issue_customer_relations_contact, issue: create(:issue, project: project), contact: create(:contact, group: group))
expect(built).to be_valid
end
end
describe '#self.find_contact_ids_by_emails' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment