ILIAS  Release_4_2_x_branch Revision 61807
 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  global $ilLog;
220  $ilLog->logStack();
221 
222  $this->ilErr->raiseError(get_class($this)."::CheckAccess(): Expect a type definition for checking a 'create' permission",
223  $this->ilErr->WARNING);
224  }
225 
226  $ops_id = ilRbacReview::_getOperationIdByName($operation."_".$a_type);
227  }
228  else
229  {
230  $ops_id = ilRbacReview::_getOperationIdByName($operation);
231  }
232  if (! in_array($ops_id,(array) $ops))
233  {
234  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$a_ops_id.' failed');
235  // Store negative outcome in cache.
236  // Note: we only cache up to 1000 results to avoid memory overflows
237  if (count(self::$_checkAccessOfUserCache) < 1000)
238  {
239  self::$_checkAccessOfUserCache[$cacheKey] = false;
240  }
241  return false;
242  }
243  }
244 
245  // Store positive outcome in cache.
246  // Note: we only cache up to 1000 results to avoid memory overflows
247  if (count(self::$_checkAccessOfUserCache) < 1000)
248  {
249  //$ilLog->write('PERMISSION: '.$a_ref_id.' -> '.$ops_id.' granted');
250  self::$_checkAccessOfUserCache[$cacheKey] = true;
251  }
252  return true;
253  }
254 
261  function preloadRbacPaCache($a_ref_ids, $a_user_id)
262  {
263  global $ilDB;
264 
265  if (!is_array($a_ref_ids))
266  {
267  return;
268  }
269 
270  $ref_ids = array();
271  foreach ($a_ref_ids as $ref_id)
272  {
273  if (!isset(self::$_paCache[$a_user_id.":".$ref_id]))
274  {
275  $roles[$ref_id] = $this->fetchAssignedRoles($a_user_id, $ref_id);
276  $ops[$ref_id] = array();
277  $ref_ids[] = $ref_id;
278  }
279  }
280 
281  if (count($ref_ids) > 0)
282  {
283 
284  // Data is not in PA cache, perform database query
285  $q = "SELECT * FROM rbac_pa ".
286  "WHERE ".$ilDB->in("ref_id", $ref_ids, false, "integer");
287 
288  $r = $this->ilDB->query($q);
289 
290  while ($row = $r->fetchRow(DB_FETCHMODE_OBJECT))
291  {
292  if (in_array($row->rol_id, $roles[$row->ref_id]))
293  {
294  $ops[$row->ref_id] = array_merge($ops[$row->ref_id],
295  unserialize(stripslashes($row->ops_id)));
296  }
297  }
298  foreach ($a_ref_ids as $ref_id)
299  {
300  self::$_paCache[$a_user_id.":".$ref_id] = $ops[$ref_id];
301  }
302  }
303  }
304 
313  function checkPermission($a_ref_id,$a_rol_id,$a_operation)
314  {
315  global $ilDB;
316 
317  $ops = array();
318 
319  $query = 'SELECT ops_id FROM rbac_operations '.
320  'WHERE operation = '.$ilDB->quote($a_operation,'text');
321  $res = $ilDB->query($query);
322  while($row = $ilDB->fetchObject($res))
323  {
324  $ops_id = $row->ops_id;
325  }
326 
327  $query = "SELECT * FROM rbac_pa ".
328  "WHERE rol_id = ".$ilDB->quote($a_rol_id,'integer')." ".
329  "AND ref_id = ".$ilDB->quote($a_ref_id,'integer')." ";
330  $res = $ilDB->query($query);
331 
332  while($row = $ilDB->fetchObject($res))
333  {
334  $ops = array_merge($ops,unserialize($row->ops_id));
335  }
336  return in_array($ops_id,$ops);
337  }
338 
339  function __filterOwnerPermissions($a_user_id,$a_operations,$a_ref_id)
340  {
341  global $ilObjDataCache,$ilUser;
342 
343  // member view constraints
344  if($this->mem_view['active'] and $a_user_id == $ilUser->getId())
345  {
346  if(in_array($a_ref_id, $this->mem_view['items']))
347  {
348  return $a_operations;
349  }
350  }
351 
352  if($a_user_id != $ilObjDataCache->lookupOwner($ilObjDataCache->lookupObjId($a_ref_id)))
353  {
354  return $a_operations;
355  }
356  // Is owner
357  $new_ops = false;
358  foreach(explode(",",$a_operations) as $operation)
359  {
360  if($operation != 'cat_administrate_users' and $operation != 'edit_permission' and !preg_match('/^create/',$operation))
361  {
362  continue;
363  }
364  if(!strlen($new_ops))
365  {
366  $new_ops = $operation;
367  }
368  else
369  {
370  $new_ops .= (','.$operation);
371  }
372  }
373  return $new_ops;
374 
375 
376  }
377 
386  private function fetchAssignedRoles($a_usr_id,$a_ref_id)
387  {
388  global $ilUser,$rbacreview;
389 
390  // Member view constraints
391  if($this->mem_view['active'] and $a_usr_id == $ilUser->getId())
392  {
393  // check if current ref_id is subitem of active container
394  if(in_array($a_ref_id, $this->mem_view['items']) and $this->mem_view['role'])
395  {
396  // Return default member role
397  return array($this->mem_view['role']);
398  }
399  }
400 
401  if(isset(self::$user_role_cache[$a_usr_id]) and is_array(self::$user_role_cache))
402  {
403  return self::$user_role_cache[$a_usr_id];
404  }
405 
406 
407 
408  return self::$user_role_cache[$a_usr_id] = $rbacreview->assignedRoles($a_usr_id);
409  }
410 
415  public function initMemberView()
416  {
417  include_once './Services/Container/classes/class.ilMemberViewSettings.php';
418  $settings = ilMemberViewSettings::getInstance();
419  if($settings->isEnabled() and isset($_GET['mv']))
420  {
421  $settings->toggleActivation((int) $_GET['ref_id'], (int) $_GET['mv']);
422  }
423 
424  if(!$settings->isActive())
425  {
426  $this->mem_view['active'] = false;
427  $this->mem_view['items'] = array();
428  $this->mem_view['role'] = 0;
429  }
430  else
431  {
432  global $tree;
433 
434  $this->mem_view['active'] = true;
435  $this->mem_view['items'] = $tree->getSubTreeIds($settings->getContainer());
436  $this->mem_view['items'] = array_merge($this->mem_view['items'],array($settings->getContainer()));
437  include_once './Services/Membership/classes/class.ilParticipants.php';
438  $this->mem_view['role'] = ilParticipants::getDefaultMemberRole($settings->getContainer());
439 
440  }
441  return true;
442  }
443 
444 } // END class.RbacSystem
445 ?>