ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups 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  self::$_paCache[$a_user_id.":".$ref_id] = $ops[$ref_id];
298  }
299  }
300  }
301 
310  function checkPermission($a_ref_id,$a_rol_id,$a_operation)
311  {
312  global $ilDB;
313 
314  $ops = array();
315 
316  $query = 'SELECT ops_id FROM rbac_operations '.
317  'WHERE operation = '.$ilDB->quote($a_operation,'text');
318  $res = $ilDB->query($query);
319  while($row = $ilDB->fetchObject($res))
320  {
321  $ops_id = $row->ops_id;
322  }
323 
324  $query = "SELECT * FROM rbac_pa ".
325  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
326  "AND ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
327  $res = $ilDB->query($query);
328 
329  while($row = $ilDB->fetchObject($res))
330  {
331  $ops = array_merge($ops,unserialize($row->ops_id));
332  }
333  return in_array($ops_id,$ops);
334  }
335 
336  function __filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id)
337  {
338  global $ilObjDataCache,$ilUser;
339 
340  // member view constraints
341  if($this->mem_view['active'] and $a_user_id == $ilUser->getId())
342  {
343  if(in_array($a_ref_id, $this->mem_view['items']))
344  {
345  return $a_operations;
346  }
347  }
348 
349  if($a_user_id != $ilObjDataCache->lookupOwner($ilObjDataCache->lookupObjId($a_ref_id)))
350  {
351  return $a_operations;
352  }
353  // Is owner
354  $new_ops = false;
355  foreach(explode(",",$a_operations) as $operation)
356  {
357  if($operation != 'cat_administrate_users' and $operation != 'edit_permission' and $operation != 'edit_learning_progress' and !preg_match('/^create/',$operation))
358  {
359  continue;
360  }
361  if(!strlen($new_ops))
362  {
363  $new_ops = $operation;
364  }
365  else
366  {
367  $new_ops .= (','.$operation);
368  }
369  }
370  return $new_ops;
371 
372 
373  }
374 
383  private function fetchAssignedRoles($a_usr_id,$a_ref_id)
384  {
385  global $ilUser,$rbacreview;
386 
387  // Member view constraints
388  if($this->mem_view['active'] and $a_usr_id == $ilUser->getId())
389  {
390  // check if current ref_id is subitem of active container
391  if(in_array($a_ref_id, $this->mem_view['items']) and $this->mem_view['role'])
392  {
393  // Return default member role
394  return array($this->mem_view['role']);
395  }
396  }
397 
398  if(isset(self::$user_role_cache[$a_usr_id]) and is_array(self::$user_role_cache))
399  {
400  return self::$user_role_cache[$a_usr_id];
401  }
402 
403 
404 
405  return self::$user_role_cache[$a_usr_id] = $rbacreview->assignedRoles($a_usr_id);
406  }
407 
412  public function initMemberView()
413  {
414  include_once './Services/Container/classes/class.ilMemberViewSettings.php';
415  $settings = ilMemberViewSettings::getInstance();
416  if($settings->isEnabled() and isset($_GET['mv']))
417  {
418  $settings->toggleActivation((int) $_GET['ref_id'], (int) $_GET['mv']);
419  }
420 
421  if(!$settings->isActive())
422  {
423  $this->mem_view['active'] = false;
424  $this->mem_view['items'] = array();
425  $this->mem_view['role'] = 0;
426  }
427  else
428  {
429  global $tree;
430 
431  $this->mem_view['active'] = true;
432  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
433  $this->mem_view['items'] = array_merge($this->mem_view['items'],array($settings->getContainer()));
434  include_once './Services/Membership/classes/class.ilParticipants.php';
435  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
436 
437  }
438  return true;
439  }
440 
441  public function addTemporaryRole($a_usr_id, $a_role_id)
442  {
443  if(!in_array($a_role_id, self::$user_role_cache[$a_usr_id]))
444  {
445  self::$user_role_cache[$a_usr_id][] = $a_role_id;
446  }
447  }
448 
449  public function resetPACache($a_usr_id, $a_ref_id)
450  {
451  $paCacheKey = $a_usr_id.':'.$a_ref_id;
452  unset(self::$_paCache[$paCacheKey]);
453  }
454 
455 } // END class.RbacSystem
456 ?>