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