gitlab-org--gitlab-foss/app/finders/clusters/agent_authorizations_finder.rb

65 lines
2 KiB
Ruby

# frozen_string_literal: true
module Clusters
class AgentAuthorizationsFinder
def initialize(project)
@project = project
end
def execute
# closest, most-specific authorization for a given agent wins
(project_authorizations + implicit_authorizations + group_authorizations)
.uniq(&:agent_id)
end
private
attr_reader :project
def implicit_authorizations
project.cluster_agents.map do |agent|
Clusters::Agents::ImplicitAuthorization.new(agent: agent)
end
end
# rubocop: disable CodeReuse/ActiveRecord
def project_authorizations
ancestor_ids = project.group ? project.ancestors.select(:id) : project.namespace_id
Clusters::Agents::ProjectAuthorization
.where(project_id: project.id)
.joins(agent: :project)
.preload(agent: :project)
.where(cluster_agents: { projects: { namespace_id: ancestor_ids } })
.with_available_ci_access_fields(project)
.to_a
end
def group_authorizations
return [] unless project.group
authorizations = Clusters::Agents::GroupAuthorization.arel_table
ordered_ancestors_cte = Gitlab::SQL::CTE.new(
:ordered_ancestors,
project.group.self_and_ancestors(hierarchy_order: :asc).reselect(:id)
)
cte_join_sources = authorizations.join(ordered_ancestors_cte.table).on(
authorizations[:group_id].eq(ordered_ancestors_cte.table[:id])
).join_sources
Clusters::Agents::GroupAuthorization
.with(ordered_ancestors_cte.to_arel)
.joins(cte_join_sources)
.joins(agent: :project)
.where('projects.namespace_id IN (SELECT id FROM ordered_ancestors)')
.with_available_ci_access_fields(project)
.order(Arel.sql('agent_id, array_position(ARRAY(SELECT id FROM ordered_ancestors)::bigint[], agent_group_authorizations.group_id)'))
.select('DISTINCT ON (agent_id) agent_group_authorizations.*')
.preload(agent: :project)
.to_a
end
# rubocop: enable CodeReuse/ActiveRecord
end
end