debian-mirror-gitlab/app/finders/snippets_finder.rb

160 lines
4.1 KiB
Ruby
Raw Normal View History

2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2018-12-13 13:39:08 +05:30
# Finder for retrieving snippets that a user can see, optionally scoped to a
# project or snippets author.
2018-03-17 18:26:18 +05:30
#
2018-12-13 13:39:08 +05:30
# Basic usage:
2018-03-17 18:26:18 +05:30
#
2018-12-13 13:39:08 +05:30
# user = User.find(1)
2018-03-17 18:26:18 +05:30
#
2018-12-13 13:39:08 +05:30
# SnippetsFinder.new(user).execute
2018-03-17 18:26:18 +05:30
#
2018-12-13 13:39:08 +05:30
# To limit the snippets to a specific project, supply the `project:` option:
#
# user = User.find(1)
# project = Project.find(1)
#
# SnippetsFinder.new(user, project: project).execute
#
# Limiting snippets to an author can be done by supplying the `author:` option:
#
# user = User.find(1)
# project = Project.find(1)
#
# SnippetsFinder.new(user, author: user).execute
#
# To filter snippets using a specific visibility level, you can provide the
# `scope:` option:
#
# user = User.find(1)
# project = Project.find(1)
#
# SnippetsFinder.new(user, author: user, scope: :are_public).execute
#
# Valid `scope:` values are:
#
# * `:are_private`
# * `:are_internal`
# * `:are_public`
#
# Any other value will be ignored.
2017-08-17 22:00:37 +05:30
class SnippetsFinder < UnionFinder
2018-03-27 19:54:05 +05:30
include FinderMethods
2018-12-13 13:39:08 +05:30
attr_accessor :current_user, :project, :author, :scope
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
def initialize(current_user = nil, params = {})
2017-08-17 22:00:37 +05:30
@current_user = current_user
2018-03-17 18:26:18 +05:30
@project = params[:project]
2018-12-13 13:39:08 +05:30
@author = params[:author]
@scope = params[:scope].to_s
if project && author
raise(
ArgumentError,
'Filtering by both an author and a project is not supported, ' \
'as this finder is not optimised for this use case'
)
end
2017-08-17 22:00:37 +05:30
end
def execute
2018-12-13 13:39:08 +05:30
base =
if project
snippets_for_a_single_project
else
snippets_for_multiple_projects
end
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
base.with_optional_visibility(visibility_from_scope).fresh
2015-04-26 12:48:37 +05:30
end
2019-07-07 11:18:12 +05:30
private
2018-12-13 13:39:08 +05:30
# Produces a query that retrieves snippets from multiple projects.
#
# The resulting query will, depending on the user's permissions, include the
# following collections of snippets:
#
# 1. Snippets that don't belong to any project.
# 2. Snippets of projects that are visible to the current user (e.g. snippets
# in public projects).
# 3. Snippets of projects that the current user is a member of.
#
# Each collection is constructed in isolation, allowing for greater control
# over the resulting SQL query.
def snippets_for_multiple_projects
queries = [global_snippets]
if Ability.allowed?(current_user, :read_cross_project)
queries << snippets_of_visible_projects
queries << snippets_of_authorized_projects if current_user
2018-03-17 18:26:18 +05:30
end
2018-12-13 13:39:08 +05:30
find_union(queries, Snippet)
2015-04-26 12:48:37 +05:30
end
2018-12-13 13:39:08 +05:30
def snippets_for_a_single_project
Snippet.for_project_with_user(project, current_user)
2017-08-17 22:00:37 +05:30
end
2018-03-27 19:54:05 +05:30
2018-12-13 13:39:08 +05:30
def global_snippets
snippets_for_author_or_visible_to_user.only_global_snippets
2018-03-17 18:26:18 +05:30
end
2018-12-13 13:39:08 +05:30
# Returns the snippets that the current user (logged in or not) can view.
def snippets_of_visible_projects
snippets_for_author_or_visible_to_user
.only_include_projects_visible_to(current_user)
.only_include_projects_with_snippets_enabled
2018-03-17 18:26:18 +05:30
end
2018-12-13 13:39:08 +05:30
# Returns the snippets that the currently logged in user has access to by
# being a member of the project the snippets belong to.
#
# This method requires that `current_user` returns a `User` instead of `nil`,
# and is optimised for this specific scenario.
def snippets_of_authorized_projects
base = author ? snippets_for_author : Snippet.all
base
.only_include_projects_with_snippets_enabled(include_private: true)
.only_include_authorized_projects(current_user)
2017-08-17 22:00:37 +05:30
end
2018-12-13 13:39:08 +05:30
def snippets_for_author_or_visible_to_user
if author
snippets_for_author
elsif current_user
Snippet.visible_to_or_authored_by(current_user)
else
Snippet.public_to_user
end
2015-04-26 12:48:37 +05:30
end
2018-12-13 13:39:08 +05:30
def snippets_for_author
base = author.snippets
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
if author == current_user
# If the current user is also the author of all snippets, then we can
# include private snippets.
base
else
base.public_to_user(current_user)
end
2017-08-17 22:00:37 +05:30
end
def visibility_from_scope
2018-12-13 13:39:08 +05:30
case scope
2017-08-17 22:00:37 +05:30
when 'are_private'
Snippet::PRIVATE
when 'are_internal'
Snippet::INTERNAL
when 'are_public'
Snippet::PUBLIC
2015-04-26 12:48:37 +05:30
else
2017-08-17 22:00:37 +05:30
nil
2015-04-26 12:48:37 +05:30
end
end
end