ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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(DB_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(DB_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';
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
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?>
$result
const PEAR_ERROR_CALLBACK
Definition: PEAR.php:35
$_GET["client_id"]
const DB_FETCHMODE_OBJECT
Definition: class.ilDB.php:11
Database Wrapper.
Definition: class.ilDB.php:29
query($sql, $a_handle_error=true)
Query.
static getInstance()
Get instance.
static getDefaultMemberRole($a_ref_id)
static _getOperationIdByName($a_operation)
get operation id by name of operation @access public @access static
class ilRbacSystem system function like checkAccess, addActiveRole ... Supporting system functions ar...
resetPACache($a_usr_id, $a_ref_id)
static $_checkAccessOfUserCache
fetchAssignedRoles($a_usr_id, $a_ref_id)
Fetch assigned roles This method caches the assigned roles per user
static resetCaches()
Reset internal caches.
__construct()
Constructor @access public.
__filterOwnerPermissions($a_user_id, $a_operations, $a_ref_id)
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 ...
checkPermission($a_ref_id, $a_rol_id, $a_operation)
check if a specific role has the permission '$a_operation' of an object @access public
checkAccessOfUser($a_user_id, $a_operations, $a_ref_id, $a_type="")
addTemporaryRole($a_usr_id, $a_role_id)
preloadRbacPaCache($a_ref_ids, $a_user_id)
Preload rbac_pa cache.
initMemberView()
Init member view.
if(!file_exists(getcwd().'/ilias.ini.php')) if(isset( $_GET["client_id"]))
registration confirmation script for ilias
Definition: confirmReg.php:20
$r
Definition: example_031.php:79
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
global $ilBench
Definition: ilias.php:18
redirection script todo: (a better solution should control the processing via a xml file)
$ref_id
Definition: sahs_server.php:39
global $ilDB
global $ilUser
Definition: imgupload.php:15