diff options
author | Yorick Peterse <yorickpeterse@gmail.com> | 2018-03-02 20:41:00 +0000 |
---|---|---|
committer | Yorick Peterse <yorickpeterse@gmail.com> | 2018-03-02 20:41:00 +0000 |
commit | 369d34c7c8e006d2568e4a1b12b6493830811270 (patch) | |
tree | bf488070115d6461a40f84bfd73b36bf27a102ce /app/finders | |
parent | ddad22c4c4fde6dbec4a9224a3c2500af8bc7bf0 (diff) | |
parent | 39011be53daee921dac1648044d1e68b9706197c (diff) | |
download | gitlab-ce-369d34c7c8e006d2568e4a1b12b6493830811270.tar.gz |
Merge branch '42877-fix-visibility-change-performance' into 'master'
Revert Project.public_or_visible_to_user changes but apply change to SnippetsFinder
Closes #42877
See merge request gitlab-org/gitlab-ce!17476
Diffstat (limited to 'app/finders')
-rw-r--r-- | app/finders/snippets_finder.rb | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb index a73c573736e..d498a2d6d11 100644 --- a/app/finders/snippets_finder.rb +++ b/app/finders/snippets_finder.rb @@ -58,11 +58,37 @@ class SnippetsFinder < UnionFinder .public_or_visible_to_user(current_user) end + # Returns a collection of projects that is either public or visible to the + # logged in user. + # + # A caller must 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. + def projects_for_user + return yield(Project.public_to_user) unless current_user + + # If the current_user is allowed to see all projects, + # we can shortcut and just return. + return yield(Project.all) if current_user.full_private_access? + + authorized_projects = yield(Project.where('EXISTS (?)', current_user.authorizations_for_projects)) + + levels = Gitlab::VisibilityLevel.levels_for_user(current_user) + visible_projects = yield(Project.where(visibility_level: levels)) + + # We use a UNION here instead of OR clauses since this results in better + # performance. + union = Gitlab::SQL::Union.new([authorized_projects.select('projects.id'), visible_projects.select('projects.id')]) + + Project.from("(#{union.to_sql}) AS #{Project.table_name}") + end + 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| + projects = projects_for_user do |part| part.with_feature_available_for_user(:snippets, current_user) end.select(:id) |