2018-09-11 15:08:34 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-01-18 11:07:06 -05:00
|
|
|
# Snippets Finder
|
|
|
|
#
|
|
|
|
# Used to filter Snippets collections by a set of params
|
|
|
|
#
|
|
|
|
# Arguments.
|
|
|
|
#
|
|
|
|
# current_user - The current user, nil also can be used.
|
|
|
|
# params:
|
|
|
|
# visibility (integer) - Individual snippet visibility: Public(20), internal(10) or private(0).
|
|
|
|
# project (Project) - Project related.
|
|
|
|
# author (User) - Author related.
|
|
|
|
#
|
|
|
|
# params are optional
|
2017-04-28 18:06:27 -04:00
|
|
|
class SnippetsFinder < UnionFinder
|
2018-01-18 11:07:06 -05:00
|
|
|
include Gitlab::Allowable
|
2017-12-11 09:21:06 -05:00
|
|
|
include FinderMethods
|
|
|
|
|
|
|
|
attr_accessor :current_user, :project, :params
|
2017-04-28 18:06:27 -04:00
|
|
|
|
|
|
|
def initialize(current_user, params = {})
|
|
|
|
@current_user = current_user
|
|
|
|
@params = params
|
2018-01-18 11:07:06 -05:00
|
|
|
@project = params[:project]
|
2017-04-28 18:06:27 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def execute
|
|
|
|
items = init_collection
|
|
|
|
items = by_author(items)
|
|
|
|
items = by_visibility(items)
|
|
|
|
|
|
|
|
items.fresh
|
2014-10-08 09:44:25 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2017-04-28 18:06:27 -04:00
|
|
|
def init_collection
|
2018-01-18 11:07:06 -05:00
|
|
|
if project.present?
|
|
|
|
authorized_snippets_from_project
|
|
|
|
else
|
|
|
|
authorized_snippets
|
|
|
|
end
|
|
|
|
end
|
2017-04-28 18:06:27 -04:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2018-01-18 11:07:06 -05:00
|
|
|
def authorized_snippets_from_project
|
|
|
|
if can?(current_user, :read_project_snippet, project)
|
|
|
|
if project.team.member?(current_user)
|
|
|
|
project.snippets
|
|
|
|
else
|
|
|
|
project.snippets.public_to_user(current_user)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
Snippet.none
|
|
|
|
end
|
2014-10-08 09:44:25 -04:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-10-08 09:44:25 -04:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2018-01-18 11:07:06 -05:00
|
|
|
def authorized_snippets
|
2018-06-13 20:20:11 -04:00
|
|
|
# This query was intentionally converted to a raw one to get it work in Rails 5.0.
|
|
|
|
# In Rails 5.0 and 5.1 there's a bug: https://github.com/rails/arel/issues/531
|
|
|
|
# Please convert it back when on rails 5.2 as it works again as expected since 5.2.
|
|
|
|
Snippet.where("#{feature_available_projects} OR #{not_project_related}")
|
2017-12-11 09:21:06 -05:00
|
|
|
.public_or_visible_to_user(current_user)
|
2018-01-18 11:07:06 -05:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-10-08 09:44:25 -04:00
|
|
|
|
2018-03-02 03:29:12 -05:00
|
|
|
# Returns a collection of projects that is either public or visible to the
|
|
|
|
# logged in user.
|
|
|
|
#
|
2018-03-02 04:15:52 -05:00
|
|
|
# A caller must pass in a block to modify individual parts of
|
2018-03-02 03:29:12 -05:00
|
|
|
# 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.
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2018-03-02 04:15:52 -05:00
|
|
|
def projects_for_user
|
|
|
|
return yield(Project.public_to_user) unless current_user
|
2018-03-02 03:29:12 -05:00
|
|
|
|
|
|
|
# If the current_user is allowed to see all projects,
|
|
|
|
# we can shortcut and just return.
|
2018-03-02 04:15:52 -05:00
|
|
|
return yield(Project.all) if current_user.full_private_access?
|
2018-03-02 03:29:12 -05:00
|
|
|
|
2018-03-02 10:01:06 -05:00
|
|
|
authorized_projects = yield(Project.where('EXISTS (?)', current_user.authorizations_for_projects))
|
2018-03-02 03:29:12 -05:00
|
|
|
|
|
|
|
levels = Gitlab::VisibilityLevel.levels_for_user(current_user)
|
2018-03-02 04:15:52 -05:00
|
|
|
visible_projects = yield(Project.where(visibility_level: levels))
|
2018-03-02 03:29:12 -05:00
|
|
|
|
|
|
|
# We use a UNION here instead of OR clauses since this results in better
|
|
|
|
# performance.
|
2018-09-11 11:31:34 -04:00
|
|
|
Project.from_union([authorized_projects, visible_projects])
|
2018-03-02 03:29:12 -05:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2018-03-02 03:29:12 -05:00
|
|
|
|
2018-01-18 11:07:06 -05:00
|
|
|
def feature_available_projects
|
2017-12-11 09:21:06 -05:00
|
|
|
# Don't return any project related snippets if the user cannot read cross project
|
2018-06-13 20:20:11 -04:00
|
|
|
return table[:id].eq(nil).to_sql unless Ability.allowed?(current_user, :read_cross_project)
|
2017-12-11 09:21:06 -05:00
|
|
|
|
2018-03-02 03:29:12 -05:00
|
|
|
projects = projects_for_user do |part|
|
|
|
|
part.with_feature_available_for_user(:snippets, current_user)
|
|
|
|
end.select(:id)
|
2018-02-16 10:05:32 -05:00
|
|
|
|
2018-06-13 20:20:11 -04:00
|
|
|
# This query was intentionally converted to a raw one to get it work in Rails 5.0.
|
|
|
|
# In Rails 5.0 and 5.1 there's a bug: https://github.com/rails/arel/issues/531
|
|
|
|
# Please convert it back when on rails 5.2 as it works again as expected since 5.2.
|
|
|
|
"snippets.project_id IN (#{projects.to_sql})"
|
2014-10-08 09:44:25 -04:00
|
|
|
end
|
|
|
|
|
2018-01-18 11:07:06 -05:00
|
|
|
def not_project_related
|
2018-06-13 20:20:11 -04:00
|
|
|
table[:project_id].eq(nil).to_sql
|
2018-01-18 11:07:06 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def table
|
|
|
|
Snippet.arel_table
|
2017-04-28 18:06:27 -04:00
|
|
|
end
|
2014-10-08 09:44:25 -04:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2017-04-28 18:06:27 -04:00
|
|
|
def by_visibility(items)
|
|
|
|
visibility = params[:visibility] || visibility_from_scope
|
|
|
|
|
|
|
|
return items unless visibility
|
|
|
|
|
|
|
|
items.where(visibility_level: visibility)
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2017-04-28 18:06:27 -04:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2017-04-28 18:06:27 -04:00
|
|
|
def by_author(items)
|
|
|
|
return items unless params[:author]
|
|
|
|
|
|
|
|
items.where(author_id: params[:author].id)
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2017-04-28 18:06:27 -04:00
|
|
|
|
|
|
|
def visibility_from_scope
|
|
|
|
case params[:scope].to_s
|
2016-12-09 15:40:48 -05:00
|
|
|
when 'are_private'
|
2017-04-28 18:06:27 -04:00
|
|
|
Snippet::PRIVATE
|
2016-12-09 15:40:48 -05:00
|
|
|
when 'are_internal'
|
2017-04-28 18:06:27 -04:00
|
|
|
Snippet::INTERNAL
|
2016-12-09 15:40:48 -05:00
|
|
|
when 'are_public'
|
2017-04-28 18:06:27 -04:00
|
|
|
Snippet::PUBLIC
|
2016-12-09 15:40:48 -05:00
|
|
|
else
|
2017-04-28 18:06:27 -04:00
|
|
|
nil
|
2016-12-09 15:40:48 -05:00
|
|
|
end
|
|
|
|
end
|
2014-10-08 09:44:25 -04:00
|
|
|
end
|