28acd2b087
We're filtering the events using `Event#visible_to_user?`. At most we're loading 100 events at once. Pagination is also dealt with in the finder, but the resulting array is wrapped in a `Kaminari.paginate_array` so the API's pagination helpers keep working. We're passing the total count into that paginatable array, which would include confidential events. But we're not disclosing anything.
86 lines
2.2 KiB
Ruby
86 lines
2.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Module to prepend into finders to specify wether or not the finder requires
|
|
# cross project access
|
|
#
|
|
# This module depends on the finder implementing the following methods:
|
|
#
|
|
# - `#execute` should return an `ActiveRecord::Relation` or the `model` needs to
|
|
# be defined in the call to `requires_cross_project_access`.
|
|
# - `#current_user` the user that requires access (or nil)
|
|
module FinderWithCrossProjectAccess
|
|
extend ActiveSupport::Concern
|
|
extend ::Gitlab::Utils::Override
|
|
|
|
prepended do
|
|
extend Gitlab::CrossProjectAccess::ClassMethods
|
|
|
|
cattr_accessor :finder_model
|
|
|
|
def self.requires_cross_project_access(*args)
|
|
super
|
|
|
|
self.finder_model = extract_model_from_arguments(args)
|
|
end
|
|
|
|
private
|
|
|
|
def self.extract_model_from_arguments(args)
|
|
args.detect { |argument| argument.is_a?(Hash) && argument[:model] }
|
|
&.fetch(:model)
|
|
end
|
|
end
|
|
|
|
override :execute
|
|
def execute(*args)
|
|
check = Gitlab::CrossProjectAccess.find_check(self)
|
|
original = -> { super }
|
|
|
|
return original.call unless check
|
|
return original.call if should_skip_cross_project_check || can_read_cross_project?
|
|
|
|
if check.should_run?(self)
|
|
finder_model&.none || original.call.model.none
|
|
else
|
|
original.call
|
|
end
|
|
end
|
|
|
|
# We can skip the cross project check for finding indivitual records.
|
|
# this would be handled by the `can?(:read_*, result)` call in `FinderMethods`
|
|
# itself.
|
|
override :find_by!
|
|
def find_by!(*args)
|
|
skip_cross_project_check { super }
|
|
end
|
|
|
|
override :find_by
|
|
def find_by(*args)
|
|
skip_cross_project_check { super }
|
|
end
|
|
|
|
override :find
|
|
def find(*args)
|
|
skip_cross_project_check { super }
|
|
end
|
|
|
|
attr_accessor :should_skip_cross_project_check
|
|
|
|
def skip_cross_project_check
|
|
self.should_skip_cross_project_check = true
|
|
|
|
yield
|
|
ensure
|
|
# The find could raise an `ActiveRecord::RecordNotFound`, after which we
|
|
# still want to re-enable the check.
|
|
self.should_skip_cross_project_check = false
|
|
end
|
|
|
|
def can_read_cross_project?
|
|
Ability.allowed?(current_user, :read_cross_project)
|
|
end
|
|
|
|
def can_read_project?(project)
|
|
Ability.allowed?(current_user, :read_project, project)
|
|
end
|
|
end
|