-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication Guide
auth-introductionauth-configauth-aclauth-case
Authentication management is an important section of website. It mainly contains user roles definition, resources definition, and authentication distribute. In this user guide, we will introduce the following content:
- Module configuration creation for defining roles, resources and permission.
- Using
Pi\Acl\Aclto add rules and check permission.
Pi use acl.php and page.php to defind roles, resources and rules. Therefore users must first create the configuration files of module in the config folder.
config\acl.php
The array structure of acl.php must be like the following:
return array(
// Definition roles
'roles' => array(
// Case 1
'roleName' => array(
'title' => 'Title',
'parents' => array('parent'),
),
// Case 2
'admin' => array(
'title' => __('Administrator'),
'section' => 'admin',
),
// Case 3
'staff' => array(
'title' => __('Staff'),
'section' => 'admin',
),
// Case 4
'manager' => array(
'title' => __('Manager'),
'section' => 'admin',
'parents' => array('admin', 'staff'),
),
...
),
// Definition resources
'resources' => array(
...
),
);
The above acl configuration allowed users to defind roles and module resources, let's take a look at roles difinition first.
- The
rolesfield tells application the array is used to add roles to application, in the four case - the
roleName,admin,staffandmanagerare the role name. And thetitlefield indicate the role tile.
Note: The difference between role name and role title is that: role name is used to distinguish different roles, so it must be unique; and the role title can be the same.
-
sectionfield - this value is used to decide which section a role is belonged to. It can beadmin,front, and it can be ignored if the role is in front section. Refer to Case 1. -
parentsfield - this value indicates the inherited relationship between different roles. Its parents are passed by an array, if the array contains only one data, it called single inheritance, or else, called multi-inheritance. Refer to Case 2, 3, 4.
Note: In Pi, a child role will inherit the allow permission of its parent roles, which is said that if a parent allow a resource, the child will can not deny the resource in split of child choose the deny permission.
Definition resources
What is a resource, in Pi, a resources can be a page (it also known as controller/action), or a string.
The following codes is the resources part of the acl.php:
'resources' => array(
// Front resources
'front' => array(
'category' => array(
'module' => 'system',
'title' => __('Category'),
'parent' => 'parentCategory',
'access' => array(
'guest' => 0,
'member' => 1,
),
'privileges' => array(
'read' => array(
'title' => 'Read articles',
),
'post' => array(
'title' => 'Post articles',
'access' => array(
'guest' => 0,
),
),
'delete' => array(
'title' => 'Post articles',
'access' => array(
'guest' => 0,
'member' => 0,
),
),
),
),
...
),
'admin' => array(
...
),
),
The code above will insert a system type resource into the acl_resource table.
In the array, the front and admin fields indicate the resource section. And the category field indicates the resource name.
-
modulefield - indicates the resource module, it can be ignored, therefore the current module name will be used. -
titlefield - resource title. -
parentfield - this field indicates the current resource's parent, it will insert current resource as a child of its parent resource. The value of this field can be string or array.The value must be exist resource name if it is string:
'parent' => 'categoryName',The value can contain resource information if it is an array:
'parent' => array( 'section' => 'admin', 'module' => 'system', ), -
accessfield - this field defines the rules between roles and resources, theguest,memberis the role name, and the value 0 and 1 define whether the role has permission to access this resource, it will be allowed if this value is set to 1. -
privilegesfield - NOT ACHIEVE YET!
Note: acturally, the access field and privileges can not define at the same time in the same resource.
config/page.php
The page.php configuration file is used to add pages and page type resources of a module. It will define the page's controller and action, and its parent resource user defined in the acl.php.
return array(
// front pages
'front' => array(
...
),
'admin' => array(
// Case 1
array(
'title' => __('All articles'),
'module' => 'article',
'controller' => 'article',
'action' => 'published',
'cache_ttl' => 60,
'cache_level' => 'role',
'block' => 0,
'permission' => array(
'access' => array(
'manager' => 1,
'staff' => 0,
),
),
),
// Case 2
array(
'controller' => 'dashboard',
'permission' => array(
'parent' => 'category',
),
),
),
// Exception of admin pages to skip ACL check
'exception' => array(
array(
'controller' => 'ajax',
),
array(
'controller' => 'upload',
'action' => 'upload',
),
),
);
In the codes, we introduce two cases, the first one define a page with cache and permissions, and the second one define a page and the permission of which is defined in acl.php.
The declare of the field can be known in the module configuration section of this document.
If user want to define a page resource, case 2 is recommended, in the array:
-
controllerfield - indicates the module controller. -
parentfield - indicates the parent resource defined in theacl.phpand its value is the resource name.
Some controller or action need to skip acl check, then we can use exception field to realize it.
So far, we have defined all the resources, but we have extra thing to do to make it more perfect.
Make navigation hide the denied resource
In the navigation.php configuration, we need to add extra code to help application hide or display menu according to the permission.
config/navigation.php
return array(
...
'admin' => array(
'article' => array(
...
'resource' => array(
'resource' => 'article',
),
),
),
);
In the code, we add a resource array, and assign the resource name article to the resource field. Then the application will check whether current user have permission to access the resource.
Add installing configuration
The last step is to tell the application that we have a acl and page configuration to install, this will be achieve by adding fields in module.php.
config/module.php
return array(
...
'acl' => 'acl.php',
'page' => 'page.php',
);
Note: the acl.php must be defined before page.php, or else permission will not take effect after installs.
Pi\Acl\Acl class is used to manage authentication, it achieve tasks such as:
- Loading user roles;
- Getting resources;
- Adding authentication rules;
- Checking whether a role has permission to access resources.
Methods provided by this class are list as follows:
RowGateway getModel(string $modelName);
Acl setSection(string $section);
string getSection();
Acl setDefault(bool $default);
bool getDefault();
Acl setModule(string $module);
string getModule();
Acl setRole(string $role);
string getRole();
bool addRule(bool|int $allowed, string $role, string $section, string $module, string|int $resource, string $privilege = null);
bool removeRule(string $role, string $section, string $module, string|int $resource, $string $privilege = null);
bool setRule(bool|int $allowed, string $role, string $section, string $module, string|int $resource, string $privilege);
bool isAllowed(string $role, string|array|object $resource, string $privilege = null);
bool checkAccess(string|array|object $resource, string $privilege = null);
array getResources(array|Where $where = null, bool $allowed = true);
array loadRoles(string $role = null);
array loadResources(string|array|Node $resource);
-
Construction
The construction of
Aclneeds two parameters.Parameters
$section: set the resource section, such as:
front,admin.$default: set the default permission, when a rule is not specified.
Examples
$aclHandler = new \Pi\Acl\Acl; $aclHandler = new \Pi\Acl\Acl('admin'); $aclHandler = new \Pi\Acl\Acl('admin', true);
-
getModel
Gets a acl model and set section/module if applicable. That is said, users should set section and module before calling
getModelmethod if he/she when to set section and module.Parameters
$modelName: acl model name, can be
edge,inherit,privilege,resource,roleandrule.Examples
$model = $aclHandler->getModel('role'); $model->getAncestors('manager');
-
setSection($section) and getSection()
Resources section operation methods, used to set section for resources and get current application section.
Parameters
$section: section name, can be
adminandfront.Examples
echo $aclHandler->setSection('admin')->getSection();
Output:
'admin'
-
setDefault($default) and getDefault()
Default permission operation.
Parameters
$default: default permission vaule.
Examples
echo $aclHandler->setDefault(true)->getDefault();
Output:
true
-
setModule($module) and getModule()
Setting resource module and getting current resource module.
Parameters
$module: module name.
Examples
echo $aclHandler->setModule('demo')->getModule();
Output:
'demo'
-
setRole($role) and getRole()
Role operation, the
getRolemethod will load from current authenticated user if role is not set.Parameters
$role: role name.
Examples
Suppose current authentication user is
admin:// Set current role $aclHandler->setRole('manager'); echo $aclHandler->getRole(); // Not set current role echo $aclHandler->getRole();
Output:
'manager' 'admin'
-
addRule()
This method is used to add a rule to database for later use, this method will add a new record into database whatever it is exists.
Parameters
$allowed: whether to allow role to access resources, indicate allowed if set to true.
$role: role name.
$section: resource section.
$module: the name of module resources belong to.
$resource: resource name.
$privilege: resource privilege, can be ignored.
Examples
$aclHandler->setRule(true, 'manager', 'admin', 'demo', $resourceName);
-
removeRule
Remove a exist rule from database.
Parameters
$role: role name.
$section: resource section.
$module: the name of module resources belong to.
$resource: resource name.
$privilege: resource privilege, can be ignored.
Examples
$aclHandler->removeRule('manager', 'admin', 'demo', $resourceName);
-
setRule
This method is also used to add rule, but the difference is that it will update the record if the data is exists.
Parameters
$allowed: whether to allow role to access resources, indicate allowed if set to true.
$role: role name.
$section: resource section.
$module: the name of module resources belong to.
$resource: resource name.
$privilege: resource privilege, can be ignored.
Examples
$aclHandler->setRule(true, 'manager', 'admin', 'demo', $resourceName);
-
isAllowed
This method is used to check access to a resource by given role parameter. It will return true if the resource is allowed to access.
Parameters
$role: role name.
$resource: this parameter can be a string indicate the resource name, or an array contains resource data. The resource type can refer to
loadResourcesmethod.$privilege: resource privilege, can be ignored.
Examples
$aclHandler->isAllowed('manager', array( 'module' => 'system', 'controller' => 'config', )); $aclHandler->isAllowed('manager', 'config');
-
checkAccess
This method is used to access a resource privilege for a given role, if the role is not set, current authentication role will be used.
Parameters
$resource: resource name, as same as
isAllowedmethod.$privilege: privilege name.
// use given role $aclHandler->setRole('manager')->checkAccess(array( 'name' => 'config', )); // use current role $aclHandler->checkAccess(5);
-
getResources
This method is used to get resources to which a group of roles by given conditions.
Parameters
$where: the given conditions.
$allowed: whether to choose allowed resources.
Examples
$aclHandler->getResources(array( 'resource' => 'system', 'module' => 'system', ), false);
-
loadRoles
This method is used to load ancestors of a role from database.
Parameters
$role: role name.
Examples
$aclHandler->loadRoles('manager');
Output:
array( 0 => 'admin', 1 => 'staff', )
-
loadResources
This method is used to load ancestors of a resource from database.
Parameters
$resource
The resource parameter can be string which is the resource name or id, or an array contain resource data.
Examples
-
Case 1: load a page resource (which describes by controller/action) by array, it will return two resource ids which is a system resource id and a page resource id, and the page resource is the child of system resource.
Note: the
modulefield is needed.$resource = array( 'module' => 'system', 'controller' => 'config', ); // Alternate $resource = array( 'type' => 'system', // this field can be ignored 'name' => 'config', ); $aclHandler->loadResources($resource);
Output:
array( 0 => 5, // system resource id 1 => 26, // page resource id )
-
Case 2: load only a system resource, note that do not set 'module' field.
$resource = array( 'type' => 'system', // this field can be ignored 'name' => 'config', ); $aclHandler->loadResources($resource);
Output:
array( 0 => 5, // system resource id )
-
Case 3: load a resource by digit
$aclHandler->loadResources('3'); $aclHandler->loadResources(5);
Output:
array( 0 => 3, )
array( 0 => 4, )
-
Case 4: load a resource by string name
$aclHandler->loadResources('config');
Output:
array( 0 => 4, )
Now we will introduce how to create module authentication by a case, this case will achieve the following tasks:
- Adding a module role and its child to application;
- Adding a page resource (also a navigation menu) and a system resource by configuration;
- Allowing the created roles to access the resource;
- Enabling show the view menu when the user has authentication to access the resource;
- Adding a page resource and a system resource in module;
- Checking whether the role has authentication to access the resources.
Supposing our module named article.
TASK 1, TASK 2 and TASK 3
module/article/config/acl.php
return array(
// Creating roles
'roles' => array(
// Admin role inherit from manager for article module
'contributor' => array(
'title' => __('Contributor'),
'section' => 'admin',
'parents' => array('staff'),
),
// Temporary editor inherit from contributor
'temporary' => array(
'title' => __('Temporary editor'),
'section' => 'admin',
'parents' => array('contributor'),
),
),
// Creating resources
'resources' => array(
'admin' => array(
// Creating a system resource
'editor' => array(
'module' => 'article',
'title' => __('Editor'),
'access' => array(
'temporary' => 1,
),
),
// Page resource, defined in page.php
// This is also the navigation menu of article module
'article' => array(
'module' => 'article',
'title' => __('All article management'),
'access' => array(
'contributor' => 1,
),
),
),
),
);
module/article/config/page.php
return array(
'admin' => array(
// Indicating the article resource is a page resource
array(
'controller' => 'article',
'permission' => array(
'parent' => 'article',
),
),
),
// Exception of admin pages to skip ACL check
'exception' => array(
array(
'controller' => 'ajax',
),
),
);
In the above case, we define two role and two resources, and the contributor role is defined as child role of system role staff, by defining in acl.php to indicate the article resource is a page resource, then the access field is used to tell the application contributor role is allow to access the article resource.
In module, we may have some ajax action, this action is always allowed to access, so we use exception field to tell the application this action do not need acl check.
TASK 4
module/article/config/navigation.php
return array(
'item' => array(
'admin' => array(
'article' => array(
'label' => 'All articles',
'route' => 'admin',
'controller' => 'article',
'resource' => array(
'resource' => 'article',
),
'pages' => array(
...
),
),
),
),
);
In this case, we define a resource field, and assign resource name article to it to tell the application check the authentication of this resource, and decide whether to hidden the navigation menu.
Add configuration file to the module.php
module/article/config/module.php
return array(
...
'acl' => 'acl.php',
'page' => 'page.php',
);
TASK 5 and TASK 6
module/article/src/Controller/Admin/IndexController.php
...
use Pi\Acl\Acl;
class IndexController extends ActionController
{
public function indexAction()
{
...
$acl = new Acl('admin');
// Allow system role to access system resource
$acl->setRule(true, 'contributor', 'admin', $this->getModule(), 'edit');
// Allow system role to access page resource
$acl->setRule(true, 'contributor', 'admin', $this->getModule(), array(
'module' => $this->getModule(),
'controller' => 'index',
'action' => 'perm'
));
// Allow dynmic role to access system resource
$acl->setRule(true, 'editor', 'admin', $this->getModule(), 'delete');
...
}
public function permAction()
{
...
$acl = new Acl('admin');
$acl->setModule($this->getModule());
// Checking page resource
if ($acl->checkAccess(array(
'module' => $this->getModule(),
'controller' => 'index',
'action' => 'perm'
))) {
return $this->jumpToDenied('__denied__');
}
// Checking system resource
$rules['edit'] = $acl->checkAccess('edit');
// Checking resource for dynmic role
$rules['delete'] = $acl->->isAllowed('editor', 'delete');
$this->view()->assign('rules', $rules);
...
}
}
module/article/template/admin/index-perm.phtml
<?php if ($rule['edit']) { ?>
<div><a href="#"><?php echo __('Edit') ?></a></div>
<?php } ?>
<?php if ($rule['delete']) { ?>
<div><a href="#"><?php echo __('Delete') ?></a></div>
<?php } ?>