diff options
author | Francisco Javier López <fjlopez@gitlab.com> | 2019-05-07 11:08:25 +0000 |
---|---|---|
committer | James Lopez <james@gitlab.com> | 2019-05-07 11:08:25 +0000 |
commit | 68e533dc219be27f3485d2335e70aa61a193dabb (patch) | |
tree | f26b2a94b515469839f8498e18698f3782187260 /app/models | |
parent | 0910dfb9d6eb9748b6ca24e10a3382a6515615e5 (diff) | |
download | gitlab-ce-68e533dc219be27f3485d2335e70aa61a193dabb.tar.gz |
Add improvements to the global search process
Removed the conditions added to
Project.with_feature_available_for_user, and moved to the
IssuableFinder. Now, we ensure that, in the projects retrieved
in the Finder, the user has enough access for the feature.
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/project.rb | 28 | ||||
-rw-r--r-- | app/models/user.rb | 8 |
2 files changed, 22 insertions, 14 deletions
diff --git a/app/models/project.rb b/app/models/project.rb index da72186c8a0..61d245478ca 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -464,10 +464,12 @@ class Project < ApplicationRecord # 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) + def self.public_or_visible_to_user(user = nil, min_access_level = nil) + min_access_level = nil if user&.admin? + if user where('EXISTS (?) OR projects.visibility_level IN (?)', - user.authorizations_for_projects, + user.authorizations_for_projects(min_access_level: min_access_level), Gitlab::VisibilityLevel.levels_for_user(user)) else public_to_user @@ -477,30 +479,32 @@ class Project < ApplicationRecord # project features may be "disabled", "internal", "enabled" or "public". If "internal", # they are only available to team members. This scope returns projects where # the feature is either public, enabled, or internal with permission for the user. + # Note: this scope doesn't enforce that the user has access to the projects, it just checks + # that the user has access to the feature. It's important to use this scope with others + # that checks project authorizations first. # # This method uses an optimised version of `with_feature_access_level` for # logged in users to more efficiently get private projects with the given # feature. def self.with_feature_available_for_user(feature, user) visible = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC] - min_access_level = ProjectFeature.required_minimum_access_level(feature) if user&.admin? with_feature_enabled(feature) elsif user + min_access_level = ProjectFeature.required_minimum_access_level(feature) column = ProjectFeature.quoted_access_level_column(feature) with_project_feature - .where( - "(projects.visibility_level > :private AND (#{column} IS NULL OR #{column} >= (:public_visible) OR (#{column} = :private_visible AND EXISTS(:authorizations))))"\ - " OR (projects.visibility_level = :private AND (#{column} IS NULL OR #{column} >= :private_visible) AND EXISTS(:authorizations))", - { - private: Gitlab::VisibilityLevel::PRIVATE, - public_visible: ProjectFeature::ENABLED, - private_visible: ProjectFeature::PRIVATE, - authorizations: user.authorizations_for_projects(min_access_level: min_access_level) - }) + .where("#{column} IS NULL OR #{column} IN (:public_visible) OR (#{column} = :private_visible AND EXISTS (:authorizations))", + { + public_visible: visible, + private_visible: ProjectFeature::PRIVATE, + authorizations: user.authorizations_for_projects(min_access_level: min_access_level) + }) else + # This has to be added to include features whose value is nil in the db + visible << nil with_feature_access_level(feature, visible) end end diff --git a/app/models/user.rb b/app/models/user.rb index 43039f3760e..4a1bf5514fe 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -757,11 +757,15 @@ class User < ApplicationRecord # Typically used in conjunction with projects table to get projects # a user has been given access to. + # The param `related_project_column` is the column to compare to the + # project_authorizations. By default is projects.id # # Example use: # `Project.where('EXISTS(?)', user.authorizations_for_projects)` - def authorizations_for_projects(min_access_level: nil) - authorizations = project_authorizations.select(1).where('project_authorizations.project_id = projects.id') + def authorizations_for_projects(min_access_level: nil, related_project_column: 'projects.id') + authorizations = project_authorizations + .select(1) + .where("project_authorizations.project_id = #{related_project_column}") return authorizations unless min_access_level.present? |