Gestion des ACL
Installation
Installez le module Ubiquity-acl à partir de l’invite de commande ou des Webtools (partie Composer).
composer require phpmv/ubiquity-acl
Activez ensuite l’affichage de la partie Acl dans les Webtools :
Interface ACL dans les webtools :
Règles Acl
Les ACLs sont utilisées pour définir l’accès à une application Ubiquity. Elles sont définies selon les principes suivants :
- Une application Ubiquity est composée de :
Ressources (éventuellement des contrôleurs, ou des actions de ces contrôleurs)
Rôles, éventuellement attribués à des utilisateurs. Chaque Rôle peut hériter de rôles parents.
Permissions, qui correspondent à un droit de faire. Chaque permission a un niveau (représenté par une valeur entière).
- Règles supplémentaires :
Un AclElement (Allow) accorde une permission à un rôle sur une ressource.
Chaque rôle hérite des autorisations de ses parents, en plus des siennes.
Si un rôle a un certain niveau d’autorisation d’accès à une ressource, il aura également toutes les autorisations d’un niveau inférieur sur cette ressource.
L’association d’une ressource et d’une permission à un contrôleur ou à une action de contrôleur définit un élément map.
- Règles de nommage :
Rôle, en lettres capitales, commençant par une arobase (@USER, @ADMIN, @ALL…).
Permissions, en majuscules, nommées à l’aide d’un verbe (READ, WRITE, OPEN…).
Ressource, majuscule à la première lettre (Produits, Clients…)
Démarrage des ACLs
Le service AclManager peut être démarré directement depuis l’interface webtools, dans la partie Security.
Le service est démarré dans le fichier
services.php
.
\Ubiquity\security\acl\AclManager::startWithCacheProvider();
ACLCacheProvider
Ce fournisseur par défaut vous permet de gérer les ACL définies par des attributs ou des annotations.
AclController
Un AclController permet de gérer automatiquement les accès à ses propres ressources en se basant sur des ACL.
Il est possible de les créer automatiquement à partir des webtools.
Mais il ne s’agit que d’un contrôleur de base, utilisant le trait AclControllerTrait.
Ce contrôleur va juste redéfinir la méthode _getRole
, pour qu’elle renvoie le rôle de l’utilisateur actif, par exemple.
<?php
namespace controllers;
use Ubiquity\controllers\Controller;
use Ubiquity\security\acl\controllers\AclControllerTrait;
use Ubiquity\attributes\items\acl\Allow;
class BaseAclController extends Controller {
use AclControllerTrait;
#[Allow('@ME')]
public function index() {
$this->loadView("BaseAclController/index.html");
}
public function _getRole() {
$_GET['role']??'@ME';//Just for testing: logically, this is the active user's role
}
/**
* {@inheritdoc}
* @see \Ubiquity\controllers\Controller::onInvalidControl()
*/
public function onInvalidControl() {
echo $this->_getRole() . ' is not allowed!';
}
}
- L’autorisation a été accordée pour la ressource :
Sans spécifier la ressource, chaque action du contrôleur est définie comme une ressource.
Sans spécifier la permission, la permission « ALL » est utilisée.
Et cette association est présente dans la map des Acls :
AclController avec authentication
Note
L’utilisation à la fois de WithAuthTrait
et de ``AclControllerTrait`” nécessite de lever l’ambiguïté sur la méthode ``isValid`”.
class BaseAclController extends Controller {
use AclControllerTrait,WithAuthTrait{
WithAuthTrait::isValid insteadof AclControllerTrait;
AclControllerTrait::isValid as isValidAcl;
}
public function isValid($action){
return parent::isValid($action)&& $this->isValidAcl($action);
}
}
Allow avec Rôle, ressource et permission
Allow sans création préalable :
@USER
est autorisé à accéder à la ressource Foo
avec la permission READ
.
use Ubiquity\attributes\items\acl\Allow;
class BaseAclController extends Controller {
use AclControllerTrait;
...
#[Allow('@USER','Foo', 'READ')]
public function foo(){
echo 'foo page allowed for @USER and @ME';
}
}
Note
Le rôle, la ressource et la permission sont automatiquement créés dès qu’ils sont invoqués avec Allow
.
Allow avec création explicite :
use Ubiquity\attributes\items\acl\Allow;
use Ubiquity\attributes\items\acl\Permission;
class BaseAclController extends Controller {
use AclControllerTrait;
...
#[Permission('READ',500)]
#[Allow('@USER','Foo', 'READ')]
public function foo(){
echo 'foo page allowed for @USER and @ME';
}
}
Ajout d’ACL à l’exécution
Que ce soit dans un contrôleur ou dans un service, il est possible d’ajouter des rôles, des ressources, des permissions et des autorisations au moment de l’exécution :
Par exemple :\N- Ajouter un rôle @USER
héritant de @GUEST
.
use Ubiquity\security\acl\AclManager;
AclManager::addRole('@GUEST');
AclManager::addRole('@USER',['@GUEST']);
Définir les ACLs avec une base de données
Les ACL définies dans la base de données s’ajoutent aux ACL définies via les annotations ou les attributs.
Initialisation
L’initialisation permet de créer les tables associées aux ACLs (Role, Resource, Permission, AclElement). Elle ne doit être faite qu’une seule fois, et en mode dev uniquement.
A placer par exemple dans le fichier app/config/bootstrap.php
:
use Ubiquity\controllers\Startup;
use Ubiquity\security\acl\AclManager;
$config=Startup::$config;
AclManager::initializeDAOProvider($config, 'default');
Démarrage
Dans le fichier app/config/services.php
:
use Ubiquity\security\acl\AclManager;
use Ubiquity\security\acl\persistence\AclCacheProvider;
use Ubiquity\security\acl\persistence\AclDAOProvider;
use Ubiquity\orm\DAO;
DAO::start();//Optional, to use only if dbOffset is not default
AclManager::start();
AclManager::initFromProviders([
new AclCacheProvider(), new AclDAOProvider($config)
]);
Stratégies de définition des ACL
Avec peu de ressources :
Définir les autorisations pour chaque action du contrôleur ou chaque groupe d’actions :
Les ressources correspondent logiquement aux contrôleurs, et les permissions aux actions. Mais cette règle peut ne pas être respectée, et une action peut être définie comme une ressource, selon les besoins.
La seule règle obligatoire est qu’une paire contrôleur/action ne peut correspondre qu’à une seule paire ressource/permission (pas nécessairement unique).
namespace controllers;
use Ubiquity\controllers\Controller;
use Ubiquity\security\acl\controllers\AclControllerTrait;
use Ubiquity\attributes\items\acl\Permission;
use Ubiquity\attributes\items\acl\Resource;
#[Resource('Foo')]
#[Allow('@ADMIN')]
class FooController extends Controller {
use AclControllerTrait;
#[Allow('@NONE')]
public function index() {
echo 'index';
}
#[Allow('@USER')]
public function read() {
echo 'read';
}
#[Allow('@USER')]
public function write() {
echo 'write';
}
public function admin() {
echo 'admin';
}
public function _getRole() {
return $_GET['role']??'@NONE';
}
/**
* {@inheritdoc}
* @see \Ubiquity\controllers\Controller::onInvalidControl()
*/
public function onInvalidControl() {
echo $this->_getRole() . ' is not allowed!';
}
}
Avec plus de ressources :
namespace controllers;
use Ubiquity\controllers\Controller;
use Ubiquity\security\acl\controllers\AclControllerTrait;
use Ubiquity\attributes\items\acl\Permission;
use Ubiquity\attributes\items\acl\Resource;
#[Resource('Foo')]
class FooController extends Controller {
use AclControllerTrait;
#[Permission('INDEX',1)]
public function index() {
echo 'index';
}
#[Permission('READ',2)]
public function read() {
echo 'read';
}
#[Permission('WRITE',3)]
public function write() {
echo 'write';
}
#[Permission('ADMIN',10)]
public function admin() {
echo 'admin';
}
public function _getRole() {
return $_GET['role']??'NONE';
}
/**
* {@inheritdoc}
* @see \Ubiquity\controllers\Controller::onInvalidControl()
*/
public function onInvalidControl() {
echo $this->_getRole() . ' is not allowed!';
}
}