pictcode / lib / Cake / Model / Permission.php @ 635eef61
履歴 | 表示 | アノテート | ダウンロード (6.44 KB)
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 |
} |