<?php
namespace App\Security;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Security;
use App\Mask\UserRolesMask;
use Lexik\Bundle\JWTAuthenticationBundle\Security\User\JWTUser;
use Doctrine\ORM\EntityManagerInterface;
class BridgeVoter extends Voter {
// these strings are just invented: you can use anything
const READ = 'READ';
const EDIT = 'EDIT';
private $container;
private $security;
private $userRolesMask;
private $entityManager;
private $roleHierarchy;
// modifs 12/12 Guillaume
private $entites_sans_partage;
private $user_admin_editions;
public function __construct(
ContainerInterface $container,
Security $security,
UserRolesMask $userRolesMask,
EntityManagerInterface $entityManager,
RoleHierarchyInterface $roleHierarchy
) {
$this->security = $security;
$this->container = $container;
$this->userRolesMask = $userRolesMask;
$this->entityManager = $entityManager;
$this->roleHierarchy = $roleHierarchy;
// modifs 12/12 Guillaume
$userNameTemp = $this->container->getParameter('user_admin_editions');
if($userNameTemp !='')
$this->user_admin_editions = $this->entityManager->getRepository("App\Entity\User")->findOneBy(array('username' => $userNameTemp));
$entites_sans_partage = $this->container->getParameter('entites_sans_partage');
$this->entites_sans_partage = explode(',',$entites_sans_partage);
if(!is_array($this->entites_sans_partage))
$this->entites_sans_partage = array($this->entites_sans_partage);
}
protected function supports( $attribute, $subject ) {
$supportsAttribute = in_array($attribute, ['READ', 'EDIT']);
return $supportsAttribute;
}
protected function voteOnAttribute( $attribute, $subject, TokenInterface $token ) {
$disable_data_voter = $this->container->getParameter('disable_data_voter');
if($disable_data_voter == "true") {
return true;
}
// Le voter ne s'applique que pour les entités qui ont des propriétés owner ET entity
if ( ! method_exists ( $subject , 'getOwner' ) || !method_exists ( $subject , 'getEntity' ) )
{
return true;
}
$JWTuser = $token->getUser();
if ( ! $JWTuser instanceof JWTUser )
{
// the user must be logged in; if not, deny access
return false;
}
$username = $JWTuser->getUsername();
$user = $this->entityManager->getRepository('App\\Entity\\User')->findOneBy(['username' => $username]);
switch ( $attribute )
{
case self::READ:
return $this->canView( $subject, $user );
case self::EDIT:
return $this->canEdit( $subject, $user );
}
throw new \LogicException( 'This code should not be reached!' );
}
private function canView( $object, User $user ) {
// if they can edit, they can view
$owner = $object->getOwner();
$entity = $object->getEntity();
$currentEntity = $user->getEntity();
$currentEntityId = '';
$user_admin_editions = $this->container->getParameter('user_admin_editions');
if(isset($currentEntity))
$currentEntityId = (string) $currentEntity->getId();
if ( $this->canEdit( $object, $user ) )
{
return true;
}
// Ici on checke les roles
$refRoles = $this->userRolesMask::ENTITY_ROLES;
$class = get_class($object);
$classTrimmed = substr($class, 11);
if(isset($refRoles[$classTrimmed])) {
$baseRole = $refRoles[$classTrimmed] . '_RO';
// On récupère les rôles hérités (ou sous-rôles) du user
$userRoles = $this->roleHierarchy->getReachableRoleNames($this->security->getUser()->getRoles());
if (in_array($baseRole, $userRoles)) {
$ownerId = '';
$userId = '';
$entityId = '';
if(isset($owner)) {
$ownerId = $owner->getId();
// Cas spécial du user admin éditions dont tous doivent pouvoir voir les données en lecture seule
$ownerName = $owner->getUsername();
if($user_admin_editions == $ownerName)
return true;
}
if(isset($user))
$userId = $user->getId();
if(isset($entity))
$entityId = $entity->getId();
// return ($owner === $user || ($entity === $currentEntity && isset($currentEntity) && !in_array($currentEntityId,$this->entites_sans_partage)));
return ($ownerId == $userId || ($entityId == $currentEntityId && isset($currentEntity) && !in_array($currentEntityId,$this->entites_sans_partage)));
}
}
return false;
}
private function canEdit( $object, User $user ) {
// die('coucdcou');
$owner = $object->getOwner();
$entity = $object->getEntity();
$currentEntity = $user->getEntity();
$currentEntityId = '';
if(isset($currentEntity))
$currentEntityId = (string) $currentEntity->getId();
// modifs 12/12 Guillaume
/*$username = $user->getUsername();
$userDoctrine = $this->entityManager->getRepository('App\\Entity\\User')->findOneBy(['username' => $username]);
$userEntity = $userDoctrine->getEntity();*/
// Ici on checke les roles
$refRoles = $this->userRolesMask::ENTITY_ROLES;
$class = get_class($object);
$classTrimmed = substr($class, 11);
if(isset($refRoles[$classTrimmed])) {
$baseRole = $refRoles[$classTrimmed] . '_RW';
// On récupère les rôles hérités (ou sous-rôles) du user
$userRoles = $this->roleHierarchy->getReachableRoleNames($this->security->getUser()->getRoles());
if (in_array($baseRole, $userRoles)) {
// print_r($userRoles);
$ownerId = '';
$userId = '';
$entityId = '';
if(isset($owner))
$ownerId = $owner->getId();
if(isset($user))
$userId = $user->getId();
if(isset($entity))
$entityId = $entity->getId();
//return ($owner === $user || $entity === $currentEntity);
return ($ownerId == $userId || ($entityId == $currentEntityId && isset($currentEntity) && !in_array($currentEntityId,$this->entites_sans_partage)));
}
}
return false;
}
}