ILIAS  Release_4_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilRbacSystem.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 
37 {
38  protected static $instance = null;
39 
40  protected $mem_view;
41 
42  protected static $user_role_cache = array();
43  var $ilias;
44 
45  // Cache accesses to RBAC PA
46  private static $_paCache = null;
47 
48  // Cache outcomes of calls to checkAccessOfuser
49  private static $_checkAccessOfUserCache = null;
50 
55  protected function ilRbacSystem()
56  {
57  global $ilDB,$ilErr,$ilias;
58 
59  $this->ilias =& $ilias;
60 
61  // set db & error handler
62  (isset($ilDB)) ? $this->ilDB =& $ilDB : $this->ilDB =& $ilias->db;
63 
64  if (!isset($ilErr))
65  {
66  $ilErr = new ilErrorHandling();
67  $ilErr->setErrorHandling(PEAR_ERROR_CALLBACK,array($ilErr,'errorHandler'));
68  }
69  else
70  {
71  $this->ilErr =& $ilErr;
72  }
73  }
74 
75  public static function getInstance()
76  {
77  if(self::$instance)
78  {
79  return self::$instance;
80  }
81  return self::$instance = new ilRbacSystem();
82  }
83 
103  function checkAccess($a_operations,$a_ref_id,$a_type = "")
104  {
105  global $ilUser,$ilBench;
106 
107  $ilBench->start("RBAC", "system_checkAccess");
108 
109  $result = $this->checkAccessOfUser($ilUser->getId(), $a_operations, $a_ref_id, $a_type);
110 
111  $ilBench->stop("RBAC", "system_checkAccess");
112 
113  return $result;
114  }
115 
116  function checkAccessOfUser($a_user_id, $a_operations, $a_ref_id, $a_type = "")
117  {
118  global $ilUser, $rbacreview,$ilObjDataCache,$ilDB,$ilLog;
119 
120  // Create the user cache key
121  $cacheKey = $a_user_id.':'.$a_operations.':'.$a_ref_id.':'.$a_type;
122 
123  // Create the cache if it does not yet exist
124  if (! is_array(self::$_checkAccessOfUserCache)) {
125  self::$_checkAccessOfUserCache = array();
126  }
127 
128  // Try to return result from cache
129  if (array_key_exists($cacheKey, self::$_checkAccessOfUserCache)) {
130  return self::$_checkAccessOfUserCache[$cacheKey];
131  }
132 
133  #echo ++$counter;
134 
135  // DISABLED
136  // Check For owner
137  // Owners do always have full access to their objects
138  // Excluded are the permissions create and perm
139  // This method call return all operations that are NOT granted by the owner status
140  if(!$a_operations = $this->__filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id))
141  {
142  // Store positive outcome in cache.
143  // Note: we only cache up to 1000 results to avoid memory overflows
144  if (count(self::$_checkAccessOfUserCache) < 1000) {
145  self::$_checkAccessOfUserCache[$cacheKey] = true;
146  }
147  return true;
148  }
149 
150 
151  // get roles using role cache
152  $roles = $this->fetchAssignedRoles($a_user_id,$a_ref_id);
153 
154  // exclude system role from rbac
155  if (in_array(SYSTEM_ROLE_ID, $roles))
156  {
157  // Store positive outcome in cache.
158  // Note: we only cache up to 1000 results to avoid memory overflows
159  if (count(self::$_checkAccessOfUserCache) < 1000) {
160  self::$_checkAccessOfUserCache[$cacheKey] = true;
161  }
162  return true;
163  }
164 
165  if (!isset($a_operations) or !isset($a_ref_id))
166  {
167  $GLOBALS['ilLog']->logStack();
168  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Missing parameter! ".
169  "ref_id: ".$a_ref_id." operations: ".$a_operations,$this->ilErr->WARNING);
170  }
171 
172  if (!is_string($a_operations))
173  {
174  $GLOBALS['ilLog']->logStack();
175  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Wrong datatype for operations!",$this->ilErr->WARNING);
176  }
177 
178  // Create the PA cache if it does not exist yet
179  $paCacheKey = $a_user_id.':'.$a_ref_id;
180  if (! is_array(self::$_paCache)) {
181  self::$_paCache = array();
182  }
183 
184  if (array_key_exists($paCacheKey, self::$_paCache)) {
185  // Return result from PA cache
186  $ops = self::$_paCache[$paCacheKey];
187  }
188  else
189  {
190  // Data is not in PA cache, perform database query
191  $q = "SELECT * FROM rbac_pa ".
192  "WHERE ref_id = ".$ilDB->quote($a_ref_id, 'integer');
193 
194  $r = $this->ilDB->query($q);
195 
196  $ops = array();
197 
198  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
199  {
200  if (in_array($row->rol_id, $roles))
201  {
202  $ops = array_merge($ops,unserialize(stripslashes($row->ops_id)));
203  }
204  }
205  // Cache up to 1000 entries in the PA cache
206  if (count(self::$_paCache) < 1000)
207  {
208  self::$_paCache[$paCacheKey] = $ops;
209  }
210  }
211 
212  $operations = explode(",",$a_operations);
213  foreach ($operations as $operation)
214  {
215  if ($operation == "create")
216  {
217  if (empty($a_type))
218  {
219  $this->ilErr->raiseError(get_class($this)."::CheckAccess(): Expect a type definition for checking a 'create' permission",
220  $this->ilErr->WARNING);
221  }
222 
223  $ops_id = ilRbacReview::_getOperationIdByName($operation."_".$a_type);
224  }
225  else
226  {
227  $ops_id = ilRbacReview::_getOperationIdByName($operation);
228  }
229  if (! in_array($ops_id,$ops))
230  {
231  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$a_ops_id.' failed');
232  // Store negative outcome in cache.
233  // Note: we only cache up to 1000 results to avoid memory overflows
234  if (count(self::$_checkAccessOfUserCache) < 1000)
235  {
236  self::$_checkAccessOfUserCache[$cacheKey] = false;
237  }
238  return false;
239  }
240  }
241 
242  // Store positive outcome in cache.
243  // Note: we only cache up to 1000 results to avoid memory overflows
244  if (count(self::$_checkAccessOfUserCache) < 1000)
245  {
246  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$ops_id.' granted');
247  self::$_checkAccessOfUserCache[$cacheKey] = true;
248  }
249  return true;
250  }
251 
260  function checkPermission($a_ref_id,$a_rol_id,$a_operation)
261  {
262  global $ilDB;
263 
264  $ops = array();
265 
266  $query = 'SELECT ops_id FROM rbac_operations '.
267  'WHERE operation = '.$ilDB->quote($a_operation,'text');
268  $res = $ilDB->query($query);
269  while($row = $ilDB->fetchObject($res))
270  {
271  $ops_id = $row->ops_id;
272  }
273 
274  $query = "SELECT * FROM rbac_pa ".
275  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
276  "AND ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
277  $res = $ilDB->query($query);
278 
279  while($row = $ilDB->fetchObject($res))
280  {
281  $ops = array_merge($ops,unserialize($row->ops_id));
282  }
283  return in_array($ops_id,$ops);
284  }
285 
286  function __filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id)
287  {
288  global $ilObjDataCache,$ilUser;
289 
290  // member view constraints
291  if($this->mem_view['active'] and $a_user_id == $ilUser->getId())
292  {
293  if(in_array($a_ref_id, $this->mem_view['items']))
294  {
295  return $a_operations;
296  }
297  }
298 
299  if($a_user_id != $ilObjDataCache->lookupOwner($ilObjDataCache->lookupObjId($a_ref_id)))
300  {
301  return $a_operations;
302  }
303  // Is owner
304  foreach(explode(",",$a_operations) as $operation)
305  {
306  if($operation != 'cat_administrate_users' and $operation != 'edit_permission' and !preg_match('/^create/',$operation))
307  {
308  continue;
309  }
310  if(!strlen($new_ops))
311  {
312  $new_ops = $operation;
313  }
314  else
315  {
316  $new_ops .= (','.$operation);
317  }
318  }
319  return $new_ops;
320 
321 
322  }
323 
332  private function fetchAssignedRoles($a_usr_id,$a_ref_id)
333  {
334  global $ilUser,$rbacreview;
335 
336  // Member view constraints
337  if($this->mem_view['active'] and $a_usr_id == $ilUser->getId())
338  {
339  // check if current ref_id is subitem of active container
340  if(in_array($a_ref_id, $this->mem_view['items']) and $this->mem_view['role'])
341  {
342  // Return default member role
343  return array($this->mem_view['role']);
344  }
345  }
346 
347  if(isset(self::$user_role_cache[$a_usr_id]) and is_array(self::$user_role_cache))
348  {
349  return self::$user_role_cache[$a_usr_id];
350  }
351 
352 
353 
354  return self::$user_role_cache[$a_usr_id] = $rbacreview->assignedRoles($a_usr_id);
355  }
356 
361  public function initMemberView()
362  {
363  include_once './Services/Container/classes/class.ilMemberViewSettings.php';
364  $settings = ilMemberViewSettings::getInstance();
365  if($settings->isEnabled() and isset($_GET['mv']))
366  {
367  $settings->toggleActivation((int) $_GET['ref_id'], (int) $_GET['mv']);
368  }
369 
370  if(!$settings->isActive())
371  {
372  $this->mem_view['active'] = false;
373  $this->mem_view['items'] = array();
374  $this->mem_view['role'] = 0;
375  }
376  else
377  {
378  global $tree;
379 
380  $this->mem_view['active'] = true;
381  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
382  $this->mem_view['items'] = array_merge($this->mem_view['items'],array($settings->getContainer()));
383  include_once './Services/Membership/classes/class.ilParticipants.php';
384  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
385 
386  }
387  return true;
388  }
389 
390 } // END class.RbacSystem
391 ?>