Commit 004a62ef authored by Yorick Peterse's avatar Yorick Peterse Committed by Andreas Brandl
Browse files

Revert Project.public_or_visible_to_user changes

These changes were introduced in MR In we discovered
these changes lead to a pretty drastic increase in SQL response timings.

We'll revert these changes so we can work on a better solution in the
mean time without (or other installations) experiecing
reduced performance in the mean time.
parent d2c93fe7ab42
......@@ -62,9 +62,8 @@ def feature_available_projects
# Don't return any project related snippets if the user cannot read cross project
return table[:id].eq(nil) unless Ability.allowed?(current_user, :read_cross_project)
projects = Project.public_or_visible_to_user(current_user, use_where_in: false) do |part|
part.with_feature_available_for_user(:snippets, current_user)
projects = Project.public_or_visible_to_user(current_user)
.with_feature_available_for_user(:snippets, current_user).select(:id)
arel_query =
......@@ -317,42 +317,18 @@ class Project < ActiveRecord::Base
# Returns a collection of projects that is either public or visible to the
# logged in user.
# A caller may pass in a block to modify individual parts of
# the query, e.g. to apply .with_feature_available_for_user on top of it.
# This is useful for performance as we can stick those additional filters
# at the bottom of e.g. the UNION.
# Optionally, turning `use_where_in` off leads to returning a
# relation using #from instead of #where. This can perform much better
# but leads to trouble when used in conjunction with AR's #merge method.
def self.public_or_visible_to_user(user = nil, use_where_in: true, &block)
# If we don't get a block passed, use identity to avoid if/else repetitions
block = ->(part) { part } unless block_given?
return unless user
# If the user is allowed to see all projects,
# we can shortcut and just return.
return if user.full_private_access?
authorized = user
.where('project_authorizations.project_id =')
authorized_projects ='EXISTS (?)', authorized))
levels = Gitlab::VisibilityLevel.levels_for_user(user)
visible_projects = levels))
# We use a UNION here instead of OR clauses since this results in better
# performance.
union =[''),'')])
if use_where_in
where(" IN (#{union.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection
def self.public_or_visible_to_user(user = nil)
if user
authorized = user
.where('project_authorizations.project_id =')
levels = Gitlab::VisibilityLevel.levels_for_user(user)
where('EXISTS (?) OR projects.visibility_level IN (?)', authorized, levels)
from("(#{union.to_sql}) AS #{table_name}")
title: Revert Project.public_or_visible_to_user changes
type: fixed
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment