zammad/lib/auth/permissions.rb
2026-01-02 15:41:09 +02:00

71 lines
1.7 KiB
Ruby

# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
class Auth::Permissions
attr_reader :object, :query
def initialize(object, query)
@object = object
@query = Array(query)
end
def self.authorized?(object, query)
Auth::RequestCache.fetch_value(cache_key(object, query)) do
new(object, query).authorized?
end
rescue URI::GID::MissingModelIdError
new(object, query).authorized?
end
def self.cache_key(object, query)
object_key = object.to_global_id.to_s
query_key = Array(query).join('|')
"permissions/#{object_key}_#{query_key}"
end
private_class_method :cache_key
def authorized?
query.any? do |elem|
check_single_permission_option(elem)
end
end
private
def check_single_permission_option(input)
input
.split('+')
.all? do |elem|
check_single_permission_option_component(elem)
end
end
def check_single_permission_option_component(input)
if input.exclude?('.')
return permissions_cache.include?(input)
end
# See "chain-of-ancestry quirk" in spec file
if !input.end_with?('.*') && Permission.lookup(name: input)&.active == false
return
end
Permission
.with_parents(input)
.any? do |parent_or_self|
check_permission_name_in_ancestry_chain(parent_or_self)
end
end
def check_permission_name_in_ancestry_chain(input)
if input.end_with?('.*')
permissions_cache.any? { |elem| elem.starts_with?(input.delete_suffix('*')) }
else
permissions_cache.include?(input)
end
end
def permissions_cache
@permissions_cache ||= object.permissions.pluck(:name)
end
end