ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilRbacAdmin.php
Go to the documentation of this file.
1 <?php
2 
18 declare(strict_types=1);
19 
31 {
32  protected ilDBInterface $db;
34  protected ilLogger $logger;
35 
40  public function __construct()
41  {
42  global $DIC;
43 
44  $this->db = $DIC->database();
45  $this->rbacreview = $DIC->rbac()->review();
46  $this->logger = $DIC->logger()->ac();
47  }
48 
49  public function setBlockedStatus(int $a_role_id, int $a_ref_id, bool $a_blocked_status): void
50  {
51  ilLoggerFactory::getLogger('crs')->logStack();
52  $query = 'UPDATE rbac_fa set blocked = ' . $this->db->quote($a_blocked_status, 'integer') . ' ' .
53  'WHERE rol_id = ' . $this->db->quote($a_role_id, 'integer') . ' ' .
54  'AND parent = ' . $this->db->quote($a_ref_id, 'integer');
55  $this->db->manipulate($query);
56  }
57 
62  public function removeUser(int $a_usr_id): void
63  {
64  foreach ($this->rbacreview->assignedRoles($a_usr_id) as $role_id) {
65  $this->deassignUser($role_id, $a_usr_id);
66  }
67  $query = "DELETE FROM rbac_ua WHERE usr_id = " . $this->db->quote($a_usr_id, 'integer');
68  $res = $this->db->manipulate($query);
69  }
70 
74  public function deleteRole(int $a_rol_id, int $a_ref_id): void
75  {
76  if ($a_rol_id == SYSTEM_ROLE_ID) {
77  $this->logger->logStack(ilLogLevel::DEBUG);
78  throw new DomainException('System administrator role is not deletable.');
79  }
80 
82  $mapping->deleteRole($a_rol_id);
83 
84  // TODO: check assigned users before deletion
85  // This is done in ilObjRole. Should be better moved to this place?
86 
87  // delete user assignements
88  $query = "DELETE FROM rbac_ua " .
89  "WHERE rol_id = " . $this->db->quote($a_rol_id, 'integer');
90  $res = $this->db->manipulate($query);
91 
92  // delete permission assignments
93  $query = "DELETE FROM rbac_pa " .
94  "WHERE rol_id = " . $this->db->quote($a_rol_id, 'integer') . " ";
95  $res = $this->db->manipulate($query);
96 
97  //delete rbac_templates and rbac_fa
98  $this->deleteLocalRole($a_rol_id);
99  }
100 
104  public function deleteTemplate(int $a_obj_id): void
105  {
106  $query = 'DELETE FROM rbac_templates ' .
107  'WHERE rol_id = ' . $this->db->quote($a_obj_id, 'integer');
108  $res = $this->db->manipulate($query);
109 
110  $query = 'DELETE FROM rbac_fa ' .
111  'WHERE rol_id = ' . $this->db->quote($a_obj_id, 'integer');
112  $res = $this->db->manipulate($query);
113  }
114 
118  public function deleteLocalRole(int $a_rol_id, int $a_ref_id = 0): void
119  {
120  // exclude system role from rbac
121  if ($a_rol_id == SYSTEM_ROLE_ID) {
122  $this->logger->logStack(ilLogLevel::NOTICE);
123  $this->logger->notice('System administrator role is not deletable.');
124  return;
125  }
126 
127  $clause = '';
128  if ($a_ref_id != 0) {
129  $clause = 'AND parent = ' . $this->db->quote($a_ref_id, 'integer') . ' ';
130  }
131 
132  $query = 'DELETE FROM rbac_fa ' .
133  'WHERE rol_id = ' . $this->db->quote($a_rol_id, 'integer') . ' ' .
134  $clause;
135  $res = $this->db->manipulate($query);
136 
137  $query = 'DELETE FROM rbac_templates ' .
138  'WHERE rol_id = ' . $this->db->quote($a_rol_id, 'integer') . ' ' .
139  $clause;
140  $res = $this->db->manipulate($query);
141  }
142 
143  public function assignUserLimited(
144  int $a_role_id,
145  int $a_usr_id,
146  int $a_limit,
147  array $a_limited_roles = []
148  ): bool {
149  $ilDB = $this->db;
150  $ilAtomQuery = $this->db->buildAtomQuery();
151  $ilAtomQuery->addTableLock('rbac_ua');
152  $ilAtomQuery->addQueryCallable(
153  function (ilDBInterface $ilDB) use (&$ret, $a_role_id, $a_usr_id, $a_limit, $a_limited_roles): void {
154  $ret = true;
155  $limit_query = 'SELECT COUNT(*) num FROM rbac_ua ' .
156  'WHERE ' . $ilDB->in('rol_id', (array) $a_limited_roles, false, 'integer');
157  $res = $ilDB->query($limit_query);
158  $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT);
159  if ($row->num >= $a_limit) {
160  $ret = false;
161  return;
162  }
163 
164  $query = "INSERT INTO rbac_ua (usr_id, rol_id) " .
165  "VALUES (" .
166  $ilDB->quote($a_usr_id, 'integer') . "," . $ilDB->quote($a_role_id, 'integer') .
167  ")";
168  $res = $ilDB->manipulate($query);
169  }
170  );
171  $ilAtomQuery->run();
172 
173  if (!$ret) {
174  return false;
175  }
176 
177  $this->rbacreview->setAssignedCacheEntry($a_role_id, $a_usr_id, true);
179  $mapping->assign($a_role_id, $a_usr_id);
180 
181  return true;
182  }
183 
187  public function assignUser(int $a_rol_id, int $a_usr_id): void
188  {
189  // check if already assigned user id and role_id
190  $alreadyAssigned = $this->rbacreview->isAssigned($a_usr_id, $a_rol_id);
191 
192  // enhanced: only if we haven't had this role for this user
193  if (!$alreadyAssigned) {
194  $query = "INSERT INTO rbac_ua (usr_id, rol_id) " .
195  "VALUES (" . $this->db->quote($a_usr_id, 'integer') . "," . $this->db->quote(
196  $a_rol_id,
197  'integer'
198  ) . ")";
199  $res = $this->db->manipulate($query);
200 
201  $this->rbacreview->setAssignedCacheEntry($a_rol_id, $a_usr_id, true);
202  }
203 
205  $mapping->assign($a_rol_id, $a_usr_id);
206 
207  $ref_id = $this->rbacreview->getObjectReferenceOfRole($a_rol_id);
208  $obj_id = ilObject::_lookupObjId($ref_id);
209  $type = ilObject::_lookupType($obj_id);
210 
211  if (!$alreadyAssigned) {
212  ilLoggerFactory::getInstance()->getLogger('ac')->debug('Raise event assign user');
213  $GLOBALS['DIC']['ilAppEventHandler']->raise(
214  'Services/AccessControl',
215  'assignUser',
216  [
217  'obj_id' => $obj_id,
218  'usr_id' => $a_usr_id,
219  'role_id' => $a_rol_id,
220  'type' => $type
221  ]
222  );
223  }
224  }
225 
229  public function deassignUser(int $a_rol_id, int $a_usr_id): void
230  {
231  $query = "DELETE FROM rbac_ua " .
232  "WHERE usr_id = " . $this->db->quote($a_usr_id, 'integer') . " " .
233  "AND rol_id = " . $this->db->quote($a_rol_id, 'integer') . " ";
234  $res = $this->db->manipulate($query);
235 
236  $this->rbacreview->setAssignedCacheEntry($a_rol_id, $a_usr_id, false);
237 
239  $mapping->deassign($a_rol_id, $a_usr_id);
240 
241  if ($res) {
242  $ref_id = $GLOBALS['DIC']['rbacreview']->getObjectReferenceOfRole($a_rol_id);
243  $obj_id = ilObject::_lookupObjId($ref_id);
244  $type = ilObject::_lookupType($obj_id);
245 
246  ilLoggerFactory::getInstance()->getLogger('ac')->debug('Raise event deassign user');
247  $GLOBALS['DIC']['ilAppEventHandler']->raise('Services/AccessControl', 'deassignUser', [
248  'obj_id' => $obj_id,
249  'usr_id' => $a_usr_id,
250  'role_id' => $a_rol_id,
251  'type' => $type,
252  ]);
253  }
254  }
255 
259  public function grantPermission(int $a_rol_id, array $a_ops, int $a_ref_id): void
260  {
261  // exclude system role from rbac
262  if ($a_rol_id == SYSTEM_ROLE_ID) {
263  $this->logger->logStack(ilLogLevel::DEBUG);
264  return;
265  }
266 
267  // convert all values to integer
268  foreach ($a_ops as $key => $operation) {
269  $a_ops[$key] = (int) $operation;
270  }
271 
272  $ops_ids = serialize($a_ops);
273 
274  $query = 'DELETE FROM rbac_pa ' .
275  'WHERE rol_id = %s ' .
276  'AND ref_id = %s';
277  $res = $this->db->queryF(
278  $query,
279  ['integer', 'integer'],
280  [$a_rol_id, $a_ref_id]
281  );
282 
283  if ($a_ops === []) {
284  return;
285  }
286 
287  $query = "INSERT INTO rbac_pa (rol_id,ops_id,ref_id) " .
288  "VALUES " .
289  "(" . $this->db->quote($a_rol_id, 'integer') . "," . $this->db->quote(
290  $ops_ids,
291  'text'
292  ) . "," . $this->db->quote($a_ref_id, 'integer') . ")";
293  $res = $this->db->manipulate($query);
294  }
295 
301  public function revokePermission(int $a_ref_id, int $a_rol_id = 0, bool $a_keep_protected = true): void
302  {
303  if ($a_rol_id == SYSTEM_ROLE_ID) {
304  $this->logger->logStack(ilLogLevel::DEBUG);
305  return;
306  }
307 
308  // bypass protected status of roles
309  if ($a_keep_protected != true) {
310  if ($a_rol_id) {
311  $and1 = " AND rol_id = " . $this->db->quote($a_rol_id, 'integer') . " ";
312  } else {
313  $and1 = "";
314  }
315 
316  $query = "DELETE FROM rbac_pa " .
317  "WHERE ref_id = " . $this->db->quote($a_ref_id, 'integer') .
318  $and1;
319  $res = $this->db->manipulate($query);
320  return;
321  }
322 
323  // consider protected status of roles
324 
325  // in any case, get all roles in scope first
326  $roles_in_scope = $this->rbacreview->getParentRoleIds($a_ref_id);
327 
328  if (!$a_rol_id) {
329  $role_ids = [];
330 
331  foreach ($roles_in_scope as $role) {
332  if ($role['protected'] == true) {
333  continue;
334  }
335 
336  $role_ids[] = $role['obj_id'];
337  }
338 
339  // return if no role in array
340  if ($role_ids === []) {
341  return;
342  }
343 
344  $query = 'DELETE FROM rbac_pa ' .
345  'WHERE ' . $this->db->in('rol_id', $role_ids, false, 'integer') . ' ' .
346  'AND ref_id = ' . $this->db->quote($a_ref_id, 'integer');
347  $res = $this->db->manipulate($query);
348  } else {
349  // exclude protected permission settings from revoking
350  if ($roles_in_scope[$a_rol_id]['protected'] == true) {
351  return;
352  }
353 
354  $query = "DELETE FROM rbac_pa " .
355  "WHERE ref_id = " . $this->db->quote($a_ref_id, 'integer') . " " .
356  "AND rol_id = " . $this->db->quote($a_rol_id, 'integer') . " ";
357  $res = $this->db->manipulate($query);
358  }
359  }
360 
364  public function revokeSubtreePermissions(int $a_ref_id, int $a_role_id): void
365  {
366  $query = 'DELETE FROM rbac_pa ' .
367  'WHERE ref_id IN ' .
368  '( ' . $GLOBALS['DIC']['tree']->getSubTreeQuery($a_ref_id, ['child']) . ' ) ' .
369  'AND rol_id = ' . $this->db->quote($a_role_id, 'integer');
370 
371  $this->db->manipulate($query);
372  }
373 
377  public function deleteSubtreeTemplates(int $a_ref_id, int $a_rol_id): void
378  {
379  $query = 'DELETE FROM rbac_templates ' .
380  'WHERE parent IN ( ' .
381  $GLOBALS['DIC']['tree']->getSubTreeQuery($a_ref_id, ['child']) . ' ) ' .
382  'AND rol_id = ' . $this->db->quote($a_rol_id, 'integer');
383 
384  $this->db->manipulate($query);
385 
386  $query = 'DELETE FROM rbac_fa ' .
387  'WHERE parent IN ( ' .
388  $GLOBALS['DIC']['tree']->getSubTreeQuery($a_ref_id, ['child']) . ' ) ' .
389  'AND rol_id = ' . $this->db->quote($a_rol_id, 'integer');
390 
391  $this->db->manipulate($query);
392  }
393 
397  public function revokePermissionList(array $a_ref_ids, int $a_rol_id): void
398  {
399  // exclude system role from rbac
400  if ($a_rol_id == SYSTEM_ROLE_ID) {
401  $this->logger->logStack(ilLogLevel::DEBUG);
402  return;
403  }
404  $query = "DELETE FROM rbac_pa " .
405  "WHERE " . $this->db->in('ref_id', $a_ref_ids, false, 'integer') . ' ' .
406  "AND rol_id = " . $this->db->quote($a_rol_id, 'integer');
407  $res = $this->db->manipulate($query);
408  }
409 
413  public function copyRolePermissions(
414  int $a_source_id,
415  int $a_source_parent,
416  int $a_dest_parent,
417  int $a_dest_id,
418  bool $a_consider_protected = true
419  ): void {
420  // Copy template permissions
422  $a_source_id,
423  $a_source_parent,
424  $a_dest_parent,
425  $a_dest_id,
426  $a_consider_protected
427  );
428  $ops = $this->rbacreview->getRoleOperationsOnObject($a_source_id, $a_source_parent);
429 
430  $this->revokePermission($a_dest_parent, $a_dest_id);
431  $this->grantPermission($a_dest_id, $ops, $a_dest_parent);
432  }
433 
439  int $a_source_id,
440  int $a_source_parent,
441  int $a_dest_parent,
442  int $a_dest_id,
443  bool $a_consider_protected = true
444  ): void {
445  // exclude system role from rbac
446  if ($a_dest_id == SYSTEM_ROLE_ID) {
447  $this->logger->logStack(ilLogLevel::DEBUG);
448  return;
449  }
450 
451  // Read operations
452  $query = 'SELECT * FROM rbac_templates ' .
453  'WHERE rol_id = ' . $this->db->quote($a_source_id, 'integer') . ' ' .
454  'AND parent = ' . $this->db->quote($a_source_parent, 'integer');
455  $res = $this->db->query($query);
456  $operations = [];
457  $rownum = 0;
458  while ($row = $this->db->fetchObject($res)) {
459  $operations[$rownum]['type'] = $row->type;
460  $operations[$rownum]['ops_id'] = $row->ops_id;
461  $rownum++;
462  }
463 
464  // Delete target permissions
465  $query = 'DELETE FROM rbac_templates WHERE rol_id = ' . $this->db->quote($a_dest_id, 'integer') . ' ' .
466  'AND parent = ' . $this->db->quote($a_dest_parent, 'integer');
467  $res = $this->db->manipulate($query);
468 
469  foreach ($operations as $op) {
470  $query = 'INSERT INTO rbac_templates (rol_id,type,ops_id,parent) ' .
471  'VALUES (' .
472  $this->db->quote($a_dest_id, 'integer') . "," .
473  $this->db->quote($op['type'], 'text') . "," .
474  $this->db->quote($op['ops_id'], 'integer') . "," .
475  $this->db->quote($a_dest_parent, 'integer') . ")";
476  $this->db->manipulate($query);
477  }
478 
479  // copy also protection status if applicable
480  if ($a_consider_protected == true) {
481  if ($this->rbacreview->isProtected($a_source_parent, $a_source_id)) {
482  $this->setProtected($a_dest_parent, $a_dest_id, 'y');
483  }
484  }
485  }
486 
492  int $a_source1_id,
493  int $a_source1_parent,
494  int $a_source2_id,
495  int $a_source2_parent,
496  int $a_dest_parent,
497  int $a_dest_id
498  ): void {
499  // exclude system role from rbac
500  if ($a_dest_id == SYSTEM_ROLE_ID) {
501  $this->logger->logStack(ilLogLevel::DEBUG);
502  return;
503  }
504  $query = "SELECT s1.type, s1.ops_id " .
505  "FROM rbac_templates s1, rbac_templates s2 " .
506  "WHERE s1.rol_id = " . $this->db->quote($a_source1_id, 'integer') . " " .
507  "AND s1.parent = " . $this->db->quote($a_source1_parent, 'integer') . " " .
508  "AND s2.rol_id = " . $this->db->quote($a_source2_id, 'integer') . " " .
509  "AND s2.parent = " . $this->db->quote($a_source2_parent, 'integer') . " " .
510  "AND s1.type = s2.type " .
511  "AND s1.ops_id = s2.ops_id";
512 
513  $res = $this->db->query($query);
514  $operations = [];
515  $rowNum = 0;
516  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
517  $operations[$rowNum]['type'] = $row->type;
518  $operations[$rowNum]['ops_id'] = $row->ops_id;
519 
520  $rowNum++;
521  }
522 
523  // Delete template permissions of target
524  $query = 'DELETE FROM rbac_templates WHERE rol_id = ' . $this->db->quote($a_dest_id, 'integer') . ' ' .
525  'AND parent = ' . $this->db->quote($a_dest_parent, 'integer');
526  $res = $this->db->manipulate($query);
527 
528  $query = 'INSERT INTO rbac_templates (rol_id,type,ops_id,parent) ' .
529  'VALUES (?,?,?,?)';
530  $sta = $this->db->prepareManip($query, ['integer', 'text', 'integer', 'integer']);
531  foreach ($operations as $set) {
532  $this->db->execute($sta, [
533  $a_dest_id,
534  $set['type'],
535  $set['ops_id'],
536  $a_dest_parent
537  ]);
538  }
539  }
540 
541  public function copyRolePermissionUnion(
542  int $a_source1_id,
543  int $a_source1_parent,
544  int $a_source2_id,
545  int $a_source2_parent,
546  int $a_dest_id,
547  int $a_dest_parent
548  ): void {
549  // exclude system role from rbac
550  if ($a_dest_id == SYSTEM_ROLE_ID) {
551  $this->logger->logStack(ilLogLevel::DEBUG);
552  return;
553  }
554  $s1_ops = $this->rbacreview->getAllOperationsOfRole($a_source1_id, $a_source1_parent);
555  $s2_ops = $this->rbacreview->getAllOperationsOfRole($a_source2_id, $a_source2_parent);
556  $this->deleteRolePermission($a_dest_id, $a_dest_parent);
557 
558  foreach ($s1_ops as $type => $ops) {
559  foreach ($ops as $op) {
560  // insert all permission of source 1
561  // #15469
562  $query = 'INSERT INTO rbac_templates (rol_id,type,ops_id,parent) ' .
563  'VALUES( ' .
564  $this->db->quote($a_dest_id, 'integer') . ', ' .
565  $this->db->quote($type, 'text') . ', ' .
566  $this->db->quote($op, 'integer') . ', ' .
567  $this->db->quote($a_dest_parent, 'integer') . ' ' .
568  ')';
569  $this->db->manipulate($query);
570  }
571  }
572 
573  // and the other direction...
574  foreach ($s2_ops as $type => $ops) {
575  foreach ($ops as $op) {
576  if (!isset($s1_ops[$type]) || !in_array($op, $s1_ops[$type])) {
577  $query = 'INSERT INTO rbac_templates (rol_id,type,ops_id,parent) ' .
578  'VALUES( ' .
579  $this->db->quote($a_dest_id, 'integer') . ', ' .
580  $this->db->quote($type, 'text') . ', ' .
581  $this->db->quote($op, 'integer') . ', ' .
582  $this->db->quote($a_dest_parent, 'integer') . ' ' .
583  ')';
584  $this->db->manipulate($query);
585  }
586  }
587  }
588  }
589 
593  public function copyRolePermissionSubtract(
594  int $a_source_id,
595  int $a_source_parent,
596  int $a_dest_id,
597  int $a_dest_parent
598  ): void {
599  if ($a_dest_id == SYSTEM_ROLE_ID) {
600  $this->logger->logStack(ilLogLevel::DEBUG);
601  return;
602  }
603  $s1_ops = $this->rbacreview->getAllOperationsOfRole($a_source_id, $a_source_parent);
604  $d_ops = $this->rbacreview->getAllOperationsOfRole($a_dest_id, $a_dest_parent);
605 
606  foreach ($s1_ops as $type => $ops) {
607  foreach ($ops as $op) {
608  if (isset($d_ops[$type]) && in_array($op, $d_ops[$type])) {
609  $query = 'DELETE FROM rbac_templates ' .
610  'WHERE rol_id = ' . $this->db->quote($a_dest_id, 'integer') . ' ' .
611  'AND type = ' . $this->db->quote($type, 'text') . ' ' .
612  'AND ops_id = ' . $this->db->quote($op, 'integer') . ' ' .
613  'AND parent = ' . $this->db->quote($a_dest_parent, 'integer');
614  $this->db->manipulate($query);
615  }
616  }
617  }
618  }
619 
625  public function deleteRolePermission(
626  int $a_rol_id,
627  int $a_ref_id,
628  ?string $a_type = null
629  ): void {
630  if ($a_rol_id == SYSTEM_ROLE_ID) {
631  $this->logger->logStack(ilLogLevel::DEBUG);
632  return;
633  }
634  $and_type = '';
635  if ($a_type !== null) {
636  $and_type = " AND type=" . $this->db->quote($a_type, 'text') . " ";
637  }
638  $query = 'DELETE FROM rbac_templates ' .
639  'WHERE rol_id = ' . $this->db->quote($a_rol_id, 'integer') . ' ' .
640  'AND parent = ' . $this->db->quote($a_ref_id, 'integer') . ' ' .
641  $and_type;
642  $res = $this->db->manipulate($query);
643  }
644 
649  public function setRolePermission(int $a_rol_id, string $a_type, array $a_ops, int $a_ref_id): void
650  {
651  if ($a_rol_id == SYSTEM_ROLE_ID) {
652  $this->logger->logStack();
653  return;
654  }
655  foreach ($a_ops as $op) {
656  $this->db->replace(
657  'rbac_templates',
658  [
659  'rol_id' => ['integer', $a_rol_id],
660  'type' => ['text', $a_type],
661  'ops_id' => ['integer', $op],
662  'parent' => ['integer', $a_ref_id]
663  ],
664  []
665  );
666  }
667  }
668 
676  public function assignRoleToFolder(
677  int $a_rol_id,
678  int $a_parent,
679  string $a_assign = "y"
680  ): void {
681  if ($a_rol_id == SYSTEM_ROLE_ID) {
682  // ignore system role
683  return;
684  }
685  // if a wrong value is passed, always set assign to "n"
686  if ($a_assign != "y") {
687  $a_assign = "n";
688  }
689 
690  // check if already assigned
691  $query = 'SELECT rol_id FROM rbac_fa ' .
692  'WHERE rol_id = ' . $this->db->quote($a_rol_id, 'integer') . ' ' .
693  'AND parent = ' . $this->db->quote($a_parent, 'integer');
694  $res = $this->db->query($query);
695  if ($res->numRows()) {
696  return;
697  }
698  $query = sprintf(
699  'INSERT INTO rbac_fa (rol_id, parent, assign, protected) ' .
700  'VALUES (%s,%s,%s,%s)',
701  $this->db->quote($a_rol_id, 'integer'),
702  $this->db->quote($a_parent, 'integer'),
703  $this->db->quote($a_assign, 'text'),
704  $this->db->quote('n', 'text')
705  );
706  $res = $this->db->manipulate($query);
707  }
708 
713  public function assignOperationToObject(int $a_type_id, int $a_ops_id): void
714  {
715  $query = "INSERT INTO rbac_ta (typ_id, ops_id) " .
716  "VALUES(" . $this->db->quote($a_type_id, 'integer') . "," . $this->db->quote($a_ops_id, 'integer') . ")";
717  $res = $this->db->manipulate($query);
718  }
719 
724  public function deassignOperationFromObject(int $a_type_id, int $a_ops_id): void
725  {
726  $query = "DELETE FROM rbac_ta " .
727  "WHERE typ_id = " . $this->db->quote($a_type_id, 'integer') . " " .
728  "AND ops_id = " . $this->db->quote($a_ops_id, 'integer');
729  $res = $this->db->manipulate($query);
730  }
731 
735  public function setProtected(int $a_ref_id, int $a_role_id, string $a_value): void
736  {
737  // ref_id not used yet. protected permission acts 'global' for each role,
738  // regardless of any broken inheritance before
739  $query = 'UPDATE rbac_fa ' .
740  'SET protected = ' . $this->db->quote($a_value, 'text') . ' ' .
741  'WHERE rol_id = ' . $this->db->quote($a_role_id, 'integer');
742  $res = $this->db->manipulate($query);
743  }
744 
750  public function copyLocalRoles(int $a_source_id, int $a_target_id): void
751  {
752  $real_local = [];
753  foreach ($this->rbacreview->getRolesOfRoleFolder($a_source_id, false) as $role_data) {
754  $title = ilObject::_lookupTitle($role_data);
755  if (substr($title, 0, 3) == 'il_') {
756  continue;
757  }
758  $real_local[] = $role_data;
759  }
760  if ($real_local === []) {
761  return;
762  }
763  // Create role folder
764  foreach ($real_local as $role) {
765  $orig = new ilObjRole($role);
766  $orig->read();
767 
768  $roleObj = new ilObjRole();
769  $roleObj->setTitle($orig->getTitle());
770  $roleObj->setDescription($orig->getDescription());
771  $roleObj->setImportId($orig->getImportId());
772  $roleObj->create();
773 
774  $this->assignRoleToFolder($roleObj->getId(), $a_target_id, "y");
775  $this->copyRolePermissions($role, $a_source_id, $a_target_id, $roleObj->getId(), true);
776  }
777  }
778 
780  int $a_ref_id,
781  int $a_role_id,
782  int $a_role_parent,
783  int $a_template_id,
784  int $a_template_parent
785  ): void {
786  if ($this->rbacreview->isProtected($a_role_parent, $a_role_id)) {
787  // Assign object permissions
788  $new_ops = $this->rbacreview->getOperationsOfRole(
789  $a_role_id,
790  ilObject::_lookupType($a_ref_id, true),
791  $a_role_parent
792  );
793 
794  // set new permissions for object
795  $this->grantPermission(
796  $a_role_id,
797  (array) $new_ops,
798  $a_ref_id
799  );
800  return;
801  }
802  if (!$a_template_id) {
803  ilLoggerFactory::getLogger('ac')->info('No template id given. Aborting.');
804  return;
805  }
806  // create template permission intersection
808  $a_template_id,
809  $a_template_parent,
810  $a_role_id,
811  $a_role_parent,
812  $a_ref_id,
813  $a_role_id
814  );
815 
816  // assign role to folder
817  $this->assignRoleToFolder(
818  $a_role_id,
819  $a_ref_id,
820  'n'
821  );
822 
823  // Assign object permissions
824  $new_ops = $this->rbacreview->getOperationsOfRole(
825  $a_role_id,
826  ilObject::_lookupType($a_ref_id, true),
827  $a_ref_id
828  );
829 
830  // revoke existing permissions
831  $this->revokePermission($a_ref_id, $a_role_id);
832 
833  // set new permissions for object
834  $this->grantPermission(
835  $a_role_id,
836  (array) $new_ops,
837  $a_ref_id
838  );
839  }
840 
846  protected function applyMovedObjectDidacticTemplates(int $a_ref_id, int $a_old_parent): void
847  {
849  if (!$tpl_id) {
850  return;
851  }
852  foreach (ilDidacticTemplateActionFactory::getActionsByTemplateId($tpl_id) as $action) {
853  if ($action instanceof ilDidacticTemplateLocalRoleAction) {
854  continue;
855  }
856  $action->setRefId($a_ref_id);
857  $action->apply();
858  }
859  }
860 
867  public function adjustMovedObjectPermissions(int $ref_id, int $old_parent): void
868  {
869  global $DIC;
870 
871  $tree = $DIC['tree'];
872 
873  $new_parent = $tree->getParentId($ref_id);
874  $old_context_roles = $this->rbacreview->getParentRoleIds($old_parent, false);
875  $new_context_roles = $this->rbacreview->getParentRoleIds($new_parent, false);
876 
882  $tree->useCache(false);
883 
884  $for_addition = $for_deletion = [];
885  foreach ($new_context_roles as $new_role_id => $new_role) {
886  if (!isset($old_context_roles[$new_role_id])) {
887  $for_addition[] = $new_role_id;
888  } elseif ($new_role['parent'] != $old_context_roles[$new_role_id]['parent']) {
889  // handle stopped inheritance
890  $for_deletion[] = $new_role_id;
891  $for_addition[] = $new_role_id;
892  }
893  }
894  foreach ($old_context_roles as $old_role_id => $old_role) {
895  if (!isset($new_context_roles[$old_role_id])) {
896  $for_deletion[] = $old_role_id;
897  }
898  }
899  if ($for_deletion === [] && $for_addition === []) {
900  $this->applyMovedObjectDidacticTemplates($ref_id, $old_parent);
901  return;
902  }
903 
904  $rbac_log_active = ilRbacLog::isActive();
905  if ($rbac_log_active) {
906  $role_ids = array_unique(array_merge(array_keys($for_deletion), array_keys($for_addition)));
907  }
908 
909  foreach ($tree->getSubTree($tree->getNodeData($ref_id), true) as $node_data) {
910  $node_id = (int) $node_data['child'];
911  if ($rbac_log_active) {
912  $log_old = ilRbacLog::gatherFaPa($node_id, $role_ids);
913  }
914 
915  // If $node_data['type'] is not set, this means there is a tree entry without
916  // object_reference and/or object_data entry
917  // Continue in this case
918  if (!($node_data['type'] ?? false)) {
919  continue;
920  }
921  if (!$node_id) {
922  continue;
923  }
924 
925  foreach ($for_deletion as $role_id) {
926  $this->deleteLocalRole($role_id, $node_id);
927  $this->revokePermission($node_id, $role_id, false);
928  }
929  foreach ($for_addition as $role_id) {
930  $role_parent_id = $this->rbacreview->getParentOfRole($role_id, $ref_id);
931  switch ($node_data['type']) {
932  case 'grp':
933  $tpl_id = ilObjGroup::lookupGroupStatusTemplateId((int) $node_data['obj_id']);
934 
936  $node_id,
937  $role_id,
938  $role_parent_id,
939  $tpl_id,
941  );
942  break;
943 
944  case 'crs':
947  $node_id,
948  $role_id,
949  $role_parent_id,
950  $tpl_id,
952  );
953  break;
954 
955  default:
956  $this->grantPermission(
957  $role_id,
958  $this->rbacreview->getOperationsOfRole($role_id, $node_data['type'], $role_parent_id),
959  $node_id
960  );
961  break;
962  }
963  }
964 
965  if ($rbac_log_active) {
966  $log_new = ilRbacLog::gatherFaPa($node_id, $role_ids);
967  $log = ilRbacLog::diffFaPa($log_old, $log_new);
969  }
970  }
971 
975  $tree->useCache();
976 
977  $this->applyMovedObjectDidacticTemplates($ref_id, $old_parent);
978  }
979 }
removeUser(int $a_usr_id)
deletes a user from rbac_ua all user <-> role relations are deleted
Class ilObjRole.
static gatherFaPa(int $a_ref_id, array $a_role_ids, bool $a_add_action=false)
$res
Definition: ltiservices.php:69
grantPermission(int $a_rol_id, array $a_ops, int $a_ref_id)
Grants a permission to an object and a specific role.
adjustMovedObjectPermissions(int $ref_id, int $old_parent)
Adjust permissions of moved objects.
setRolePermission(int $a_rol_id, string $a_type, array $a_ops, int $a_ref_id)
Inserts template permissions in rbac_templates for an specific object type.
deleteRolePermission(int $a_rol_id, int $a_ref_id, ?string $a_type=null)
Deletes all entries of a template.
deleteSubtreeTemplates(int $a_ref_id, int $a_rol_id)
Delete all template permissions of subtree nodes.
static getLogger(string $a_component_id)
Get component logger.
deassignOperationFromObject(int $a_type_id, int $a_ops_id)
Deassign an existing operation from an object Update of rbac_ta.
applyMovedObjectDidacticTemplates(int $a_ref_id, int $a_old_parent)
Apply didactic templates after object movement.
static lookupCourseNonMemberTemplatesId()
copyRoleTemplatePermissions(int $a_source_id, int $a_source_parent, int $a_dest_parent, int $a_dest_id, bool $a_consider_protected=true)
Copies template permissions of one role to another.
const SYSTEM_ROLE_ID
Definition: constants.php:29
revokePermissionList(array $a_ref_ids, int $a_rol_id)
Revokes permissions of a LIST of objects of ONE role.
assignUser(int $a_rol_id, int $a_usr_id)
Assigns an user to a role.
quote($value, string $type)
static isActive()
revokePermission(int $a_ref_id, int $a_rol_id=0, bool $a_keep_protected=true)
Revokes permissions of an object of one role.
revokeSubtreePermissions(int $a_ref_id, int $a_role_id)
Revoke subtree permissions.
static lookupGroupStatusTemplateId(int $a_obj_id)
static diffFaPa(array $a_old, array $a_new)
copyRolePermissions(int $a_source_id, int $a_source_parent, int $a_dest_parent, int $a_dest_id, bool $a_consider_protected=true)
Copies template permissions and permission of one role to another.
static _lookupObjId(int $ref_id)
global $DIC
Definition: feed.php:28
static _getInstance()
Get singleton instance of this class.
$ref_id
Definition: ltiauth.php:67
static add(int $a_action, int $a_ref_id, array $a_diff, bool $a_source_ref_id=false)
static _lookupTitle(int $obj_id)
$GLOBALS["DIC"]
Definition: wac.php:31
deleteTemplate(int $a_obj_id)
Deletes a template from role folder and deletes all entries in rbac_templates, rbac_fa.
$log
Definition: result.php:33
initIntersectionPermissions(int $a_ref_id, int $a_role_id, int $a_role_parent, int $a_template_id, int $a_template_parent)
string $key
Consumer key/client ID value.
Definition: System.php:193
copyLocalRoles(int $a_source_id, int $a_target_id)
Copy local roles This method creates a copy of all local role.
ilDBInterface $db
query(string $query)
Run a (read-only) Query on the database.
const ROLE_FOLDER_ID
Definition: constants.php:34
copyRolePermissionIntersection(int $a_source1_id, int $a_source1_parent, int $a_source2_id, int $a_source2_parent, int $a_dest_parent, int $a_dest_id)
Copies the intersection of the template permissions of two roles to a third role. ...
__construct()
Constructor public.
setProtected(int $a_ref_id, int $a_role_id, string $a_value)
Set protected.
assignRoleToFolder(int $a_rol_id, int $a_parent, string $a_assign="y")
Assigns a role to a role folder A role folder is an object to store roles.
in(string $field, array $values, bool $negate=false, string $type="")
deleteLocalRole(int $a_rol_id, int $a_ref_id=0)
Deletes a local role and entries in rbac_fa and rbac_templates.
deleteRole(int $a_rol_id, int $a_ref_id)
Deletes a role and deletes entries in rbac_pa, rbac_templates, rbac_ua, rbac_fa.
static getActionsByTemplateId(int $a_tpl_id)
Get actions of one template.
represents a creation of local roles action
assignUserLimited(int $a_role_id, int $a_usr_id, int $a_limit, array $a_limited_roles=[])
ilRbacReview $rbacreview
copyRolePermissionSubtract(int $a_source_id, int $a_source_parent, int $a_dest_id, int $a_dest_parent)
Subtract role permissions.
const MOVE_OBJECT
Class ilRbacAdmin Core functions for role based access control.
assignOperationToObject(int $a_type_id, int $a_ops_id)
Assign an existing operation to an object Update of rbac_ta.
manipulate(string $query)
Run a (write) Query on the database.
static _lookupType(int $id, bool $reference=false)
setBlockedStatus(int $a_role_id, int $a_ref_id, bool $a_blocked_status)
copyRolePermissionUnion(int $a_source1_id, int $a_source1_parent, int $a_source2_id, int $a_source2_parent, int $a_dest_id, int $a_dest_parent)
deassignUser(int $a_rol_id, int $a_usr_id)
Deassigns a user from a role.