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';
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
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
$result
const PEAR_ERROR_CALLBACK
Definition: PEAR.php:35
PHPExcel root directory.
Definition: PHPExcel.php:30
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
Database Wrapper.
Definition: class.ilDB.php:30
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.
$r
Definition: example_031.php:79
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
global $ilBench
Definition: ilias.php:18
redirection script todo: (a better solution should control the processing via a xml file)
$query
global $ilErr
Definition: raiseError.php:16
foreach($_POST as $key=> $value) $res
global $ilDB
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:92