<?php
/**
* This file is part of the Pimcore X Installation by
* ercas GmbH & CO. KG <https://www.ercasdieagentur.de>
*
* @license GPLv3
*/
namespace App\mvk\Auth\Services;
use Pimcore\Model\DataObject\Agent;
use Pimcore\Model\DataObject\BmsSubAgent;
use Pimcore\Model\DataObject\SubAgent;
use Pimcore\Model\DataObject\Supervisor;
use Psr\Container\ContainerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security ;
use Symfony\Component\Security\Core\User\UserInterface;
class VoterPermissions extends Voter
{
private $permissionService;
public function __construct(private Security $security, private ContainerInterface $container)
{
$this->security = $security;
$this->container = $container;
$this->permissionService = $container->get('auth.frontend_permission_toolkit_bundle');
}
const SUBJECTS = ['Policy', 'Policyholder', 'PolicyDocument', 'Agent', 'SubAgent', 'BmsSubAgent', 'AgentDocument', 'InsuranceApplication', 'InsuranceOffer', 'DamageDeclaration'];
const VIEWCUSTOMERLIST = 'viewCustmerList';
const VIEWSETTLEMENTS = 'viewSettlements';
const VIEWGDVDOWNLOAD = 'viewGdvDownload';
const VIEWAUFSICHTSRAT = 'viewAufsichtsrat';
const VIEWMYUSERS = 'viewMyUsers';
const GDVDOWNLOAD = 'gdvDownload';
const AGENTDOCUMENTDOWNLOAD = 'agentDocumentDownload';
const ACCESS = 'access';
protected function supports(string $attribute, mixed $subject): bool
{
/** if the attribute isn't one we support, return false */
if (!in_array($attribute, [self::VIEWCUSTOMERLIST, self::VIEWSETTLEMENTS, self::VIEWGDVDOWNLOAD, self::VIEWMYUSERS, self::VIEWAUFSICHTSRAT, self::GDVDOWNLOAD, self::AGENTDOCUMENTDOWNLOAD, self::ACCESS])) {
return false;
}
/** if the subject isn't one we support, return false. (can also use instanceof ) */
if ($subject && !in_array($subject->getClassName(), self::SUBJECTS)) {
return false;
}
return true;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
/** the user must be logged in; if not, deny access */
if (!$user instanceof UserInterface) {
return false;
}
$orginalUser= $this->getOriginalUser($user);
return match($attribute) {
self::GDVDOWNLOAD => $this->canGdvDownload($attribute, $orginalUser),
self::AGENTDOCUMENTDOWNLOAD => $this->canAgentDocumentDownload($attribute, $orginalUser),
self::VIEWCUSTOMERLIST => $this->canViewCustmerList($attribute, $orginalUser),
self::VIEWAUFSICHTSRAT => $this->canViewAufsichtsrat($attribute, $orginalUser),
self::VIEWSETTLEMENTS => $this->canViewSettlements($attribute, $orginalUser),
self::VIEWGDVDOWNLOAD => $this->canViewGdvDownload($attribute, $orginalUser),
self::VIEWMYUSERS => $this->canViewMyUsers($attribute, $orginalUser),
self::ACCESS => $this->canAccess($orginalUser, $subject),
default => throw new \LogicException('This code should not be reached!')
};
}
/**
* This function checks Subjects that don't need special Treatments
*/
private function checkSubject($user, $subject): bool
{
$subject= $this->reset($subject);
$method= 'get'.$user->getClassName();
if ($user instanceof SubAgent || $user instanceof BmsSubAgent) {
$user = $user->getAgent();
if (!$user) {
return false;
}
$method = 'getAgent';
}
$userId= $this->getUserOwners($user);
$allowedUsers= $this->getAllowedUsers($subject, $method);
return $this->getFinalDecision($allowedUsers, $userId);
}
/**
* This function checks Subjects that need special Treatments
*/
private function checkSubjectSpecial($user, $subject, $attribute): bool
{
$subject= $this->reset($subject);
if ($user instanceof Agent || $user instanceof SubAgent) {
$method = 'getId';
if ($user instanceof SubAgent) {
if (!$this->canAgentDocumentDownload($attribute, $user)) {
return false;
}
$user = $user->getAgent();
if (!$user) {
return false;
}
}
$userId= $this->getUserOwners($user);
$allowedUsers= $this->getAllowedUsers($subject, $method);
return $this->getFinalDecision($allowedUsers, $userId);
}
return false;
}
/**
* This function checks Related SubAgent and BmsSubAgent to an Agent
*/
private function checkRelatedAgent($user, $subject)
{
if ($user instanceof Agent && $subject instanceof Agent) {
if ($subject->getId() === $user->getId()) {
return true;
}
}
if ($user instanceof Agent && ($subject instanceof SubAgent || $subject instanceof BmsSubAgent)) {
$user = $subject->getAgent();
if (!$user) {
return false;
}
$method = 'getAgent';
$userId= $this->getUserOwners($user);
$allowedUsers= $this->getAllowedUsers($subject, $method);
return $this->getFinalDecision($allowedUsers, $userId);
}
if ($user instanceof SubAgent || $user instanceof BmsSubAgent) {
$user = $user->getAgent();
if (!$user) {
return false;
}
$method = 'getAgent';
$userId= $this->getUserOwners($user);
$allowedUsers= $this->getAllowedUsers($subject, $method);
return $this->getFinalDecision($allowedUsers, $userId);
}
return false;
}
/**
* This function checks Policy Object
*/
private function checkPolicy($user, $subject): bool
{
return $this->checkSubject($user, $subject);
}
/**
* This function checks PolicyHolder Object
*/
private function checkPolicyHolder($user, $subject): bool
{
$subject = $subject->getPolicies();
return $this->checkPolicy($user, $subject);
}
/**
* This function checks Agent Object
*/
private function checkAgent($user, $subject): bool
{
return $this->checkRelatedAgent($user, $subject);
}
/**
* This function checks SubAgent Object
*/
private function checkSubAgent($user, $subject): bool
{
return $this->checkRelatedAgent($user, $subject);
}
/**
* This function checks BmsSubAgent Object
*/
private function checkBmsSubAgent($user, $subject): bool
{
return $this->checkRelatedAgent($user, $subject);
}
/**
* This function checks InsuranceApplication Object
*/
private function checkInsuranceApplication($user, $subject): bool
{
return $this->checkSubject($user, $subject);
}
/**
* This function checks InsuranceOffer Object
*/
private function checkInsuranceOffer($user, $subject): bool
{
return $this->checkSubject($user, $subject);
}
/**
* This function checks DamageDeclaration Object
*/
private function checkDamageDeclaration($user, $subject): bool
{
return $this->checkSubject($user, $subject);
}
/**
* This function checks PolicyDocument Object
*/
private function checkPolicyDocument($user, $subject): bool
{
$subject = $subject->getpolicyNr();
return $this->checkSubject($user, $subject);
}
/**
* This function checks AgentDocument Object
*/
private function checkAgentDocument($user, $subject): bool
{
$subject = $subject->getagentNr();
return $this->checkSubjectSpecial($user, $subject, 'agentDocumentDownload');
}
/**
* This function that get called in controllers with different subjects
*/
private function canAccess($user, $subject): bool
{
$method= 'check'.$subject->getClassName();
return $this->$method($user, $subject);
}
/**
* This function checks User's Role GdvDownload
*/
private function canGdvDownload($attribute, $user): bool
{
if ($user instanceof Agent) {
return true;
} else {
if ($this->isAllowed('viewGdvDownload', $user)) {
return true;
}
}
return false;
}
/**
* This function checks User's Role AgentDocumentDownload
*/
private function canAgentDocumentDownload($attribute, $user): bool
{
if ($user instanceof Agent) {
return true;
} else {
if ($this->isAllowed('viewSettlements', $user)) {
return true;
}
}
return false;
}
/**
* This function checks wether the user can view Kundenliste Pimcore Document
*/
private function canViewCustmerList($attribute, $user): bool
{
if ($user instanceof Agent || $user instanceof SubAgent || $user instanceof BmsSubAgent) {
return true;
}
return false;
}
/**
* This function checks wether the user can access ViewAufsichtsrat
*/
private function canViewAufsichtsrat($attribute, $user): bool
{
if ($user instanceof Supervisor) {
return true;
}
return false;
}
/**
* This function checks wether the user can view Abrechnungen Pimcore Document
*/
private function canViewSettlements($attribute, $user): bool
{
return $this->canAgentDocumentDownload($attribute, $user);
}
/**
* This function checks wether the user can view GDV Download Pimcore Document
*/
private function canViewGdvDownload($attribute, $user): bool
{
return $this->canGdvDownload($attribute, $user);
}
/**
* This function checks wether the user can view Meine Benutzer Pimcore Document
*/
private function canViewMyUsers($attribute, $user): bool
{
if ($user instanceof Agent) {
return true;
}
return false;
}
/**
* This function checks wether the user is granted the permission based on their Role
*/
private function isAllowed($attribute, $user)
{
if ($this->permissionService->isAllowed($user, $attribute)) {
return true;
}
return false;
}
private function getOriginalUser($user)
{
$class= "Pimcore\Model\DataObject\\".$user->getClassName();
$user = $class::getById($user->getId());
return $user;
}
private function reset($subject)
{
if (is_array($subject) && count($subject)==1) {
$subject = reset($subject);
}
return $subject;
}
private function getAllowedUsers($subject, $method)
{
$allowedUsers=[];
if (is_array($subject)) {
foreach ($subject as $mSubject) {
$holder = $mSubject->$method();
if ($holder) {
$holder= $this->reset($holder);
if (is_array($holder)) {
foreach ($holder as $subHolder) {
array_push($allowedUsers, $subHolder->getId());
}
} else {
is_int($holder) ? $holderId=$holder : $holderId=$holder->getId();
array_push($allowedUsers, $holderId);
}
}
}
} else {
$holder = $subject->$method();
if ($holder) {
$holder= $this->reset($holder);
if (is_array($holder)) {
$method = 'getId';
$allowedUsers = $this->getAllowedUsers($holder, $method);
} else {
$holder= $this->reset($holder);
is_int($holder) ? $holderId=$holder : $holderId=$holder->getId();
array_push($allowedUsers, $holderId);
}
}
}
return $allowedUsers;
}
private function getUserOwners($user)
{
$users=[];
if (is_array($user)) {
foreach ($user as $agent) {
array_push($users, $agent->getId());
}
} else {
array_push($users, $user->getId());
}
return $users;
}
private function getFinalDecision($allowedUsers, $userId)
{
if ($allowedUsers) {
if (is_array($userId)) {
foreach ($userId as $user) {
if (in_array($user, $allowedUsers)) {
return true;
}
}
} else {
if (in_array($userId, $allowedUsers)) {
return true;
}
}
}
return false;
}
}