From 3cccd102ba543e02725d247893729e5c73b38295 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 20 Apr 2022 10:00:54 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-10-stable-ee --- app/models/customer_relations/contact.rb | 32 ++++++++++++++++++++++++-- app/models/customer_relations/issue_contact.rb | 16 ++++++++++--- app/models/customer_relations/organization.rb | 28 ++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) (limited to 'app/models/customer_relations') diff --git a/app/models/customer_relations/contact.rb b/app/models/customer_relations/contact.rb index 4fa2c3fb8cf..cdb449e00bf 100644 --- a/app/models/customer_relations/contact.rb +++ b/app/models/customer_relations/contact.rb @@ -23,7 +23,7 @@ class CustomerRelations::Contact < ApplicationRecord validates :last_name, presence: true, length: { maximum: 255 } validates :email, length: { maximum: 255 } validates :description, length: { maximum: 1024 } - validates :email, uniqueness: { scope: :group_id } + validates :email, uniqueness: { case_sensitive: false, scope: :group_id } validate :validate_email_format validate :validate_root_group @@ -42,7 +42,7 @@ class CustomerRelations::Contact < ApplicationRecord def self.find_ids_by_emails(group, emails) raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK - where(group: group, email: emails).pluck(:id) + where(group: group).where('lower(email) in (?)', emails.map(&:downcase)).pluck(:id) end def self.exists_for_group?(group) @@ -51,6 +51,34 @@ class CustomerRelations::Contact < ApplicationRecord exists?(group: group) end + def self.move_to_root_group(group) + update_query = <<~SQL + UPDATE #{CustomerRelations::IssueContact.table_name} + SET contact_id = new_contacts.id + FROM #{table_name} AS existing_contacts + JOIN #{table_name} AS new_contacts ON new_contacts.group_id = :old_group_id AND LOWER(new_contacts.email) = LOWER(existing_contacts.email) + WHERE existing_contacts.group_id = :new_group_id AND contact_id = existing_contacts.id + SQL + connection.execute(sanitize_sql([ + update_query, + old_group_id: group.root_ancestor.id, + new_group_id: group.id + ])) + + dupes_query = <<~SQL + DELETE FROM #{table_name} AS existing_contacts + USING #{table_name} AS new_contacts + WHERE existing_contacts.group_id = :new_group_id AND new_contacts.group_id = :old_group_id AND LOWER(new_contacts.email) = LOWER(existing_contacts.email) + SQL + connection.execute(sanitize_sql([ + dupes_query, + old_group_id: group.root_ancestor.id, + new_group_id: group.id + ])) + + where(group: group).update_all(group_id: group.root_ancestor.id) + end + private def validate_email_format diff --git a/app/models/customer_relations/issue_contact.rb b/app/models/customer_relations/issue_contact.rb index dc7a3fd87bc..70a30e583d5 100644 --- a/app/models/customer_relations/issue_contact.rb +++ b/app/models/customer_relations/issue_contact.rb @@ -8,6 +8,8 @@ class CustomerRelations::IssueContact < ApplicationRecord validate :contact_belongs_to_root_group + BATCH_DELETE_SIZE = 1_000 + def self.find_contact_ids_by_emails(issue_id, emails) raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK @@ -17,9 +19,17 @@ class CustomerRelations::IssueContact < ApplicationRecord end def self.delete_for_project(project_id) - joins(:issue) - .where(issues: { project_id: project_id }) - .delete_all + loop do + deleted_records = joins(:issue).where(issues: { project_id: project_id }).limit(BATCH_DELETE_SIZE).delete_all + break if deleted_records == 0 + end + end + + def self.delete_for_group(group) + loop do + deleted_records = joins(issue: :project).where(projects: { namespace: group.self_and_descendants }).limit(BATCH_DELETE_SIZE).delete_all + break if deleted_records == 0 + end end private diff --git a/app/models/customer_relations/organization.rb b/app/models/customer_relations/organization.rb index a23b9d8fe28..32adcc7492b 100644 --- a/app/models/customer_relations/organization.rb +++ b/app/models/customer_relations/organization.rb @@ -26,6 +26,34 @@ class CustomerRelations::Organization < ApplicationRecord .where('LOWER(name) = LOWER(?)', name) end + def self.move_to_root_group(group) + update_query = <<~SQL + UPDATE #{CustomerRelations::Contact.table_name} + SET organization_id = new_organizations.id + FROM #{table_name} AS existing_organizations + JOIN #{table_name} AS new_organizations ON new_organizations.group_id = :old_group_id AND LOWER(new_organizations.name) = LOWER(existing_organizations.name) + WHERE existing_organizations.group_id = :new_group_id AND organization_id = existing_organizations.id + SQL + connection.execute(sanitize_sql([ + update_query, + old_group_id: group.root_ancestor.id, + new_group_id: group.id + ])) + + dupes_query = <<~SQL + DELETE FROM #{table_name} AS existing_organizations + USING #{table_name} AS new_organizations + WHERE existing_organizations.group_id = :new_group_id AND new_organizations.group_id = :old_group_id AND LOWER(new_organizations.name) = LOWER(existing_organizations.name) + SQL + connection.execute(sanitize_sql([ + dupes_query, + old_group_id: group.root_ancestor.id, + new_group_id: group.id + ])) + + where(group: group).update_all(group_id: group.root_ancestor.id) + end + private def validate_root_group -- cgit v1.2.1