PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/code/ryzom/tools/server/www/webtt/cake/console/libs/acl.php

https://bitbucket.org/mattraykowski/ryzomcore_demoshard
PHP | 602 lines | 378 code | 60 blank | 164 comment | 72 complexity | d6e3f5b4f01851c9b0e88ed40d1f606b MD5 | raw file
Possible License(s): AGPL-3.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Acl Shell provides Acl access in the CLI environment
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice.
  12. *
  13. * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP(tm) Project
  15. * @package cake
  16. * @subpackage cake.cake.console.libs
  17. * @since CakePHP(tm) v 1.2.0.5012
  18. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  19. */
  20. App::import('Component', 'Acl');
  21. App::import('Model', 'DbAcl');
  22. /**
  23. * Shell for ACL management. This console is known to have issues with zend.ze1_compatibility_mode
  24. * being enabled. Be sure to turn it off when using this shell.
  25. *
  26. * @package cake
  27. * @subpackage cake.cake.console.libs
  28. */
  29. class AclShell extends Shell {
  30. /**
  31. * Contains instance of AclComponent
  32. *
  33. * @var AclComponent
  34. * @access public
  35. */
  36. var $Acl;
  37. /**
  38. * Contains arguments parsed from the command line.
  39. *
  40. * @var array
  41. * @access public
  42. */
  43. var $args;
  44. /**
  45. * Contains database source to use
  46. *
  47. * @var string
  48. * @access public
  49. */
  50. var $connection = 'default';
  51. /**
  52. * Contains tasks to load and instantiate
  53. *
  54. * @var array
  55. * @access public
  56. */
  57. var $tasks = array('DbConfig');
  58. /**
  59. * Override startup of the Shell
  60. *
  61. * @access public
  62. */
  63. function startup() {
  64. if (isset($this->params['connection'])) {
  65. $this->connection = $this->params['connection'];
  66. }
  67. if (!in_array(Configure::read('Acl.classname'), array('DbAcl', 'DB_ACL'))) {
  68. $out = "--------------------------------------------------\n";
  69. $out .= __("Error: Your current Cake configuration is set to", true) . "\n";
  70. $out .= __("an ACL implementation other than DB. Please change", true) . "\n";
  71. $out .= __("your core config to reflect your decision to use", true) . "\n";
  72. $out .= __("DbAcl before attempting to use this script", true) . ".\n";
  73. $out .= "--------------------------------------------------\n";
  74. $out .= sprintf(__("Current ACL Classname: %s", true), Configure::read('Acl.classname')) . "\n";
  75. $out .= "--------------------------------------------------\n";
  76. $this->err($out);
  77. $this->_stop();
  78. }
  79. if ($this->command && !in_array($this->command, array('help'))) {
  80. if (!config('database')) {
  81. $this->out(__("Your database configuration was not found. Take a moment to create one.", true), true);
  82. $this->args = null;
  83. return $this->DbConfig->execute();
  84. }
  85. require_once (CONFIGS.'database.php');
  86. if (!in_array($this->command, array('initdb'))) {
  87. $this->Acl =& new AclComponent();
  88. $controller = null;
  89. $this->Acl->startup($controller);
  90. }
  91. }
  92. }
  93. /**
  94. * Override main() for help message hook
  95. *
  96. * @access public
  97. */
  98. function main() {
  99. $out = __("Available ACL commands:", true) . "\n";
  100. $out .= "\t - create\n";
  101. $out .= "\t - delete\n";
  102. $out .= "\t - setParent\n";
  103. $out .= "\t - getPath\n";
  104. $out .= "\t - check\n";
  105. $out .= "\t - grant\n";
  106. $out .= "\t - deny\n";
  107. $out .= "\t - inherit\n";
  108. $out .= "\t - view\n";
  109. $out .= "\t - initdb\n";
  110. $out .= "\t - help\n\n";
  111. $out .= __("For help, run the 'help' command. For help on a specific command, run 'help <command>'", true);
  112. $this->out($out);
  113. }
  114. /**
  115. * Creates an ARO/ACO node
  116. *
  117. * @access public
  118. */
  119. function create() {
  120. $this->_checkArgs(3, 'create');
  121. $this->checkNodeType();
  122. extract($this->__dataVars());
  123. $class = ucfirst($this->args[0]);
  124. $parent = $this->parseIdentifier($this->args[1]);
  125. if (!empty($parent) && $parent != '/' && $parent != 'root') {
  126. $parent = $this->_getNodeId($class, $parent);
  127. } else {
  128. $parent = null;
  129. }
  130. $data = $this->parseIdentifier($this->args[2]);
  131. if (is_string($data) && $data != '/') {
  132. $data = array('alias' => $data);
  133. } elseif (is_string($data)) {
  134. $this->error(__('/ can not be used as an alias!', true), __("\t/ is the root, please supply a sub alias", true));
  135. }
  136. $data['parent_id'] = $parent;
  137. $this->Acl->{$class}->create();
  138. if ($this->Acl->{$class}->save($data)) {
  139. $this->out(sprintf(__("New %s '%s' created.\n", true), $class, $this->args[2]), true);
  140. } else {
  141. $this->err(sprintf(__("There was a problem creating a new %s '%s'.", true), $class, $this->args[2]));
  142. }
  143. }
  144. /**
  145. * Delete an ARO/ACO node.
  146. *
  147. * @access public
  148. */
  149. function delete() {
  150. $this->_checkArgs(2, 'delete');
  151. $this->checkNodeType();
  152. extract($this->__dataVars());
  153. $identifier = $this->parseIdentifier($this->args[1]);
  154. $nodeId = $this->_getNodeId($class, $identifier);
  155. if (!$this->Acl->{$class}->delete($nodeId)) {
  156. $this->error(__("Node Not Deleted", true), sprintf(__("There was an error deleting the %s. Check that the node exists", true), $class) . ".\n");
  157. }
  158. $this->out(sprintf(__("%s deleted", true), $class) . ".\n", true);
  159. }
  160. /**
  161. * Set parent for an ARO/ACO node.
  162. *
  163. * @access public
  164. */
  165. function setParent() {
  166. $this->_checkArgs(3, 'setParent');
  167. $this->checkNodeType();
  168. extract($this->__dataVars());
  169. $target = $this->parseIdentifier($this->args[1]);
  170. $parent = $this->parseIdentifier($this->args[2]);
  171. $data = array(
  172. $class => array(
  173. 'id' => $this->_getNodeId($class, $target),
  174. 'parent_id' => $this->_getNodeId($class, $parent)
  175. )
  176. );
  177. $this->Acl->{$class}->create();
  178. if (!$this->Acl->{$class}->save($data)) {
  179. $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);
  180. } else {
  181. $this->out(sprintf(__("Node parent set to %s", true), $this->args[2]) . "\n", true);
  182. }
  183. }
  184. /**
  185. * Get path to specified ARO/ACO node.
  186. *
  187. * @access public
  188. */
  189. function getPath() {
  190. $this->_checkArgs(2, 'getPath');
  191. $this->checkNodeType();
  192. extract($this->__dataVars());
  193. $identifier = $this->parseIdentifier($this->args[1]);
  194. $id = $this->_getNodeId($class, $identifier);
  195. $nodes = $this->Acl->{$class}->getPath($id);
  196. if (empty($nodes)) {
  197. $this->error(
  198. sprintf(__("Supplied Node '%s' not found", true), $this->args[1]),
  199. __("No tree returned.", true)
  200. );
  201. }
  202. $this->out(__('Path:', true));
  203. $this->hr();
  204. for ($i = 0; $i < count($nodes); $i++) {
  205. $this->_outputNode($class, $nodes[$i], $i);
  206. }
  207. }
  208. /**
  209. * Outputs a single node, Either using the alias or Model.key
  210. *
  211. * @param string $class Class name that is being used.
  212. * @param array $node Array of node information.
  213. * @param integer $indent indent level.
  214. * @return void
  215. * @access protected
  216. */
  217. function _outputNode($class, $node, $indent) {
  218. $indent = str_repeat(' ', $indent);
  219. $data = $node[$class];
  220. if ($data['alias']) {
  221. $this->out($indent . "[" . $data['id'] . "] " . $data['alias']);
  222. } else {
  223. $this->out($indent . "[" . $data['id'] . "] " . $data['model'] . '.' . $data['foreign_key']);
  224. }
  225. }
  226. /**
  227. * Check permission for a given ARO to a given ACO.
  228. *
  229. * @access public
  230. */
  231. function check() {
  232. $this->_checkArgs(3, 'check');
  233. extract($this->__getParams());
  234. if ($this->Acl->check($aro, $aco, $action)) {
  235. $this->out(sprintf(__("%s is allowed.", true), $aroName), true);
  236. } else {
  237. $this->out(sprintf(__("%s is not allowed.", true), $aroName), true);
  238. }
  239. }
  240. /**
  241. * Grant permission for a given ARO to a given ACO.
  242. *
  243. * @access public
  244. */
  245. function grant() {
  246. $this->_checkArgs(3, 'grant');
  247. extract($this->__getParams());
  248. if ($this->Acl->allow($aro, $aco, $action)) {
  249. $this->out(__("Permission granted.", true), true);
  250. } else {
  251. $this->out(__("Permission was not granted.", true), true);
  252. }
  253. }
  254. /**
  255. * Deny access for an ARO to an ACO.
  256. *
  257. * @access public
  258. */
  259. function deny() {
  260. $this->_checkArgs(3, 'deny');
  261. extract($this->__getParams());
  262. if ($this->Acl->deny($aro, $aco, $action)) {
  263. $this->out(__("Permission denied.", true), true);
  264. } else {
  265. $this->out(__("Permission was not denied.", true), true);
  266. }
  267. }
  268. /**
  269. * Set an ARO to inhermit permission to an ACO.
  270. *
  271. * @access public
  272. */
  273. function inherit() {
  274. $this->_checkArgs(3, 'inherit');
  275. extract($this->__getParams());
  276. if ($this->Acl->inherit($aro, $aco, $action)) {
  277. $this->out(__("Permission inherited.", true), true);
  278. } else {
  279. $this->out(__("Permission was not inherited.", true), true);
  280. }
  281. }
  282. /**
  283. * Show a specific ARO/ACO node.
  284. *
  285. * @access public
  286. */
  287. function view() {
  288. $this->_checkArgs(1, 'view');
  289. $this->checkNodeType();
  290. extract($this->__dataVars());
  291. if (isset($this->args[1])) {
  292. $identity = $this->parseIdentifier($this->args[1]);
  293. $topNode = $this->Acl->{$class}->find('first', array(
  294. 'conditions' => array($class . '.id' => $this->_getNodeId($class, $identity))
  295. ));
  296. $nodes = $this->Acl->{$class}->find('all', array(
  297. 'conditions' => array(
  298. $class . '.lft >=' => $topNode[$class]['lft'],
  299. $class . '.lft <=' => $topNode[$class]['rght']
  300. ),
  301. 'order' => $class . '.lft ASC'
  302. ));
  303. } else {
  304. $nodes = $this->Acl->{$class}->find('all', array('order' => $class . '.lft ASC'));
  305. }
  306. if (empty($nodes)) {
  307. if (isset($this->args[1])) {
  308. $this->error(sprintf(__("%s not found", true), $this->args[1]), __("No tree returned.", true));
  309. } elseif (isset($this->args[0])) {
  310. $this->error(sprintf(__("%s not found", true), $this->args[0]), __("No tree returned.", true));
  311. }
  312. }
  313. $this->out($class . " tree:");
  314. $this->hr();
  315. $stack = array();
  316. $last = null;
  317. foreach ($nodes as $n) {
  318. $stack[] = $n;
  319. if (!empty($last)) {
  320. $end = end($stack);
  321. if ($end[$class]['rght'] > $last) {
  322. foreach ($stack as $k => $v) {
  323. $end = end($stack);
  324. if ($v[$class]['rght'] < $end[$class]['rght']) {
  325. unset($stack[$k]);
  326. }
  327. }
  328. }
  329. }
  330. $last = $n[$class]['rght'];
  331. $count = count($stack);
  332. $this->_outputNode($class, $n, $count);
  333. }
  334. $this->hr();
  335. }
  336. /**
  337. * Initialize ACL database.
  338. *
  339. * @access public
  340. */
  341. function initdb() {
  342. $this->Dispatch->args = array('schema', 'create', 'DbAcl');
  343. $this->Dispatch->dispatch();
  344. }
  345. /**
  346. * Show help screen.
  347. *
  348. * @access public
  349. */
  350. function help() {
  351. $head = "-----------------------------------------------\n";
  352. $head .= __("Usage: cake acl <command> <arg1> <arg2>...", true) . "\n";
  353. $head .= "-----------------------------------------------\n";
  354. $head .= __("Commands:", true) . "\n";
  355. $commands = array(
  356. 'create' => "create aro|aco <parent> <node>\n" .
  357. "\t" . __("Creates a new ACL object <node> under the parent", true) . "\n" .
  358. "\t" . __("specified by <parent>, an id/alias.", true) . "\n" .
  359. "\t" . __("The <parent> and <node> references can be", true) . "\n" .
  360. "\t" . __("in one of the following formats:", true) . "\n\n" .
  361. "\t\t- " . __("<model>.<id> - The node will be bound to a", true) . "\n" .
  362. "\t\t" . __("specific record of the given model.", true) . "\n\n" .
  363. "\t\t- " . __("<alias> - The node will be given a string alias,", true) . "\n" .
  364. "\t\t" . __(" (or path, in the case of <parent>)", true) . "\n" .
  365. "\t\t " . __("i.e. 'John'. When used with <parent>,", true) . "\n" .
  366. "\t\t" . __("this takes the form of an alias path,", true) . "\n" .
  367. "\t\t " . __("i.e. <group>/<subgroup>/<parent>.", true) . "\n\n" .
  368. "\t" . __("To add a node at the root level,", true) . "\n" .
  369. "\t" . __("enter 'root' or '/' as the <parent> parameter.", true) . "\n",
  370. 'delete' => "delete aro|aco <node>\n" .
  371. "\t" . __("Deletes the ACL object with the given <node> reference", true) . "\n" .
  372. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  373. "\t" . __("see help for the 'create' command.", true),
  374. 'setparent' => "setParent aro|aco <node> <parent node>\n" .
  375. "\t" . __("Moves the ACL object specified by <node> beneath", true) . "\n" .
  376. "\t" . __("the parent ACL object specified by <parent>.", true) . "\n" .
  377. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  378. "\t" . __("see help for the 'create' command.", true),
  379. 'getpath' => "getPath aro|aco <node>\n" .
  380. "\t" . __("Returns the path to the ACL object specified by <node>. This command", true) . "\n" .
  381. "\t" . __("is useful in determining the inhertiance of permissions for a certain", true) . "\n" .
  382. "\t" . __("object in the tree.", true) . "\n" .
  383. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  384. "\t" . __("see help for the 'create' command.", true),
  385. 'check' => "check <node> <node> [<aco_action>] " . __("or", true) . " all\n" .
  386. "\t" . __("Use this command to check ACL permissions.", true) . "\n" .
  387. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  388. "\t" . __("see help for the 'create' command.", true),
  389. 'grant' => "grant <aronode> <aconode> [<aco_action>] " . __("or", true) . " all\n" .
  390. "\t" . __("Use this command to grant ACL permissions. Once executed, the ARO", true) . "\n" .
  391. "\t" . __("specified (and its children, if any) will have ALLOW access to the", true) . "\n" .
  392. "\t" . __("specified ACO action (and the ACO's children, if any).", true) . "\n" .
  393. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  394. "\t" . __("see help for the 'create' command.", true),
  395. 'deny' => "deny <aronode> <aconode> [<aco_action>]" . __("or", true) . " all\n" .
  396. "\t" . __("Use this command to deny ACL permissions. Once executed, the ARO", true) . "\n" .
  397. "\t" . __("specified (and its children, if any) will have DENY access to the", true) . "\n" .
  398. "\t" . __("specified ACO action (and the ACO's children, if any).", true) . "\n" .
  399. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  400. "\t" . __("see help for the 'create' command.", true),
  401. 'inherit' => "inherit <aronode> <aconode> [<aco_action>]" . __("or", true) . " all\n" .
  402. "\t" . __("Use this command to force a child ARO object to inherit its", true) . "\n" .
  403. "\t" . __("permissions settings from its parent.", true) . "\n" .
  404. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  405. "\t" . __("see help for the 'create' command.", true),
  406. 'view' => "view aro|aco [<node>]\n" .
  407. "\t" . __("The view command will return the ARO or ACO tree.", true) . "\n" .
  408. "\t" . __("The optional node parameter allows you to return", true) . "\n" .
  409. "\t" . __("only a portion of the requested tree.", true) . "\n" .
  410. "\t" . __("For more detailed parameter usage info,", true) . "\n" .
  411. "\t" . __("see help for the 'create' command.", true),
  412. 'initdb' => "initdb\n".
  413. "\t" . __("Uses this command : cake schema run create DbAcl", true),
  414. 'help' => "help [<command>]\n" .
  415. "\t" . __("Displays this help message, or a message on a specific command.", true)
  416. );
  417. $this->out($head);
  418. if (!isset($this->args[0])) {
  419. foreach ($commands as $cmd) {
  420. $this->out("{$cmd}\n\n");
  421. }
  422. } elseif (isset($commands[strtolower($this->args[0])])) {
  423. $this->out($commands[strtolower($this->args[0])] . "\n\n");
  424. } else {
  425. $this->out(sprintf(__("Command '%s' not found", true), $this->args[0]));
  426. }
  427. }
  428. /**
  429. * Check that first argument specifies a valid Node type (ARO/ACO)
  430. *
  431. * @access public
  432. */
  433. function checkNodeType() {
  434. if (!isset($this->args[0])) {
  435. return false;
  436. }
  437. if ($this->args[0] != 'aco' && $this->args[0] != 'aro') {
  438. $this->error(sprintf(__("Missing/Unknown node type: '%s'", true), $this->args[0]), __('Please specify which ACL object type you wish to create. Either "aro" or "aco"', true));
  439. }
  440. }
  441. /**
  442. * Checks that given node exists
  443. *
  444. * @param string $type Node type (ARO/ACO)
  445. * @param integer $id Node id
  446. * @return boolean Success
  447. * @access public
  448. */
  449. function nodeExists() {
  450. if (!$this->checkNodeType() && !isset($this->args[1])) {
  451. return false;
  452. }
  453. extract($this->__dataVars($this->args[0]));
  454. $key = is_numeric($this->args[1]) ? $secondary_id : 'alias';
  455. $conditions = array($class . '.' . $key => $this->args[1]);
  456. $possibility = $this->Acl->{$class}->find('all', compact('conditions'));
  457. if (empty($possibility)) {
  458. $this->error(sprintf(__("%s not found", true), $this->args[1]), __("No tree returned.", true));
  459. }
  460. return $possibility;
  461. }
  462. /**
  463. * Parse an identifier into Model.foriegnKey or an alias.
  464. * Takes an identifier determines its type and returns the result as used by other methods.
  465. *
  466. * @param string $identifier Identifier to parse
  467. * @return mixed a string for aliases, and an array for model.foreignKey
  468. */
  469. function parseIdentifier($identifier) {
  470. if (preg_match('/^([\w]+)\.(.*)$/', $identifier, $matches)) {
  471. return array(
  472. 'model' => $matches[1],
  473. 'foreign_key' => $matches[2],
  474. );
  475. }
  476. return $identifier;
  477. }
  478. /**
  479. * Get the node for a given identifier. $identifier can either be a string alias
  480. * or an array of properties to use in AcoNode::node()
  481. *
  482. * @param string $class Class type you want (Aro/Aco)
  483. * @param mixed $identifier A mixed identifier for finding the node.
  484. * @return int Integer of NodeId. Will trigger an error if nothing is found.
  485. */
  486. function _getNodeId($class, $identifier) {
  487. $node = $this->Acl->{$class}->node($identifier);
  488. if (empty($node)) {
  489. if (is_array($identifier)) {
  490. $identifier = var_export($identifier, true);
  491. }
  492. $this->error(sprintf(__('Could not find node using reference "%s"', true), $identifier));
  493. }
  494. return Set::extract($node, "0.{$class}.id");
  495. }
  496. /**
  497. * get params for standard Acl methods
  498. *
  499. * @return array aro, aco, action
  500. * @access private
  501. */
  502. function __getParams() {
  503. $aro = is_numeric($this->args[0]) ? intval($this->args[0]) : $this->args[0];
  504. $aco = is_numeric($this->args[1]) ? intval($this->args[1]) : $this->args[1];
  505. $aroName = $aro;
  506. $acoName = $aco;
  507. if (is_string($aro)) {
  508. $aro = $this->parseIdentifier($aro);
  509. }
  510. if (is_string($aco)) {
  511. $aco = $this->parseIdentifier($aco);
  512. }
  513. $action = null;
  514. if (isset($this->args[2])) {
  515. $action = $this->args[2];
  516. if ($action == '' || $action == 'all') {
  517. $action = '*';
  518. }
  519. }
  520. return compact('aro', 'aco', 'action', 'aroName', 'acoName');
  521. }
  522. /**
  523. * Build data parameters based on node type
  524. *
  525. * @param string $type Node type (ARO/ACO)
  526. * @return array Variables
  527. * @access private
  528. */
  529. function __dataVars($type = null) {
  530. if ($type == null) {
  531. $type = $this->args[0];
  532. }
  533. $vars = array();
  534. $class = ucwords($type);
  535. $vars['secondary_id'] = (strtolower($class) == 'aro') ? 'foreign_key' : 'object_id';
  536. $vars['data_name'] = $type;
  537. $vars['table_name'] = $type . 's';
  538. $vars['class'] = $class;
  539. return $vars;
  540. }
  541. }