From 92b8251ffdc2ca0025a88a12b9fbf78d4330875a Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Mon, 23 Oct 2023 18:34:50 +0200 Subject: [PATCH] Simplify Project.find_package - LinkedProject scope to be able ignore remote project links - Introduces update_project to explicitly avoid the update_instance_or_self trap - Introduces check_access? instance method, the class method is doing things we've already done while instantiating --- src/api/app/models/linked_project.rb | 2 ++ src/api/app/models/package.rb | 4 +++ src/api/app/models/project.rb | 40 +++++++++++++++++----------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/api/app/models/linked_project.rb b/src/api/app/models/linked_project.rb index 5bb982c5474..b65b071c167 100644 --- a/src/api/app/models/linked_project.rb +++ b/src/api/app/models/linked_project.rb @@ -4,6 +4,8 @@ class LinkedProject < ApplicationRecord validate :validate_duplicates + scope :local, -> { where.not(linked_db_project: nil) } + protected def validate_duplicates diff --git a/src/api/app/models/package.rb b/src/api/app/models/package.rb index 42b721c8152..e1f155f17e3 100644 --- a/src/api/app/models/package.rb +++ b/src/api/app/models/package.rb @@ -276,6 +276,10 @@ def check_source_access? true end + def check_access? + Project.check_access?(project) + end + def check_source_access! return if check_source_access? # TODO: Use pundit for authorization instead diff --git a/src/api/app/models/project.rb b/src/api/app/models/project.rb index 30b9173e62a..6badb2c8c9b 100644 --- a/src/api/app/models/project.rb +++ b/src/api/app/models/project.rb @@ -548,6 +548,19 @@ def update_instance_or_self(namespace = 'OBS', name = 'UpdateProject') self end + # Find the project defined in the OBS:UpdateProject attribute + def update_project + attribute = find_attribute('OBS', 'UpdateProject') + return unless attribute + return if attribute.values.first.value.empty? + + update_project_name = attribute.values.first.value + project = Project.find_by(name: update_project_name) + return project if project + + raise Project::Errors::UnknownObjectError, "Update project configured in #{name} but not found: #{update_project_name}" + end + def cleanup_linking_repos # replace links to this project repositories with links to the "deleted" repository find_repos(:linking_repositories) do |linking_repository| @@ -814,25 +827,16 @@ def find_package(package_name, check_update_project = nil, processed = {}) end processed[self] = 1 - # package exists in this project - pkg = nil - pkg = update_instance_or_self.packages.find_by_name(package_name) if check_update_project - pkg = packages.find_by_name(package_name) if pkg.nil? - return pkg if pkg && Package.check_access?(pkg) + pkg = find_package_on_update_project(package_name) if check_update_project + pkg ||= packages.find_by(name: package_name) + return pkg if pkg&.check_access? # search via all linked projects - linking_to.each do |lp| + linking_to.local.each do |lp| raise CycleError, 'project links against itself, this is not allowed' if self == lp.linked_db_project - pkg = if lp.linked_db_project.nil? - # We can't get a package object from a remote instance ... how shall we handle this ? - nil - else - lp.linked_db_project.find_package(package_name, check_update_project, processed) - end - unless pkg.nil? - return pkg if Package.check_access?(pkg) - end + pkg = lp.linked_db_project.find_package(package_name, check_update_project, processed) + return pkg if pkg&.check_access? end # no package found @@ -840,6 +844,12 @@ def find_package(package_name, check_update_project = nil, processed = {}) nil end + def find_package_on_update_project(package_name) + return unless update_project + + update_project.packages.find_by(name: package_name) + end + def expand_all_repositories repositories.collect(&:expand_all_repositories).flatten.uniq end