ILIAS  Release_4_4_x_branch Revision 61816
 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  // #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  if($settings->isEnabled() and isset($_GET['mv']))
421  {
422  $settings->toggleActivation((int) $_GET['ref_id'], (int) $_GET['mv']);
423  }
424 
425  if(!$settings->isActive())
426  {
427  $this->mem_view['active'] = false;
428  $this->mem_view['items'] = array();
429  $this->mem_view['role'] = 0;
430  }
431  else
432  {
433  global $tree;
434 
435  $this->mem_view['active'] = true;
436  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
437  $this->mem_view['items'] = array_merge($this->mem_view['items'],array($settings->getContainer()));
438  include_once './Services/Membership/classes/class.ilParticipants.php';
439  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
440 
441  }
442  return true;
443  }
444 
445  public function addTemporaryRole($a_usr_id, $a_role_id)
446  {
447  if(!in_array($a_role_id, self::$user_role_cache[$a_usr_id]))
448  {
449  self::$user_role_cache[$a_usr_id][] = $a_role_id;
450  }
451  }
452 
453  public function resetPACache($a_usr_id, $a_ref_id)
454  {
455  $paCacheKey = $a_usr_id.':'.$a_ref_id;
456  unset(self::$_paCache[$paCacheKey]);
457  }
458 
459 } // END class.RbacSystem
460 ?>