1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: App::uses('AppModel', 'Model');
18:
19: 20: 21: 22: 23:
24: class Permission extends AppModel {
25:
26: 27: 28: 29: 30:
31: public $cacheQueries = false;
32:
33: 34: 35: 36: 37:
38: public $useTable = 'aros_acos';
39:
40: 41: 42: 43: 44:
45: public $belongsTo = array('Aro', 'Aco');
46:
47: 48: 49: 50: 51:
52: public $actsAs = null;
53:
54: 55: 56: 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: 68: 69: 70: 71: 72: 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: 163: 164: 165: 166: 167: 168: 169: 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: 213: 214: 215: 216: 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: 243: 244: 245: 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: }
258: