ILIAS  Release_5_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 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 
17 {
18  protected static $instance = null;
19 
20  protected $mem_view;
21 
22  protected static $user_role_cache = array();
23  var $ilias;
24 
25  // Cache accesses to RBAC PA
26  private static $_paCache = null;
27 
28  // Cache outcomes of calls to checkAccessOfuser
29  private static $_checkAccessOfUserCache = null;
30 
35  protected function __construct()
36  {
37  global $ilDB,$ilErr,$ilias;
38 
39  $this->ilias =& $ilias;
40 
41  // set db & error handler
42  (isset($ilDB)) ? $this->ilDB =& $ilDB : $this->ilDB =& $ilias->db;
43 
44  if (!isset($ilErr))
45  {
46  $ilErr = new ilErrorHandling();
47  $ilErr->setErrorHandling(PEAR_ERROR_CALLBACK,array($ilErr,'errorHandler'));
48  }
49  else
50  {
51  $this->ilErr =& $ilErr;
52  }
53  }
54 
55  public static function getInstance()
56  {
57  if(self::$instance)
58  {
59  return self::$instance;
60  }
61  return self::$instance = new ilRbacSystem();
62  }
63 
83  function checkAccess($a_operations,$a_ref_id,$a_type = "")
84  {
85  global $ilUser,$ilBench;
86 
87  $ilBench->start("RBAC", "system_checkAccess");
88 
89  $result = $this->checkAccessOfUser($ilUser->getId(), $a_operations, $a_ref_id, $a_type);
90 
91  $ilBench->stop("RBAC", "system_checkAccess");
92 
93  return $result;
94  }
95 
96  function checkAccessOfUser($a_user_id, $a_operations, $a_ref_id, $a_type = "")
97  {
98  global $ilUser, $rbacreview,$ilObjDataCache,$ilDB,$ilLog;
99 
100  // Create the user cache key
101  $cacheKey = $a_user_id.':'.$a_operations.':'.$a_ref_id.':'.$a_type;
102 
103  // Create the cache if it does not yet exist
104  if (! is_array(self::$_checkAccessOfUserCache)) {
105  self::$_checkAccessOfUserCache = array();
106  }
107 
108  // Try to return result from cache
109  if (array_key_exists($cacheKey, self::$_checkAccessOfUserCache)) {
110  return self::$_checkAccessOfUserCache[$cacheKey];
111  }
112 
113  #echo ++$counter;
114 
115  // DISABLED
116  // Check For owner
117  // Owners do always have full access to their objects
118  // Excluded are the permissions create and perm
119  // This method call return all operations that are NOT granted by the owner status
120  if(!$a_operations = $this->__filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id))
121  {
122  // Store positive outcome in cache.
123  // Note: we only cache up to 1000 results to avoid memory overflows
124  if (count(self::$_checkAccessOfUserCache) < 1000) {
125  self::$_checkAccessOfUserCache[$cacheKey] = true;
126  }
127  return true;
128  }
129 
130 
131  // get roles using role cache
132  $roles = $this->fetchAssignedRoles($a_user_id,$a_ref_id);
133 
134  // exclude system role from rbac
135  if (in_array(SYSTEM_ROLE_ID, $roles))
136  {
137  // Store positive outcome in cache.
138  // Note: we only cache up to 1000 results to avoid memory overflows
139  if (count(self::$_checkAccessOfUserCache) < 1000) {
140  self::$_checkAccessOfUserCache[$cacheKey] = true;
141  }
142  return true;
143  }
144 
145  if (!isset($a_operations) or !isset($a_ref_id))
146  {
147  $GLOBALS['ilLog']->logStack();
148  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Missing parameter! ".
149  "ref_id: ".$a_ref_id." operations: ".$a_operations,$this->ilErr->WARNING);
150  }
151 
152  if (!is_string($a_operations))
153  {
154  $GLOBALS['ilLog']->logStack();
155  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Wrong datatype for operations!",$this->ilErr->WARNING);
156  }
157 
158  // Create the PA cache if it does not exist yet
159  $paCacheKey = $a_user_id.':'.$a_ref_id;
160  if (! is_array(self::$_paCache)) {
161  self::$_paCache = array();
162  }
163 
164  if (array_key_exists($paCacheKey, self::$_paCache)) {
165  // Return result from PA cache
166  $ops = self::$_paCache[$paCacheKey];
167  }
168  else
169  {
170  // Data is not in PA cache, perform database query
171  $q = "SELECT * FROM rbac_pa ".
172  "WHERE ref_id = ".$ilDB->quote($a_ref_id, 'integer');
173 
174  $r = $this->ilDB->query($q);
175 
176  $ops = array();
177 
178  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
179  {
180  if (in_array($row->rol_id, $roles))
181  {
182  $ops = array_merge($ops,unserialize(stripslashes($row->ops_id)));
183  }
184  }
185  // Cache up to 1000 entries in the PA cache
186  if (count(self::$_paCache) < 1000)
187  {
188  self::$_paCache[$paCacheKey] = $ops;
189  }
190  }
191 
192  $operations = explode(",",$a_operations);
193  foreach ($operations as $operation)
194  {
195  if ($operation == "create")
196  {
197  if (empty($a_type))
198  {
199  $this->ilErr->raiseError(get_class($this)."::CheckAccess(): Expect a type definition for checking a 'create' permission",
200  $this->ilErr->WARNING);
201  }
202 
203  $ops_id = ilRbacReview::_getOperationIdByName($operation."_".$a_type);
204  }
205  else
206  {
207  $ops_id = ilRbacReview::_getOperationIdByName($operation);
208  }
209  if (! in_array($ops_id,(array) $ops))
210  {
211  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$a_ops_id.' failed');
212  // Store negative outcome in cache.
213  // Note: we only cache up to 1000 results to avoid memory overflows
214  if (count(self::$_checkAccessOfUserCache) < 1000)
215  {
216  self::$_checkAccessOfUserCache[$cacheKey] = false;
217  }
218  return false;
219  }
220  }
221 
222  // Store positive outcome in cache.
223  // Note: we only cache up to 1000 results to avoid memory overflows
224  if (count(self::$_checkAccessOfUserCache) < 1000)
225  {
226  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$ops_id.' granted');
227  self::$_checkAccessOfUserCache[$cacheKey] = true;
228  }
229  return true;
230  }
231 
238  function preloadRbacPaCache($a_ref_ids, $a_user_id)
239  {
240  global $ilDB;
241 
242  if (!is_array($a_ref_ids))
243  {
244  return;
245  }
246 
247  $ref_ids = array();
248  foreach ($a_ref_ids as $ref_id)
249  {
250  if (!isset(self::$_paCache[$a_user_id.":".$ref_id]))
251  {
252  $roles[$ref_id] = $this->fetchAssignedRoles($a_user_id, $ref_id);
253  $ops[$ref_id] = array();
254  $ref_ids[] = $ref_id;
255  }
256  }
257 
258  if (count($ref_ids) > 0)
259  {
260 
261  // Data is not in PA cache, perform database query
262  $q = "SELECT * FROM rbac_pa ".
263  "WHERE ".$ilDB->in("ref_id", $ref_ids, false, "integer");
264 
265  $r = $this->ilDB->query($q);
266 
267  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
268  {
269  if (in_array($row->rol_id, $roles[$row->ref_id]))
270  {
271  $ops[$row->ref_id] = array_merge($ops[$row->ref_id],
272  unserialize(stripslashes($row->ops_id)));
273  }
274  }
275  foreach ($a_ref_ids as $ref_id)
276  {
277  // #11313
278  if (!isset(self::$_paCache[$a_user_id.":".$ref_id]))
279  {
280  self::$_paCache[$a_user_id.":".$ref_id] = $ops[$ref_id];
281  }
282  }
283  }
284  }
285 
294  function checkPermission($a_ref_id,$a_rol_id,$a_operation)
295  {
296  global $ilDB;
297 
298  $ops = array();
299 
300  $query = 'SELECT ops_id FROM rbac_operations '.
301  'WHERE operation = '.$ilDB->quote($a_operation,'text');
302  $res = $ilDB->query($query);
303  while($row = $ilDB->fetchObject($res))
304  {
305  $ops_id = $row->ops_id;
306  }
307 
308  $query = "SELECT * FROM rbac_pa ".
309  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
310  "AND ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
311  $res = $ilDB->query($query);
312 
313  while($row = $ilDB->fetchObject($res))
314  {
315  $ops = array_merge($ops,unserialize($row->ops_id));
316  }
317  return in_array($ops_id,$ops);
318  }
319 
320  function __filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id)
321  {
322  global $ilObjDataCache,$ilUser;
323 
324  // member view constraints
325  if($this->mem_view['active'] and $a_user_id == $ilUser->getId())
326  {
327  if(in_array($a_ref_id, $this->mem_view['items']))
328  {
329  return $a_operations;
330  }
331  }
332 
333  if($a_user_id != $ilObjDataCache->lookupOwner($ilObjDataCache->lookupObjId($a_ref_id)))
334  {
335  return $a_operations;
336  }
337  // Is owner
338  $new_ops = false;
339  foreach(explode(",",$a_operations) as $operation)
340  {
341  if($operation != 'cat_administrate_users' and $operation != 'edit_permission' and $operation != 'edit_learning_progress' and $operation != 'read_learning_progress' and !preg_match('/^create/',$operation))
342  {
343  continue;
344  }
345  if(!strlen($new_ops))
346  {
347  $new_ops = $operation;
348  }
349  else
350  {
351  $new_ops .= (','.$operation);
352  }
353  }
354  return $new_ops;
355 
356 
357  }
358 
367  private function fetchAssignedRoles($a_usr_id,$a_ref_id)
368  {
369  global $ilUser,$rbacreview;
370 
371  // Member view constraints
372  if($this->mem_view['active'] and $a_usr_id == $ilUser->getId())
373  {
374  // check if current ref_id is subitem of active container
375  if(in_array($a_ref_id, $this->mem_view['items']) and $this->mem_view['role'])
376  {
377  // Return default member role
378  return array($this->mem_view['role']);
379  }
380  }
381 
382  if(isset(self::$user_role_cache[$a_usr_id]) and is_array(self::$user_role_cache))
383  {
384  return self::$user_role_cache[$a_usr_id];
385  }
386 
387 
388 
389  return self::$user_role_cache[$a_usr_id] = $rbacreview->assignedRoles($a_usr_id);
390  }
391 
396  public function initMemberView()
397  {
398  include_once './Services/Container/classes/class.ilMemberViewSettings.php';
399  $settings = ilMemberViewSettings::getInstance();
400  if($settings->isEnabled() and isset($_GET['mv']))
401  {
402  $settings->toggleActivation((int) $_GET['ref_id'], (int) $_GET['mv']);
403  }
404 
405  if(!$settings->isActive())
406  {
407  $this->mem_view['active'] = false;
408  $this->mem_view['items'] = array();
409  $this->mem_view['role'] = 0;
410  }
411  else
412  {
413  global $tree;
414 
415  $this->mem_view['active'] = true;
416  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
417  $this->mem_view['items'] = array_merge($this->mem_view['items'],array($settings->getContainer()));
418  include_once './Services/Membership/classes/class.ilParticipants.php';
419  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
420 
421  }
422  return true;
423  }
424 
425  public function addTemporaryRole($a_usr_id, $a_role_id)
426  {
427  if(!in_array($a_role_id, self::$user_role_cache[$a_usr_id]))
428  {
429  self::$user_role_cache[$a_usr_id][] = $a_role_id;
430  }
431  }
432 
433  public function resetPACache($a_usr_id, $a_ref_id)
434  {
435  $paCacheKey = $a_usr_id.':'.$a_ref_id;
436  unset(self::$_paCache[$paCacheKey]);
437  }
438 
439 } // END class.RbacSystem
440 ?>