diff options
Diffstat (limited to 'app/models/ci/catalog/resource.rb')
-rw-r--r-- | app/models/ci/catalog/resource.rb | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/app/models/ci/catalog/resource.rb b/app/models/ci/catalog/resource.rb index f947c5158cf..d1b3a3a4d8a 100644 --- a/app/models/ci/catalog/resource.rb +++ b/app/models/ci/catalog/resource.rb @@ -8,7 +8,8 @@ module Ci # dependency on the Project model and its need to join with that table # in order to generate the CI/CD catalog. class Resource < ::ApplicationRecord - include Gitlab::SQL::Pattern + include PgFullTextSearchable + include Gitlab::VisibilityLevel self.table_name = 'catalog_resources' @@ -17,9 +18,14 @@ module Ci inverse_of: :catalog_resource has_many :versions, class_name: 'Ci::Catalog::Resources::Version', foreign_key: :catalog_resource_id, inverse_of: :catalog_resource + has_many :sync_events, class_name: 'Ci::Catalog::Resources::SyncEvent', foreign_key: :catalog_resource_id, + inverse_of: :catalog_resource scope :for_projects, ->(project_ids) { where(project_id: project_ids) } - scope :search, ->(query) { fuzzy_search(query, [:name, :description], use_minimum_char_limit: false) } + + # The `search_vector` column contains a tsvector that has a greater weight on `name` than `description`. + # The vector is automatically generated by the database when `name` or `description` is updated. + scope :search, ->(query) { pg_full_text_search_in_model(query) } scope :order_by_created_at_desc, -> { reorder(created_at: :desc) } scope :order_by_created_at_asc, -> { reorder(created_at: :asc) } @@ -28,14 +34,38 @@ module Ci scope :order_by_latest_released_at_desc, -> { reorder(arel_table[:latest_released_at].desc.nulls_last) } scope :order_by_latest_released_at_asc, -> { reorder(arel_table[:latest_released_at].asc.nulls_last) } - delegate :avatar_path, :star_count, :forks_count, to: :project + delegate :avatar_path, :star_count, :full_path, to: :project enum state: { draft: 0, published: 1 } before_create :sync_with_project - def unpublish! - update!(state: :draft) + class << self + def public_or_visible_to_user(user) + return public_to_user unless user + + where( + 'EXISTS (?) OR catalog_resources.visibility_level IN (?)', + user.authorizations_for_projects(related_project_column: 'catalog_resources.project_id'), + Gitlab::VisibilityLevel.levels_for_user(user) + ) + end + + def visible_to_user(user) + return none unless user + + where_exists(user.authorizations_for_projects(related_project_column: 'catalog_resources.project_id')) + end + + # Used by Ci::ProcessSyncEventsService + def sync!(event) + # There may be orphaned records since this table does not enforce FKs + event.catalog_resource&.sync_with_project! + end + end + + def to_param + full_path end def publish! @@ -47,12 +77,21 @@ module Ci save! end + # Triggered in Ci::Catalog::Resources::Version and Release model callbacks + def update_latest_released_at! + update!(latest_released_at: versions.latest&.released_at) + end + + # Required for Gitlab::VisibilityLevel module + def visibility_level_field + :visibility_level + end + private - # These columns are denormalized from the `projects` table. We first sync these - # columns when the catalog resource record is created. Then any updates to the - # `projects` columns will be synced to the `catalog_resources` table by a worker - # (to be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/429376.) + # These denormalized columns are first synced when a new catalog resource is created. + # A PG trigger adds a SyncEvent when the associated project updates any of these columns. + # A worker processes the SyncEvents with Ci::ProcessSyncEventsService. def sync_with_project self.name = project.name self.description = project.description |