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';
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
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
$result
const PEAR_ERROR_CALLBACK
Definition: PEAR.php:35
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
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'))
registration confirmation script for ilias
Definition: confirmReg.php:12
$r
Definition: example_031.php:79
global $ilBench
Definition: ilias.php:18
$row
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.
redirection script todo: (a better solution should control the processing via a xml file)
$query
$ilErr
Definition: raiseError.php:18
global $DIC
Definition: saml.php:7
foreach($_POST as $key=> $value) $res
global $ilDB
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:92