Subversion-Projekte lars-tiefland.cakephp

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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