Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/project_authorizations.rb')
-rw-r--r--lib/gitlab/project_authorizations.rb140
1 files changed, 89 insertions, 51 deletions
diff --git a/lib/gitlab/project_authorizations.rb b/lib/gitlab/project_authorizations.rb
index c770260a66e..0fcb8321dae 100644
--- a/lib/gitlab/project_authorizations.rb
+++ b/lib/gitlab/project_authorizations.rb
@@ -12,62 +12,56 @@ module Gitlab
end
def calculate
- cte = if Feature.enabled?(:linear_project_authorization, user)
- linear_cte
- else
- recursive_cte
- end
-
- cte_alias = cte.table.alias(Group.table_name)
- projects = Project.arel_table
- links = ProjectGroupLink.arel_table
-
- relations = [
- # The project a user has direct access to.
- user.projects_with_active_memberships.select_for_project_authorization,
-
- # The personal projects of the user.
- user.personal_projects.select_project_owner_for_project_authorization,
+ if Feature.enabled?(:compare_project_authorization_linear_cte, user)
+ linear_relation = calculate_with_linear_query
+ recursive_relation = calculate_with_recursive_query
+ recursive_set = Set.new(recursive_relation.to_a.pluck(:project_id, :access_level))
+ linear_set = Set.new(linear_relation.to_a.pluck(:project_id, :access_level))
+ if linear_set == recursive_set
+ Gitlab::AppJsonLogger.info(event: 'linear_authorized_projects_check',
+ user_id: user.id,
+ matching_results: true)
+ return calculate_with_linear_query
+ else
+ Gitlab::AppJsonLogger.warn(event: 'linear_authorized_projects_check',
+ user_id: user.id,
+ matching_results: false)
+ end
+ end
- # Projects that belong directly to any of the groups the user has
- # access to.
- Namespace
- .unscoped
- .select([alias_as_column(projects[:id], 'project_id'),
- cte_alias[:access_level]])
- .from(cte_alias)
- .joins(:projects),
-
- # Projects shared with any of the namespaces the user has access to.
- Namespace
- .unscoped
- .select([
- links[:project_id],
- least(cte_alias[:access_level], links[:group_access], 'access_level')
- ])
- .from(cte_alias)
- .joins('INNER JOIN project_group_links ON project_group_links.group_id = namespaces.id')
- .joins('INNER JOIN projects ON projects.id = project_group_links.project_id')
- .joins('INNER JOIN namespaces p_ns ON p_ns.id = projects.namespace_id')
- .where('p_ns.share_with_group_lock IS FALSE')
- ]
+ Gitlab::AppJsonLogger.info(event: 'linear_authorized_projects_check_with_flag',
+ feature_flag_status: Feature.enabled?(:linear_project_authorization, user))
if Feature.enabled?(:linear_project_authorization, user)
- ProjectAuthorization
- .unscoped
- .with(cte.to_arel)
- .select_from_union(relations)
+ calculate_with_linear_query
else
- ProjectAuthorization
- .unscoped
- .with
- .recursive(cte.to_arel)
- .select_from_union(relations)
+ calculate_with_recursive_query
end
end
private
+ def calculate_with_linear_query
+ cte = linear_cte
+ cte_alias = cte.table.alias(Group.table_name)
+
+ ProjectAuthorization
+ .unscoped
+ .with(cte.to_arel)
+ .select_from_union(relations(cte_alias: cte_alias))
+ end
+
+ def calculate_with_recursive_query
+ cte = recursive_cte
+ cte_alias = cte.table.alias(Group.table_name)
+
+ ProjectAuthorization
+ .unscoped
+ .with
+ .recursive(cte.to_arel)
+ .select_from_union(relations(cte_alias: cte_alias))
+ end
+
# Builds a recursive CTE that gets all the groups the current user has
# access to, including any nested groups and any shared groups.
def recursive_cte
@@ -83,9 +77,11 @@ module Gitlab
# Namespaces shared with any of the group
cte << Group.select([namespaces[:id],
- least(members[:access_level],
- group_group_links[:group_access],
- 'access_level')])
+ least(
+ members[:access_level],
+ group_group_links[:group_access],
+ 'access_level'
+ )])
.joins(join_group_group_links)
.joins(join_members_on_group_group_links)
@@ -120,7 +116,9 @@ module Gitlab
.merge(user.group_members)
.merge(GroupMember.active_state)
- union = Namespace.from_union([shared_groups, member_groups_with_ancestors])
+ union = Namespace
+ .select("namespaces.id, access_level")
+ .from_union([shared_groups, member_groups_with_ancestors])
Gitlab::SQL::CTE.new(:linear_namespaces_cte, union)
end
@@ -185,5 +183,45 @@ module Gitlab
def alias_as_column(value, alias_to)
Arel::Nodes::As.new(value, Arel::Nodes::SqlLiteral.new(alias_to))
end
+
+ def relations(cte_alias:)
+ [
+ user.projects_with_active_memberships.select_for_project_authorization,
+ user.personal_projects.select_project_owner_for_project_authorization,
+ projects_belonging_directy_to_any_groups_user_has_access_to(cte_alias: cte_alias),
+ projects_shared_with_namespaces_user_has_access_to(cte_alias: cte_alias)
+ ]
+ end
+
+ def projects_shared_with_namespaces_user_has_access_to(cte_alias:)
+ Namespace
+ .unscoped
+ .select([
+ links[:project_id],
+ least(cte_alias[:access_level], links[:group_access], 'access_level')
+ ])
+ .from(cte_alias)
+ .joins('INNER JOIN project_group_links ON project_group_links.group_id = namespaces.id')
+ .joins('INNER JOIN projects ON projects.id = project_group_links.project_id')
+ .joins('INNER JOIN namespaces p_ns ON p_ns.id = projects.namespace_id')
+ .where('p_ns.share_with_group_lock IS FALSE')
+ end
+
+ def projects_belonging_directy_to_any_groups_user_has_access_to(cte_alias:)
+ Namespace
+ .unscoped
+ .select([alias_as_column(projects[:id], 'project_id'),
+ cte_alias[:access_level]])
+ .from(cte_alias)
+ .joins(:projects)
+ end
+
+ def projects
+ Project.arel_table
+ end
+
+ def links
+ ProjectGroupLink.arel_table
+ end
end
end