ILIAS  release_4-4 Revision
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilRbacSystem.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 
37 {
38  protected static $instance = null;
39 
40  protected $mem_view;
41 
42  protected static $user_role_cache = array();
43  var $ilias;
44 
45  // Cache accesses to RBAC PA
46  private static $_paCache = null;
47 
48  // Cache outcomes of calls to checkAccessOfuser
49  private static $_checkAccessOfUserCache = null;
50 
55  protected function ilRbacSystem()
56  {
57  global $ilDB,$ilErr,$ilias;
58 
59  $this->ilias =& $ilias;
60 
61  // set db & error handler
62  (isset($ilDB)) ? $this->ilDB =& $ilDB : $this->ilDB =& $ilias->db;
63 
64  if (!isset($ilErr))
65  {
66  $ilErr = new ilErrorHandling();
67  $ilErr->setErrorHandling(PEAR_ERROR_CALLBACK,array($ilErr,'errorHandler'));
68  }
69  else
70  {
71  $this->ilErr =& $ilErr;
72  }
73  }
74 
75  public static function getInstance()
76  {
77  if(self::$instance)
78  {
79  return self::$instance;
80  }
81  return self::$instance = new ilRbacSystem();
82  }
83 
103  function checkAccess($a_operations,$a_ref_id,$a_type = "")
104  {
105  global $ilUser,$ilBench;
106 
107  $ilBench->start("RBAC", "system_checkAccess");
108 
109  $result = $this->checkAccessOfUser($ilUser->getId(), $a_operations, $a_ref_id, $a_type);
110 
111  $ilBench->stop("RBAC", "system_checkAccess");
112 
113  return $result;
114  }
115 
116  function checkAccessOfUser($a_user_id, $a_operations, $a_ref_id, $a_type = "")
117  {
118  global $ilUser, $rbacreview,$ilObjDataCache,$ilDB,$ilLog;
119 
120  // Create the user cache key
121  $cacheKey = $a_user_id.':'.$a_operations.':'.$a_ref_id.':'.$a_type;
122 
123  // Create the cache if it does not yet exist
124  if (! is_array(self::$_checkAccessOfUserCache)) {
125  self::$_checkAccessOfUserCache = array();
126  }
127 
128  // Try to return result from cache
129  if (array_key_exists($cacheKey, self::$_checkAccessOfUserCache)) {
130  return self::$_checkAccessOfUserCache[$cacheKey];
131  }
132 
133  #echo ++$counter;
134 
135  // DISABLED
136  // Check For owner
137  // Owners do always have full access to their objects
138  // Excluded are the permissions create and perm
139  // This method call return all operations that are NOT granted by the owner status
140  if(!$a_operations = $this->__filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id))
141  {
142  // Store positive outcome in cache.
143  // Note: we only cache up to 1000 results to avoid memory overflows
144  if (count(self::$_checkAccessOfUserCache) < 1000) {
145  self::$_checkAccessOfUserCache[$cacheKey] = true;
146  }
147  return true;
148  }
149 
150 
151  // get roles using role cache
152  $roles = $this->fetchAssignedRoles($a_user_id,$a_ref_id);
153 
154  // exclude system role from rbac
155  if (in_array(SYSTEM_ROLE_ID, $roles))
156  {
157  // Store positive outcome in cache.
158  // Note: we only cache up to 1000 results to avoid memory overflows
159  if (count(self::$_checkAccessOfUserCache) < 1000) {
160  self::$_checkAccessOfUserCache[$cacheKey] = true;
161  }
162  return true;
163  }
164 
165  if (!isset($a_operations) or !isset($a_ref_id))
166  {
167  $GLOBALS['ilLog']->logStack();
168  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Missing parameter! ".
169  "ref_id: ".$a_ref_id." operations: ".$a_operations,$this->ilErr->WARNING);
170  }
171 
172  if (!is_string($a_operations))
173  {
174  $GLOBALS['ilLog']->logStack();
175  $this->ilErr->raiseError(get_class($this)."::checkAccess(): Wrong datatype for operations!",$this->ilErr->WARNING);
176  }
177 
178  // Create the PA cache if it does not exist yet
179  $paCacheKey = $a_user_id.':'.$a_ref_id;
180  if (! is_array(self::$_paCache)) {
181  self::$_paCache = array();
182  }
183 
184  if (array_key_exists($paCacheKey, self::$_paCache)) {
185  // Return result from PA cache
186  $ops = self::$_paCache[$paCacheKey];
187  }
188  else
189  {
190  // Data is not in PA cache, perform database query
191  $q = "SELECT * FROM rbac_pa ".
192  "WHERE ref_id = ".$ilDB->quote($a_ref_id, 'integer');
193 
194  $r = $this->ilDB->query($q);
195 
196  $ops = array();
197 
198  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
199  {
200  if (in_array($row->rol_id, $roles))
201  {
202  $ops = array_merge($ops,unserialize(stripslashes($row->ops_id)));
203  }
204  }
205  // Cache up to 1000 entries in the PA cache
206  if (count(self::$_paCache) < 1000)
207  {
208  self::$_paCache[$paCacheKey] = $ops;
209  }
210  }
211 
212  $operations = explode(",",$a_operations);
213  foreach ($operations as $operation)
214  {
215  if ($operation == "create")
216  {
217  if (empty($a_type))
218  {
219  $this->ilErr->raiseError(get_class($this)."::CheckAccess(): Expect a type definition for checking a 'create' permission",
220  $this->ilErr->WARNING);
221  }
222 
223  $ops_id = ilRbacReview::_getOperationIdByName($operation."_".$a_type);
224  }
225  else
226  {
227  $ops_id = ilRbacReview::_getOperationIdByName($operation);
228  }
229  if (! in_array($ops_id,(array) $ops))
230  {
231  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$a_ops_id.' failed');
232  // Store negative outcome in cache.
233  // Note: we only cache up to 1000 results to avoid memory overflows
234  if (count(self::$_checkAccessOfUserCache) < 1000)
235  {
236  self::$_checkAccessOfUserCache[$cacheKey] = false;
237  }
238  return false;
239  }
240  }
241 
242  // Store positive outcome in cache.
243  // Note: we only cache up to 1000 results to avoid memory overflows
244  if (count(self::$_checkAccessOfUserCache) < 1000)
245  {
246  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$ops_id.' granted');
247  self::$_checkAccessOfUserCache[$cacheKey] = true;
248  }
249  return true;
250  }
251 
258  function preloadRbacPaCache($a_ref_ids, $a_user_id)
259  {
260  global $ilDB;
261 
262  if (!is_array($a_ref_ids))
263  {
264  return;
265  }
266 
267  $ref_ids = array();
268  foreach ($a_ref_ids as $ref_id)
269  {
270  if (!isset(self::$_paCache[$a_user_id.":".$ref_id]))
271  {
272  $roles[$ref_id] = $this->fetchAssignedRoles($a_user_id, $ref_id);
273  $ops[$ref_id] = array();
274  $ref_ids[] = $ref_id;
275  }
276  }
277 
278  if (count($ref_ids) > 0)
279  {
280 
281  // Data is not in PA cache, perform database query
282  $q = "SELECT * FROM rbac_pa ".
283  "WHERE ".$ilDB->in("ref_id", $ref_ids, false, "integer");
284 
285  $r = $this->ilDB->query($q);
286 
287  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
288  {
289  if (in_array($row->rol_id, $roles[$row->ref_id]))
290  {
291  $ops[$row->ref_id] = array_merge($ops[$row->ref_id],
292  unserialize(stripslashes($row->ops_id)));
293  }
294  }
295  foreach ($a_ref_ids as $ref_id)
296  {
297  // #11313
298  if (!isset(self::$_paCache[$a_user_id.":".$ref_id]))
299  {
300  self::$_paCache[$a_user_id.":".$ref_id] = $ops[$ref_id];
301  }
302  }
303  }
304  }
305 
314  function checkPermission($a_ref_id,$a_rol_id,$a_operation)
315  {
316  global $ilDB;
317 
318  $ops = array();
319 
320  $query = 'SELECT ops_id FROM rbac_operations '.
321  'WHERE operation = '.$ilDB->quote($a_operation,'text');
322  $res = $ilDB->query($query);
323  while($row = $ilDB->fetchObject($res))
324  {
325  $ops_id = $row->ops_id;
326  }
327 
328  $query = "SELECT * FROM rbac_pa ".
329  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
330  "AND ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
331  $res = $ilDB->query($query);
332 
333  while($row = $ilDB->fetchObject($res))
334  {
335  $ops = array_merge($ops,unserialize($row->ops_id));
336  }
337  return in_array($ops_id,$ops);
338  }
339 
340  function __filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id)
341  {
342  global $ilObjDataCache,$ilUser;
343 
344  // member view constraints
345  if($this->mem_view['active'] and $a_user_id == $ilUser->getId())
346  {
347  if(in_array($a_ref_id, $this->mem_view['items']))
348  {
349  return $a_operations;
350  }
351  }
352 
353  if($a_user_id != $ilObjDataCache->lookupOwner($ilObjDataCache->lookupObjId($a_ref_id)))
354  {
355  return $a_operations;
356  }
357  // Is owner
358  $new_ops = false;
359  foreach(explode(",",$a_operations) as $operation)
360  {
361  if($operation != 'cat_administrate_users' and $operation != 'edit_permission' and $operation != 'edit_learning_progress' and !preg_match('/^create/',$operation))
362  {
363  continue;
364  }
365  if(!strlen($new_ops))
366  {
367  $new_ops = $operation;
368  }
369  else
370  {
371  $new_ops .= (','.$operation);
372  }
373  }
374  return $new_ops;
375 
376 
377  }
378 
387  private function fetchAssignedRoles($a_usr_id,$a_ref_id)
388  {
389  global $ilUser,$rbacreview;
390 
391  // Member view constraints
392  if($this->mem_view['active'] and $a_usr_id == $ilUser->getId())
393  {
394  // check if current ref_id is subitem of active container
395  if(in_array($a_ref_id, $this->mem_view['items']) and $this->mem_view['role'])
396  {
397  // Return default member role
398  return array($this->mem_view['role']);
399  }
400  }
401 
402  if(isset(self::$user_role_cache[$a_usr_id]) and is_array(self::$user_role_cache))
403  {
404  return self::$user_role_cache[$a_usr_id];
405  }
406 
407 
408 
409  return self::$user_role_cache[$a_usr_id] = $rbacreview->assignedRoles($a_usr_id);
410  }
411 
416  public function initMemberView()
417  {
418  include_once './Services/Container/classes/class.ilMemberViewSettings.php';
419  $settings = ilMemberViewSettings::getInstance();
420 
421  if(!isset($_GET['mv']))
422  {
423  // nothing to do
424  return true;
425  }
426 
427  // disable member view
428  if(!$_GET['mv'])
429  {
430  // force deactivation
431  $settings->toggleActivation((int) $_GET['ref_id'], false);
432  }
433  else
434  {
435  if($this->checkAccess('write', (int) $_GET['ref_id']))
436  {
437  $settings->toggleActivation((int) $_GET['ref_id'], true);
438  }
439  }
440 
441  if(!$settings->isActive())
442  {
443  $this->mem_view['active'] = false;
444  $this->mem_view['items'] = array();
445  $this->mem_view['role'] = 0;
446  }
447  else
448  {
449  global $tree;
450 
451  $this->mem_view['active'] = true;
452  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
453  $this->mem_view['items'] = array_merge($this->mem_view['items'],array($settings->getContainer()));
454  include_once './Services/Membership/classes/class.ilParticipants.php';
455  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
456 
457  }
458  return true;
459  }
460 
461  public function addTemporaryRole($a_usr_id, $a_role_id)
462  {
463  if(!in_array($a_role_id, self::$user_role_cache[$a_usr_id]))
464  {
465  self::$user_role_cache[$a_usr_id][] = $a_role_id;
466  }
467  }
468 
469  public function resetPACache($a_usr_id, $a_ref_id)
470  {
471  $paCacheKey = $a_usr_id.':'.$a_ref_id;
472  unset(self::$_paCache[$paCacheKey]);
473  }
474 
475 } // END class.RbacSystem
476 ?>
class ilRbacSystem system function like checkAccess, addActiveRole ...
const PEAR_ERROR_CALLBACK
Definition: PEAR.php:35
ilRbacSystem()
Constructor public.
$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)
addTemporaryRole($a_usr_id, $a_role_id)
static getDefaultMemberRole($a_ref_id)
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
const DB_FETCHMODE_OBJECT
Definition: class.ilDB.php:11
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.
initMemberView()
Init member view.
$GLOBALS['ct_recipient']
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="")
if(!file_exists(getcwd().'/ilias.ini.php')) if(isset( $_GET["client_id"]))
registration confirmation script for ilias
Definition: confirmReg.php:20
static _getOperationIdByName($a_operation)
get operation id by name of operation public static
Error Handling & global info handling uses PEAR error class.
global $ilUser
Definition: imgupload.php:15
Database Wrapper.
Definition: class.ilDB.php:28
$ref_id
Definition: sahs_server.php:39
static getInstance()
Get instance.
global $ilBench
Definition: ilias.php:18
__filterOwnerPermissions($a_user_id, $a_operations, $a_ref_id)
$r