1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
19:
20: App::uses('AppModel', 'Model');
21:
22: 23: 24: 25: 26:
27: class Permission extends AppModel {
28:
29: 30: 31: 32: 33:
34: public $name = 'Permission';
35:
36: 37: 38: 39: 40:
41: public $cacheQueries = false;
42:
43: 44: 45: 46: 47:
48: public $useTable = 'aros_acos';
49:
50: 51: 52: 53: 54:
55: public $belongsTo = array('Aro', 'Aco');
56:
57: 58: 59: 60: 61:
62: public $actsAs = null;
63:
64: 65: 66: 67:
68: public function __construct() {
69: $config = Configure::read('Acl.database');
70: if (!empty($config)) {
71: $this->useDbConfig = $config;
72: }
73: parent::__construct();
74: }
75:
76: 77: 78: 79: 80: 81: 82: 83:
84: public function check($aro, $aco, $action = "*") {
85: if (!$aro || !$aco) {
86: return false;
87: }
88:
89: $permKeys = $this->getAcoKeys($this->schema());
90: $aroPath = $this->Aro->node($aro);
91: $acoPath = $this->Aco->node($aco);
92:
93: if (!$aroPath || !$acoPath) {
94: trigger_error(__d('cake_dev', "DbAcl::check() - Failed ARO/ACO node lookup in permissions check. Node references:\nAro: ") . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
95: return false;
96: }
97:
98: if (!$acoPath) {
99: trigger_error(__d('cake_dev', "DbAcl::check() - Failed ACO node lookup in permissions check. Node references:\nAro: ") . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
100: return false;
101: }
102:
103: if ($action !== '*' && !in_array('_' . $action, $permKeys)) {
104: trigger_error(__d('cake_dev', "ACO permissions key %s does not exist in DbAcl::check()", $action), E_USER_NOTICE);
105: return false;
106: }
107:
108: $inherited = array();
109: $acoIDs = Hash::extract($acoPath, '{n}.' . $this->Aco->alias . '.id');
110:
111: $count = count($aroPath);
112: for ($i = 0; $i < $count; $i++) {
113: $permAlias = $this->alias;
114:
115: $perms = $this->find('all', array(
116: 'conditions' => array(
117: "{$permAlias}.aro_id" => $aroPath[$i][$this->Aro->alias]['id'],
118: "{$permAlias}.aco_id" => $acoIDs
119: ),
120: 'order' => array($this->Aco->alias . '.lft' => 'desc'),
121: 'recursive' => 0
122: ));
123:
124: if (empty($perms)) {
125: continue;
126: }
127: $perms = Hash::extract($perms, '{n}.' . $this->alias);
128: foreach ($perms as $perm) {
129: if ($action === '*') {
130:
131: foreach ($permKeys as $key) {
132: if (!empty($perm)) {
133: if ($perm[$key] == -1) {
134: return false;
135: } elseif ($perm[$key] == 1) {
136: $inherited[$key] = 1;
137: }
138: }
139: }
140:
141: if (count($inherited) === count($permKeys)) {
142: return true;
143: }
144: } else {
145: switch ($perm['_' . $action]) {
146: case -1:
147: return false;
148: case 0:
149: continue;
150: case 1:
151: return true;
152: }
153: }
154: }
155: }
156: return false;
157: }
158:
159: 160: 161: 162: 163: 164: 165: 166: 167: 168:
169: public function allow($aro, $aco, $actions = "*", $value = 1) {
170: $perms = $this->getAclLink($aro, $aco);
171: $permKeys = $this->getAcoKeys($this->schema());
172: $save = array();
173:
174: if (!$perms) {
175: trigger_error(__d('cake_dev', 'DbAcl::allow() - Invalid node'), E_USER_WARNING);
176: return false;
177: }
178: if (isset($perms[0])) {
179: $save = $perms[0][$this->alias];
180: }
181:
182: if ($actions === "*") {
183: $save = array_combine($permKeys, array_pad(array(), count($permKeys), $value));
184: } else {
185: if (!is_array($actions)) {
186: $actions = array('_' . $actions);
187: }
188: foreach ($actions as $action) {
189: if ($action{0} !== '_') {
190: $action = '_' . $action;
191: }
192: if (!in_array($action, $permKeys, true)) {
193: throw new AclException(__d('cake_dev', 'Invalid permission key "%s"', $action));
194: }
195: $save[$action] = $value;
196: }
197: }
198: list($save['aro_id'], $save['aco_id']) = array($perms['aro'], $perms['aco']);
199:
200: if ($perms['link'] && !empty($perms['link'])) {
201: $save['id'] = $perms['link'][0][$this->alias]['id'];
202: } else {
203: unset($save['id']);
204: $this->id = null;
205: }
206: return ($this->save($save) !== false);
207: }
208:
209: 210: 211: 212: 213: 214: 215:
216: public function getAclLink($aro, $aco) {
217: $obj = array();
218: $obj['Aro'] = $this->Aro->node($aro);
219: $obj['Aco'] = $this->Aco->node($aco);
220:
221: if (empty($obj['Aro']) || empty($obj['Aco'])) {
222: return false;
223: }
224: $aro = Hash::extract($obj, 'Aro.0.' . $this->Aro->alias . '.id');
225: $aco = Hash::extract($obj, 'Aco.0.' . $this->Aco->alias . '.id');
226: $aro = current($aro);
227: $aco = current($aco);
228:
229: return array(
230: 'aro' => $aro,
231: 'aco' => $aco,
232: 'link' => $this->find('all', array('conditions' => array(
233: $this->alias . '.aro_id' => $aro,
234: $this->alias . '.aco_id' => $aco
235: )))
236: );
237: }
238:
239: 240: 241: 242: 243: 244:
245: public function getAcoKeys($keys) {
246: $newKeys = array();
247: $keys = array_keys($keys);
248: foreach ($keys as $key) {
249: if (!in_array($key, array('id', 'aro_id', 'aco_id'))) {
250: $newKeys[] = $key;
251: }
252: }
253: return $newKeys;
254: }
255: }
256: