Commit e4ab5db1 authored by charlie ablett's avatar charlie ablett

Merge branch '225293-emaill-participants' into 'master'

Create IssueEmailParticipant model

Closes #225293

See merge request gitlab-org/gitlab!42943
parents e92d1853 997ee4fa
......@@ -56,6 +56,7 @@ class Issue < ApplicationRecord
dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_many :issue_assignees
has_many :issue_email_participants
has_many :assignees, class_name: "User", through: :issue_assignees
has_many :zoom_meetings
has_many :user_mentions, class_name: "IssueUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
......
# frozen_string_literal: true
class IssueEmailParticipant < ApplicationRecord
belongs_to :issue
validates :email, presence: true, uniqueness: { scope: [:issue_id] }
validates :issue, presence: true
validate :validate_email_format
def validate_email_format
self.errors.add(:email, I18n.t(:invalid, scope: 'valid_email.validations.email')) unless ValidateEmail.valid?(self.email)
end
end
---
title: Add issue_email_participants table and related model
merge_request: 42943
author:
type: other
# frozen_string_literal: true
class CreateIssueEmailParticipants < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless table_exists?(:issue_email_participants)
with_lock_retries do
create_table :issue_email_participants do |t|
t.references :issue, index: false, null: false, foreign_key: { on_delete: :cascade }
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :updated_at, null: false
t.text :email, null: false
t.index [:issue_id, :email], unique: true
end
end
add_text_limit(:issue_email_participants, :email, 255)
end
end
def down
with_lock_retries do
drop_table :issue_email_participants
end
end
end
384d022662437de21b4b3b97bf2f1dec2925be6afe4b62828c97dc9b3b3fc77c
\ No newline at end of file
......@@ -12676,6 +12676,24 @@ CREATE TABLE issue_assignees (
issue_id integer NOT NULL
);
CREATE TABLE issue_email_participants (
id bigint NOT NULL,
issue_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
email text NOT NULL,
CONSTRAINT check_2c321d408d CHECK ((char_length(email) <= 255))
);
CREATE SEQUENCE issue_email_participants_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE issue_email_participants_id_seq OWNED BY issue_email_participants.id;
CREATE TABLE issue_links (
id integer NOT NULL,
source_id integer NOT NULL,
......@@ -17447,6 +17465,8 @@ ALTER TABLE ONLY ip_restrictions ALTER COLUMN id SET DEFAULT nextval('ip_restric
ALTER TABLE ONLY issuable_severities ALTER COLUMN id SET DEFAULT nextval('issuable_severities_id_seq'::regclass);
ALTER TABLE ONLY issue_email_participants ALTER COLUMN id SET DEFAULT nextval('issue_email_participants_id_seq'::regclass);
ALTER TABLE ONLY issue_links ALTER COLUMN id SET DEFAULT nextval('issue_links_id_seq'::regclass);
ALTER TABLE ONLY issue_metrics ALTER COLUMN id SET DEFAULT nextval('issue_metrics_id_seq'::regclass);
......@@ -18565,6 +18585,9 @@ ALTER TABLE ONLY ip_restrictions
ALTER TABLE ONLY issuable_severities
ADD CONSTRAINT issuable_severities_pkey PRIMARY KEY (id);
ALTER TABLE ONLY issue_email_participants
ADD CONSTRAINT issue_email_participants_pkey PRIMARY KEY (id);
ALTER TABLE ONLY issue_links
ADD CONSTRAINT issue_links_pkey PRIMARY KEY (id);
......@@ -20349,6 +20372,8 @@ CREATE UNIQUE INDEX index_issue_assignees_on_issue_id_and_user_id ON issue_assig
CREATE INDEX index_issue_assignees_on_user_id ON issue_assignees USING btree (user_id);
CREATE UNIQUE INDEX index_issue_email_participants_on_issue_id_and_email ON issue_email_participants USING btree (issue_id, email);
CREATE INDEX index_issue_links_on_source_id ON issue_links USING btree (source_id);
CREATE UNIQUE INDEX index_issue_links_on_source_id_and_target_id ON issue_links USING btree (source_id, target_id);
......@@ -22621,6 +22646,9 @@ ALTER TABLE ONLY user_synced_attributes_metadata
ALTER TABLE ONLY project_authorizations
ADD CONSTRAINT fk_rails_0f84bb11f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY issue_email_participants
ADD CONSTRAINT fk_rails_0fdfd8b811 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
ALTER TABLE ONLY merge_request_context_commits
ADD CONSTRAINT fk_rails_0fe0039f60 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
......
# frozen_string_literal: true
FactoryBot.define do
factory :issue_email_participant do
issue
email { generate(:email) }
end
end
......@@ -51,6 +51,7 @@ issues:
- status_page_published_incident
- namespace
- note_authors
- issue_email_participants
events:
- author
- project
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe IssueEmailParticipant do
describe "Associations" do
it { is_expected.to belong_to(:issue) }
end
describe 'Validations' do
subject { build(:issue_email_participant) }
it { is_expected.to validate_presence_of(:issue) }
it { is_expected.to validate_presence_of(:email) }
it { is_expected.to validate_uniqueness_of(:email).scoped_to([:issue_id]) }
it_behaves_like 'an object with RFC3696 compliant email-formated attributes', :email
end
end
......@@ -28,6 +28,7 @@ RSpec.describe Issue do
it { is_expected.to have_and_belong_to_many(:prometheus_alert_events) }
it { is_expected.to have_and_belong_to_many(:self_managed_prometheus_alert_events) }
it { is_expected.to have_many(:prometheus_alerts) }
it { is_expected.to have_many(:issue_email_participants) }
describe 'versions.most_recent' do
it 'returns the most recent version' 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