Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
16591 anikendra 1
<?php
2
/**
3
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link          http://cakephp.org CakePHP(tm) Project
12
 * @package       Cake.Model
13
 * @since         CakePHP(tm) v 0.2.9
14
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
15
 */
16
 
17
App::uses('AppModel', 'Model');
18
 
19
/**
20
 * Permissions linking AROs with ACOs
21
 *
22
 * @package       Cake.Model
23
 */
24
class Permission extends AppModel {
25
 
26
/**
27
 * Explicitly disable in-memory query caching
28
 *
29
 * @var bool
30
 */
31
	public $cacheQueries = false;
32
 
33
/**
34
 * Override default table name
35
 *
36
 * @var string
37
 */
38
	public $useTable = 'aros_acos';
39
 
40
/**
41
 * Permissions link AROs with ACOs
42
 *
43
 * @var array
44
 */
45
	public $belongsTo = array('Aro', 'Aco');
46
 
47
/**
48
 * No behaviors for this model
49
 *
50
 * @var array
51
 */
52
	public $actsAs = null;
53
 
54
/**
55
 * Constructor, used to tell this model to use the
56
 * database configured for ACL
57
 */
58
	public function __construct() {
59
		$config = Configure::read('Acl.database');
60
		if (!empty($config)) {
61
			$this->useDbConfig = $config;
62
		}
63
		parent::__construct();
64
	}
65
 
66
/**
67
 * Checks if the given $aro has access to action $action in $aco
68
 *
69
 * @param string $aro ARO The requesting object identifier.
70
 * @param string $aco ACO The controlled object identifier.
71
 * @param string $action Action (defaults to *)
72
 * @return bool Success (true if ARO has access to action in ACO, false otherwise)
73
 */
74
	public function check($aro, $aco, $action = '*') {
75
		if (!$aro || !$aco) {
76
			return false;
77
		}
78
 
79
		$permKeys = $this->getAcoKeys($this->schema());
80
		$aroPath = $this->Aro->node($aro);
81
		$acoPath = $this->Aco->node($aco);
82
 
83
		if (!$aroPath) {
84
			$this->log(__d('cake_dev',
85
					"%s - Failed ARO node lookup in permissions check. Node references:\nAro: %s\nAco: %s",
86
					'DbAcl::check()',
87
					print_r($aro, true),
88
					print_r($aco, true)),
89
				E_USER_WARNING
90
			);
91
			return false;
92
		}
93
 
94
		if (!$acoPath) {
95
			$this->log(__d('cake_dev',
96
					"%s - Failed ACO node lookup in permissions check. Node references:\nAro: %s\nAco: %s",
97
					'DbAcl::check()',
98
					print_r($aro, true),
99
					print_r($aco, true)),
100
				E_USER_WARNING
101
			);
102
			return false;
103
		}
104
 
105
		if ($action !== '*' && !in_array('_' . $action, $permKeys)) {
106
			$this->log(__d('cake_dev', "ACO permissions key %s does not exist in %s", $action, 'DbAcl::check()'), E_USER_NOTICE);
107
			return false;
108
		}
109
 
110
		$inherited = array();
111
		$acoIDs = Hash::extract($acoPath, '{n}.' . $this->Aco->alias . '.id');
112
 
113
		$count = count($aroPath);
114
		for ($i = 0; $i < $count; $i++) {
115
			$permAlias = $this->alias;
116
 
117
			$perms = $this->find('all', array(
118
				'conditions' => array(
119
					"{$permAlias}.aro_id" => $aroPath[$i][$this->Aro->alias]['id'],
120
					"{$permAlias}.aco_id" => $acoIDs
121
				),
122
				'order' => array($this->Aco->alias . '.lft' => 'desc'),
123
				'recursive' => 0
124
			));
125
 
126
			if (empty($perms)) {
127
				continue;
128
			}
129
			$perms = Hash::extract($perms, '{n}.' . $this->alias);
130
			foreach ($perms as $perm) {
131
				if ($action === '*') {
132
 
133
					foreach ($permKeys as $key) {
134
						if (!empty($perm)) {
135
							if ($perm[$key] == -1) {
136
								return false;
137
							} elseif ($perm[$key] == 1) {
138
								$inherited[$key] = 1;
139
							}
140
						}
141
					}
142
 
143
					if (count($inherited) === count($permKeys)) {
144
						return true;
145
					}
146
				} else {
147
					switch ($perm['_' . $action]) {
148
						case -1:
149
							return false;
150
						case 0:
151
							continue;
152
						case 1:
153
							return true;
154
					}
155
				}
156
			}
157
		}
158
		return false;
159
	}
160
 
161
/**
162
 * Allow $aro to have access to action $actions in $aco
163
 *
164
 * @param string $aro ARO The requesting object identifier.
165
 * @param string $aco ACO The controlled object identifier.
166
 * @param string $actions Action (defaults to *) Invalid permissions will result in an exception
167
 * @param int $value Value to indicate access type (1 to give access, -1 to deny, 0 to inherit)
168
 * @return bool Success
169
 * @throws AclException on Invalid permission key.
170
 */
171
	public function allow($aro, $aco, $actions = '*', $value = 1) {
172
		$perms = $this->getAclLink($aro, $aco);
173
		$permKeys = $this->getAcoKeys($this->schema());
174
		$save = array();
175
 
176
		if (!$perms) {
177
			$this->log(__d('cake_dev', '%s - Invalid node', 'DbAcl::allow()'), E_USER_WARNING);
178
			return false;
179
		}
180
		if (isset($perms[0])) {
181
			$save = $perms[0][$this->alias];
182
		}
183
 
184
		if ($actions === '*') {
185
			$save = array_combine($permKeys, array_pad(array(), count($permKeys), $value));
186
		} else {
187
			if (!is_array($actions)) {
188
				$actions = array('_' . $actions);
189
			}
190
			foreach ($actions as $action) {
191
				if ($action{0} !== '_') {
192
					$action = '_' . $action;
193
				}
194
				if (!in_array($action, $permKeys, true)) {
195
					throw new AclException(__d('cake_dev', 'Invalid permission key "%s"', $action));
196
				}
197
				$save[$action] = $value;
198
			}
199
		}
200
		list($save['aro_id'], $save['aco_id']) = array($perms['aro'], $perms['aco']);
201
 
202
		if ($perms['link'] && !empty($perms['link'])) {
203
			$save['id'] = $perms['link'][0][$this->alias]['id'];
204
		} else {
205
			unset($save['id']);
206
			$this->id = null;
207
		}
208
		return ($this->save($save) !== false);
209
	}
210
 
211
/**
212
 * Get an array of access-control links between the given Aro and Aco
213
 *
214
 * @param string $aro ARO The requesting object identifier.
215
 * @param string $aco ACO The controlled object identifier.
216
 * @return array Indexed array with: 'aro', 'aco' and 'link'
217
 */
218
	public function getAclLink($aro, $aco) {
219
		$obj = array();
220
		$obj['Aro'] = $this->Aro->node($aro);
221
		$obj['Aco'] = $this->Aco->node($aco);
222
 
223
		if (empty($obj['Aro']) || empty($obj['Aco'])) {
224
			return false;
225
		}
226
		$aro = Hash::extract($obj, 'Aro.0.' . $this->Aro->alias . '.id');
227
		$aco = Hash::extract($obj, 'Aco.0.' . $this->Aco->alias . '.id');
228
		$aro = current($aro);
229
		$aco = current($aco);
230
 
231
		return array(
232
			'aro' => $aro,
233
			'aco' => $aco,
234
			'link' => $this->find('all', array('conditions' => array(
235
				$this->alias . '.aro_id' => $aro,
236
				$this->alias . '.aco_id' => $aco
237
			)))
238
		);
239
	}
240
 
241
/**
242
 * Get the crud type keys
243
 *
244
 * @param array $keys Permission schema
245
 * @return array permission keys
246
 */
247
	public function getAcoKeys($keys) {
248
		$newKeys = array();
249
		$keys = array_keys($keys);
250
		foreach ($keys as $key) {
251
			if (!in_array($key, array('id', 'aro_id', 'aco_id'))) {
252
				$newKeys[] = $key;
253
			}
254
		}
255
		return $newKeys;
256
	}
257
}