ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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 
67  public static function resetCaches()
68  {
69  self::$user_role_cache = array();
70  self::$_paCache = null;
71  self::$_checkAccessOfUserCache = null;
72  }
73 
93  function checkAccess($a_operations,$a_ref_id,$a_type = "")
94  {
95  global $ilUser,$ilBench;
96 
97  $ilBench->start("RBAC", "system_checkAccess");
98 
99  $result = $this->checkAccessOfUser($ilUser->getId(), $a_operations, $a_ref_id, $a_type);
100 
101  $ilBench->stop("RBAC", "system_checkAccess");
102 
103  return $result;
104  }
105 
106  function checkAccessOfUser($a_user_id, $a_operations, $a_ref_id, $a_type = "")
107  {
108  global $ilUser, $rbacreview,$ilObjDataCache,$ilDB,$ilLog;
109 
110  // Create the user cache key
111  $cacheKey = $a_user_id.':'.$a_operations.':'.$a_ref_id.':'.$a_type;
112 
113  // Create the cache if it does not yet exist
114  if (! is_array(self::$_checkAccessOfUserCache)) {
115  self::$_checkAccessOfUserCache = array();
116  }
117 
118  // Try to return result from cache
119  if (array_key_exists($cacheKey, self::$_checkAccessOfUserCache)) {
120  return self::$_checkAccessOfUserCache[$cacheKey];
121  }
122 
123 
124  // DISABLED
125  // Check For owner
126  // Owners do always have full access to their objects
127  // Excluded are the permissions create and perm
128  // This method call return all operations that are NOT granted by the owner status
129  if(!$a_operations = $this->__filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id))
130  {
131  // Store positive outcome in cache.
132  // Note: we only cache up to 1000 results to avoid memory overflows
133  if (count(self::$_checkAccessOfUserCache) < 1000) {
134  self::$_checkAccessOfUserCache[$cacheKey] = true;
135  }
136  return true;
137  }
138 
139 
140  // get roles using role cache
141  $roles = $this->fetchAssignedRoles($a_user_id,$a_ref_id);
142 
143  // exclude system role from rbac
144  if (in_array(SYSTEM_ROLE_ID, $roles))
145  {
146  // Store positive outcome in cache.
147  // Note: we only cache up to 1000 results to avoid memory overflows
148  if (count(self::$_checkAccessOfUserCache) < 1000) {
149  self::$_checkAccessOfUserCache[$cacheKey] = true;
150  }
151  return true;
152  }
153 
154  if (!isset($a_operations) or !isset($a_ref_id))
155  {
156  $GLOBALS['ilLog']->logStack();
157  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Missing parameter! ".
158  "ref_id: ".$a_ref_id." operations: ".$a_operations,$this->ilErr->WARNING);
159  }
160 
161  if (!is_string($a_operations))
162  {
163  $GLOBALS['ilLog']->logStack();
164  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Wrong datatype for operations!",$this->ilErr->WARNING);
165  }
166 
167  // Create the PA cache if it does not exist yet
168  $paCacheKey = $a_user_id.':'.$a_ref_id;
169  if (! is_array(self::$_paCache)) {
170  self::$_paCache = array();
171  }
172 
173  if (array_key_exists($paCacheKey, self::$_paCache)) {
174  // Return result from PA cache
175  $ops = self::$_paCache[$paCacheKey];
176  }
177  else
178  {
179  // Data is not in PA cache, perform database query
180  $q = "SELECT * FROM rbac_pa ".
181  "WHERE ref_id = ".$ilDB->quote($a_ref_id, 'integer');
182 
183  $r = $this->ilDB->query($q);
184 
185  $ops = array();
186 
187  while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
188  {
189  if (in_array($row->rol_id, $roles))
190  {
191  $ops = array_merge($ops,unserialize(stripslashes($row->ops_id)));
192  }
193  }
194  // Cache up to 1000 entries in the PA cache
195  if (count(self::$_paCache) < 1000)
196  {
197  self::$_paCache[$paCacheKey] = $ops;
198  }
199  }
200 
201  $operations = explode(",",$a_operations);
202  foreach ($operations as $operation)
203  {
204  if ($operation == "create")
205  {
206  if (empty($a_type))
207  {
208  $this->ilErr->raiseError(get_class($this)."::CheckAccess(): Expect a type definition for checking a 'create' permission",
209  $this->ilErr->WARNING);
210  }
211 
212  $ops_id = ilRbacReview::_getOperationIdByName($operation."_".$a_type);
213  }
214  else
215  {
216  $ops_id = ilRbacReview::_getOperationIdByName($operation);
217  }
218  if (! in_array($ops_id,(array) $ops))
219  {
220  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$a_ops_id.' failed');
221  // Store negative outcome in cache.
222  // Note: we only cache up to 1000 results to avoid memory overflows
223  if (count(self::$_checkAccessOfUserCache) < 1000)
224  {
225  self::$_checkAccessOfUserCache[$cacheKey] = false;
226  }
227  return false;
228  }
229  }
230 
231  // Store positive outcome in cache.
232  // Note: we only cache up to 1000 results to avoid memory overflows
233  if (count(self::$_checkAccessOfUserCache) < 1000)
234  {
235  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$ops_id.' granted');
236  self::$_checkAccessOfUserCache[$cacheKey] = true;
237  }
238  return true;
239  }
240 
247  function preloadRbacPaCache($a_ref_ids, $a_user_id)
248  {
249  global $ilDB;
250 
251  if (!is_array($a_ref_ids))
252  {
253  return;
254  }
255 
256  $ref_ids = array();
257  foreach ($a_ref_ids as $ref_id)
258  {
259  if (!isset(self::$_paCache[$a_user_id.":".$ref_id]))
260  {
261  $roles[$ref_id] = $this->fetchAssignedRoles($a_user_id, $ref_id);
262  $ops[$ref_id] = array();
263  $ref_ids[] = $ref_id;
264  }
265  }
266 
267  if (count($ref_ids) > 0)
268  {
269 
270  // Data is not in PA cache, perform database query
271  $q = "SELECT * FROM rbac_pa ".
272  "WHERE ".$ilDB->in("ref_id", $ref_ids, false, "integer");
273 
274  $r = $this->ilDB->query($q);
275 
276  while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
277  {
278  if (in_array($row->rol_id, $roles[$row->ref_id]))
279  {
280  $ops[$row->ref_id] = array_merge($ops[$row->ref_id],
281  unserialize(stripslashes($row->ops_id)));
282  }
283  }
284  foreach ($a_ref_ids as $ref_id)
285  {
286  // #11313
287  if (!isset(self::$_paCache[$a_user_id.":".$ref_id]))
288  {
289  self::$_paCache[$a_user_id.":".$ref_id] = $ops[$ref_id];
290  }
291  }
292  }
293  }
294 
303  function checkPermission($a_ref_id,$a_rol_id,$a_operation)
304  {
305  global $ilDB;
306 
307  $ops = array();
308 
309  $query = 'SELECT ops_id FROM rbac_operations '.
310  'WHERE operation = '.$ilDB->quote($a_operation,'text');
311  $res = $ilDB->query($query);
312  while($row = $ilDB->fetchObject($res))
313  {
314  $ops_id = $row->ops_id;
315  }
316 
317  $query = "SELECT * FROM rbac_pa ".
318  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
319  "AND ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
320  $res = $ilDB->query($query);
321 
322  while($row = $ilDB->fetchObject($res))
323  {
324  $ops = array_merge($ops,unserialize($row->ops_id));
325  }
326  return in_array($ops_id,$ops);
327  }
328 
329  function __filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id)
330  {
331  global $ilObjDataCache,$ilUser;
332 
333  // member view constraints
334  if($this->mem_view['active'] and $a_user_id == $ilUser->getId())
335  {
336  if(in_array($a_ref_id, $this->mem_view['items']))
337  {
338  return $a_operations;
339  }
340  }
341 
342  if($a_user_id != $ilObjDataCache->lookupOwner($ilObjDataCache->lookupObjId($a_ref_id)))
343  {
344  return $a_operations;
345  }
346  // Is owner
347  $new_ops = false;
348  foreach(explode(",",$a_operations) as $operation)
349  {
350  if($operation != 'cat_administrate_users' and $operation != 'edit_permission' and $operation != 'edit_learning_progress' and $operation != 'read_learning_progress' and !preg_match('/^create/',$operation))
351  {
352  continue;
353  }
354  if(!strlen($new_ops))
355  {
356  $new_ops = $operation;
357  }
358  else
359  {
360  $new_ops .= (','.$operation);
361  }
362  }
363  return $new_ops;
364 
365 
366  }
367 
376  private function fetchAssignedRoles($a_usr_id,$a_ref_id)
377  {
378  global $ilUser,$rbacreview;
379 
380  // Member view constraints
381  if($this->mem_view['active'] and $a_usr_id == $ilUser->getId())
382  {
383  // check if current ref_id is subitem of active container
384  if(in_array($a_ref_id, $this->mem_view['items']) and $this->mem_view['role'])
385  {
386  // Return default member role
387  return array($this->mem_view['role']);
388  }
389  }
390 
391  if(isset(self::$user_role_cache[$a_usr_id]) and is_array(self::$user_role_cache))
392  {
393  return self::$user_role_cache[$a_usr_id];
394  }
395 
396 
397 
398  return self::$user_role_cache[$a_usr_id] = $rbacreview->assignedRoles($a_usr_id);
399  }
400 
405  public function initMemberView()
406  {
407  include_once './Services/Container/classes/class.ilMemberViewSettings.php';
408  $settings = ilMemberViewSettings::getInstance();
409 
410  // disable member view
411  if(
412  isset($_GET['mv']) &&
413  $_GET['mv'] == 0
414  )
415  {
416  // force deactivation
417  $settings->toggleActivation((int) $_GET['ref_id'], false);
418  }
419  if(
420  isset($_GET['mv']) &&
421  $_GET['mv'] == 1
422  )
423  {
424  if($this->checkAccess('write', (int) $_GET['ref_id']))
425  {
426  $settings->toggleActivation((int) $_GET['ref_id'], true);
427  // reset caches
428  self::resetCaches();
429  }
430  }
431 
432  if(!$settings->isActive())
433  {
434  $this->mem_view['active'] = false;
435  $this->mem_view['items'] = array();
436  $this->mem_view['role'] = 0;
437  }
438  else
439  {
440  global $tree;
441 
442  $this->mem_view['active'] = true;
443  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
444  $this->mem_view['items'] = array_merge($this->mem_view['items'],array($settings->getContainer()));
445 
446  include_once './Services/Membership/classes/class.ilParticipants.php';
447  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
448 
449  }
450  return true;
451  }
452 
453  public function addTemporaryRole($a_usr_id, $a_role_id)
454  {
455  if(!in_array($a_role_id, self::$user_role_cache[$a_usr_id]))
456  {
457  self::$user_role_cache[$a_usr_id][] = $a_role_id;
458  }
459  }
460 
461  public function resetPACache($a_usr_id, $a_ref_id)
462  {
463  $paCacheKey = $a_usr_id.':'.$a_ref_id;
464  unset(self::$_paCache[$paCacheKey]);
465  }
466 
467 } // END class.RbacSystem
468 ?>
global $ilErr
Definition: raiseError.php:16
class ilRbacSystem system function like checkAccess, addActiveRole ...
const PEAR_ERROR_CALLBACK
Definition: PEAR.php:35
$result
static $_checkAccessOfUserCache
$_GET["client_id"]
query($sql, $a_handle_error=true)
Query.
preloadRbacPaCache($a_ref_ids, $a_user_id)
Preload rbac_pa cache.
resetPACache($a_usr_id, $a_ref_id)
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
addTemporaryRole($a_usr_id, $a_role_id)
static getDefaultMemberRole($a_ref_id)
static resetCaches()
Reset internal caches.
checkPermission($a_ref_id, $a_rol_id, $a_operation)
check if a specific role has the permission &#39;$a_operation&#39; of an object public
checkAccess($a_operations, $a_ref_id, $a_type="")
checkAccess represents the main method of the RBAC-system in ILIAS3 developers want to use With this ...
fetchAssignedRoles($a_usr_id, $a_ref_id)
Fetch assigned roles This method caches the assigned roles per user.
$a_type
Definition: workflow.php:93
$r
Definition: example_031.php:79
initMemberView()
Init member view.
$ilUser
Definition: imgupload.php:18
redirection script todo: (a better solution should control the processing via a xml file) ...
checkAccessOfUser($a_user_id, $a_operations, $a_ref_id, $a_type="")
Create styles array
The data for the language used.
static _getOperationIdByName($a_operation)
get operation id by name of operation public static
Database Wrapper.
Definition: class.ilDB.php:29
$ref_id
Definition: sahs_server.php:39
static getInstance()
Get instance.
global $ilBench
Definition: ilias.php:18
global $ilDB
__filterOwnerPermissions($a_user_id, $a_operations, $a_ref_id)
__construct()
Constructor public.
PHPExcel root directory.
Definition: Database.php:30