Käyttäjäroolit ja oikeudet
Pike sisältää \Pike\Auth\ACL
-luokan, jolla on helppo luoda systeemi, jolla tarkastaa mitä kukin applikaation käyttäjärooli saa, ja ei saa tehdä.
Sisällysluettelo
Peruskäyttö
Setuppi:
use \Pike\Auth\ACL;
$resources = (object) [
'products' => (object) [
'create' => 1 << 1,
'edit' => 1 << 2,
'comment' => 1 << 3,
],
'reviews' => (object) [
'post' => 1 << 1,
'moderate' => 1 << 2,
]
];
$userPermissions = (object) [
ACL::ROLE_EDITOR => (object) [
'products' => ACL::makePermissions(['comment', 'edit'], $resources->products),
'reviews' => ACL::makePermissions('*', $resources->reviews),
],
ACL::ROLE_CONTRIBUTOR => (object) [
'products' => ACL::makePermissions(['comment'], $resources->products),
'reviews' => ACL::makePermissions(['post'], $resources->reviews),
]
];
$acl = new ACL;
$acl->setRules((object)['resources' => $resources,
'userPermissions' => $userPermissions]);
Käyttäminen:
$acl->can(ACL::ROLE_EDITOR, 'create', 'products'); // false
$acl->can(ACL::ROLE_EDITOR, 'edit', 'products'); // true
$acl->can(ACL::ROLE_EDITOR, 'comment', 'products'); // true
$acl->can(ACL::ROLE_EDITOR, 'post', 'reviews'); // true
$acl->can(ACL::ROLE_EDITOR, 'moderate', 'reviews'); // true
$acl->can(ACL::ROLE_CONTRIBUTOR, 'create', 'products'); // false
$acl->can(ACL::ROLE_CONTRIBUTOR, 'edit', 'products'); // false
$acl->can(ACL::ROLE_CONTRIBUTOR, 'comment', 'products'); // true
$acl->can(ACL::ROLE_CONTRIBUTOR, 'post', 'reviews'); // true
$acl->can(ACL::ROLE_CONTRIBUTOR, 'moderate', 'reviews'); // false
Oletuskäyttäytyminen:
// false, jos role|action|resource ei olemassa
$acl->can(NONEXISTING_ROLE, 'post', 'reviews'); // false
$acl->can(ACL::ROLE_EDITOR, 'nonExistingAction', 'reviews'); // false
$acl->can(ACL::ROLE_EDITOR, 'post', 'nonExistingResource'); // false
// true, jos kyseessä super-admin
$acl->can(ACL::ROLE_SUPER_ADMIN, 'nonExistingAction', 'reviews'); // true
$acl->can(ACL::ROLE_SUPER_ADMIN, 'post', 'nonExistingResource'); // true
$acl->can(ACL::ROLE_SUPER_ADMIN, 'kissat koiria', 'gfffögkfhjd'); // true
Liittäminen reitteihin
ACL:n ja HTTP-reitteihin yhdistämiseen tarvitaan kaksi asiaa:
- ACL-ohjeiden lisääminen reittimääritelmiin $router->map(…)
- ACL-ohjeiden prosessointi HTTP-pyyntöjen yhteydessä $router->on(“*”, …)
ACL-ohjeiden lisääminen reittimääritelmiin
...
final class MyModule {
/**
* @param \Pike\AppContext $ctx
*/
public function init(AppContext $ctx): void {
// Ohjeet
// |
$ctx->router->map('POST', '/products', // \/
[ProductController::class, 'handleCreateProduct', 'create:products']
);
$ctx->router->map('PUT', '/products/[i:productId]',
[ProductController::class, 'handleEditProduct', 'edit:products']
);
...
}
...
}
ACL-ohjeiden prosessointi HTTP-pyyntöjen yhteydessä
...
final class MyAuthModule {
/**
* @param \Pike\AppContext $ctx
*/
public function init(AppContext $ctx): void {
$ctx->acl = new \Pike\Auth\ACL;
$ctx->acl->setRules(self::makeMyAclRules());
//
$ctx->router->on('*', function ($req, $res, $next) use ($ctx) {
// Tämä tulisi normaalisti sessiosta ($ctx->auth->getIdentity()->role)
$userRole = \Pike\Auth\ACL::ROLE_EDITOR;
// ks. Step 3
[$action, $resource] = explode(':', $req->routeInfo->myCtx);
if (!$ctx->acl->can($userRole, $action, $resource))
$res->status(403)->json(['err' => 'Not permitted']);
else
$next();
});
}
/**
* @return \stdClass
*/
private static function makeMyAclRules(): \stdClass {
// Nämä tulisi normaalisti esim. tiedostosta tai tietokannasta.
$resources = (object) [
'products' => ...,
'reviews' => ...
];
$userPermissions = (object) [
ACL::ROLE_EDITOR => (object) [
'products' => ...,
'reviews' => ...,
],
ACL::ROLE_CONTRIBUTOR => (object) [
'products' => ...,
'reviews' => ...,
]
];
return (object) [
'resources' => $resources,
'userPermissions' => $userPermissions
];
}
}
Muista myös lisätä prosessoiva moduuli applikaation moduulilistaan. Moduuli tulisi olla aina ensimmäisenä:
$myModules = [new MyAuthModule, ...];
$app = new \Pike\App($myModules);
...