統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Model / Permission.php @ 0b1b8047

履歴 | 表示 | アノテート | ダウンロード (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
}