... @@ -461,10 +461,12 @@ class Project < ApplicationRecord
... @@ -461,10 +461,12 @@ class Project < ApplicationRecord
# Returns a collection of projects that is either public or visible to the
# Returns a collection of projects that is either public or visible to the
# logged in user.
# 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
if user
where ( 'EXISTS (?) OR projects.visibility_level IN (?)' ,
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 ))
Gitlab :: VisibilityLevel . levels_for_user ( user ))
else
else
public_to_user
public_to_user
... @@ -474,30 +476,32 @@ class Project < ApplicationRecord
... @@ -474,30 +476,32 @@ class Project < ApplicationRecord
# project features may be "disabled", "internal", "enabled" or "public". If "internal",
# project features may be "disabled", "internal", "enabled" or "public". If "internal",
# they are only available to team members. This scope returns projects where
# 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.
# 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
# This method uses an optimised version of `with_feature_access_level` for
# logged in users to more efficiently get private projects with the given
# logged in users to more efficiently get private projects with the given
# feature.
# feature.
def self . with_feature_available_for_user ( feature , user )
def self . with_feature_available_for_user ( feature , user )
visible = [ ProjectFeature :: ENABLED , ProjectFeature :: PUBLIC ]
visible = [ ProjectFeature :: ENABLED , ProjectFeature :: PUBLIC ]
min_access_level = ProjectFeature . required_minimum_access_level ( feature )
if user & . admin?
if user & . admin?
with_feature_enabled ( feature )
with_feature_enabled ( feature )
elsif user
elsif user
min_access_level = ProjectFeature . required_minimum_access_level ( feature )
column = ProjectFeature . quoted_access_level_column ( feature )
column = ProjectFeature . quoted_access_level_column ( feature )
with_project_feature
with_project_feature
. where (
. where ( " #{ column } IS NULL OR #{ column } IN (:public_visible) OR ( #{ column } = :private_visible AND EXISTS (:authorizations))" ,
"(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: visible ,
public_visible: ProjectFeature :: ENABLED ,
private_visible: ProjectFeature :: PRIVATE ,
private_visible: ProjectFeature :: PRIVATE ,
authorizations: user . authorizations_for_projects ( min_access_level: min_access_level )
authorizations: user . authorizations_for_projects ( min_access_level: min_access_level )
})
})
else
else
# This has to be added to include features whose value is nil in the db
visible << nil
with_feature_access_level ( feature , visible )
with_feature_access_level ( feature , visible )
end
end
end
end
...
...
... ...