ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 $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  $ilErr = new ilErrorHandling();
46  $ilErr->setErrorHandling(PEAR_ERROR_CALLBACK, array($ilErr,'errorHandler'));
47  } else {
48  $this->ilErr =&$ilErr;
49  }
50  }
51 
52  public static function getInstance()
53  {
54  if (self::$instance) {
55  return self::$instance;
56  }
57  return self::$instance = new ilRbacSystem();
58  }
59 
63  public static function resetCaches()
64  {
65  self::$user_role_cache = array();
66  self::$_paCache = null;
67  self::$_checkAccessOfUserCache = null;
68  }
69 
89  public function checkAccess($a_operations, $a_ref_id, $a_type = "")
90  {
91  global $ilUser,$ilBench;
92 
93  $ilBench->start("RBAC", "system_checkAccess");
94 
95  $result = $this->checkAccessOfUser($ilUser->getId(), $a_operations, $a_ref_id, $a_type);
96 
97  $ilBench->stop("RBAC", "system_checkAccess");
98 
99  return $result;
100  }
101 
102  public function checkAccessOfUser($a_user_id, $a_operations, $a_ref_id, $a_type = "")
103  {
104  global $ilUser, $rbacreview,$ilObjDataCache,$ilDB,$ilLog;
105 
106  // Create the user cache key
107  $cacheKey = $a_user_id . ':' . $a_operations . ':' . $a_ref_id . ':' . $a_type;
108 
109  // Create the cache if it does not yet exist
110  if (!is_array(self::$_checkAccessOfUserCache)) {
111  self::$_checkAccessOfUserCache = array();
112  }
113 
114  // Try to return result from cache
115  if (array_key_exists($cacheKey, self::$_checkAccessOfUserCache)) {
116  return self::$_checkAccessOfUserCache[$cacheKey];
117  }
118 
119 
120  // DISABLED
121  // Check For owner
122  // Owners do always have full access to their objects
123  // Excluded are the permissions create and perm
124  // This method call return all operations that are NOT granted by the owner status
125  if (!$a_operations = $this->__filterOwnerPermissions($a_user_id, $a_operations, $a_ref_id)) {
126  // Store positive outcome in cache.
127  // Note: we only cache up to 1000 results to avoid memory overflows
128  if (count(self::$_checkAccessOfUserCache) < 1000) {
129  self::$_checkAccessOfUserCache[$cacheKey] = true;
130  }
131  return true;
132  }
133 
134 
135  // get roles using role cache
136  $roles = $this->fetchAssignedRoles($a_user_id, $a_ref_id);
137 
138  // exclude system role from rbac
139  if (in_array(SYSTEM_ROLE_ID, $roles)) {
140  // Store positive outcome in cache.
141  // Note: we only cache up to 1000 results to avoid memory overflows
142  if (count(self::$_checkAccessOfUserCache) < 1000) {
143  self::$_checkAccessOfUserCache[$cacheKey] = true;
144  }
145  return true;
146  }
147 
148  if (!isset($a_operations) or !isset($a_ref_id)) {
149  $GLOBALS['ilLog']->logStack();
150  $this->ilErr->raiseError(get_class($this) . "::checkAccess(): Missing parameter! " .
151  "ref_id: " . $a_ref_id . " operations: " . $a_operations, $this->ilErr->WARNING);
152  }
153 
154  if (!is_string($a_operations)) {
155  $GLOBALS['ilLog']->logStack();
156  $this->ilErr->raiseError(get_class($this) . "::checkAccess(): Wrong datatype for operations!", $this->ilErr->WARNING);
157  }
158 
159  // Create the PA cache if it does not exist yet
160  $paCacheKey = $a_user_id . ':' . $a_ref_id;
161  if (!is_array(self::$_paCache)) {
162  self::$_paCache = array();
163  }
164 
165  if (array_key_exists($paCacheKey, self::$_paCache)) {
166  // Return result from PA cache
167  $ops = self::$_paCache[$paCacheKey];
168  } else {
169  // Data is not in PA cache, perform database query
170  $q = "SELECT * FROM rbac_pa " .
171  "WHERE ref_id = " . $ilDB->quote($a_ref_id, 'integer');
172 
173  $r = $this->ilDB->query($q);
174 
175  $ops = array();
176 
177  while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
178  if (in_array($row->rol_id, $roles)) {
179  $ops = array_merge($ops, unserialize(stripslashes($row->ops_id)));
180  }
181  }
182  // Cache up to 1000 entries in the PA cache
183  if (count(self::$_paCache) < 1000) {
184  self::$_paCache[$paCacheKey] = $ops;
185  }
186  }
187 
188  $operations = explode(",", $a_operations);
189  foreach ($operations as $operation) {
190  if ($operation == "create") {
191  if (empty($a_type)) {
192  $this->ilErr->raiseError(
193  get_class($this) . "::CheckAccess(): Expect a type definition for checking a 'create' permission",
194  $this->ilErr->WARNING
195  );
196  }
197 
198  $ops_id = ilRbacReview::_getOperationIdByName($operation . "_" . $a_type);
199  } else {
200  $ops_id = ilRbacReview::_getOperationIdByName($operation);
201  }
202  if (!in_array($ops_id, (array) $ops)) {
203  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$a_ops_id.' failed');
204  // Store negative outcome in cache.
205  // Note: we only cache up to 1000 results to avoid memory overflows
206  if (count(self::$_checkAccessOfUserCache) < 1000) {
207  self::$_checkAccessOfUserCache[$cacheKey] = false;
208  }
209  return false;
210  }
211  }
212 
213  // Store positive outcome in cache.
214  // Note: we only cache up to 1000 results to avoid memory overflows
215  if (count(self::$_checkAccessOfUserCache) < 1000) {
216  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$ops_id.' granted');
217  self::$_checkAccessOfUserCache[$cacheKey] = true;
218  }
219  return true;
220  }
221 
228  public function preloadRbacPaCache($a_ref_ids, $a_user_id)
229  {
230  global $ilDB;
231 
232  if (!is_array($a_ref_ids)) {
233  return;
234  }
235 
236  $ref_ids = array();
237  foreach ($a_ref_ids as $ref_id) {
238  if (!isset(self::$_paCache[$a_user_id . ":" . $ref_id])) {
239  $roles[$ref_id] = $this->fetchAssignedRoles($a_user_id, $ref_id);
240  $ops[$ref_id] = array();
241  $ref_ids[] = $ref_id;
242  }
243  }
244 
245  if (count($ref_ids) > 0) {
246 
247  // Data is not in PA cache, perform database query
248  $q = "SELECT * FROM rbac_pa " .
249  "WHERE " . $ilDB->in("ref_id", $ref_ids, false, "integer");
250 
251  $r = $this->ilDB->query($q);
252 
253  while ($row = $r->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
254  if (in_array($row->rol_id, $roles[$row->ref_id])) {
255  $ops[$row->ref_id] = array_merge(
256  $ops[$row->ref_id],
257  unserialize(stripslashes($row->ops_id))
258  );
259  }
260  }
261  foreach ($a_ref_ids as $ref_id) {
262  // #11313
263  if (!isset(self::$_paCache[$a_user_id . ":" . $ref_id])) {
264  self::$_paCache[$a_user_id . ":" . $ref_id] = $ops[$ref_id];
265  }
266  }
267  }
268  }
269 
278  public function checkPermission($a_ref_id, $a_rol_id, $a_operation)
279  {
280  global $ilDB;
281 
282  $ops = array();
283 
284  $query = 'SELECT ops_id FROM rbac_operations ' .
285  'WHERE operation = ' . $ilDB->quote($a_operation, 'text');
286  $res = $ilDB->query($query);
287  while ($row = $ilDB->fetchObject($res)) {
288  $ops_id = $row->ops_id;
289  }
290 
291  $query = "SELECT * FROM rbac_pa " .
292  "WHERE rol_id = " . $ilDB->quote($a_rol_id, 'integer') . " " .
293  "AND ref_id = " . $ilDB->quote($a_ref_id, 'integer') . " ";
294  $res = $ilDB->query($query);
295 
296  while ($row = $ilDB->fetchObject($res)) {
297  $ops = array_merge($ops, unserialize($row->ops_id));
298  }
299  return in_array($ops_id, $ops);
300  }
301 
302  public function __filterOwnerPermissions($a_user_id, $a_operations, $a_ref_id)
303  {
304  global $ilObjDataCache,$ilUser;
305 
306  // member view constraints
307  if ($this->mem_view['active'] and $a_user_id == $ilUser->getId()) {
308  if (in_array($a_ref_id, $this->mem_view['items'])) {
309  return $a_operations;
310  }
311  }
312 
313  if ($a_user_id != $ilObjDataCache->lookupOwner($ilObjDataCache->lookupObjId($a_ref_id))) {
314  return $a_operations;
315  }
316  // Is owner
317  $new_ops = false;
318  foreach (explode(",", $a_operations) as $operation) {
319  if ($operation != 'cat_administrate_users' and $operation != 'edit_permission' and $operation != 'edit_learning_progress' and $operation != 'read_learning_progress' and !preg_match('/^create/', $operation)) {
320  continue;
321  }
322  if (!strlen($new_ops)) {
323  $new_ops = $operation;
324  } else {
325  $new_ops .= (',' . $operation);
326  }
327  }
328  return $new_ops;
329  }
330 
339  private function fetchAssignedRoles($a_usr_id, $a_ref_id)
340  {
341  global $ilUser,$rbacreview;
342 
343  // Member view constraints
344  if ($this->mem_view['active'] and $a_usr_id == $ilUser->getId()) {
345  // check if current ref_id is subitem of active container
346  if (in_array($a_ref_id, $this->mem_view['items']) and $this->mem_view['role']) {
347  // Return default member role
348  return array($this->mem_view['role']);
349  }
350  }
351 
352  if (isset(self::$user_role_cache[$a_usr_id]) and is_array(self::$user_role_cache)) {
353  return self::$user_role_cache[$a_usr_id];
354  }
355 
356 
357 
358  return self::$user_role_cache[$a_usr_id] = $rbacreview->assignedRoles($a_usr_id);
359  }
360 
365  public function initMemberView()
366  {
367  include_once './Services/Container/classes/class.ilMemberViewSettings.php';
368  $settings = ilMemberViewSettings::getInstance();
369 
370  // disable member view
371  if (
372  isset($_GET['mv']) &&
373  $_GET['mv'] == 0
374  ) {
375  // force deactivation
376  $settings->toggleActivation((int) $_GET['ref_id'], false);
377  }
378  if (
379  isset($_GET['mv']) &&
380  $_GET['mv'] == 1
381  ) {
382  if ($this->checkAccess('write', (int) $_GET['ref_id'])) {
383  $settings->toggleActivation((int) $_GET['ref_id'], true);
384  // reset caches
385  self::resetCaches();
386  }
387  }
388 
389  if (!$settings->isActive()) {
390  $this->mem_view['active'] = false;
391  $this->mem_view['items'] = array();
392  $this->mem_view['role'] = 0;
393  } else {
394  global $tree;
395 
396  $this->mem_view['active'] = true;
397  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
398  $this->mem_view['items'] = array_merge($this->mem_view['items'], array($settings->getContainer()));
399 
400  include_once './Services/Membership/classes/class.ilParticipants.php';
401  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
402  }
403  return true;
404  }
405 
406  public function addTemporaryRole($a_usr_id, $a_role_id)
407  {
408  if (!in_array($a_role_id, self::$user_role_cache[$a_usr_id])) {
409  self::$user_role_cache[$a_usr_id][] = $a_role_id;
410  }
411  }
412 
413  public function resetPACache($a_usr_id, $a_ref_id)
414  {
415  $paCacheKey = $a_usr_id . ':' . $a_ref_id;
416  unset(self::$_paCache[$paCacheKey]);
417  }
418 } // END class.RbacSystem
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:92
$r
Definition: example_031.php:79
initMemberView()
Init member view.
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
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
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