From 177339a7f54d6714214015c62d482b2302298b29 Mon Sep 17 00:00:00 2001 From: Eugenia Grieff <egrieff@gitlab.com> Date: Fri, 6 Oct 2023 00:42:03 +0000 Subject: [PATCH] Add work items related link restrictions table Adds table which will be used for storing related links restrictions for work item types. Changelog: added --- app/models/concerns/enums/issuable_link.rb | 12 +++++++ app/models/concerns/issuable_link.rb | 5 ++- .../work_items/related_link_restriction.rb | 16 ++++++++++ .../work_item_related_link_restrictions.yml | 10 ++++++ ...930094139_add_related_link_restrictions.rb | 21 +++++++++++++ db/schema_migrations/20230930094139 | 1 + db/structure.sql | 31 +++++++++++++++++++ ee/app/models/concerns/ee/issuable_link.rb | 1 + .../work_items/related_link_restrictions.rb | 9 ++++++ .../related_link_restriction_spec.rb | 22 +++++++++++++ 10 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 app/models/concerns/enums/issuable_link.rb create mode 100644 app/models/work_items/related_link_restriction.rb create mode 100644 db/docs/work_item_related_link_restrictions.yml create mode 100644 db/migrate/20230930094139_add_related_link_restrictions.rb create mode 100644 db/schema_migrations/20230930094139 create mode 100644 spec/factories/work_items/related_link_restrictions.rb create mode 100644 spec/models/work_items/related_link_restriction_spec.rb diff --git a/app/models/concerns/enums/issuable_link.rb b/app/models/concerns/enums/issuable_link.rb new file mode 100644 index 0000000000000..ca5728c26001e --- /dev/null +++ b/app/models/concerns/enums/issuable_link.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Enums + module IssuableLink + TYPE_RELATES_TO = 'relates_to' + TYPE_BLOCKS = 'blocks' + + def self.link_types + { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1 } + end + end +end diff --git a/app/models/concerns/issuable_link.rb b/app/models/concerns/issuable_link.rb index 4a922d3c2ea9e..dcd2705185f0c 100644 --- a/app/models/concerns/issuable_link.rb +++ b/app/models/concerns/issuable_link.rb @@ -10,8 +10,7 @@ module IssuableLink extend ActiveSupport::Concern MAX_LINKS_COUNT = 100 - TYPE_RELATES_TO = 'relates_to' - TYPE_BLOCKS = 'blocks' ## EE-only. Kept here to be used on link_type enum. + TYPE_RELATES_TO = Enums::IssuableLink::TYPE_RELATES_TO class_methods do def inverse_link_type(type) @@ -43,7 +42,7 @@ def available_link_types scope :for_source_or_target, ->(issuable) { where(source: issuable).or(where(target: issuable)) } - enum link_type: { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1 } + enum link_type: Enums::IssuableLink.link_types private diff --git a/app/models/work_items/related_link_restriction.rb b/app/models/work_items/related_link_restriction.rb new file mode 100644 index 0000000000000..d4a66c95ffb95 --- /dev/null +++ b/app/models/work_items/related_link_restriction.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module WorkItems + class RelatedLinkRestriction < ApplicationRecord + self.table_name = 'work_item_related_link_restrictions' + + belongs_to :source_type, class_name: 'WorkItems::Type' + belongs_to :target_type, class_name: 'WorkItems::Type' + + validates :source_type, presence: true + validates :target_type, presence: true + validates :target_type, uniqueness: { scope: [:source_type_id, :link_type] } + + enum link_type: Enums::IssuableLink.link_types + end +end diff --git a/db/docs/work_item_related_link_restrictions.yml b/db/docs/work_item_related_link_restrictions.yml new file mode 100644 index 0000000000000..1f76b0482be01 --- /dev/null +++ b/db/docs/work_item_related_link_restrictions.yml @@ -0,0 +1,10 @@ +--- +table_name: work_item_related_link_restrictions +classes: + - WorkItems::RelatedLinkRestriction +feature_categories: + - portfolio_management +description: Restrictions applied to related links. +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133044 +milestone: '16.5' +gitlab_schema: gitlab_main diff --git a/db/migrate/20230930094139_add_related_link_restrictions.rb b/db/migrate/20230930094139_add_related_link_restrictions.rb new file mode 100644 index 0000000000000..e67f32b860cfb --- /dev/null +++ b/db/migrate/20230930094139_add_related_link_restrictions.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AddRelatedLinkRestrictions < Gitlab::Database::Migration[2.1] + UNIQUE_INDEX_NAME = 'index_work_item_link_restrictions_on_source_link_type_target' + + def up + create_table :work_item_related_link_restrictions do |t| + t.references :source_type, index: false, null: false, + foreign_key: { on_delete: :cascade, to_table: :work_item_types } + t.references :target_type, index: true, null: false, + foreign_key: { on_delete: :cascade, to_table: :work_item_types } + t.integer :link_type, null: false, limit: 2, default: 0 + + t.index [:source_type_id, :link_type, :target_type_id], unique: true, name: UNIQUE_INDEX_NAME + end + end + + def down + drop_table :work_item_related_link_restrictions + end +end diff --git a/db/schema_migrations/20230930094139 b/db/schema_migrations/20230930094139 new file mode 100644 index 0000000000000..d076adbb7f781 --- /dev/null +++ b/db/schema_migrations/20230930094139 @@ -0,0 +1 @@ +e5a56945b0f18c1014905534f6ac8cbd026582bb57b49368558435331f0746de \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index bc5b2b20a8482..3486dfa3d0c0c 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -25139,6 +25139,22 @@ CREATE TABLE work_item_progresses ( last_reminder_sent_at timestamp with time zone ); +CREATE TABLE work_item_related_link_restrictions ( + id bigint NOT NULL, + source_type_id bigint NOT NULL, + target_type_id bigint NOT NULL, + link_type smallint DEFAULT 0 NOT NULL +); + +CREATE SEQUENCE work_item_related_link_restrictions_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE work_item_related_link_restrictions_id_seq OWNED BY work_item_related_link_restrictions.id; + CREATE TABLE work_item_types ( id bigint NOT NULL, base_type smallint DEFAULT 0 NOT NULL, @@ -26923,6 +26939,8 @@ ALTER TABLE ONLY work_item_hierarchy_restrictions ALTER COLUMN id SET DEFAULT ne ALTER TABLE ONLY work_item_parent_links ALTER COLUMN id SET DEFAULT nextval('work_item_parent_links_id_seq'::regclass); +ALTER TABLE ONLY work_item_related_link_restrictions ALTER COLUMN id SET DEFAULT nextval('work_item_related_link_restrictions_id_seq'::regclass); + ALTER TABLE ONLY work_item_types ALTER COLUMN id SET DEFAULT nextval('work_item_types_id_seq'::regclass); ALTER TABLE ONLY work_item_widget_definitions ALTER COLUMN id SET DEFAULT nextval('work_item_widget_definitions_id_seq'::regclass); @@ -29570,6 +29588,9 @@ ALTER TABLE ONLY work_item_parent_links ALTER TABLE ONLY work_item_progresses ADD CONSTRAINT work_item_progresses_pkey PRIMARY KEY (issue_id); +ALTER TABLE ONLY work_item_related_link_restrictions + ADD CONSTRAINT work_item_related_link_restrictions_pkey PRIMARY KEY (id); + ALTER TABLE ONLY work_item_types ADD CONSTRAINT work_item_types_pkey PRIMARY KEY (id); @@ -34641,10 +34662,14 @@ CREATE UNIQUE INDEX index_work_item_hierarchy_restrictions_on_parent_and_child O CREATE INDEX index_work_item_hierarchy_restrictions_on_parent_type_id ON work_item_hierarchy_restrictions USING btree (parent_type_id); +CREATE UNIQUE INDEX index_work_item_link_restrictions_on_source_link_type_target ON work_item_related_link_restrictions USING btree (source_type_id, link_type, target_type_id); + CREATE UNIQUE INDEX index_work_item_parent_links_on_work_item_id ON work_item_parent_links USING btree (work_item_id); CREATE INDEX index_work_item_parent_links_on_work_item_parent_id ON work_item_parent_links USING btree (work_item_parent_id); +CREATE INDEX index_work_item_related_link_restrictions_on_target_type_id ON work_item_related_link_restrictions USING btree (target_type_id); + CREATE INDEX index_work_item_types_on_base_type_and_id ON work_item_types USING btree (base_type, id); CREATE UNIQUE INDEX index_work_item_widget_definitions_on_default_witype_and_name ON work_item_widget_definitions USING btree (work_item_type_id, name) WHERE (namespace_id IS NULL); @@ -38175,6 +38200,9 @@ ALTER TABLE ONLY merge_request_assignees ALTER TABLE ONLY packages_dependency_links ADD CONSTRAINT fk_rails_4437bf4070 FOREIGN KEY (dependency_id) REFERENCES packages_dependencies(id) ON DELETE CASCADE; +ALTER TABLE ONLY work_item_related_link_restrictions + ADD CONSTRAINT fk_rails_4513f0061c FOREIGN KEY (target_type_id) REFERENCES work_item_types(id) ON DELETE CASCADE; + ALTER TABLE ONLY project_auto_devops ADD CONSTRAINT fk_rails_45436b12b2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; @@ -38925,6 +38953,9 @@ ALTER TABLE ONLY pool_repositories ALTER TABLE ONLY vulnerability_statistics ADD CONSTRAINT fk_rails_af61a7df4c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; +ALTER TABLE ONLY work_item_related_link_restrictions + ADD CONSTRAINT fk_rails_b013a0fa65 FOREIGN KEY (source_type_id) REFERENCES work_item_types(id) ON DELETE CASCADE; + ALTER TABLE ONLY resource_label_events ADD CONSTRAINT fk_rails_b126799f57 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE SET NULL; diff --git a/ee/app/models/concerns/ee/issuable_link.rb b/ee/app/models/concerns/ee/issuable_link.rb index 07808dc9efe7a..3a89dfb3e9469 100644 --- a/ee/app/models/concerns/ee/issuable_link.rb +++ b/ee/app/models/concerns/ee/issuable_link.rb @@ -8,6 +8,7 @@ module IssuableLink # we don't store is_blocked_by in the db but need it for displaying the relation # from the target TYPE_IS_BLOCKED_BY = 'is_blocked_by' + TYPE_BLOCKS = ::Enums::IssuableLink::TYPE_BLOCKS end class_methods do diff --git a/spec/factories/work_items/related_link_restrictions.rb b/spec/factories/work_items/related_link_restrictions.rb new file mode 100644 index 0000000000000..b1e2547f00428 --- /dev/null +++ b/spec/factories/work_items/related_link_restrictions.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :related_link_restriction, class: 'WorkItems::RelatedLinkRestriction' do + source_type { association :work_item_type, :default } + target_type { association :work_item_type, :default } + link_type { 0 } + end +end diff --git a/spec/models/work_items/related_link_restriction_spec.rb b/spec/models/work_items/related_link_restriction_spec.rb new file mode 100644 index 0000000000000..1dc2286c0bf61 --- /dev/null +++ b/spec/models/work_items/related_link_restriction_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe WorkItems::RelatedLinkRestriction, feature_category: :portfolio_management do + describe 'associations' do + it { is_expected.to belong_to(:source_type) } + it { is_expected.to belong_to(:target_type) } + end + + describe 'validations' do + subject { build(:related_link_restriction) } + + it { is_expected.to validate_presence_of(:source_type) } + it { is_expected.to validate_presence_of(:target_type) } + it { is_expected.to validate_uniqueness_of(:target_type).scoped_to([:source_type_id, :link_type]) } + end + + describe '.link_type' do + it { is_expected.to define_enum_for(:link_type).with_values(relates_to: 0, blocks: 1) } + end +end -- GitLab