Access Control Library
Gleez_ACL provides a lightweight and flexible database-based Access Control Library (ACL) implementation for privileges management. In general, an application may utilize such ACL's to control access to certain protected objects by other requesting objects.
Class declared in MODPATH/gleez/classes/gleez/acl.php on line 29.
bool FALSE
bool TRUE
integer 1
integer 2
string(9) "Anonymous"boolean $cacheIndicates whether perms are cached
bool TRUE
array $_all_permsAll permissions
array(1) ( "user" => array(5) ( "administer permissions" => array(3) ( "title" => string(22) "Administer permissions" "restrict access" => bool TRUE "description" => string(23) "Managing user authority" ) "administer users" => array(3) ( "title" => string(16) "Administer users" "restrict access" => bool TRUE "description" => string(16) "Users management" ) "access profiles" => array(3) ( "title" => string(15) "Access profiles" "restrict access" => bool FALSE "description" => string(22) "Access to all profiles" ) "edit profile" => array(3) ( "title" => string(12) "Edit profile" "restrict access" => bool FALSE "description" => string(29) "The ability to change profile" ) "change own username" => array(3) ( "title" => string(19) "Change own username" "restrict access" => bool TRUE "description" => string(34) "The ability to change own username" ) ) )
array $_permSingle permission
array(0) Retrieves all named permissions
Example:
$permissions = ACL::all();
array - Perms by namepublic static function all()
{
return ACL::$_all_perms;
}
Saves or loads the ACL cache
If your perms will remain the same for a long period of time, use this to reload the ACL from the cache rather than redefining them on every page load.
Example:
if ( ! ACL::cache())
{
// Set perms here
ACL::cache(TRUE);
}
boolean
$save
= bool FALSE - Cache the current permsboolean
$append
= bool FALSE - Append, rather than replace, cached perms when loadingvoid - When saving permsboolean - When loading permspublic static function cache($save = FALSE, $append = FALSE)
{
if ($save)
{
// Cache all defined perms
Kohana::cache('ACL::cache()', ACL::$_all_perms);
}
else
{
if ($perms = Kohana::cache('ACL::cache()'))
{
if ($append)
{
// Append cached perms
ACL::$_all_perms = Arr::merge(ACL::$_all_perms, $perms);
}
else
{
// Replace existing perms
ACL::$_all_perms = $perms;
}
// perms were cached
return ACL::$cache = TRUE;
}
else
{
// perms were not cached
return ACL::$cache = FALSE;
}
}
}
Checks if the current user has permission to access the current request
If the user is not given, used currently active user
string
$perm_name
required - Permession nameModel_User
$user
= NULL - User object [Optional]booleanpublic static function check($perm_name, Model_User $user = NULL)
{
// If we weren't given an auth object
if (is_null($user))
{
// Just get the default instance.
$user = User::active_user();
}
// User #2 has all privileges:
if ($user->id == self::ID_ADMIN)
{
return ACL::ALLOW;
}
// To reduce the number of SQL queries, we cache the user's permissions
// in a static variable.
if ( ! isset(ACL::$_perm[$user->id]))
{
$roles = self::get_user_roles($user);
if ( ! $role_permissions = ACL::role_can($roles))
{
return FALSE;
}
ACL::$_perm[$user->id] = call_user_func_array('array_merge', $role_permissions);
}
return isset(ACL::$_perm[$user->id][$perm_name]);
}
Make sure the user has permission to do the action on this object
Similar to Comment::access but this return TRUE/FALSE instead of exception
string
$action
= string(4) "view" - The action `view|edit|delete` default `view`ORM
$comment
required - The comment objectModel_User
$user
= NULL - The user object to check permission, defaults to logded in userstring
$misc
= NULL - The misc element usually `id|slug` for logging purposebooleanpublic static function comment($action = 'view', ORM $comment, Model_User $user = NULL, $misc = NULL)
{
if ( ! in_array($action, array('view', 'edit', 'delete', 'add', 'list'), TRUE))
{
// If the $action was not one of the supported ones, we return access denied.
Kohana::$log->add(Log::NOTICE, 'Unauthorised attempt to non-existent action :act.',
array(':act' => $action)
);
return FALSE;
}
if ( ! $comment->loaded())
{
// If the $action was not one of the supported ones, we return access denied.
throw new HTTP_Exception_404('Attempt to non-existent comment.');
}
// If no user object is supplied, the access check is for the current user.
if (is_null($user))
{
$user = User::active_user();
}
if (ACL::check('bypass comment access', $user))
{
return TRUE;
}
// Allow other modules to interact with access
Module::event('comment_access', $action, $comment);
if ($action === 'view')
{
if ($comment->status === 'publish' AND ACL::check('access comment', $user))
{
return TRUE;
}
// Check if commenters can view their own unpublished comments.
elseif ($comment->status != 'publish'
AND $comment->author == (int)$user->id
AND $user->id != 1)
{
return TRUE;
}
elseif (ACL::check('administer comment', $user))
{
return TRUE;
}
else
{
return FALSE;
}
}
if ($action === 'edit')
{
if (ACL::check('edit own comment')
AND $comment->author == (int)$user->id
AND $user->id != 1)
{
return TRUE;
}
elseif (ACL::check('administer comment', $user))
{
return TRUE;
}
else
{
return FALSE;
}
}
if ($action === 'delete')
{
if ((ACL::check('delete own comment') OR ACL::check('delete any comment'))
AND $comment->author == (int)$user->id
AND $user->id != 1)
{
return TRUE;
}
elseif (ACL::check('administer comment', $user))
{
return TRUE;
}
else
{
return FALSE;
}
}
return TRUE;
}
Returns a specific permission
string
$name
required - The name of the permission.ACLpublic static function get($name)
{
if ( ! isset(ACL::$_all_perms[$name]))
{
throw new Gleez_Exception('The requested Permission does not exist: :permission',
array(':permission' => $name));
}
return ACL::$_all_perms[$name];
}
Make sure the user has permission to do certain action on this object
Similar to Post::access but this return TRUE/FALSE instead of exception
string
$action
= string(4) "view" - The action `view|edit|delete` default `view`ORM
$post
required - The post objectModel_User
$user
= NULL - The user object to check permission, defaults to logded in userstring
$misc
= NULL - The misc element usually `id|slug` for logging purposebooleanpublic static function post($action = 'view', $post, Model_User $user = NULL, $misc = NULL)
{
if ( ! in_array($action, array('view', 'edit', 'delete', 'add', 'list'), TRUE))
{
// If the $action was not one of the supported ones, we return access denied.
Kohana::$log->add(Log::NOTICE, 'Unauthorised attempt to non-existent action :act.',
array(':act' => $action)
);
return FALSE;
}
if ($post instanceof ORM AND ! $post->loaded())
{
// If the post was not loaded, we return access denied.
throw new HTTP_Exception_404('Attempt to non-existent post.');
}
if ( ! $post instanceof ORM)
{
$post = (object) $post;
}
// If no user object is supplied, the access check is for the current user.
if (is_null($user))
{
$user = User::active_user();
}
if (ACL::check('bypass post access', $user))
{
return TRUE;
}
// Allow other modules to interact with access
Module::event('post_access', $action, $post);
if ($action === 'view')
{
if ($post->status === 'publish' AND ACL::check('access content', $user))
{
return TRUE;
}
// Check if authors can view their own unpublished posts.
elseif ($post->status != 'publish'
AND ACL::check('view own unpublished content', $user)
AND $post->author == (int)$user->id
AND $user->id != 1)
{
return TRUE;
}
else
{
return ACL::check('administer content', $user) OR ACL::check('administer content '.$post->type, $user);
}
}
if ($action === 'edit')
{
if ((ACL::check('edit own '.$post->type) OR ACL::check('edit any '.$post->type))
AND $post->author == (int)$user->id
AND $user->id != 1)
{
return TRUE;
}
else
{
return ACL::check('administer content', $user) OR ACL::check('administer content '.$post->type, $user);
}
}
if ($action === 'delete')
{
if ((ACL::check('delete own '.$post->type) OR ACL::check('delete any '.$post->type))
AND $post->author == (int)$user->id
AND $user->id != 1)
{
return TRUE;
}
else
{
return ACL::check('administer content', $user) OR ACL::check('administer content '.$post->type, $user);
}
}
return TRUE;
}
Check permission for current user
Checks permission and redirects if is required to URL
defined in $route
string
$perm_name
required - Permission namestring
$route
= NULL - Route name [Optional]array
$uri
= array(0) - Additional route params [Optional]public static function redirect($perm_name, $route = NULL, array $uri = array())
{
if ( ! ACL::check($perm_name))
{
if ( ! is_null($route) AND is_string($route))
{
Request::initial()->redirect(Route::get($route)->uri($uri), 403);
return;
}
Kohana::$log->add(Log::ALERT, 'Unauthorised access attempt to action :act.',
array(':act' => $perm_name)
);
// If the action is set and the role hasn't been matched, the user doesn't have permission.
throw new HTTP_Exception_403('Unauthorised access attempt to action :act.',
array(':act' => $perm_name)
);
}
}
Check permission for user
If the user doesn't have this permission,
failed with an HTTP_Exception_403 or execute $callback if it is defined
Example with a callable function:
ACL::required(
'administer site',
NULL,
$this->request->redirect(Route::get('user')->uri(array('action' => 'login')))
);
Simple check:
ACL::required('administer site');
string
$perm_name
required - Permession nameModel_User
$user
= NULL - User object [Optional]callable
$callback
= NULL - A callable function that execute if it is defined [Optional]array
$args
= array(0) - The callback's argumentsbooleanpublic static function required($perm_name, Model_User $user = NULL, $callback = NULL, array $args = array())
{
if ( ! ACL::check($perm_name, $user))
{
if ( ! is_null($callback))
{
// Check if the $callback is a valid callback
if ( ! is_callable($callback))
{
throw new Exception('An invalid callback was added to the ACL::required().');
}
call_user_func($callback, $args);
return;
}
Kohana::$log->add(Log::ALERT, 'Unauthorised access attempt to action :act.',
array(':act' => $perm_name)
);
// If the action is set and the role hasn't been matched, the user doesn't have permission.
throw new HTTP_Exception_403('Unauthorised access attempt to action :act.',
array(':act' => $perm_name)
);
}
}
Checks whether the role(s) have some permission(s)
array
$roles
required - An array of roles as id => nameboolean - FALSE If the role(s) doesn't have any permissionarray - Role(s) with permission(s) as arraypublic static function role_can($roles)
{
$perms = array();
if (is_array($roles))
{
$result = DB::select('rid', 'permission')
->from('permissions')
->where('rid', 'IN', array_keys($roles))
->as_object(TRUE)
->execute();
if ( ! count($result))
{
return FALSE;
}
foreach ($result as $row)
{
$perms[$row->rid][$row->permission] = ACL::ALLOW;
}
}
return $perms;
}
Sets up a named Permission and returns it.
Example:
ACL::set('admin/widgets',
array(
'administer site widgets',
'administer admin widgets'
)
);
string
$name
required - Permission namearray
$access_names
required - Access keysACLpublic static function set($name, array $access_names)
{
// Adds the action to the action array and returns it.
return ACL::$_all_perms[$name] = $access_names;
}
Get all roles for user
Model_User
$user
required - User objectarray - All roles for userprivate static function get_user_roles(Model_User $user)
{
$roles = array();
// User #1 is guest
if ($user->id == self::ID_GUEST)
{
$roles[self::ID_GUEST] = self::ANONYMOUS_ROLE;
}
else
{
// Loop through each role in the object
foreach ($user->roles() as $role)
{
$roles[$role->id] = $role->name;
}
}
return $roles;
}