aliroAuthorisationAdmin.php

Go to the documentation of this file.
00001 <?php
00002 
00003 /*******************************************************************************
00004  * Aliro - the modern, accessible content management system
00005  *
00006  * Aliro is open source software, free to use, and licensed under GPL.
00007  * You can find the full licence at http://www.gnu.org/copyleft/gpl.html GNU/GPL
00008  *
00009  * The author freely draws attention to the fact that Aliro derives from Mambo,
00010  * software that is controlled by the Mambo Foundation.  However, this section
00011  * of code is totally new.  If it should contain any fragments that are similar
00012  * to Mambo, please bear in mind (1) there are only so many ways to do things
00013  * and (2) the author of Aliro is also the author and copyright owner for large
00014  * parts of Mambo 4.6.
00015  *
00016  * Tribute should be paid to all the developers who took Mambo to the stage
00017  * it had reached at the time Aliro was created.  It is a feature rich system
00018  * that contains a good deal of innovation.
00019  *
00020  * Your attention is also drawn to the fact that Aliro relies on other items of
00021  * open source software, which is very much in the spirit of open source.  Aliro
00022  * wishes to give credit to those items of code.  Please refer to
00023  * http://aliro.org/credits for details.  The credits are not included within
00024  * the Aliro package simply to avoid providing a marker that allows hackers to
00025  * identify the system.
00026  *
00027  * Copyright in this code is strictly reserved by its author, Martin Brampton.
00028  * If it seems appropriate, the copyright will be vested in the Aliro Organisation
00029  * at a suitable time.
00030  *
00031  * Copyright (c) 2007 Martin Brampton
00032  *
00033  * http://aliro.org
00034  *
00035  * counterpoint@aliro.org
00036  *
00037  * aliroAuthorisationAdmin complements aliroAuthoriser, which answers questions about
00038  * permissions through the Aliro Role Based Access Control (RBAC) system.  This class
00039  * is used to set the permissions and assignments that are involved.  It can be used from
00040  * either the user or admin sides, depending on how RBAC management is deployed in a
00041  * particular application.
00042  *
00043  */
00044 
00045 class aliroAuthorisationAdmin {
00046     private static $instance = __CLASS__;
00047 
00048     private $handler = null;
00049     private $authoriser = null;
00050     private $database = null;
00051 
00052     private function __construct () {
00053         $this->handler = aliroAuthoriserCache::getInstance();
00054         $this->authoriser = aliroAuthoriser::getInstance();
00055         $this->database = aliroCoreDatabase::getInstance();
00056     }
00057 
00058     private function __clone () {
00059         // Enforce singleton
00060     }
00061 
00062     public static function getInstance () {
00063         return is_object(self::$instance) ? self::$instance : (self::$instance = new self::$instance());
00064     }
00065 
00066     private function doSQL ($sql, $clear=false) {
00067         $this->database->doSQL($sql);
00068         if ($clear) $this->clearCache();
00069     }
00070 
00071     private function clearCache () {
00072         $this->handler->clearCache();
00073         $this->authoriser->clearCache();
00074     }
00075 
00076     public function getAllRoles ($addSpecial=false) {
00077         return $this->authoriser->getAllRoles($addSpecial);
00078     }
00079 
00080     public function getTranslatedRole ($role) {
00081         return $this->authoriser->getTranslatedRole($role);
00082     }
00083 
00084     private function &permissionHolders ($subject_type, $subject_id) {
00085         $sql = "SELECT DISTINCT role, action, control, subject_type, subject_id FROM #__permissions";
00086         if ($subject_type != '*') $where[] = "(subject_type='$subject_type' OR subject_type='*')";
00087         if ($subject_id != '*') $where[] = "(subject_id='$subject_id' OR subject_id='*')";
00088         if (isset($where)) $sql .= " WHERE ".implode(' AND ', $where);
00089         $result = $this->database->doSQLget($sql);
00090         return $result;
00091     }
00092 
00093     public function permittedRoles ($actions, $subject_type, $subject_id, $excluding=null) {
00094         $nonspecific = true;
00095         foreach ($this->permissionHolders ($subject_type, $subject_id) as $possible) {
00096             if ('*' == $possible->action OR in_array($possible->action, (array) $actions)) {
00097                 $result[$possible->role] = $this->getTranslatedRole($possible->role);
00098                 if ('*' != $possible->subject_type AND '*' != $possible->subject_id) $nonspecific = false;
00099             }
00100         }
00101         if (!isset($result) OR $nonspecific) $result['Visitor'] = $this->getTranslatedRole('Visitor');
00102         foreach ((array) $excluding as $exclude) if (isset($result[$exclude])) unset($result[$exclude]);
00103         return $result;
00104     }
00105 
00106     private function &nonLocalPermissionHolders ($subject_type, $subject_id) {
00107         $sql = "SELECT role, action, control FROM #__permissions WHERE (action='*' OR subject_type='*' OR subject_id='*') AND ((subject_type='$subject_type' OR subject_type='*') AND (subject_id='$subject_id' OR subject_id='*'))";
00108         return $this->database->doSQLget($sql);
00109     }
00110 
00111     private function permitSQL ($role, $control, $action, $subject_type, $subject_id) {
00112         $this->database->setQuery("SELECT id FROM #__permissions WHERE role='$role' AND action='$action' AND subject_type='$subject_type' AND subject_id='$subject_id'");
00113         $id = $this->database->loadResult();
00114         if ($id) return "UPDATE #__permissions SET control=$control WHERE id=$id";
00115         else return "INSERT INTO #__permissions (role, control, action, subject_type, subject_id) VALUES ('$role', '$control', '$action', '$subject_type', '$subject_id')";
00116     }
00117 
00118     public function permit ($role, $control, $action, $subject_type, $subject_id) {
00119         $sql = $this->permitSQL($role, $control, $action, $subject_type, $subject_id);
00120         $this->doSQL($sql, true);
00121     }
00122 
00123     public function assign ($role, $access_type, $access_id, $clear=true) {
00124         if ($this->handler->barredRole($role)) return false;
00125         $this->database->setQuery("SELECT id FROM #__assignments WHERE role='$role' AND access_type='$access_type' AND access_id='$access_id'");
00126         if ($this->database->loadResult()) return true;
00127         $sql = "INSERT INTO #__assignments (role, access_type, access_id) VALUES ('$role', '$access_type', '$access_id')";
00128         $this->doSQL($sql, $clear);
00129         return true;
00130     }
00131 
00132     public function unassign ($role, $access_type, $access_id) {
00133         $this->database->doSQL("DELETE FROM #__assignments WHERE role='$role' AND access_type='$access_type' AND access_id='$access_id'", true);
00134         return true;
00135     }
00136 
00137     public function assignRoleSet ($roleset, $access_type, $access_id) {
00138         $this->dropAccess ($access_type, $access_id);
00139         $roleset = $this->authoriser->minimizeRoleSet($roleset);
00140         foreach ($roleset as $role) $this->assign ($role, $access_type, $access_id, false);
00141         $this->clearCache();
00142     }
00143 
00144     public function dropAccess ($access_type, $access_id) {
00145         $sql = "DELETE FROM #__assignments WHERE access_type='$access_type' AND access_id='$access_id'";
00146         $this->doSQL($sql, true);
00147     }
00148 
00149     public function &getMyControllingRoles ($action, $subject_type, $subject_id) {
00150         $user = aliroUser::getInstance();
00151         $sql = "SELECT a.role FROM #__permissions AS p INNER JOIN #__assignments AS a ON a.role=p.role"
00152         ." WHERE a.access_type='aUser'"
00153         ." AND a.access_id='$user->id' AND (p.control&1)"
00154         ." AND p.action='$action' AND p.subject_type='$subject_type' AND p.subject_id='$subject_id'";
00155         $this->doSQL($sql);
00156         $roles = $this->database->loadResultArray();
00157         return $roles;
00158     }
00159 
00160     public function &getMyPermissions () {
00161         $user = aliroUser::getInstance();
00162         $sql = 'SELECT p.action, p.subject_type, p.subject_id, control '
00163         . ' FROM #__permissions AS p INNER JOIN #__assignments AS a ON p.role=a.role '
00164         . " WHERE a.access_type='aUser' AND (a.access_id='$user->id' OR a.access_id='*')"
00165         . ' AND (p.control&1)';
00166         $this->doSQL($sql);
00167         $permissions = $this->database->loadObjectList();
00168         return $permissions;
00169     }
00170 
00171     public function getMyJointPermissions ($role) {
00172         $user = aliroUser::getInstance();
00173         $sql = "SELECT p2.control AS hiscontrol, p1.control AS mycontrol, p1.action, p1.subject_type, p1.subject_id"
00174         ." FROM `#__assignments` AS a INNER JOIN `#__permissions` AS p1 ON p1.role=a.role "
00175         ." LEFT JOIN `#__permissions` AS p2"
00176         ." ON (p2.role='$role' AND p1.action=p2.action AND p1.subject_type=p2.subject_type AND p1.subject_id=p2.subject_id)"
00177         ." WHERE  (p1.control&1) AND a.access_type='aUser' AND (a.access_id='$user->id' OR a.access_id='*')";
00178         $this->doSQL($sql);
00179         $permissions = $this->database->loadObjectList();
00180         return $permissions;
00181     }
00182 
00183     public function getAccessLists ($access_type, $access_id, $action, $subject_type, $subject_id) {
00184         if ($this->authoriser->checkControl($access_type, $access_id, $action, $subject_type, $subject_id)) {
00185             $cangrant = $this->authoriser->checkGrant($access_type, $access_id, $action, $subject_type, $subject_id);
00186             $permissions = $this->permissionHolders($subject_type, $subject_id);
00187             $allroles = $this->getAllRoles();
00188             $alirohtml = aliroHTML::getInstance();
00189             foreach ($allroles as $role) {
00190                 $itemc[] = $optionc = $alirohtml->makeOption($role, $role);
00191                 $itema[] = $optiona = $alirohtml->makeOption($role, $role);
00192                 if ($cangrant) $itemg[] = $optiong = $alirohtml->makeOption($role, $role);
00193                 foreach ($permissions as $permission) {
00194                     if (($permission->action == '*' OR $permission->action == $action) AND $permission->role == $role) {
00195                         if ($permission->control & 1) $cselected[] = $optionc;
00196                         if ($permission->control & 2) $aselected[] = $optiona;
00197                         if ($cangrant AND $permission->control & 4) $gselected[] = $optiong;
00198                     }
00199                 }
00200             }
00201             $results[] = $alirohtml->selectList($itema, $action.'_arole[]', 'multiple="multiple"', 'value', 'text', $aselected);
00202             $results[] = $alirohtml->selectList($itemc, $action.'_crole[]', 'multiple="multiple"', 'value', 'text', $cselected);
00203             if ($cangrant) $results[] = $alirohtml->selectList($itemg, $action.'_grole[]', 'multiple="multiple"', 'value', 'text', $gselected);
00204         }
00205         else $results = array();
00206         return $results;
00207     }
00208 
00209     public function resetPermissions ($action, $subject_type, $subject_id) {
00210         $control_types = array ('crole', 'arole', 'grole');
00211         $control_values = array (1,2,4);
00212         $permissions = $this->nonLocalPermissionHolders($subject_type, $subject_id);
00213         $this->dropPermissions($action, $subject_type, $subject_id);
00214         foreach ($control_types as $i=>$type) {
00215             $key = $action.'_'.$type;
00216             if (isset($_POST[$key])) {
00217                 foreach ($_POST[$key] as $role) {
00218                     $value = isset($newpermits[$role]) ? $newpermits[$role] : 0;
00219                     $newpermits[$role] = $value | $control_values[$i];
00220                 }
00221             }
00222         }
00223         $sql = '';
00224         foreach ($newpermits as $role=>$value) {
00225             $needed = true;
00226             foreach ($permissions as $permission) {
00227                 if (($permission->action == '*' OR $permission->action == $action) AND $permission->role == $role) {
00228                     if (($value & $permission->control) === $value) {
00229                         $needed = false;
00230                         break;
00231                     }
00232                 }
00233             }
00234             if ($needed) $sql .= $this->permitSQL ($role, $value, $action, $subject_type, $subject_id);
00235         }
00236         if ($sql) $this->doSQL($sql, true);
00237     }
00238 
00239     public function roleExists ($role) {
00240         return in_array($role, $this->getAllRoles());
00241     }
00242 
00243     public function dropRole ($role) {
00244         $sql = "DELETE FROM #__permissions WHERE action='administer' AND subject_type='$role' AND system=0";
00245         $this->doSQL($sql);
00246         $sql = "DELETE a FROM #__assignments AS a LEFT JOIN #__permissions AS p ON a.role=p.role WHERE a.role='$role' AND (p.system=0 OR p.system IS NULL)";
00247         $this->doSQL($sql);
00248         $sql = "DELETE FROM #__permissions WHERE role='$role' AND system=0";
00249         $this->doSQL($sql, true);
00250     }
00251 
00252     public function dropPermissions ($action, $subject_type, $subject_id) {
00253         $sql = "DELETE FROM #__permissions WHERE action='$action' AND subject_type='$subject_type'AND subject_id='$subject_id' AND system=0";
00254         $this->doSQL($sql, true);
00255     }
00256 
00257 }

Generated on Thu Apr 17 13:03:26 2008 for ALIRO by  doxygen 1.5.5