Modules

Gleez_ACL

Access Control Library

Introduction

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.

Dependencies

  • Default Database module
  • Any ORM implementation
  • Gleez User
  • Gleez Core
package
Gleez\ACL
version
2.0
author
Sandeep Sangamreddi - Gleez
Sergey Yakovlev - Gleez
copyright
© 2011-2013 Gleez Technologies
license
http://gleezcms.org/license Gleez CMS License Agreement
todo
Implement their own exceptions (eg. ACL_Exception)

Class declared in MODPATH/gleez/classes/gleez/acl.php on line 29.

Constants

DENY

bool FALSE

ALLOW

bool TRUE

ID_GUEST

integer 1

ID_ADMIN

integer 2

ANONYMOUS_ROLE

string(9) "Anonymous"

Properties

public static boolean $cache

Indicates whether perms are cached

bool TRUE

protected static array $_all_perms

All 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"
        )
    )
)

protected static array $_perm

Single permission

array(0) 

Methods

public static all( ) (defined in Gleez_ACL)

Retrieves all named permissions

Example:
$permissions = ACL::all();

Return Values

  • array - Perms by name

Source Code

public static function all()
{
	return ACL::$_all_perms;
}

public static cache( [ boolean $save = bool FALSE , boolean $append = bool FALSE ] ) (defined in Gleez_ACL)

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); }

Parameters

  • boolean $save = bool FALSE - Cache the current perms
  • boolean $append = bool FALSE - Append, rather than replace, cached perms when loading

Tags

Return Values

  • void - When saving perms
  • boolean - When loading perms

Source Code

public 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;
		}
	}
}

public static check( string $perm_name [, Model_User $user = NULL ] ) (defined in Gleez_ACL)

Checks if the current user has permission to access the current request

If the user is not given, used currently active user

Parameters

  • string $perm_name required - Permession name
  • Model_User $user = NULL - User object [Optional]

Tags

Return Values

  • boolean

Source Code

public 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]);
}

public static comment( [ string $action = string(4) "view" , ORM $comment , Model_User $user = NULL , string $misc = NULL ] ) (defined in Gleez_ACL)

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

Parameters

  • string $action = string(4) "view" - The action `view|edit|delete` default `view`
  • ORM $comment required - The comment object
  • Model_User $user = NULL - The user object to check permission, defaults to logded in user
  • string $misc = NULL - The misc element usually `id|slug` for logging purpose

Tags

Return Values

  • boolean

Source Code

public 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;
}

public static get( string $name ) (defined in Gleez_ACL)

Returns a specific permission

Parameters

  • string $name required - The name of the permission.

Tags

Return Values

  • ACL

Source Code

public 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];
}

public static post( [ string $action = string(4) "view" , ORM $post , Model_User $user = NULL , string $misc = NULL ] ) (defined in Gleez_ACL)

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

Parameters

  • string $action = string(4) "view" - The action `view|edit|delete` default `view`
  • ORM $post required - The post object
  • Model_User $user = NULL - The user object to check permission, defaults to logded in user
  • string $misc = NULL - The misc element usually `id|slug` for logging purpose

Tags

Return Values

  • boolean

Source Code

public 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;
}

public static redirect( string $perm_name [, string $route = NULL , array $uri = array(0) ] ) (defined in Gleez_ACL)

Check permission for current user

Checks permission and redirects if is required to URL defined in $route

Parameters

  • string $perm_name required - Permission name
  • string $route = NULL - Route name [Optional]
  • array $uri = array(0) - Additional route params [Optional]

Tags

Source Code

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)
		);
	}
}

public static required( string $perm_name [, Model_User $user = NULL , callable $callback = NULL , array $args = array(0) ] ) (defined in Gleez_ACL)

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');

Parameters

  • string $perm_name required - Permession name
  • Model_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 arguments

Tags

Return Values

  • boolean

Source Code

public 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)
		);
	}
}

public static role_can( array $roles ) (defined in Gleez_ACL)

Checks whether the role(s) have some permission(s)

Parameters

  • array $roles required - An array of roles as id => name

Tags

  • Since - 2.0

Return Values

  • boolean - FALSE If the role(s) doesn't have any permission
  • array - Role(s) with permission(s) as array

Source Code

public 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;
}

public static set( string $name , array $access_names ) (defined in Gleez_ACL)

Sets up a named Permission and returns it.

Example:
ACL::set('admin/widgets', array( 'administer site widgets', 'administer admin widgets' ) );

Parameters

  • string $name required - Permission name
  • array $access_names required - Access keys

Return Values

  • ACL

Source Code

public static function set($name, array $access_names)
{
	// Adds the action to the action array and returns it.
	return ACL::$_all_perms[$name] = $access_names;
}

private static get_user_roles( Model_User $user ) (defined in Gleez_ACL)

Get all roles for user

Parameters

  • Model_User $user required - User object

Tags

  • Since - 2.0

Return Values

  • array - All roles for user

Source Code

private 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;
}
Documentation comments powered by Disqus