Commit 2b13a20f authored by Laurent Lécluse's avatar Laurent Lécluse
Browse files

Intégration de la gestion des privilèges et des droits.

parent 87b6f3a7
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace UnicaenAuth; namespace UnicaenAuth;
use UnicaenAuth\Guard\PrivilegeController;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface; use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface; use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\ServiceProviderInterface; use Zend\ModuleManager\Feature\ServiceProviderInterface;
...@@ -23,6 +24,8 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface ...@@ -23,6 +24,8 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
return include __DIR__ . '/config/module.config.php'; return include __DIR__ . '/config/module.config.php';
} }
/** /**
* *
* @return array * @return array
...@@ -42,26 +45,30 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface ...@@ -42,26 +45,30 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
]; ];
} }
/** /**
* This method is called once the MVC bootstrapping is complete, * This method is called once the MVC bootstrapping is complete,
* after the "loadModule.post" event, once $application->bootstrap() is called. * after the "loadModule.post" event, once $application->bootstrap() is called.
* *
* @param EventInterface $e * @param EventInterface $e
*
* @see BootstrapListenerInterface * @see BootstrapListenerInterface
*/ */
public function onBootstrap(\Zend\EventManager\EventInterface $e) /* @var \Zend\Mvc\MvcEvent $e */ public function onBootstrap(\Zend\EventManager\EventInterface $e)
/* @var \Zend\Mvc\MvcEvent $e */
{ {
$application = $e->getApplication(); $application = $e->getApplication();
/* @var $services \Zend\ServiceManager\ServiceManager */ /* @var $services \Zend\ServiceManager\ServiceManager */
$services = $application->getServiceManager(); $services = $application->getServiceManager();
// transmission des ACL aux aides de vue de navigation // transmission des ACL aux aides de vue de navigation
try { try {
$authorizeService = $services->get('BjyAuthorize\Service\Authorize'); /* @var $authorizeService \BjyAuthorize\Service\Authorize */ $authorizeService = $services->get('BjyAuthorize\Service\Authorize');
/* @var $authorizeService \BjyAuthorize\Service\Authorize */
\Zend\View\Helper\Navigation::setDefaultAcl($authorizeService->getAcl()); \Zend\View\Helper\Navigation::setDefaultAcl($authorizeService->getAcl());
\Zend\View\Helper\Navigation::setDefaultRole($authorizeService->getIdentity()); \Zend\View\Helper\Navigation::setDefaultRole($authorizeService->getIdentity());
} } catch (\Zend\ServiceManager\Exception\ServiceNotFoundException $snfe) {
catch (\Zend\ServiceManager\Exception\ServiceNotFoundException $snfe) {
// pas de module BjyAuthorize : pas d'ACL // pas de module BjyAuthorize : pas d'ACL
} }
...@@ -75,21 +82,21 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface ...@@ -75,21 +82,21 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
$router->addRoutes([ $router->addRoutes([
// remplace les routes existantes (cf. config du module) // remplace les routes existantes (cf. config du module)
'zfcuser' => [ 'zfcuser' => [
'type' => 'Literal', 'type' => 'Literal',
'priority' => 1000, 'priority' => 1000,
'options' => [ 'options' => [
'route' => '/auth', 'route' => '/auth',
'defaults' => [ 'defaults' => [
'controller' => 'zfcuser', 'controller' => 'zfcuser',
'action' => 'index', 'action' => 'index',
], ],
], ],
'may_terminate' => true, 'may_terminate' => true,
'child_routes' => [ 'child_routes' => [
'login' => [ 'login' => [
'type' => 'Literal', 'type' => 'Literal',
'options' => [ 'options' => [
'route' => '/connexion', 'route' => '/connexion',
'defaults' => [ 'defaults' => [
'controller' => 'zfcuser', 'controller' => 'zfcuser',
'action' => 'authenticate', // zappe l'action 'login' 'action' => 'authenticate', // zappe l'action 'login'
...@@ -97,9 +104,9 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface ...@@ -97,9 +104,9 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
], ],
], ],
'logout' => [ 'logout' => [
'type' => 'Literal', 'type' => 'Literal',
'options' => [ 'options' => [
'route' => '/deconnexion', 'route' => '/deconnexion',
'defaults' => [ 'defaults' => [
'controller' => 'zfcuser', 'controller' => 'zfcuser',
'action' => 'logout', 'action' => 'logout',
...@@ -107,11 +114,13 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface ...@@ -107,11 +114,13 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
], ],
], ],
], ],
] ],
]); ]);
} }
} }
/** /**
* *
* @return array * @return array
...@@ -122,14 +131,50 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface ...@@ -122,14 +131,50 @@ class Module implements ConfigProviderInterface, ServiceProviderInterface
return [ return [
'factories' => [ 'factories' => [
// verrue pour forcer le label de l'identifiant qqsoit l'options 'auth_identity_fields' // verrue pour forcer le label de l'identifiant qqsoit l'options 'auth_identity_fields'
'zfcuser_login_form' => function($sm) { 'zfcuser_login_form' => function ($sm) {
$options = $sm->get('zfcuser_module_options'); $options = $sm->get('zfcuser_module_options');
$form = new \ZfcUser\Form\Login(null, $options); $form = new \ZfcUser\Form\Login(null, $options);
$form->setInputFilter(new \ZfcUser\Form\LoginFilter($options)); $form->setInputFilter(new \ZfcUser\Form\LoginFilter($options));
$form->get('identity')->setLabel("Username"); $form->get('identity')->setLabel("Username");
return $form; return $form;
}, },
], ],
]; ];
} }
/**
* Retourne le menu de navigation (à placer où vous voulez)!!
*
* @return array
*/
static public function getDroitsNavigation($label=null, $title=null)
{
if (!$label) $label = "Droits d'accès";
if (!$title) $title = "Gestion des droits d'accès";
return [
'label' => $label,
'title' => $title,
'route' => 'droits',
'resource' => PrivilegeController::getResourceId('UnicaenAuth\Controller\Droits','index'),
'pages' => [
'roles' => [
'label' => "Rôles",
'title' => "Gestion des rôles",
'route' => 'droits/roles',
'resource' => PrivilegeController::getResourceId('UnicaenAuth\Controller\Droits','roles'),
'withtarget' => true,
],
'privileges' => [
'label' => "Privilèges",
'title' => "Gestion des privilèges",
'route' => 'droits/privileges',
'resource' => PrivilegeController::getResourceId('UnicaenAuth\Controller\Droits','privileges'),
'withtarget' => true,
],
],
];
}
} }
\ No newline at end of file
This diff is collapsed.
...@@ -16,6 +16,11 @@ $settings = [ ...@@ -16,6 +16,11 @@ $settings = [
* (i.e. créer un compte dans la table des utilisateurs). * (i.e. créer un compte dans la table des utilisateurs).
*/ */
'enable_registration' => false, 'enable_registration' => false,
/**
* Nom du gestionnaire d'entités doctrine qui sera utilisé pour accéder à la base de données des rôles,
* utilisateurs et privilèges.
*/
//'entity_manager_name' => 'doctrine.entitymanager.orm_default',
]; ];
/** /**
......
...@@ -9,6 +9,7 @@ CREATE TABLE user ( ...@@ -9,6 +9,7 @@ CREATE TABLE user (
UNIQUE INDEX `unique_username` (`username` ASC) UNIQUE INDEX `unique_username` (`username` ASC)
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `user_role` ( CREATE TABLE IF NOT EXISTS `user_role` (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` INT(11) NOT NULL AUTO_INCREMENT,
`role_id` VARCHAR(64) NOT NULL, `role_id` VARCHAR(64) NOT NULL,
...@@ -21,6 +22,7 @@ CREATE TABLE IF NOT EXISTS `user_role` ( ...@@ -21,6 +22,7 @@ CREATE TABLE IF NOT EXISTS `user_role` (
CONSTRAINT `fk_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `user_role` (`id`) ON DELETE SET NULL CONSTRAINT `fk_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `user_role` (`id`) ON DELETE SET NULL
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci; ) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `user_role_linker` ( CREATE TABLE IF NOT EXISTS `user_role_linker` (
`user_id` INT(11) NOT NULL, `user_id` INT(11) NOT NULL,
`role_id` INT(11) NOT NULL, `role_id` INT(11) NOT NULL,
...@@ -53,6 +55,7 @@ CREATE TABLE IF NOT EXISTS privilege ( ...@@ -53,6 +55,7 @@ CREATE TABLE IF NOT EXISTS privilege (
CONSTRAINT fk_categorie_id FOREIGN KEY (categorie_id) REFERENCES categorie_privilege (id) ON DELETE CASCADE CONSTRAINT fk_categorie_id FOREIGN KEY (categorie_id) REFERENCES categorie_privilege (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS role_privilege ( CREATE TABLE IF NOT EXISTS role_privilege (
role_id INT(11) NOT NULL, role_id INT(11) NOT NULL,
privilege_id INT(11) NOT NULL, privilege_id INT(11) NOT NULL,
...@@ -63,8 +66,25 @@ CREATE TABLE IF NOT EXISTS role_privilege ( ...@@ -63,8 +66,25 @@ CREATE TABLE IF NOT EXISTS role_privilege (
CONSTRAINT fk_rp_privilege_id FOREIGN KEY (privilege_id) REFERENCES privilege (id) ON DELETE CASCADE CONSTRAINT fk_rp_privilege_id FOREIGN KEY (privilege_id) REFERENCES privilege (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci;
-- Données
INSERT INTO `user_role` (`id`, `role_id`, `is_default`, `parent_id`) VALUES INSERT INTO `user_role` (`id`, `role_id`, `is_default`, `parent_id`) VALUES
(1, 'Standard', 1, NULL), (1, 'Standard', 1, NULL),
(2, 'Gestionnaire', 0, 1), (2, 'Gestionnaire', 0, 1),
(3, 'Super-gestionnaire', 0, 2), (3, 'Super-gestionnaire', 0, 2),
(4, 'Administrateur de l''application', 0, 3); (4, 'Administrateur', 0, 3);
INSERT INTO `categorie_privilege` (`id`, `code`, `libelle`, `ordre`) VALUES
(1, 'droit', 'Gestion des droits', 1);
INSERT INTO `privilege` (`id`, `categorie_id`, `code`, `libelle`, `ordre`) VALUES
(1, 1, 'role-visualisation', 'Rôles - Visualisation', 1),
(2, 1, 'role-edition', 'Rôles - Édition', 2),
(3, 1, 'privilege-visualisation', 'Privilèges - Visualisation', 3),
(4, 1, 'privilege-edition', 'Privilèges - Édition', 4);
INSERT INTO `role_privilege` (`role_id`, `privilege_id`) VALUES
(4, 1),
(4, 2),
(4, 3),
(4, 4);
\ No newline at end of file
CREATE TABLE "USER" CREATE TABLE USER
( "ID" NUMBER(*,0) NOT NULL ENABLE, ( "ID" NUMBER(*,0) NOT NULL ENABLE,
"USERNAME" VARCHAR2(255 CHAR), "USERNAME" VARCHAR2(255 CHAR),
"EMAIL" VARCHAR2(255 CHAR), "EMAIL" VARCHAR2(255 CHAR),
...@@ -8,7 +8,7 @@ CREATE TABLE "USER" ...@@ -8,7 +8,7 @@ CREATE TABLE "USER"
CONSTRAINT "USER_USERNAME_UN" UNIQUE ("USERNAME") CONSTRAINT "USER_USERNAME_UN" UNIQUE ("USERNAME")
); );
CREATE TABLE "USER_ROLE" CREATE TABLE USER_ROLE
( "ID" NUMBER(*,0) NOT NULL ENABLE, ( "ID" NUMBER(*,0) NOT NULL ENABLE,
"ROLE_ID" VARCHAR2(64 CHAR) NOT NULL ENABLE, "ROLE_ID" VARCHAR2(64 CHAR) NOT NULL ENABLE,
"IS_DEFAULT" NUMBER(38,0) NOT NULL ENABLE, "IS_DEFAULT" NUMBER(38,0) NOT NULL ENABLE,
...@@ -19,7 +19,7 @@ CREATE TABLE "USER_ROLE" ...@@ -19,7 +19,7 @@ CREATE TABLE "USER_ROLE"
); );
CREATE INDEX "USER_ROLE_PARENT__IDX" ON "USER_ROLE" ("PARENT_ID"); CREATE INDEX "USER_ROLE_PARENT__IDX" ON "USER_ROLE" ("PARENT_ID");
CREATE TABLE "OSE"."USER_ROLE_LINKER" CREATE TABLE USER_ROLE_LINKER
( "USER_ID" NUMBER(*,0) NOT NULL ENABLE, ( "USER_ID" NUMBER(*,0) NOT NULL ENABLE,
"ROLE_ID" NUMBER(*,0) NOT NULL ENABLE, "ROLE_ID" NUMBER(*,0) NOT NULL ENABLE,
CONSTRAINT "USER_ROLE_LINKER_PK" PRIMARY KEY ("USER_ID", "ROLE_ID") CONSTRAINT "USER_ROLE_LINKER_PK" PRIMARY KEY ("USER_ID", "ROLE_ID")
...@@ -27,4 +27,3 @@ CREATE TABLE "OSE"."USER_ROLE_LINKER" ...@@ -27,4 +27,3 @@ CREATE TABLE "OSE"."USER_ROLE_LINKER"
CONSTRAINT "USER_ROLE_USER_ROLE_FK" FOREIGN KEY ("ROLE_ID") REFERENCES "USER_ROLE" ("ID") ON DELETE CASCADE ENABLE CONSTRAINT "USER_ROLE_USER_ROLE_FK" FOREIGN KEY ("ROLE_ID") REFERENCES "USER_ROLE" ("ID") ON DELETE CASCADE ENABLE
); );
CREATE INDEX "USER_ROLE_LINKER_ROLE_IDX" ON "USER_ROLE_LINKER" ("ROLE_ID"); CREATE INDEX "USER_ROLE_LINKER_ROLE_IDX" ON "USER_ROLE_LINKER" ("ROLE_ID");
CREATE INDEX "USER_ROLE_LINKER_USER_IDX" ON "USER_ROLE_LINKER" ("USER_ID");
\ No newline at end of file
<?php
namespace UnicaenAuth\Assertion;
use Zend\Mvc\MvcEvent;
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Assertion\AssertionInterface;
use Zend\Permissions\Acl\Resource\ResourceInterface;
use Zend\Permissions\Acl\Role\RoleInterface;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorAwareTrait;
/**
* Description of AbstractAssertion
*
* @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
*/
abstract class AbstractAssertion implements AssertionInterface, ServiceLocatorAwareInterface
{
use ServiceLocatorAwareTrait;
/**
* !!!! Pour éviter l'erreur "Serialization of 'Closure' is not allowed"... !!!!
*
* @return array
*/
public function __sleep()
{
return [];
}
/**
* Returns true if and only if the assertion conditions are met
*
* This method is passed the ACL, Role, Resource, and privilege to which the authorization query applies. If the
* $role, $this->resource, or $privilege parameters are null, it means that the query applies to all Roles, Resources, or
* privileges, respectively.
*
* @param Acl $acl
* @param RoleInterface $role
* @param ResourceInterface $resource
* @param string $privilege
*
* @return bool
*/
public final function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
{
switch (true) {
case $this->detectPrivilege($resource):
return $this->assertPrivilege($acl, $role, ltrim(strstr($resource, '/'), '/'), $privilege);
case $this->detectController($resource):
$resource = (string)$resource;
$spos = strpos($resource, '/') + 1;
$dpos = strrpos($resource, ':') + 1;
$controller = substr($resource, $spos, $dpos - $spos - 1);
$action = substr($resource, $dpos);
return $this->assertController($acl, $role, $controller, $action, $privilege);
case $this->detectEntity($resource):
return $this->assertEntity($acl, $role, $resource, $privilege);
default:
return $this->assertOther($acl, $role, $resource, $privilege);
}
}
/**
*
* @param string $resource
*
* @return boolean
*/
private function detectPrivilege($resource = null)
{
if ($resource instanceof ResourceInterface) $resource = $resource->getResourceId();
return is_string($resource) && 0 === strpos($resource, 'privilege/');
}
/**
*
* @param Acl $acl
* @param RoleInterface $role
* @param string $privilege
* @param string $subPrivilege
*
* @return boolean
*/
protected function assertPrivilege(Acl $acl, RoleInterface $role = null, $privilege = null, $subPrivilege = null)
{
return true;
}
/**
*
* @param string $resource
*
* @return boolean
*/
private function detectController($resource = null)
{
if ($resource instanceof ResourceInterface) $resource = $resource->getResourceId();
return 0 === strpos($resource, 'controller/');
}
/**
*
* @param Acl $acl
* @param RoleInterface $role
* @param string $controller
* @param string $action
* @param string $privilege
*
* @return boolean
*/
protected function assertController(Acl $acl, RoleInterface $role = null, $controller = null, $action = null, $privilege = null)
{
return true;
}
/**
*
* @param string $resource
*
* @return boolean
*/
private function detectEntity($resource = null)
{
return
is_object($resource)
&& method_exists($resource, 'getId');
}
/**
*
* @param Acl $acl
* @param RoleInterface $role
* @param ResourceInterface $entity
* @param string $privilege
*
* @return boolean
*/
protected function assertEntity(Acl $acl, RoleInterface $role = null, ResourceInterface $entity = null, $privilege = null)
{
return true;
}
/**
*
* @param Acl $acl
* @param RoleInterface $role
* @param ResourceInterface $entity
* @param string $privilege
*
* @return boolean
*/
protected function assertOther(Acl $acl, RoleInterface $role = null, ResourceInterface $entity = null, $privilege = null)
{
return true;
}
/**
*
* @return MvcEvent
*/
protected function getMvcEvent()
{
$application = $this->getServiceLocator()->get('Application');
return $application->getMvcEvent();
}
}
\ No newline at end of file
<?php
namespace UnicaenAuth\Controller;
use UnicaenAuth\Entity\Db\Privilege;
use UnicaenAuth\Entity\Db\Role;
use UnicaenAuth\Form\Droits\Traits\RoleFormAwareTrait;
use UnicaenAuth\Service\Traits\PrivilegeServiceAwareTrait;
use UnicaenAuth\Service\Traits\RoleServiceAwareTrait;
use Zend\Form\Form;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
/**
* Description of DroitsController
*
*
* @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
*/
class DroitsController extends AbstractActionController
{
use RoleServiceAwareTrait;
use RoleFormAwareTrait;
use PrivilegeServiceAwareTrait;
/**
*
* @return type
*/
public function indexAction()
{
return [];
}
public function rolesAction()
{
$roles = $this->getServiceRole()->getList();
return compact('roles');
}
public function roleEditionAction()
{
$roleId = $this->params()->fromRoute('role');
$role = $this->getServiceRole()->get($roleId);
$errors = [];
$form = $this->getFormDroitsRole();
if (empty($role)) {
$title = 'Création d\'un nouveau rôle';
$role = $this->getServiceRole()->newEntity();
$form->setObject($role);
} else {
$title = 'Édition du rôle';
$form->bind($role);
}
$form->setAttribute('action', $this->url()->fromRoute(null, [], [], true));
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());