# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ # Abstract base class for various "types" of ticket access. # # Do NOT instantiate directly; instead, # choose the appropriate subclass from below # (see commit message for details). class TicketPolicy < ApplicationPolicy class BaseScope < ApplicationPolicy::Scope # overwrite PunditPolicy#initialize to make `context` optional and use Ticket as default def initialize(user, context = Ticket) super end def resolve # rubocop:disable Metrics/AbcSize raise NoMethodError, <<~ERR.chomp if instance_of?(TicketPolicy::BaseScope) specify an access type using a subclass of TicketPolicy::BaseScope ERR sql = [] bind = [] if user.permissions?('ticket.agent') sql.push('group_id IN (?)') bind.push(user.group_ids_access(self.class::ACCESS_TYPE)) end if user.permissions?('ticket.customer') sql.push('tickets.customer_id = ?') bind.push(user.id) if user.all_organization_ids.present? Organization.where(id: user.all_organization_ids).select(&:shared).each do |organization| sql.push('tickets.organization_id = ?') bind.push(organization.id) end end end # The report permission can access all tickets. if sql.empty? && !user.permissions?('report') sql.push '0 = 1' # Forbid unlimited access for all other permissions. end scope.where sql.join(' OR '), *bind end # #resolve is UNDEFINED BEHAVIOR for the abstract base class (but not its subclasses) def respond_to?(*args) return false if args.first.to_s == 'resolve' && instance_of?(TicketPolicy::BaseScope) super end end end