00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 class aliroAuthoriserCache extends cachedSingleton {
00053 protected static $instance= __CLASS__;
00054
00055 private $linked_roles = array();
00056 private $user_roles = array();
00057 private $all_roles = array();
00058 private $all_subjects = array();
00059 private $translations = array (
00060 'Registered' => 'Registered(translated)',
00061 'Visitor' => 'Visitor(translated)',
00062 'Nobody' => 'Nobody(translated)',
00063 'none' => 'None of these(trans)'
00064 );
00065
00066 protected function __construct () {
00067
00068 $database = aliroCoreDatabase::getInstance();
00069 $database->setQuery("SELECT role, implied FROM #__role_link UNION SELECT DISTINCT role, role AS implied FROM #__assignments UNION SELECT DISTINCT role, role AS implied FROM #__permissions");
00070 $links = $database->loadObjectList();
00071 if ($links) foreach ($links as $link) {
00072 $this->all_roles[$link->role] = $link->role;
00073 $this->linked_roles[$link->role][$link->implied] = 1;
00074 foreach ($this->linked_roles as $role=>$impliedarray) {
00075 foreach ($impliedarray as $implied=>$marker) {
00076 if ($implied == $link->role OR $implied == $link->implied) {
00077 $this->linked_roles[$role][$link->implied] = 1;
00078 if (isset($this->linked_roles[$link->implied])) foreach ($this->linked_roles[$link->implied] as $more=>$marker) {
00079 $this->linked_roles[$role][$more] = 1;
00080 }
00081 }
00082 }
00083 }
00084 }
00085 $user_roles = $database->doSQLget("SELECT role, access_id FROM #__assignments WHERE access_type = 'aUser' AND (access_id = '*' OR access_id = '0')");
00086 foreach ($user_roles as $role) $this->user_roles[$role->access_id][$role->role] = 1;
00087 if (!isset($this->user_roles['0'])) $this->user_roles['0'] = array();
00088 if (isset($this->user_roles['*'])) $this->user_roles['0'] = array_merge($this->user_roles['0'], $this->user_roles['*']);
00089 $allsubject = $database->doSQLget("SELECT role, control, action FROM #__permissions WHERE subject_type = '*' AND subject_id - '*'");
00090 foreach ($allsubject as $asub) $this->all_subjects[$asub->role] = $asub;
00091
00092 }
00093
00094 public static function getInstance () {
00095 return is_object(self::$instance) ? self::$instance : (self::$instance = parent::getCachedSingleton(self::$instance));
00096 }
00097
00098 public function getTranslatedRole ($role) {
00099 if (isset($this->translations[$role])) return $this->translations[$role];
00100 else return $role;
00101 }
00102
00103 public function getAllRoles ($addSpecial=false) {
00104 $roles = $this->all_roles;
00105 if ($addSpecial) foreach ($this->translations as $raw=>$translated) $roles[$raw] = $translated;
00106 return $roles;
00107 }
00108
00109 public function barredRole ($role) {
00110 if (isset($this->translations[$role])) return true;
00111 else return false;
00112 }
00113
00114 public function getLinkedRoles () {
00115 return $this->linked_roles;
00116 }
00117
00118 public function getUserRoles ($id) {
00119 return isset($this->user_roles[$id]) ? array_keys($this->user_roles[$id]) : array();
00120 }
00121
00122 public function canRoleAccessAll ($role, $action, $control) {
00123 if (isset($this->all_subjects[$role])) {
00124 $asub = $this->all_subjects[$role];
00125 if ($action == $asub->action AND ($control & $asub->control)) return true;
00126 }
00127 return false;
00128 }
00129
00130 }
00131
00132
00133 class aliroAuthoriser {
00134 private static $instance = __CLASS__;
00135
00136 private $subj_found = array();
00137 private $permissions = array();
00138 private $access_found = array();
00139 private $access_roles = array();
00140
00141 private $linked_roles = array();
00142 private $auth_vars = array ('subj_found', 'permissions', 'access_found', 'access_roles', 'refused');
00143 private $old_groupids = array ('Registered' => 18, 'Author' => 19, 'Editor' => 20, 'Publisher' => 21, 'Manager' => 23, 'Administrator' => 24, 'Super Administrator' => 25);
00144
00145 private $handler = null;
00146 private $database = null;
00147
00148 private function __construct () {
00149
00150 aliroSessionFactory::getSession();
00151
00152 foreach ($this->auth_vars as $one_var) {
00153 if (!isset($_SESSION['aliro_auth'][$one_var])) $_SESSION['aliro_auth'][$one_var] = array();
00154 $this->$one_var =& $_SESSION['aliro_auth'][$one_var];
00155 }
00156 $this->handler = aliroAuthoriserCache::getInstance();
00157 $this->linked_roles = $this->handler->getLinkedRoles();
00158 $this->database = aliroCoreDatabase::getInstance();
00159 }
00160
00161 private function __clone () {
00162
00163 }
00164
00165 public static function getInstance () {
00166 return is_object(self::$instance) ? self::$instance : (self::$instance = new self::$instance());
00167 }
00168
00169 public function clearCache () {
00170 $this->subj_found = $this->permissions = $this->access_found = $this->access_roles = $this->refused_cache = array();
00171 }
00172
00173 public function getAllRoles ($addSpecial=false) {
00174 return $this->handler->getAllRoles($addSpecial);
00175 }
00176
00177 public function getTranslatedRole ($role) {
00178 return $this->handler->getTranslatedRole($role);
00179 }
00180
00181 public function minimizeRoleSet ($roleset) {
00182 if (0 == count($roleset)) return $roleset;
00183 $first = array_shift($roleset);
00184 foreach ($roleset as $key=>$role) {
00185 if (isset($this->linked_roles[$first][$role])) unset ($roleset[$key]);
00186 if (isset($this->linked_roles[$role][$first])) return $this->minimizeRoleSet ($roleset);
00187 }
00188 array_unshift($roleset, $first);
00189 return $roleset;
00190 }
00191
00192 private function getSubjectData ($subject, $id, $action) {
00193 $stamp = time();
00194 if (isset($this->subj_found[$subject][$action][$id]) AND (($stamp - $this->subj_found[$subject][$action][$id]) < _ALIRO_AUTHORISER_SESSION_CACHE_TIME)) return;
00195 if (isset($this->subj_found[$subject][$action]['*']) AND ($stamp - $this->subj_found[$subject][$action]['*'] < _ALIRO_AUTHORISER_SESSION_CACHE_TIME)) return;
00196 $this->database->setQuery("SELECT COUNT(*) FROM `#__permissions` WHERE `subject_type`='$subject' AND (`action`='$action' OR `action`='*')");
00197 if ($this->database->loadResult() < 100) {
00198 $this->database->setQuery("SELECT `role`, `control`, `subject_id`, `action` FROM `#__permissions` WHERE `subject_type`='$subject' AND (`action`='$action' OR `action`='*')");
00199 $new_permissions = $this->database->loadObjectList();
00200 unset($this->subj_found[$subject][$action]);
00201 $this->subj_found[$subject][$action]['*'] = $stamp;
00202 }
00203 else {
00204 $this->database->setQuery("SELECT role, control, subject_id, action FROM #__permissions WHERE subject_type='$subject' AND (subject_id='$id' OR subject_id='*') AND (action='$action' OR action='*')");
00205 $new_permissions = $this->database->loadObjectList();
00206 unset($this->subj_found[$subject][$action][$id]);
00207 }
00208 if ($new_permissions) {
00209 foreach ($new_permissions as $permit) {
00210 $this->permissions[$subject][$permit->action][$permit->subject_id][$permit->role] = $permit->control;
00211 $this->subj_found[$subject][$permit->action][$permit->subject_id] = $stamp;
00212 }
00213 }
00214 }
00215
00216 public function getAccessorRoles ($type, $id) {
00217 if ('aUser' == $type AND ('0' == $id OR '*' == $id)) return $this->handler->getUserRoles($id);
00218 if (isset($this->access_found[$type][$id])) {
00219 if ((time() - $this->access_found[$type][$id]) < _ALIRO_AUTHORISER_SESSION_CACHE_TIME) {
00220 return $this->mergeAccessorResults($type, $id);
00221 }
00222 unset ($this->access_found);
00223 $this->access_roles = array();
00224 }
00225 $sql = "SELECT role, access_id FROM #__assignments AS a WHERE a.access_type='$type'";
00226 $sql .= isset($this->access_found[$type]) ? " AND a.access_id='$id'" : " AND (a.access_id='$id' OR a.access_id='*' OR a.access_id='+')";
00227 $this->database->setQuery($sql);
00228 if ($results = $this->database->loadObjectList()) {
00229 foreach ($results as $result) {
00230 $this->access_roles[$type][$result->access_id][$result->role] = 1;
00231 }
00232 }
00233 $this->access_found[$type][$id] = time();
00234 return $this->mergeAccessorResults($type, $id);
00235 }
00236
00237 private function mergeAccessorResults ($type, $id) {
00238 if (isset($this->access_roles[$type][$id])) $result = $this->access_roles[$type][$id];
00239 else $result = array();
00240 if (isset($this->access_roles[$type]['*'])) $result = array_merge($result, $this->access_roles[$type]['*']);
00241 if ($id AND isset($this->access_roles[$type]['+'])) $result = array_merge($result, $this->access_roles[$type]['+']);
00242 if ('aUser' == $type AND $id) $result['Registered'] = 1;
00243 if (count($result)) return array_keys ($result);
00244 else return array();
00245 }
00246
00247 private function blanket ($action, $type) {
00248 return (isset($this->permissions[$type][$action]['*']) AND count($this->permissions[$type][$action]['*']));
00249 }
00250
00251 private function specific ($action, $type, $id) {
00252 return (isset($this->permissions[$type][$action][$id]) AND count($this->permissions[$type][$action][$id]));
00253 }
00254
00255 private function accessorPermissionOrControl ($mask, $a_type, $a_id, $action, $s_type='*', $s_id='*') {
00256 $this->getSubjectData ($s_type, $s_id, $action);
00257 if ('*' != $s_type AND 2 == $mask AND !$this->blanket($action, $s_type) AND !($this->specific($action, $s_type, $s_id))) return 1;
00258 if ((!isset($this->permissions[$s_type][$action][$s_id]) OR 0 == count($this->permissions[$s_type][$action][$s_id]))
00259 AND (!isset($this->permissions[$s_type][$action]['*']) OR 0 == count($this->permissions[$s_type][$action]['*']))) return 1;
00260 $roles = $this->getAccessorRoles ($a_type, $a_id);
00261 return $this->rolePermissionOrControl ($mask, $roles, $action, $s_type, $s_id);
00262 }
00263
00264 public function checkPermission ($a_type, $a_id, $action, $s_type='*', $s_id='*') {
00265 return $this->accessorPermissionOrControl(2, $a_type, $a_id, $action, $s_type, $s_id);
00266 }
00267
00268 public function checkUserPermission ($action, $s_type='*', $s_id='*') {
00269 $user = aliroUser::getInstance();
00270 return $this->checkPermission ('aUser', $user->id, $action, $s_type, $s_id);
00271 }
00272
00273 public function checkControl ($a_type, $a_id, $action, $s_type='*', $s_id='*') {
00274 return $this->accessorPermissionOrControl(1, $a_type, $a_id, $action, $s_type, $s_id);
00275 }
00276
00277 public function checkGrant ($a_type, $a_id, $action, $s_type='*', $s_id='*') {
00278 return $this->accessorPermissionOrControl(4, $a_type, $a_id, $action, $s_type, $s_id);
00279 }
00280
00281 private function rolePermissionOrControl ($mask, $roles, $actions, $s_type, $s_id) {
00282 foreach ((array) $roles as $role) {
00283 foreach ((array) $actions as $action) if ($this->handler->canRoleAccessAll ($role, $action, $mask)) return 1;
00284 }
00285 foreach ((array) $actions as $action) $this->getSubjectData ($s_type, $s_id, $action);
00286 if (in_array('Visitor', (array) $roles)) {
00287 foreach ((array) $actions as $action) {
00288 if (empty($this->permissions[$s_type][$action][$s_id])) return 1;
00289 }
00290 }
00291 if (count((array) $roles)) foreach ($this->permissions[$s_type] as $act=>$level2) {
00292 if (!in_array($act, (array) $actions) AND !in_array('*', (array) $actions)) continue;
00293 foreach ($level2 as $id=>$level3) {
00294 if ($id != $s_id AND $id != '*') continue;
00295 foreach ($level3 as $role=>$control)
00296 if (in_array($role, (array) $roles) AND ($mask & $control)) {
00297 return 1;
00298 }
00299 }
00300 }
00301 return 0;
00302 }
00303
00304 public function checkRolePermission ($role, $action, $s_type, $s_id) {
00305 return $this->rolePermissionOrControl(2, $role, $action, $s_type, $s_id);
00306 }
00307
00308 public function checkRoleControl ($role, $action, $s_type, $s_id) {
00309 return $this->rolePermissionOrControl(1, $role, $action, $s_type, $s_id);
00310 }
00311
00312 public function checkRoleGrant ($role, $action, $s_type, $s_id) {
00313 return $this->rolePermissionOrControl(4, $role, $action, $s_type, $s_id);
00314 }
00315
00316 function getRefusedList ($a_type, $a_id, $s_type, $actionlist) {
00317 $roles = $this->getAccessorRoles($a_type, $a_id);
00318 $actions = explode(',', $actionlist);
00319 foreach ($actions as $i=>$action) $actions[$i] = trim($action);
00320 $alist = implode("','", $actions);
00321 if (isset($this->refused[$s_type][$alist])) $ids = $this->refused[$s_type][$alist];
00322 else {
00323 $ids = array();
00324 $results = $this->database->doSQLget("SELECT role, subject_id, action FROM #__permissions WHERE subject_type = '$s_type' AND action IN('$alist')");
00325 foreach ($results as $result) $ids[$result->subject_id][$result->action][] = $result->role;
00326 $this->refused[$s_type][$alist] = $ids;
00327 }
00328 if (count($ids)) {
00329 $refused = array_keys($ids);
00330 foreach ($ids as $id=>$actionset) {
00331 foreach ($actions as $action) if (!isset($actionset[$action])) $permits[$id] = 1;
00332 if (!isset($permits[$id])) foreach ($actionset as $action=>$permittedroles) {
00333 if (count(array_intersect($permittedroles, $roles))) $permits[$id] = 1;
00334 }
00335 }
00336 if (isset($permits)) $refused = array_diff ($refused, array_keys($permits));
00337 }
00338 else $refused = array();
00339 return $refused;
00340 }
00341
00342 public function getRefusedListSQL ($a_type, $a_id, $s_type, $actionlist, $keyname) {
00343 $refused = $this->getRefusedList ($a_type, $a_id, $s_type, $actionlist);
00344 if (count($refused)) {
00345 $excludelist = implode("','", $refused);
00346 return " CAST($keyname AS CHAR) NOT IN ('$excludelist')";
00347 }
00348 return '';
00349 }
00350
00351 public function listPermissions ($a_type, $a_id, $action) {
00352 $roles = $this->getAccessorRoles ($a_type, $a_id);
00353 $role_list = "IN ('".implode("','", $roles)."')";
00354 $this->database->setQuery("SELECT DISTINCT subject_type FROM #__permissions WHERE role $role_list AND action='$action' AND (control & 2) ORDER BY subject_type");
00355 $subjects = $this->database->loadResultArray();
00356 return $subjects;
00357 }
00358
00359 public function &listUserPermissions ($action) {
00360 $user = aliroUser::getInstance();
00361 $results = $this->listPermissions ('aUser', $user->id, $action);
00362 return $results;
00363 }
00364
00365 public function listAccessors ($accessor_type, $role) {
00366 $this->database->setQuery("SELECT access_id FROM #__assignments WHERE access_type = '$accessor_type' AND role = '$role'");
00367 $result = $this->database->loadResultArray();
00368 return $result ? $result : array();
00369 }
00370
00371
00372 public function acl_check($aco_section_value, $aco_value,
00373 $aro_section_value, $aro_value, $axo_section_value=NULL, $axo_value=NULL) {
00374 if ($axo_section_value == 'components') return $this->checkUserPermission ($aro_value, 'aliroComponent', $axo_value);
00375 return false;
00376 }
00377
00378 public function getAroGroup ($id) {
00379 $old_roles = array_keys ($this->old_groupids);
00380 array_unshift($old_roles, '');
00381 $roles = $this->getAccessorRoles('aUser', $id);
00382 $max = 0;
00383 foreach ($roles as $role) {
00384 $key = array_search($role, $old_roles);
00385 if ($key AND $key > $max) $max = $key;
00386 }
00387 $result = new stdClass();
00388 $result->name = $old_roles[$max];
00389 return $result;
00390 }
00391
00392 public function get_group_name ($gid) {
00393 if (is_int($gid)) {
00394 $group = array_search($gid, $this->old_groupids);
00395 return $group;
00396 }
00397 return $gid;
00398 }
00399
00400 public function get_group_children_tree ($root_id=null, $root_name=null, $inclusive=true) {
00401 if (null == $root_id AND true == $inclusive) {
00402 if ('Registered' == $root_name) {
00403 $result = unserialize('a:4:{i:0;O:8:"stdClass":2:{s:5:"value";s:2:"18";s:4:"text";s:17:"- Registered";}i:1;O:8:"stdClass":2:{s:5:"value";s:2:"19";s:4:"text";s:49:" - Author";}i:2;O:8:"stdClass":2:{s:5:"value";s:2:"20";s:4:"text";s:85:" - Editor";}i:3;O:8:"stdClass":2:{s:5:"value";s:2:"21";s:4:"text";s:124:" - Publisher";}}');
00404 return $result;
00405 }
00406 if ('Public Backend' == $root_name) {
00407 $result = unserialize('a:4:{i:0;O:8:"stdClass":2:{s:5:"value";s:2:"30";s:4:"text";s:21:"- Public Backend";}i:1;O:8:"stdClass":2:{s:5:"value";s:2:"23";s:4:"text";s:50:" - Manager";}i:2;O:8:"stdClass":2:{s:5:"value";s:2:"24";s:4:"text";s:92:" - Administrator";}i:3;O:8:"stdClass":2:{s:5:"value";s:2:"25";s:4:"text";s:134:" - Super Administrator";}}');
00408 return $result;
00409 }
00410 trigger_error('Aliro emulation of get_group_children_tree needs extending');
00411 }
00412 else {
00413 foreach ($this->getAllRoles(true) as $i=>$role) $option[] = aliroHTML::makeOption($role, $role);
00414 return isset($option) ? $option : array();
00415 }
00416 }
00417
00418 public function get_object_groups ($object_section_value, $object_value, $object_type=NULL) {
00419 return $this->getAllRoles(true);
00420 }
00421
00422 public function get_group_children ($root_id=null, $root_name=null, $inclusive=true) {
00423 return array();
00424 }
00425
00426 }