diff --git a/module/Application/src/Application/Acl/IntervenantRole.php b/module/Application/src/Application/Acl/IntervenantRole.php index 6668a5cb8ff11bb40bf9edfbb6538ce55ee0779c..d12ce2d5a21f3dcb60575e72ec87d2f2fe03cafc 100644 --- a/module/Application/src/Application/Acl/IntervenantRole.php +++ b/module/Application/src/Application/Acl/IntervenantRole.php @@ -24,6 +24,19 @@ class IntervenantRole extends Role implements StructureAwareInterface, Intervena { parent::__construct($id, $parent, $name, $description, $selectable); } + + /** + * + * @param Resource|string $resource + * @param Privilege|string $privilege + */ + function hasPrivilege( $resource, $privilege ) + { + if ($statut = $this->getIntervenant()->getStatut()){ + return $statut->hasPrivilege($resource, $privilege); + } + return false; + } } diff --git a/module/Application/src/Application/Acl/Role.php b/module/Application/src/Application/Acl/Role.php index 092980cdda2f8346acb27f70e541939f797a3f11..651d6d7c36c2a31394906e37e7f9afbdd4f8edbf 100644 --- a/module/Application/src/Application/Acl/Role.php +++ b/module/Application/src/Application/Acl/Role.php @@ -3,6 +3,9 @@ namespace Application\Acl; use UnicaenAuth\Acl\NamedRole; +use Application\Entity\Db\TypeRole; +use Zend\Permissions\Acl\Resource; +use Application\Entity\Db\Privilege; /** * Rôle père de tous les rôles "administrateur". @@ -14,8 +17,45 @@ class Role extends NamedRole const ROLE_ID = 'role'; + /** + * Type de rôle + * + * @var TypeRole + */ + protected $typeRole; + + + public function __construct($id = self::ROLE_ID, $parent = 'user', $name = 'Rôle', $description = null, $selectable = true) { parent::__construct($id, $parent, $name, $description, $selectable); } + + /** + * + * @return TypeRole + */ + function getTypeRole() + { + return $this->typeRole; + } + + function setTypeRole(TypeRole $typeRole) + { + $this->typeRole = $typeRole; + return $this; + } + + /** + * + * @param Resource|string $resource + * @param Privilege|string $privilege + */ + function hasPrivilege( $resource, $privilege ) + { + if ($typeRole = $this->getTypeRole()){ + return $typeRole->hasPrivilege($resource, $privilege); + } + return false; + } } \ No newline at end of file diff --git a/module/Application/src/Application/Assertion/AbstractAssertion.php b/module/Application/src/Application/Assertion/AbstractAssertion.php index f5076ad6a21c38a1085dd8c7a4d951db30e793a6..494790e44c3f2e1fd9189dde07643e42ab4243dd 100644 --- a/module/Application/src/Application/Assertion/AbstractAssertion.php +++ b/module/Application/src/Application/Assertion/AbstractAssertion.php @@ -13,6 +13,7 @@ use Zend\Permissions\Acl\Resource\ResourceInterface; use Zend\Permissions\Acl\Role\RoleInterface; use Zend\ServiceManager\ServiceLocatorAwareInterface; use Zend\ServiceManager\ServiceLocatorAwareTrait; +use Application\Acl\Role; /** * Description of AbstractAssertion @@ -33,22 +34,36 @@ abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAw * @var Acl */ protected $acl; - + + /** + * copntrôle par les privileges activés ou non + * + * @var boolean + */ + protected $assertPrivilegesEnabled = false; + + /** + * contrôle par les ressources activés ou non + * + * @var boolean + */ + protected $assertResourcesEnabled = true; + /** * @var string */ protected $privilege; - + /** * @var ResourceInterface|string */ protected $resource; - + /** * @var RoleInterface */ protected $role; - + /** * !!!! Pour éviter l'erreur "Serialization of 'Closure' is not allowed"... !!!! * @@ -58,7 +73,7 @@ abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAw { return []; } - + /** * Returns true if and only if the assertion conditions are met * @@ -78,10 +93,34 @@ abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAw $this->resource = $resource; $this->privilege = $privilege; $this->role = $this->getSelectedIdentityRole(); - + + if (! $this->assertPrivilege() ) return false; + if (! $this->assertResource() ) return false; return true; } - + + private function assertPrivilege() + { + if (! $this->assertPrivilegesEnabled) return true; // si pas activé alors on sort + if ($this->role instanceof Role && ! empty($this->resource) && ! empty($this->privilege)){ + return $this->role->hasPrivilege($this->privilege, $this->resource); + } + return true; + } + + private function assertResource() + { + if (! $this->assertResourcesEnabled) return true; // si pas activé alors on sort + if (! $this->resource instanceof ResourceInterface) return true; // pas assez de précisions + $resourceId = $this->resource->getResourceId(); + + if (method_exists( $this, 'assertResource'.$resourceId)){ + return $this->{'assertResource'.$resourceId}( $this->resource ); + } + + return true; + } + /** * * @return MvcEvent @@ -91,7 +130,6 @@ abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAw return $this->getServiceLocator()->get('Application')->getMvcEvent(); } - /** * @return boolean */ @@ -211,4 +249,11 @@ abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAw return $now > $dateFin; } + + public static function getAssertionId() + { + $getCalledClass = get_called_class(); + $getCalledClass = substr( $getCalledClass, strrpos( $getCalledClass, '\\')+1 ); + return $getCalledClass; + } } \ No newline at end of file diff --git a/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.Privilege.dcm.xml b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.Privilege.dcm.xml new file mode 100644 index 0000000000000000000000000000000000000000..d3c9b4d2db2d79884e5c4abebf0dc3e2e897140c --- /dev/null +++ b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.Privilege.dcm.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> + <entity name="Application\Entity\Db\Privilege" table="PRIVILEGE"> + <indexes> + <index name="IDX_C3E284683C7C492D" columns="RESOURCE_ID"/> + </indexes> + <unique-constraints> + <unique-constraint name="privilege__un" columns="RESOURCE_ID,CODE"/> + </unique-constraints> + <id name="id" type="integer" column="ID"> + <generator strategy="SEQUENCE"/> + </id> + <field name="code" type="string" column="CODE" length="150" nullable="false"/> + <field name="libelle" type="string" column="LIBELLE" length="200" nullable="false"/> + <many-to-one field="ressource" target-entity="Application\Entity\Db\Ressource"> + <join-columns> + <join-column name="RESSOURCE_ID" referenced-column-name="ID"/> + </join-columns> + </many-to-one> + <many-to-many field="typeRole" target-entity="Application\Entity\Db\TypeRole" inversed-by="privilege"> + <join-table name="TYPE_ROLE_PRIVILEGE"> + <join-columns> + <join-column name="PRIVILEGE_ID" referenced-column-name="ID"/> + </join-columns> + <inverse-join-columns> + <join-column name="TYPE_ROLE_ID" referenced-column-name="ID"/> + </inverse-join-columns> + </join-table> + </many-to-many> + <many-to-many field="statut" target-entity="Application\Entity\Db\StatutIntervenant" inversed-by="privilege"> + <join-table name="STATUT_PRIVILEGE"> + <join-columns> + <join-column name="PRIVILEGE_ID" referenced-column-name="ID"/> + </join-columns> + <inverse-join-columns> + <join-column name="STATUT_ID" referenced-column-name="ID"/> + </inverse-join-columns> + </join-table> + </many-to-many> + </entity> +</doctrine-mapping> diff --git a/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.Ressource.dcm.xml b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.Ressource.dcm.xml new file mode 100644 index 0000000000000000000000000000000000000000..c2b3cadcd3c907ded3b1d7785eedd38f7cc0cc28 --- /dev/null +++ b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.Ressource.dcm.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> + <entity name="Application\Entity\Db\Ressource" table="RESSOURCE"> + <unique-constraints> + <unique-constraint name="ressource__un" columns="CODE"/> + </unique-constraints> + <id name="id" type="integer" column="ID"> + <generator strategy="SEQUENCE"/> + </id> + <field name="code" type="string" column="CODE" length="150" nullable="false"/> + <field name="libelle" type="string" column="LIBELLE" length="200" nullable="false"/> + </entity> +</doctrine-mapping> diff --git a/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.StatutIntervenant.dcm.xml b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.StatutIntervenant.dcm.xml index f0ebd73e2a073f72a1e3edc89482480020ddaa18..a849e34d81bc898f36b419d3e531693150e5ca15 100644 --- a/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.StatutIntervenant.dcm.xml +++ b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.StatutIntervenant.dcm.xml @@ -60,5 +60,6 @@ </many-to-one> <one-to-many field="typeAgrementStatut" target-entity="Application\Entity\Db\TypeAgrementStatut" mapped-by="statut" /> <one-to-many field="typePieceJointeStatut" target-entity="Application\Entity\Db\TypePieceJointeStatut" mapped-by="statut" /> + <many-to-many field="privilege" target-entity="Application\Entity\Db\Privilege" mapped-by="statut"/> </entity> </doctrine-mapping> diff --git a/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.TypeRole.dcm.xml b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.TypeRole.dcm.xml index 1b60f5aeedc3481834675859d1013f8e8c523176..a13849bc72f86318c7e04845e4cc1d69218b8acd 100644 --- a/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.TypeRole.dcm.xml +++ b/module/Application/src/Application/Entity/Db/Mapping/Application.Entity.Db.TypeRole.dcm.xml @@ -35,5 +35,6 @@ </join-columns> </many-to-one> <one-to-many field="role" target-entity="Application\Entity\Db\Role" mapped-by="type" /> + <many-to-many field="privilege" target-entity="Application\Entity\Db\Privilege" mapped-by="typeRole"/> </entity> </doctrine-mapping> diff --git a/module/Application/src/Application/Entity/Db/Privilege.php b/module/Application/src/Application/Entity/Db/Privilege.php new file mode 100644 index 0000000000000000000000000000000000000000..36449a152911b20c2c6ff8134c66c20d33de9a70 --- /dev/null +++ b/module/Application/src/Application/Entity/Db/Privilege.php @@ -0,0 +1,195 @@ +<?php + +namespace Application\Entity\Db; + +use Doctrine\ORM\Mapping as ORM; + +/** + * Privilege + */ +class Privilege +{ + /** + * @var string + */ + private $code; + + /** + * @var string + */ + private $libelle; + + /** + * @var integer + */ + private $id; + + /** + * @var \Application\Entity\Db\Ressource + */ + private $ressource; + + /** + * @var \Doctrine\Common\Collections\Collection + */ + private $typeRole; + + /** + * @var \Doctrine\Common\Collections\Collection + */ + private $statut; + + /** + * Constructor + */ + public function __construct() + { + $this->typeRole = new \Doctrine\Common\Collections\ArrayCollection(); + $this->statut = new \Doctrine\Common\Collections\ArrayCollection(); + } + + /** + * Set code + * + * @param string $code + * @return Privilege + */ + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + /** + * Get code + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Set libelle + * + * @param string $libelle + * @return Privilege + */ + public function setLibelle($libelle) + { + $this->libelle = $libelle; + + return $this; + } + + /** + * Get libelle + * + * @return string + */ + public function getLibelle() + { + return $this->libelle; + } + + /** + * Get id + * + * @return integer + */ + public function getId() + { + return $this->id; + } + + /** + * Set ressource + * + * @param \Application\Entity\Db\Ressource $ressource + * @return Privilege + */ + public function setRessource(\Application\Entity\Db\Ressource $ressource = null) + { + $this->ressource = $ressource; + + return $this; + } + + /** + * Get ressource + * + * @return \Application\Entity\Db\Ressource + */ + public function getRessource() + { + return $this->ressource; + } + + /** + * Add typeRole + * + * @param \Application\Entity\Db\TypeRole $typeRole + * @return Privilege + */ + public function addTypeRole(\Application\Entity\Db\TypeRole $typeRole) + { + $this->typeRole[] = $typeRole; + + return $this; + } + + /** + * Remove typeRole + * + * @param \Application\Entity\Db\TypeRole $typeRole + */ + public function removeTypeRole(\Application\Entity\Db\TypeRole $typeRole) + { + $this->typeRole->removeElement($typeRole); + } + + /** + * Get typeRole + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getTypeRole() + { + return $this->typeRole; + } + + /** + * Add statut + * + * @param \Application\Entity\Db\StatutIntervenant $statut + * @return Privilege + */ + public function addStatut(\Application\Entity\Db\StatutIntervenant $statut) + { + $this->statut[] = $statut; + + return $this; + } + + /** + * Remove statut + * + * @param \Application\Entity\Db\StatutIntervenant $statut + */ + public function removeStatut(\Application\Entity\Db\StatutIntervenant $statut) + { + $this->statut->removeElement($statut); + } + + /** + * Get statut + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getStatut() + { + return $this->statut; + } +} diff --git a/module/Application/src/Application/Entity/Db/Ressource.php b/module/Application/src/Application/Entity/Db/Ressource.php new file mode 100644 index 0000000000000000000000000000000000000000..4b1067b49bb3e49e0454850ac33510e8cecfcadd --- /dev/null +++ b/module/Application/src/Application/Entity/Db/Ressource.php @@ -0,0 +1,83 @@ +<?php + +namespace Application\Entity\Db; + +use Doctrine\ORM\Mapping as ORM; + +/** + * Ressource + */ +class Ressource +{ + /** + * @var string + */ + private $code; + + /** + * @var string + */ + private $libelle; + + /** + * @var integer + */ + private $id; + + + /** + * Set code + * + * @param string $code + * @return Ressource + */ + public function setCode($code) + { + $this->code = $code; + + return $this; + } + + /** + * Get code + * + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * Set libelle + * + * @param string $libelle + * @return Ressource + */ + public function setLibelle($libelle) + { + $this->libelle = $libelle; + + return $this; + } + + /** + * Get libelle + * + * @return string + */ + public function getLibelle() + { + return $this->libelle; + } + + /** + * Get id + * + * @return integer + */ + public function getId() + { + return $this->id; + } +} diff --git a/module/Application/src/Application/Entity/Db/StatutIntervenant.php b/module/Application/src/Application/Entity/Db/StatutIntervenant.php index b70b9dbd854dae0b41ea62b15b145513c3637048..dd3c532afbd7bc57b11149efbf5e0720ccf7b359 100644 --- a/module/Application/src/Application/Entity/Db/StatutIntervenant.php +++ b/module/Application/src/Application/Entity/Db/StatutIntervenant.php @@ -2,6 +2,8 @@ namespace Application\Entity\Db; +use Zend\Permissions\Acl\Resource\ResourceInterface; + /** * StatutIntervenant */ @@ -222,6 +224,11 @@ class StatutIntervenant implements HistoriqueAwareInterface, ValiditeAwareInterf */ private $typePieceJointeStatut; + /** + * @var \Doctrine\Common\Collections\Collection + */ + private $privilege; + /** * * @return boolean @@ -814,4 +821,82 @@ class StatutIntervenant implements HistoriqueAwareInterface, ValiditeAwareInterf { return $this->typePieceJointeStatut; } + + /** + * Constructor + */ + public function __construct() + { + $this->typeAgrementStatut = new \Doctrine\Common\Collections\ArrayCollection(); + $this->typePieceJointeStatut = new \Doctrine\Common\Collections\ArrayCollection(); + $this->privilege = new \Doctrine\Common\Collections\ArrayCollection(); + } + + + /** + * Add privilege + * + * @param \Application\Entity\Db\Privilege $privilege + * @return StatutIntervenant + */ + public function addPrivilege(\Application\Entity\Db\Privilege $privilege) + { + $this->privilege[] = $privilege; + + return $this; + } + + /** + * Remove privilege + * + * @param \Application\Entity\Db\Privilege $privilege + */ + public function removePrivilege(\Application\Entity\Db\Privilege $privilege) + { + $this->privilege->removeElement($privilege); + } + + /** + * Get privilege + * + * @param ResourceInterface|string|null $resource + * @return \Doctrine\Common\Collections\Collection + */ + public function getPrivilege( $resource=null ) + { + return $this->privilege->filter( function(Privilege $privilege) use ($resource){ + if (empty($resource)){ + return true; // pas de filtre + } + if ($resource instanceof ResourceInterface){ + $resource = $resource->getResourceId(); + } + return $privilege->getRessource()->getCode() === $resource; + }); + } + + /** + * Détermine si le type de rôle possède un provilège ou non. + * Si le privilège transmis est un objet de classe Privilege, alors il est inutile de fournir la ressource, sinon il est obligatoire de la préciser + * + * @param Privilege|string $privilege + * @param ResourceInterface|string|null $resource + * @return boolean + * @throws \Common\Exception\LogicException + */ + public function hasPrivilege( $privilege, $resource=null ) + { + if ($privilege instanceof Privilege){ + $resource = $privilege->getRessource(); + $privilege = $privilege->getCode(); + } + if (empty($resource)){ + throw new \Common\Exception\LogicException('La ressource du privilège n\'est pas précisée'); + } + $privileges = $this->getPrivilege($resource); + foreach( $privileges as $priv ){ + if ($priv->getCode() === $privilege) return true; + } + return false; + } } diff --git a/module/Application/src/Application/Entity/Db/TypeRole.php b/module/Application/src/Application/Entity/Db/TypeRole.php index f80e8447eb4943052a89c1d4cc7d26d0a643649a..7baaa24c1cb6bc998b92b54dc3e63ecbe8f02c32 100644 --- a/module/Application/src/Application/Entity/Db/TypeRole.php +++ b/module/Application/src/Application/Entity/Db/TypeRole.php @@ -3,6 +3,7 @@ namespace Application\Entity\Db; use Zend\Permissions\Acl\Role\RoleInterface; +use Zend\Permissions\Acl\Resource\ResourceInterface; /** * TypeRole @@ -44,12 +45,18 @@ class TypeRole implements HistoriqueAwareInterface, RoleInterface */ protected $role; + /** + * @var \Doctrine\Common\Collections\Collection + */ + private $privilege; + /** * */ public function __construct() { $this->role = new \Doctrine\Common\Collections\ArrayCollection(); + $this->privilege = new \Doctrine\Common\Collections\ArrayCollection(); } /** @@ -206,4 +213,71 @@ class TypeRole implements HistoriqueAwareInterface, RoleInterface { return $this->role; } + + /** + * Add privilege + * + * @param \Application\Entity\Db\Privilege $privilege + * @return StatutIntervenant + */ + public function addPrivilege(\Application\Entity\Db\Privilege $privilege) + { + $this->privilege[] = $privilege; + + return $this; + } + + /** + * Remove privilege + * + * @param \Application\Entity\Db\Privilege $privilege + */ + public function removePrivilege(\Application\Entity\Db\Privilege $privilege) + { + $this->privilege->removeElement($privilege); + } + + /** + * Get privilege + * + * @param ResourceInterface|string|null $resource + * @return \Doctrine\Common\Collections\Collection + */ + public function getPrivilege( $resource=null ) + { + return $this->privilege->filter( function(Privilege $privilege) use ($resource){ + if (empty($resource)){ + return true; // pas de filtre + } + if ($resource instanceof ResourceInterface){ + $resource = $resource->getResourceId(); + } + return $privilege->getRessource()->getCode() === $resource; + }); + } + + /** + * Détermine si le type de rôle possède un provilège ou non. + * Si le privilège transmis est un objet de classe Privilege, alors il est inutile de fournir la ressource, sinon il est obligatoire de la préciser + * + * @param Privilege|string $privilege + * @param ResourceInterface|string|null $resource + * @return boolean + * @throws \Common\Exception\LogicException + */ + public function hasPrivilege( $privilege, $resource=null ) + { + if ($privilege instanceof Privilege){ + $resource = $privilege->getRessource(); + $privilege = $privilege->getCode(); + } + if (empty($resource)){ + throw new \Common\Exception\LogicException('La ressource du privilège n\'est pas précisée'); + } + $privileges = $this->getPrivilege($resource); + foreach( $privileges as $priv ){ + if ($priv->getCode() === $privilege) return true; + } + return false; + } } \ No newline at end of file diff --git a/module/Application/src/Application/Provider/Role/RoleProvider.php b/module/Application/src/Application/Provider/Role/RoleProvider.php index e10779d1f55e2c6bf3e24a7f13a0ce3b0e6eb643..5add51a72876b82d95c01ab0ac32050810d9a7c6 100644 --- a/module/Application/src/Application/Provider/Role/RoleProvider.php +++ b/module/Application/src/Application/Provider/Role/RoleProvider.php @@ -79,6 +79,7 @@ class RoleProvider implements ProviderInterface, EntityManagerAwareInterface }else{ $this->roles[$roleId] = new $classname($roleId); } + $this->roles[$roleId]->setTypeRole( $role->getType() ); } } return $this->roles;