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