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