Author: phpnut
Date: 10:02:08 PM, Friday, November 04, 2005
Message:
Merging new ACL

[1312]
Author: phpnut
Date: 8:20:15 AM, Wednesday, November 02, 2005
Message:
More coding on the Security class.
Added cipher method provided by Nate to the class.
Added hash method that will be used to generate a authentication key
Added method to the CakeSession class to return all session vars if the session components read method is called with empty params.




git-svn-id: https://svn.cakephp.org/repo/trunk/cake@1329 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
phpnut 2005-11-05 04:08:14 +00:00
parent 1d4adb36f9
commit b50276f976
17 changed files with 1134 additions and 24 deletions

View file

@ -118,7 +118,7 @@ define('MAX_MD5SIZE', (5*1024)*1024 );
/**
* To use Access Control Lists with Cake...
*/
define('ACL_CLASSNAME', 'MyACL');
define('ACL_FILENAME', 'my_acl.php');
define('ACL_CLASSNAME', 'DB_ACL');
define('ACL_FILENAME', 'dbacl'.DS.'db_acl');
?>

View file

@ -0,0 +1,36 @@
CREATE TABLE `acos` (
`id` int(11) NOT NULL auto_increment,
`object_id` int(11) default NULL,
`alias` varchar(255) NOT NULL default '',
`lft` int(11) default NULL,
`rght` int(11) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `aros` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(11) default NULL,
`alias` varchar(255) NOT NULL default '',
`lft` int(11) default NULL,
`rght` int(11) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `aros_acos` (
`id` int(11) NOT NULL auto_increment,
`aro_id` int(11) default NULL,
`aco_id` int(11) default NULL,
`create` tinyint(1) NOT NULL default '0',
`read` tinyint(1) NOT NULL default '0',
`update` tinyint(1) NOT NULL default '0',
`delete` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`)
);
CREATE TABLE `aco_actions` (
`id` int(11) NOT NULL auto_increment,
`aros_acos_id` int(11) default NULL,
`action` varchar(255) NOT NULL default '',
`value` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`id`)
);

View file

@ -44,18 +44,118 @@
class AclComponent
{
var $_instance = null;
var $controller = true;
function __construct()
{
$this->getACL();
}
/**
* Static function used to gain an instance of the correct ACL class.
*
* @return MyACL
*/
function getACL()
function &getACL()
{
require_once(COMPONENTS.ACL_FILENAME);
if($this->_instance == null)
{
uses('controller'.DS.'components'.DS.ACL_FILENAME);
$classname = ACL_CLASSNAME;
$this->_instance = new $classname;
}
return $this->_instance;
}
$myacl = ACL_CLASSNAME;
return new $myacl;
function _initACL()
{
}
/**
* Pass-thru function for ACL check instance.
*
* @return boolean
*/
function check($aro, $aco, $action = "*")
{
return $this->_instance->check($aro, $aco, $action);
}
/**
* Pass-thru function for ACL allow instance.
*
* @return boolean
*/
function allow($aro, $aco, $action = "*")
{
return $this->_instance->allow($aro, $aco, $action);
}
/**
* Pass-thru function for ACL deny instance.
*
* @return boolean
*/
function deny($aro, $aco, $action = "*")
{
return $this->_instance->deny($aro, $aco, $action);
}
/**
* Pass-thru function for ACL inherit instance.
*
* @return boolean
*/
function inherit($aro, $aco, $action = "*")
{
return $this->_instance->inherit($aro, $aco, $action);
}
/**
* Pass-thru function for ACL grant instance.
*
* @return boolean
*/
function grant($aro, $aco, $action = "*")
{
return $this->_instance->grant($aro, $aco, $action);
}
/**
* Pass-thru function for ACL grant instance.
*
* @return boolean
*/
function revoke($aro, $aco, $action = "*")
{
return $this->_instance->revoke($aro, $aco, $action);
}
/**
* Pass-thru function for ACL getAro instance.
*
* @return Aro
*/
function getAro($id)
{
return $this->_instance->getAro($id);
}
/**
* Pass-thru function for ACL getAco instance.
*
* @return Aco
*/
function getAco($id)
{
return $this->_instance->getAco($id);
}
}
?>

View file

@ -55,7 +55,8 @@ class AclBase
}
function check($aro, $aco) {}
function check($aro, $aco, $action = "*") {}
}
?>

View file

@ -0,0 +1,300 @@
<?php
/* SVN FILE: $Id$ */
/**
* This is core configuration file.
*
* Use it to configure core behaviour ofCake.
*
* PHP versions 4 and 5
*
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2005, CakePHP Authors/Developers
*
* Author(s): Michal Tatarynowicz aka Pies <tatarynowicz@gmail.com>
* Larry E. Masters aka PhpNut <nut@phpnut.com>
* Kamil Dzielinski aka Brego <brego.dk@gmail.com>
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @author CakePHP Authors/Developers
* @copyright Copyright (c) 2005, CakePHP Authors/Developers
* @link https://trac.cakephp.org/wiki/Authors Authors/Developers
* @package cake
* @subpackage cake.cake.app.controllers.componenets
* @since CakePHP v 0.2.9
* @version $Revision$
* @modifiedby $LastChangedBy$
* @lastmodified $Date$
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
uses('controller'.DS.'components'.DS.'acl_base');
uses('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'aclnode');
uses('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'aco');
uses('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'acoaction');
uses('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'aro');
uses('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'aros_aco');
/**
* In this file you can extend the AclBase.
*
* @package cake
* @subpackage cake.cake.app.controllers.components
*/
class DB_ACL extends AclBase
{
function __construct()
{
}
function check($aro, $aco, $action = "*")
{
$Perms = new ArosAco();
$Aro = new Aro();
$Aco = new Aco();
if($aro == null || $aco == null)
{
return false;
}
$permKeys = $this->_getAcoKeys($Perms->loadInfo());
$aroPath = $Aro->getPath($aro);
$tmpAcoPath = $Aco->getPath($aco);
$acoPath = array();
if($action != '*' && !in_array($permKeys, '_' . $action))
{
trigger_error('ACO permissions key "' . $action . '" does not exist in DB_ACL::check()', E_USER_ERROR);
}
foreach($tmpAcoPath as $a)
{
$acoPath[] = $a['Aco']['id'];
}
$acoPath = implode(", ", $acoPath);
for($i = count($aroPath) - 1; $i >= 0; $i--)
{
$perms = $Perms->findBySql("select aros_acos.* from aros_acos left join acos on aros_acos.aco_id = acos.id where aros_acos.aro_id = " . $aroPath[$i]['Aro']['id'] . " and aros_acos.aco_id in ({$acoPath}) order by acos.lft asc");
if($perms == null || count($perms) == 0)
{
continue;
}
else
{
foreach($perms as $perm)
{
if($action == '*')
{
// ARO must be cleared for ALL ACO actions
foreach($permKeys as $key)
{
if($perm['aros_acos'][$key] != 1)
{
return false;
}
}
return true;
}
else
{
switch($perm['aros_acos']['_' . $action])
{
case -1:
return false;
case 0:
continue;
break;
case 1:
return true;
}
}
}
}
}
return false;
}
/**
* Allow
*
* @return boolean
*/
function allow($aro, $aco, $action = "*", $value = 1)
{
$Perms = new ArosAco();
$perms = $this->getAclLink($aro, $aco);
$permKeys = $this->_getAcoKeys($Perms->loadInfo());
$save = array();
if(isset($perms[0]))
{
$save = $perms[0]['aros_acos'];
}
if($action == "*")
{
$permKeys = $this->_getAcoKeys($Perms->loadInfo());
foreach($permKeys as $key)
{
$save[$key] = $value;
}
}
else
{
if(in_array('_' . $action, $permKeys))
{
$save['_' . $action] = $value;
}
else
{
// Raise an error
}
}
$save['aro_id'] = $perms['aro'];
$save['aco_id'] = $perms['aco'];
if($perms['link'] != null && count($perms['link']) > 0)
{
$save['id'] = $perms['link'][0]['aros_acos']['id'];
}
//return $Perms->save(array('ArosAco' => $save));
if(isset($save['id']))
{
$q = 'update aros_acos set ';
$saveKeys = array();
foreach($save as $key => $val)
{
if($key != 'id')
{
$saveKeys[] = $key . ' = ' . $val;
}
}
$q .= implode(', ', $saveKeys) . ' where id = ' . $save['id'];
}
else
{
$q = 'insert into aros_acos (' . implode(', ', array_keys($save)) . ') values (' . implode(', ', $save) . ')';
}
$Perms->db->query($q);
return true;
}
/**
* Deny
*
* @return boolean
*/
function deny($aro, $aco, $action = "*")
{
return $this->allow($aro, $aco, $action, -1);
}
/**
* Inherit
*
* @return boolean
*/
function inherit($aro, $aco, $action = "*")
{
return $this->allow($aro, $aco, $action, 0);
}
/**
* Allow alias
*
* @return boolean
*/
function grant($aro, $aco, $action = "*")
{
return $this->allow($aro, $aco, $action);
}
/**
* Deny alias
*
* @return boolean
*/
function revoke($aro, $aco, $action = "*")
{
return $this->deny($aro, $aco, $action);
}
function getAro($id = null)
{
if($id == null)
{
// Raise error
}
$aro = new Aro();
$tmp = $aro->find(is_string($aro) ? "aros.alias = '" . addslashes($aro) . "'" : "aros.user_id = {$aro}");
$aro->setId($tmp['aro']['id']);
return $aro;
}
function getAco($id = null)
{
if($id == null)
{
// Raise error
}
$aco = new Aco();
$tmp = $aco->find(is_string($aco) ? "acos.alias = '" . addslashes($aco) . "'" : "acos.user_id = {$aco}");
$aro->setId($tmp['aco']['id']);
return $aco;
}
function getAclLink($aro, $aco)
{
$Aro = new Aro();
$Aco = new Aco();
$qAro = (is_string($aro) ? "alias = '" . addslashes($aro) . "'" : "user_id = {$aro}");
$qAco = (is_string($aco) ? "alias = '" . addslashes($aco) . "'" : "object_id = {$aco}");
$obj = array();
$obj['Aro'] = $Aro->find($qAro);
$obj['Aco'] = $Aco->find($qAco);
$obj['Aro'] = $obj['Aro']['Aro'];
$obj['Aco'] = $obj['Aco']['Aco'];
return array(
'aro' => $obj['Aro']['id'],
'aco' => $obj['Aco']['id'],
'link' => $Aro->findBySql("select * from aros_acos where aro_id = {$obj['Aro']['id']} and aco_id = {$obj['Aco']['id']}")
);
}
function _getAcoKeys($keys)
{
$newKeys = array();
$keys = $keys->value;
foreach($keys as $key)
{
if($key['name'] != 'id' && $key['name'] != 'aro_id' && $key['name'] != 'aco_id')
{
$newKeys[] = $key['name'];
}
}
return $newKeys;
}
}
?>

View file

@ -0,0 +1,29 @@
CREATE TABLE `acos` (
`id` int(11) NOT NULL auto_increment,
`object_id` int(11) default NULL,
`alias` varchar(255) NOT NULL default '',
`lft` int(11) default NULL,
`rght` int(11) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `aros` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(11) default NULL,
`alias` varchar(255) NOT NULL default '',
`lft` int(11) default NULL,
`rght` int(11) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `aros_acos` (
`id` int(11) NOT NULL auto_increment,
`aro_id` int(11) default NULL,
`aco_id` int(11) default NULL,
`_create` int(1) NOT NULL default '0',
`_read` int(1) NOT NULL default '0',
`_update` int(1) NOT NULL default '0',
`_delete` int(11) NOT NULL default '0',
PRIMARY KEY (`id`)
);

View file

@ -0,0 +1,194 @@
<?php
require_once(CAKE . 'app_model.php');
class AclNode extends AppModel
{
var $useTable = false;
function __construct()
{
parent::__construct();
$this->__setTable();
}
function create($link_id = 0, $parent_id = null, $alias = '')
{
parent::create();
if (strtolower(get_class($this)) == "aclnode")
{
trigger_error(ERROR_ABSTRACT_CONSTRUCTION, E_USER_ERROR);
return NULL;
}
extract($this->__dataVars());
if($parent_id == null || $parent_id === 0)
{
$parent = $this->find(null, "MAX(rght)");
$parent['lft'] = $parent[0]['MAX(rght)'];
if($parent[0]['MAX(rght)'] == null)
{
// The tree is empty
$parent['lft'] = 0;
}
}
else
{
$parent = $this->find($this->_resolveID($parent_id, $secondary_id));
if($parent == null || count($parent) == 0)
{
trigger_error("Null parent in {$class}::create()", E_USER_ERROR);
}
$parent = $parent[$class];
$this->_syncTable($table_name, 1, $parent['lft'], $parent['lft']);
}
$return = $this->save(array($class => array(
$secondary_id => $link_id,
'alias' => $alias,
'lft' => $parent['lft'] + 1,
'rght' => $parent['lft'] + 2
)));
$this->setId($this->getLastInsertID());
return $return;
}
function setParent($parent_id = null, $id = null)
{
if (strtolower(get_class($this)) == "aclnode")
{
trigger_error(ERROR_ABSTRACT_CONSTRUCTION, E_USER_ERROR);
return null;
}
extract($this->__dataVars());
if($id == null && $this->id == false)
{
return false;
}
else if($id == null)
{
$id = $this->id;
}
$object = $this->find($this->_resolveID($id, $secondary_id));
if($object == null || count($object) == 0)
{
// Couldn't find object
return false;
}
$parent = $this->getParent(intval($object[$class][$secondary_id]));
// Node is already at root, or new parent == old parent
if(($parent == null && $parent_id == null) || ($parent_id == $parent[$class][$secondary_id]) || ($parent_id == $parent[$class]['alias']))
{
return false;
}
if($parent_id != null && $parent[$class]['lft'] <= $object[$class]['lft'] && $parent[$class]['rght'] >= $object[$class]['rght'])
{
// Can't move object inside self or own child
return false;
}
$this->_syncTable($table_name, 0, $object[$class]['lft'], $object[$class]['lft']);
if($parent_id == null)
{
$parent = $this->find(null, "MAX(rght)");
$parent['lft'] = $parent[0]['MAX(rght)'];
}
else
{
$parent = $this->find($this->_resolveID($parent_id, $secondary_id));
$parent = $parent[$class];
$this->_syncTable($table_name, 1, $parent['lft'], $parent['lft']);
}
$object[$class]['lft'] = $parent['lft'] + 1;
$object[$class]['rght'] = $parent['lft'] + 2;
$this->save($object);
if($parent['lft'] == 0)
{
$this->_syncTable($table_name, 2, $parent['lft'], $parent['lft']);
}
}
function getParent($id)
{
$path = $this->getPath($id);
if($path == null || count($path) < 2)
{
return null;
}
else
{
return $path[count($path) - 2];
}
}
function getPath($id)
{
if (strtolower(get_class($this)) == "aclnode")
{
trigger_error(ERROR_ABSTRACT_CONSTRUCTION, E_USER_ERROR);
return NULL;
}
extract($this->__dataVars());
$item = $this->find($this->_resolveID($id, $secondary_id));
return $this->findAll("lft <= {$item[$class]['lft']} and rght >= {$item[$class]['rght']}");
}
function getChildren($id)
{
if (strtolower(get_class($this)) == "aclnode")
{
trigger_error(ERROR_ABSTRACT_CONSTRUCTION, E_USER_ERROR);
return NULL;
}
extract($this->__dataVars());
$item = $this->find($this->_resolveID($id, $secondary_id));
return $this->findAll("lft > {$item[$class]['lft']} and rght < {$item[$class]['rght']}");
}
function _resolveID($id, $fKey)
{
$key = (is_string($id) ? 'alias' : $fKey);
$val = (is_string($id) ? '"' . addslashes($id) . '"' : $id);
return "{$key} = {$val}";
}
function _syncTable($table, $dir, $lft, $rght)
{
$shift = ($dir == 2 ? 1 : 2);
$this->db->query("UPDATE $table SET rght = rght " . ($dir > 0 ? "+" : "-") . " {$shift} WHERE rght > " . $rght);
$this->db->query("UPDATE $table SET lft = lft " . ($dir > 0 ? "+" : "-") . " {$shift} WHERE lft > " . $lft);
}
function __dataVars()
{
$vars = array();
$class = strtolower(get_class($this));
$vars['secondary_id'] = ($class == 'aro' ? 'user_id' : 'object_id');
$vars['data_name'] = $class;
$vars['table_name'] = $class . 's';
$vars['class'] = ucwords($class);
return $vars;
}
function __setTable()
{
$this->table = strtolower(get_class($this)) . "s";
}
}
?>

View file

@ -0,0 +1,10 @@
<?php
class Aco extends AclNode
{
var $hasMany = 'ArosAco,AcoActions';
}
?>

View file

@ -0,0 +1,10 @@
<?php
require_once(CAKE.'app_model.php');
class AcoAction extends AppModel
{
var $belongsTo = 'Aco';
}
?>

View file

@ -0,0 +1,9 @@
<?php
class Aro extends AclNode
{
var $hasMany = 'ArosAco';
}
?>

View file

@ -0,0 +1,9 @@
<?php
class ArosAco extends AppModel
{
var $useTable = 'aros_acos';
var $belongsTo = 'Aro,Aco';
}
?>

View file

@ -11,7 +11,8 @@
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
* Copyright (c) 2005, CakePHP Authors/Developers
*
* Author(s): Larry E. Masters aka PhpNut <nut@phpnut.com>
* Author(s): Michal Tatarynowicz aka Pies <tatarynowicz@gmail.com>
* Larry E. Masters aka PhpNut <nut@phpnut.com>
* Kamil Dzielinski aka Brego <brego.dk@gmail.com>
*
* Licensed under The MIT License
@ -30,7 +31,7 @@
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
uses(DS.'controller'.DS.'components'.DS.'acl_base');
uses('controller/components/acl_base');
/**
* In this file you can extend the AclBase.
@ -39,7 +40,7 @@ uses(DS.'controller'.DS.'components'.DS.'acl_base');
* @subpackage cake.cake.app.controllers.componenets
*/
class MyACL extends AclBase
class INI_ACL extends AclBase
{
/**
* The constructor must be overridden, as AclBase is abstract.
@ -58,7 +59,7 @@ class MyACL extends AclBase
* @param string $aco
* @return boolean
*/
function check($aro, $aco)
function check($aro, $aco, $aco_action = null)
{
$aclConfig = $this->readConfigFile(CONFIGS . 'acl.ini.php');

View file

@ -70,11 +70,12 @@ class SessionComponent extends Object
* Enter description here...
*
* Use like this. $this->Session->read('Controller.sessKey');
* Calling the method without a param will return all session vars
*
* @param unknown_type $name
* @return unknown
*/
function read($name)
function read($name = null)
{
return $this->CakeSession->readSessionVar($name);
}

View file

@ -80,6 +80,60 @@ class Security extends Object
{
return true;
}
}
function hash($string, $type='sha1')
{
$type = strtolower($type);
if ($type == 'sha1')
{
if (function_exists('sha1'))
{
return sha1($string);
}
else
{
$type = 'sha256';
}
}
if ($type == 'sha256')
{
if (function_exists('mhash'))
{
return bin2hex(mhash(MHASH_SHA256, $string));
}
else
{
$type = 'md5';
}
}
if ($type == 'md5')
{
return md5($string);
}
}
function cipher($text, $key)
{
if (!defined('CIPHER_SEED'))
{
//This is temporary will change later
define('CIPHER_SEED', 'mKEZGy8AB8FErX4t');
}
srand(CIPHER_SEED);
$out = '';
for($i = 0; $i < strlen($text); $i++)
{
for($j = 0; $j < ord(substr($key, $i % strlen($key), 1)); $j++)
{
$toss = rand(0, 255);
}
$mask = rand(0, 255);
$out .= chr(ord(substr($text, $i, 1)) ^ $mask);
}
return $out;
}
}
?>

View file

@ -156,7 +156,6 @@ class CakeSession extends Object
*/
function getError($errorNumber)
{
if(!is_array($this->error) || !array_key_exists($errorNumber, $this->error))
{
return false;
@ -202,8 +201,12 @@ class CakeSession extends Object
* @param unknown_type $name
* @return unknown
*/
function readSessionVar($name)
function readSessionVar($name = null)
{
if(is_null($name))
{
return $this->returnSessionVars();
}
if($this->checkSessionVar($name))
{
@ -214,6 +217,24 @@ class CakeSession extends Object
return false;
}
/**
* Enter description here...
*
* @param unknown_type $name
* @return unknown
*/
function returnSessionVars()
{
if(!empty($_SESSION))
{
$result = eval("return ".$_SESSION.";");
return $result;
}
$this->_setError(2, "No Session vars set");
return false;
}
/**
* Enter description here...
*

View file

@ -159,7 +159,7 @@ class AjaxHelper extends Helper
}
else
{
$html_options['onclick'] = $this->remoteFunction($options) . " return false;";
$html_options['onclick'] = $this->remoteFunction($options) . "; return false;";
return $this->Html->link($title, $href, $html_options);
}
}

335
cake/scripts/acl.php Normal file
View file

@ -0,0 +1,335 @@
#!/usr/bin/php -q
<?php
//BLAH
ini_set('display_errors', '1');
ini_set('error_reporting', '7');
define ('DS', DIRECTORY_SEPARATOR);
define ('ROOT', dirname(dirname(dirname(__FILE__))).DS);
define ('APP_DIR', 'app');
require_once (ROOT.'cake'.DS.'config'.DS.'paths.php');
require_once (CAKE.'basics.php');
require_once (CONFIGS.'core.php');
require_once (CONFIGS.'database.php');
uses ('neat_array');
uses ('model'.DS.'dbo'.DS.'dbo_factory');
uses ('controller'.DS.'controller');
uses ('controller'.DS.'components'.DS.'acl');
uses ('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'aclnode');
uses ('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'aco');
uses ('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'acoaction');
uses ('controller'.DS.'components'.DS.'dbacl'.DS.'models'.DS.'aro');
//Get and format args: first arg is the name of the script.
$wasted = array_shift($_SERVER['argv']);
$command = array_shift($_SERVER['argv']);
$args = $_SERVER['argv'];
$aclCLI = new AclCLI ($command, $args);
class AclCLI {
var $stdin;
var $stdout;
var $stderr;
var $acl;
var $controller;
var $args;
function AclCLI($command, $args)
{
$this->__construct($command, $args);
}
function __construct ($command, $args)
{
$acl = new AclComponent();
$this->acl = $acl->getACL();
$this->args = $args;
$this->controller =& new Controller();
$this->controller->constructClasses();
$this->stdin = fopen('php://stdin', 'r');
$this->stdout = fopen('php://stdout', 'w');
$this->stderr = fopen('php://stderr', 'w');
//Check to see if DB ACL is enabled
if (ACL_CLASSNAME != 'DB_ACL')
{
$out = "--------------------------------------------------\n";
$out .= "Error: Your current Cake configuration is set to \n";
$out .= "an ACL implementation other than DB. Please change \n";
$out .= "your core config to reflect your decision to use \n";
$out .= "DB_ACL before attempting to use this script.\n";
$out .= "--------------------------------------------------\n";
$out .= "Current ACL Classname: " . ACL_CLASSNAME . "\n";
$out .= "--------------------------------------------------\n";
fwrite($this->stderr, $out);
exit();
}
switch ($command)
{
case 'create':
$this->create();
break;
case 'delete':
$this->delete();
break;
case 'setParent':
$this->setParent();
break;
case 'getPath':
$this->getPath();
break;
case 'grant':
$this->grant();
break;
case 'deny':
$this->deny();
break;
case 'inherit':
$this->inherit();
break;
case 'view':
$this->view();
break;
case 'help':
$this->help();
break;
default:
fwrite($this->stderr, "Unknown ACL command '$command'.\nFor usage, try 'php acl.php help'.\n\n");
}
}
function create()
{
$this->checkArgNumber(4, 'create');
$this->checkNodeType();
extract($this->__dataVars());
$node = &new $class;
$parent = $this->nodeExists($this->args[0], $this->args[2]);
if (!$parent)
{
fwrite($this->stdout, "Warning: Parent not found. Creating this object with the root node as parent.\n");
$parent = $node->find(null, "MAX(rght)");
}
$node->create($this->args[1], $parent[$data_name]['id'], $this->args[3]);
fwrite($this->stdout, "New $class '".$this->args[3]."' created.\n\n");
}
function delete()
{
$this->checkArgNumber(2, 'delete');
$this->checkNodeType();
extract($this->__dataVars());
$node = &new $class;
//What about children?
//$node->del($this->args[1]);
//fwrite($this->stdout, "$class deleted.\n\n");
}
function setParent()
{
$this->checkArgNumber(3, 'setParent');
$this->checkNodeType();
extract($this->__dataVars());
$node = &new $class;
$parent = $this->nodeExists($this->args[0], $this->args[2]);
if (!$parent)
{
fwrite($this->stdout, "Warning: Parent not found. Setting this object with the root node as parent.\n");
$parent = $node->find(null, "MAX(rght)");
}
$node = &new $class;
$node->setParent($parent[$data_name]['id'], $this->args[1]);
fwrite($this->stdout, "Node parent set to ".$this->args[2]."\n\n");
}
function getPath()
{
$this->checkArgNumber(2, 'getPath');
$this->checkNodeType();
extract($this->__dataVars());
$suppliedNode = $this->nodeExists($this->args[0], $this->args[1]);
if (!$suppliedNode)
{
$this->displayError("Supplied Node '".$args[1]."' not found. No tree returned.");
}
$node = &new $class;
fwrite($this->stdout, print_r($node->getPath($this->args[1])));
}
function grant()
{
$this->checkArgNumber(3, 'grant');
//add existence checks for nodes involved
$this->acl->allow($this->args[0], $this->args[1], $this->args[2]);
fwrite($this->stdout, "Permission granted...");
}
function deny()
{
$this->checkArgNumber(3, 'deny');
//add existence checks for nodes involved
$this->acl->deny($this->args[0], $this->args[1], $this->args[2]);
fwrite($this->stdout, "Permission denied...");
}
function inherit() {}
function view() {}
function help()
{
$out = "Usage: php acl.php <command> <arg1> <arg2>...\n";
$out .= "-----------------------------------------------\n";
$out .= "Commands:\n";
$out .= "\n";
$out .= "\tcreate aro|aco <link_id> <parent_id> <alias>\n";
$out .= "\t\tCreates a new ACL object under the parent specified by parent_id (see\n";
$out .= "\t\t'view'). The link_id allows you to link a current user object to Cake's\n";
$out .= "\t\tACL structures. The alias parameter allows you address your object\n";
$out .= "\t\tusing a non-integer ID. Example: \"\$php acl.php create aro 0 jda57 John\"\n";
$out .= "\t\twould create a new ARO object at the root of the tree, linked to jda57\n";
$out .= "\t\tin your users table, with an internal alias 'John'.";
$out .= "\n";
$out .= "\n";
$out .= "\tdelete aro|aco <id>\n";
$out .= "\t\tDeletes the ACL object with the specified ID (see 'view').\n";
$out .= "\n";
$out .= "\n";
$out .= "\tsetParent aro|aco <id> <parent_id>\n";
$out .= "\t\tUsed to set the parent of the ACL object specified by <id> to the ID\n";
$out .= "\t\tspecified by <parent_id>.\n";
$out .= "\n";
$out .= "\n";
$out .= "\tgetPath aro|aco <id>\n";
$out .= "\t\tReturns the path to the ACL object specified by <id>. This command is\n";
$out .= "\t\tis useful in determining the inhertiance of permissions for a certain\n";
$out .= "\t\tobject in the tree.\n";
$out .= "\n";
$out .= "\n";
$out .= "\tgrant <aro_id> <aco_id> <aco_action>\n";
$out .= "\t\tUse this command to grant ACL permissions. Once executed, the ARO\n";
$out .= "\t\tspecified (and its children, if any) will have ALLOW access to the\n";
$out .= "\t\tspecified ACO action (and the ACO's children, if any).\n";
$out .= "\n";
$out .= "\n";
$out .= "\tdeny <aro_id> <aco_id> <aco_action>\n";
$out .= "\t\tUse this command to deny ACL permissions. Once executed, the ARO\n";
$out .= "\t\tspecified (and its children, if any) will have DENY access to the\n";
$out .= "\t\tspecified ACO action (and the ACO's children, if any).\n";
$out .= "\n";
$out .= "\n";
$out .= "\tinherit <aro_id> \n";
$out .= "\t\tUse this command to force a child ARO object to inherit its\n";
$out .= "\t\tpermissions settings from its parent.\n";
$out .= "\n";
$out .= "\n";
$out .= "\tview aro|aco [id]\n";
$out .= "\t\tThe view command will return the ARO or ACO tree. The optional\n";
$out .= "\t\tid/alias parameter allows you to return only a portion of the requested\n";
$out .= "\t\ttree.\n";
$out .= "\n";
$out .= "\n";
$out .= "\thelp\n";
$out .= "\t\tDisplays this help message.\n";
$out .= "\n";
$out .= "\n";
fwrite($this->stdout, $out);
}
function displayError($title, $msg)
{
$out = "\n";
$out .= "Error: $title\n";
$out .= "$msg\n";
$out .= "\n";
fwrite($this->stdout, $out);
exit();
}
function checkArgNumber($expectedNum, $command)
{
if (count($this->args) != $expectedNum)
{
$this->displayError('Wrong number of parameters: '.count($this->args), 'Please type \'php acl.php help\' for help on usage of the '.$command.' command.');
}
}
function checkNodeType()
{
if ($this->args[0] != 'aco' && $this->args[0] != 'aro')
{
$this->displayError("Missing/Unknown node type: '".$this->args[0]."'", 'Please specify which ACL object type you wish to create.');
}
}
function nodeExists($type, $id)
{
fwrite($this->stdout, "Check to see if $type with ID = $id exists...\n");
extract($this->__dataVars($type));
$node = &new $class;
$possibility = $node->find('id = ' . $id);
if (empty($possibility[$data_name]['id']))
{
return false;
}
else
{
return $possibility;
}
}
function __dataVars($type = null)
{
if ($type == null)
{
$type = $this->args[0];
}
$vars = array();
$class = ucwords($type);
$vars['secondary_id'] = ($class == 'aro' ? 'user_id' : 'object_id');
$vars['data_name'] = $type;
$vars['table_name'] = $class . 's';
$vars['class'] = $class;
return $vars;
}
}
?>