summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2019-03-22 06:39:58 -0700
committerStan Hu <stanhu@gmail.com>2019-03-27 06:15:33 -0500
commitc408be48ca3d6840076c6f16c7910411cdfca24c (patch)
tree0c4654b1dde29f6f368991695b173a7d95277729 /app/models
parent0610bb091766d3bb935fc10898dd66bc6f76b1c5 (diff)
downloadgitlab-ce-c408be48ca3d6840076c6f16c7910411cdfca24c.tar.gz
Optimize /api/v4/projects endpoint for visibility level
Previously when a user requested a list of projects, `Project#public_or_visible_to_user` would search all authorized projects and public/internal projects as well. However, when a user requests a specific `visibility_level` (e.g. private), that should reduce the search space, and we shouldn't need to load public/internal projects. Improves https://gitlab.com/gitlab-org/gitlab-ce/issues/59329
Diffstat (limited to 'app/models')
-rw-r--r--app/models/project.rb22
1 files changed, 17 insertions, 5 deletions
diff --git a/app/models/project.rb b/app/models/project.rb
index 97a17d120c6..6667076b359 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -459,13 +459,25 @@ class Project < ActiveRecord::Base
# Returns a collection of projects that is either public or visible to the
# logged in user.
- def self.public_or_visible_to_user(user = nil)
- if user
+ #
+ # requested_visiblity_levels: Normally all projects that are visible
+ # to the user (e.g. internal and public) are queried, but this
+ # parameter allows the caller to narrow the search space to optimize
+ # database queries. For instance, a caller may only want to see
+ # internal projects. Instead of querying for internal and public
+ # projects and throwing away public projects, this parameter allows
+ # the query to be targeted for only internal projects.
+ def self.public_or_visible_to_user(user = nil, requested_visibility_levels = [])
+ return public_to_user unless user
+
+ visible_levels = Gitlab::VisibilityLevel.levels_for_user(user)
+ visible_levels &= Array(requested_visibility_levels) if requested_visibility_levels.present?
+
+ if visible_levels.present?
where('EXISTS (?) OR projects.visibility_level IN (?)',
- user.authorizations_for_projects,
- Gitlab::VisibilityLevel.levels_for_user(user))
+ user.authorizations_for_projects, visible_levels)
else
- public_to_user
+ where('EXISTS (?)', user.authorizations_for_projects)
end
end