acl.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: acl.php 8177 2009-05-24 16:37:54Z mark_story $ */
00003 /**
00004  * Short description for file.
00005  *
00006  * Long description for file
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
00011  * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00012  *
00013  * Licensed under The MIT License
00014  * Redistributions of files must retain the above copyright notice.
00015  *
00016  * @filesource
00017  * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00018  * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00019  * @package       cake
00020  * @subpackage    cake.cake.console.libs
00021  * @since         CakePHP(tm) v 1.2.0.5012
00022  * @version       $Revision: 8177 $
00023  * @modifiedby    $LastChangedBy: mark_story $
00024  * @lastmodified  $Date: 2009-05-24 12:37:54 -0400 (Sun, 24 May 2009) $
00025  * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
00026  */
00027 App::import('Component', 'Acl');
00028 App::import('Model', 'DbAcl');
00029 /**
00030  * Shell for ACL management.
00031  *
00032  * @package       cake
00033  * @subpackage    cake.cake.console.libs
00034  */
00035 class AclShell extends Shell {
00036 /**
00037  * Contains instance of AclComponent
00038  *
00039  * @var AclComponent
00040  * @access public
00041  */
00042     var $Acl;
00043 /**
00044  * Contains arguments parsed from the command line.
00045  *
00046  * @var array
00047  * @access public
00048  */
00049     var $args;
00050 /**
00051  * Contains database source to use
00052  *
00053  * @var string
00054  * @access public
00055  */
00056     var $dataSource = 'default';
00057 /**
00058  * Contains tasks to load and instantiate
00059  *
00060  * @var array
00061  * @access public
00062  */
00063     var $tasks = array('DbConfig');
00064 /**
00065  * Override startup of the Shell
00066  *
00067  * @access public
00068  */
00069     function startup() {
00070         $this->dataSource = 'default';
00071 
00072         if (isset($this->params['datasource'])) {
00073             $this->dataSource = $this->params['datasource'];
00074         }
00075 
00076         if (!in_array(Configure::read('Acl.classname'), array('DbAcl', 'DB_ACL'))) {
00077             $out = "--------------------------------------------------\n";
00078             $out .= __("Error: Your current Cake configuration is set to", true) . "\n";
00079             $out .= __("an ACL implementation other than DB. Please change", true) . "\n";
00080             $out .= __("your core config to reflect your decision to use", true) . "\n";
00081             $out .= __("DbAcl before attempting to use this script", true) . ".\n";
00082             $out .= "--------------------------------------------------\n";
00083             $out .= sprintf(__("Current ACL Classname: %s", true), Configure::read('Acl.classname')) . "\n";
00084             $out .= "--------------------------------------------------\n";
00085             $this->err($out);
00086             $this->_stop();
00087         }
00088 
00089         if ($this->command && !in_array($this->command, array('help'))) {
00090             if (!config('database')) {
00091                 $this->out(__("Your database configuration was not found. Take a moment to create one.", true), true);
00092                 $this->args = null;
00093                 return $this->DbConfig->execute();
00094             }
00095             require_once (CONFIGS.'database.php');
00096 
00097             if (!in_array($this->command, array('initdb'))) {
00098                 $this->Acl = new AclComponent();
00099                 $controller = null;
00100                 $this->Acl->startup($controller);
00101             }
00102         }
00103     }
00104 /**
00105  * Override main() for help message hook
00106  *
00107  * @access public
00108  */
00109     function main() {
00110         $out  = __("Available ACL commands:", true) . "\n";
00111         $out .= "\t - create\n";
00112         $out .= "\t - delete\n";
00113         $out .= "\t - setParent\n";
00114         $out .= "\t - getPath\n";
00115         $out .= "\t - check\n";
00116         $out .= "\t - grant\n";
00117         $out .= "\t - deny\n";
00118         $out .= "\t - inherit\n";
00119         $out .= "\t - view\n";
00120         $out .= "\t - initdb\n";
00121         $out .= "\t - help\n\n";
00122         $out .= __("For help, run the 'help' command.  For help on a specific command, run 'help <command>'", true);
00123         $this->out($out);
00124     }
00125 /**
00126  * Creates an ARO/ACO node
00127  *
00128  * @access public
00129  */
00130     function create() {
00131 
00132         $this->_checkArgs(3, 'create');
00133         $this->checkNodeType();
00134         extract($this->__dataVars());
00135 
00136         $class = ucfirst($this->args[0]);
00137         $object = new $class();
00138 
00139         if (preg_match('/^([\w]+)\.(.*)$/', $this->args[1], $matches) && count($matches) == 3) {
00140             $parent = array(
00141                 'model' => $matches[1],
00142                 'foreign_key' => $matches[2],
00143             );
00144         } else {
00145             $parent = $this->args[1];
00146         }
00147 
00148         if (!empty($parent) && $parent != '/' && $parent != 'root') {
00149             @$parent = $object->node($parent);
00150             if (empty($parent)) {
00151                 $this->err(sprintf(__('Could not find parent node using reference "%s"', true), $this->args[1]));
00152                 return;
00153             } else {
00154                 $parent = Set::extract($parent, "0.{$class}.id");
00155             }
00156         } else {
00157             $parent = null;
00158         }
00159 
00160         if (preg_match('/^([\w]+)\.(.*)$/', $this->args[2], $matches) && count($matches) == 3) {
00161             $data = array(
00162                 'model' => $matches[1],
00163                 'foreign_key' => $matches[2],
00164             );
00165         } else {
00166             if (!($this->args[2] == '/')) {
00167                 $data = array('alias' => $this->args[2]);
00168             } else {
00169                 $this->error(__('/ can not be used as an alias!', true), __('\t/ is the root, please supply a sub alias', true));
00170             }
00171         }
00172 
00173         $data['parent_id'] = $parent;
00174         $object->create();
00175 
00176         if ($object->save($data)) {
00177             $this->out(sprintf(__("New %s '%s' created.\n", true), $class, $this->args[2]), true);
00178         } else {
00179             $this->err(sprintf(__("There was a problem creating a new %s '%s'.", true), $class, $this->args[2]));
00180         }
00181     }
00182 /**
00183  * Delete an ARO/ACO node.
00184  *
00185  * @access public
00186  */
00187     function delete() {
00188         $this->_checkArgs(2, 'delete');
00189         $this->checkNodeType();
00190         extract($this->__dataVars());
00191         if (!$this->Acl->{$class}->delete($this->args[1])) {
00192             $this->error(__("Node Not Deleted", true), sprintf(__("There was an error deleting the %s. Check that the node exists", true), $class) . ".\n");
00193         }
00194         $this->out(sprintf(__("%s deleted", true), $class) . ".\n", true);
00195     }
00196 
00197 /**
00198  * Set parent for an ARO/ACO node.
00199  *
00200  * @access public
00201  */
00202     function setParent() {
00203         $this->_checkArgs(3, 'setParent');
00204         $this->checkNodeType();
00205         extract($this->__dataVars());
00206         $data = array(
00207             $class => array(
00208                 'id' => $this->args[1],
00209                 'parent_id' => $this->args[2]
00210             )
00211         );
00212         $this->Acl->{$class}->create();
00213         if (!$this->Acl->{$class}->save($data)) {
00214             $this->out(__("Error in setting new parent. Please make sure the parent node exists, and is not a descendant of the node specified.", true), true);
00215         } else {
00216             $this->out(sprintf(__("Node parent set to %s", true), $this->args[2]) . "\n", true);
00217         }
00218     }
00219 /**
00220  * Get path to specified ARO/ACO node.
00221  *
00222  * @access public
00223  */
00224     function getPath() {
00225         $this->_checkArgs(2, 'getPath');
00226         $this->checkNodeType();
00227         extract($this->__dataVars());
00228         $id = ife(is_numeric($this->args[1]), intval($this->args[1]), $this->args[1]);
00229         $nodes = $this->Acl->{$class}->getPath($id);
00230         if (empty($nodes)) {
00231             $this->error(sprintf(__("Supplied Node '%s' not found", true), $this->args[1]), __("No tree returned.", true));
00232         }
00233         for ($i = 0; $i < count($nodes); $i++) {
00234             $this->out(str_repeat('  ', $i) . "[" . $nodes[$i][$class]['id'] . "]" . $nodes[$i][$class]['alias'] . "\n");
00235         }
00236     }
00237 /**
00238  * Check permission for a given ARO to a given ACO.
00239  *
00240  * @access public
00241  */
00242     function check() {
00243         $this->_checkArgs(3, 'check');
00244         extract($this->__getParams());
00245 
00246         if ($this->Acl->check($aro, $aco, $action)) {
00247             $this->out(sprintf(__("%s is allowed.", true), $aro), true);
00248         } else {
00249             $this->out(sprintf(__("%s is not allowed.", true), $aro), true);
00250         }
00251     }
00252 /**
00253  * Grant permission for a given ARO to a given ACO.
00254  *
00255  * @access public
00256  */
00257     function grant() {
00258         $this->_checkArgs(3, 'grant');
00259         extract($this->__getParams());
00260 
00261         if ($this->Acl->allow($aro, $aco, $action)) {
00262             $this->out(__("Permission granted.", true), true);
00263         } else {
00264             $this->out(__("Permission was not granted.", true), true);
00265         }
00266     }
00267 /**
00268  * Deny access for an ARO to an ACO.
00269  *
00270  * @access public
00271  */
00272     function deny() {
00273         $this->_checkArgs(3, 'deny');
00274         extract($this->__getParams());
00275 
00276         if ($this->Acl->deny($aro, $aco, $action)) {
00277             $this->out(__("Permission denied.", true), true);
00278         } else {
00279             $this->out(__("Permission was not denied.", true), true);
00280         }
00281     }
00282 /**
00283  * Set an ARO to inhermit permission to an ACO.
00284  *
00285  * @access public
00286  */
00287     function inherit() {
00288         $this->_checkArgs(3, 'inherit');
00289         extract($this->__getParams());
00290 
00291         if ($this->Acl->inherit($aro, $aco, $action)) {
00292             $this->out(__("Permission inherited.", true), true);
00293         } else {
00294             $this->out(__("Permission was not inherited.", true), true);
00295         }
00296     }
00297 /**
00298  * Show a specific ARO/ACO node.
00299  *
00300  * @access public
00301  */
00302     function view() {
00303         $this->_checkArgs(1, 'view');
00304         $this->checkNodeType();
00305         extract($this->__dataVars());
00306         if (isset($this->args[1]) && !is_null($this->args[1])) {
00307             $key = ife(is_numeric($this->args[1]), $secondary_id, 'alias');
00308             $conditions = array($class . '.' . $key => $this->args[1]);
00309         } else {
00310             $conditions = null;
00311         }
00312         $nodes = $this->Acl->{$class}->find('all', array('conditions' => $conditions, 'order' => 'lft ASC'));
00313         if (empty($nodes)) {
00314             if (isset($this->args[1])) {
00315                 $this->error(sprintf(__("%s not found", true), $this->args[1]), __("No tree returned.", true));
00316             } elseif (isset($this->args[0])) {
00317                 $this->error(sprintf(__("%s not found", true), $this->args[0]), __("No tree returned.", true));
00318             }
00319         }
00320         $this->out($class . " tree:");
00321         $this->hr();
00322         $stack = array();
00323         $last  = null;
00324         foreach ($nodes as $n) {
00325             $stack[] = $n;
00326             if (!empty($last)) {
00327                 $end = end($stack);
00328                 if ($end[$class]['rght'] > $last) {
00329                     foreach ($stack as $k => $v) {
00330                         $end = end($stack);
00331                         if ($v[$class]['rght'] < $end[$class]['rght']) {
00332                             unset($stack[$k]);
00333                         }
00334                     }
00335                 }
00336             }
00337             $last   = $n[$class]['rght'];
00338             $count  = count($stack);
00339             $indent = str_repeat('  ', $count);
00340             if ($n[$class]['alias']) {
00341                 $this->out($indent . "[" . $n[$class]['id'] . "]" . $n[$class]['alias']."\n");
00342              } else {
00343                 $this->out($indent . "[" . $n[$class]['id'] . "]" . $n[$class]['model'] . '.' . $n[$class]['foreign_key'] . "\n");
00344             }
00345         }
00346         $this->hr();
00347     }
00348 /**
00349  * Initialize ACL database.
00350  *
00351  * @access public
00352  */
00353     function initdb() {
00354         $this->Dispatch->args = array('schema', 'run', 'create', 'DbAcl');
00355         $this->Dispatch->dispatch();
00356     }
00357 /**
00358  * Show help screen.
00359  *
00360  * @access public
00361  */
00362     function help() {
00363         $head  = __("Usage: cake acl <command> <arg1> <arg2>...", true) . "\n";
00364         $head .= "-----------------------------------------------\n";
00365         $head .= __("Commands:", true) . "\n\n";
00366 
00367         $commands = array(
00368             'create' => "\tcreate aro|aco <parent> <node>\n" .
00369                         "\t\t" . __("Creates a new ACL object <node> under the parent specified by <parent>, an id/alias.", true) . "\n" .
00370                         "\t\t" . __("The <parent> and <node> references can be in one of the following formats:", true) . "\n" .
00371                         "\t\t\t- " . __("<model>.<id> - The node will be bound to a specific record of the given model", true) . "\n" .
00372                         "\t\t\t- " . __("<alias> - The node will be given a string alias (or path, in the case of <parent>),", true) . "\n" .
00373                         "\t\t\t  " . __("i.e. 'John'.  When used with <parent>, this takes the form of an alias path,", true) . "\n" .
00374                         "\t\t\t  " . __("i.e. <group>/<subgroup>/<parent>.", true) . "\n" .
00375                         "\t\t" . __("To add a node at the root level, enter 'root' or '/' as the <parent> parameter.", true) . "\n",
00376 
00377             'delete' => "\tdelete aro|aco <node>\n" .
00378                         "\t\t" . __("Deletes the ACL object with the given <node> reference (see 'create' for info on node references).", true) . "\n",
00379 
00380             'setparent' => "\tsetParent aro|aco <node> <parent>\n" .
00381                             "\t\t" . __("Moves the ACL object specified by <node> beneath the parent ACL object specified by <parent>.", true) . "\n" .
00382                             "\t\t" . __("To identify the node and parent, use the row id.", true) . "\n",
00383 
00384             'getpath' => "\tgetPath aro|aco <node>\n" .
00385                         "\t\t" . __("Returns the path to the ACL object specified by <node>. This command", true) . "\n" .
00386                         "\t\t" . __("is useful in determining the inhertiance of permissions for a certain", true) . "\n" .
00387                         "\t\t" . __("object in the tree.", true) . "\n" .
00388                         "\t\t" . __("For more detailed parameter usage info, see help for the 'create' command.", true) . "\n",
00389 
00390             'check' =>  "\tcheck <aro_id> <aco_id> [<aco_action>] " . __("or", true) . " all\n" .
00391                         "\t\t" . __("Use this command to check ACL permissions.", true) . "\n" .
00392                         "\t\t" . __("For more detailed parameter usage info, see help for the 'create' command.", true) . "\n",
00393 
00394             'grant' =>  "\tgrant <aro_id> <aco_id> [<aco_action>] " . __("or", true) . " all\n" .
00395                         "\t\t" . __("Use this command to grant ACL permissions. Once executed, the ARO", true) . "\n" .
00396                         "\t\t" . __("specified (and its children, if any) will have ALLOW access to the", true) . "\n" .
00397                         "\t\t" . __("specified ACO action (and the ACO's children, if any).", true) . "\n" .
00398                         "\t\t" . __("For more detailed parameter usage info, see help for the 'create' command.", true) . "\n",
00399 
00400             'deny' =>   "\tdeny <aro_id> <aco_id> [<aco_action>]" . __("or", true) . " all\n" .
00401                         "\t\t" . __("Use this command to deny ACL permissions. Once executed, the ARO", true) . "\n" .
00402                         "\t\t" . __("specified (and its children, if any) will have DENY access to the", true) . "\n" .
00403                         "\t\t" . __("specified ACO action (and the ACO's children, if any).", true) . "\n" .
00404                         "\t\t" . __("For more detailed parameter usage info, see help for the 'create' command.", true) . "\n",
00405 
00406             'inherit' =>    "\tinherit <aro_id> <aco_id> [<aco_action>]" . __("or", true) . " all\n" .
00407                             "\t\t" . __("Use this command to force a child ARO object to inherit its", true) . "\n" .
00408                             "\t\t" . __("permissions settings from its parent.", true) . "\n" .
00409                             "\t\t" . __("For more detailed parameter usage info, see help for the 'create' command.", true) . "\n",
00410 
00411             'view' =>   "\tview aro|aco [<node>]\n" .
00412                         "\t\t" . __("The view command will return the ARO or ACO tree. The optional", true) . "\n" .
00413                         "\t\t" . __("id/alias parameter allows you to return only a portion of the requested tree.", true) . "\n" .
00414                         "\t\t" . __("For more detailed parameter usage info, see help for the 'create' command.", true) . "\n",
00415 
00416             'initdb' => "\tinitdb\n".
00417                         "\t\t" . __("Uses this command : cake schema run create DbAcl", true) . "\n",
00418 
00419             'help' =>   "\thelp [<command>]\n" .
00420                         "\t\t" . __("Displays this help message, or a message on a specific command.", true) . "\n"
00421         );
00422 
00423         $this->out($head);
00424         if (!isset($this->args[0])) {
00425             foreach ($commands as $cmd) {
00426                 $this->out("{$cmd}\n\n");
00427             }
00428         } elseif (isset($commands[low($this->args[0])])) {
00429             $this->out($commands[low($this->args[0])] . "\n\n");
00430         } else {
00431             $this->out(sprintf(__("Command '%s' not found", true), $this->args[0]));
00432         }
00433     }
00434 /**
00435  * Check that first argument specifies a valid Node type (ARO/ACO)
00436  *
00437  * @access public
00438  */
00439     function checkNodeType() {
00440         if (!isset($this->args[0])) {
00441             return false;
00442         }
00443         if ($this->args[0] != 'aco' && $this->args[0] != 'aro') {
00444             $this->error(sprintf(__("Missing/Unknown node type: '%s'", true), $this->args[1]), __('Please specify which ACL object type you wish to create.', true));
00445         }
00446     }
00447 /**
00448  * Checks that given node exists
00449  *
00450  * @param string $type Node type (ARO/ACO)
00451  * @param integer $id Node id
00452  * @return boolean Success
00453  * @access public
00454  */
00455     function nodeExists() {
00456         if (!$this->checkNodeType() && !isset($this->args[1])) {
00457             return false;
00458         }
00459         extract($this->__dataVars($this->args[0]));
00460         $key = (ife(is_numeric($this->args[1]), $secondary_id, 'alias'));
00461         $conditions = array($class . '.' . $key => $this->args[1]);
00462         $possibility = $this->Acl->{$class}->find('all', compact('conditions'));
00463         if (empty($possibility)) {
00464             $this->error(sprintf(__("%s not found", true), $this->args[1]), __("No tree returned.", true));
00465         }
00466         return $possibility;
00467     }
00468 /**
00469  * get params for standard Acl methods
00470  *
00471  * @return array aro, aco, action
00472  * @access private
00473  */
00474     function __getParams() {
00475         $aro = ife(is_numeric($this->args[0]), intval($this->args[0]), $this->args[0]);
00476         $aco = ife(is_numeric($this->args[1]), intval($this->args[1]), $this->args[1]);
00477 
00478         if (is_string($aro) && preg_match('/^([\w]+)\.(.*)$/', $aro, $matches)) {
00479             $aro = array(
00480                 'model' => $matches[1],
00481                 'foreign_key' => $matches[2],
00482             );
00483         }
00484 
00485         if (is_string($aco) && preg_match('/^([\w]+)\.(.*)$/', $aco, $matches)) {
00486             $aco = array(
00487                 'model' => $matches[1],
00488                 'foreign_key' => $matches[2],
00489             );
00490         }
00491 
00492         $action = null;
00493         if (isset($this->args[2])) {
00494             $action = $this->args[2];
00495             if ($action == '' || $action == 'all') {
00496                 $action = '*';
00497             }
00498         }
00499         return compact('aro', 'aco', 'action');
00500     }
00501 
00502 /**
00503  * Build data parameters based on node type
00504  *
00505  * @param string $type Node type  (ARO/ACO)
00506  * @return array Variables
00507  * @access private
00508  */
00509     function __dataVars($type = null) {
00510         if ($type == null) {
00511             $type = $this->args[0];
00512         }
00513         $vars = array();
00514         $class = ucwords($type);
00515         $vars['secondary_id'] = ife(strtolower($class) == 'aro', 'foreign_key', 'object_id');
00516         $vars['data_name'] = $type;
00517         $vars['table_name'] = $type . 's';
00518         $vars['class'] = $class;
00519         return $vars;
00520     }
00521 }
00522 ?>

Generated on Sun Nov 22 00:30:51 2009 for CakePHP 1.2.x.x (v1.2.4.8284) by doxygen 1.4.7