ILIAS  trunk Revision v11.0_alpha-1769-g99a433fe2dc
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilRbacLog.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
23 
30 class ilRbacLog
31 {
32  private const LOG_TABLE_NAME = 'rbac_log';
33  public const EDIT_PERMISSIONS = 1;
34  public const MOVE_OBJECT = 2;
35  public const LINK_OBJECT = 3;
36  public const COPY_OBJECT = 4;
37  public const CREATE_OBJECT = 5;
38  public const EDIT_TEMPLATE = 6;
39  public const EDIT_TEMPLATE_EXISTING = 7;
40  public const CHANGE_OWNER = 8;
41 
42  public function __construct(
43  private readonly ilDBInterface $db
44  ) {
45  }
46 
47  public function getLogItems(
48  int $ref_id,
49  Range $range,
50  Order $order,
51  ?array $filter
52  ): array {
53  $this->db->setLimit($range->getLength(), $range->getStart());
54  $set = $this->db->query(
55  'SELECT * FROM ' . self::LOG_TABLE_NAME
56  . ' WHERE ref_id = ' . $this->db->quote($ref_id, ilDBConstants::T_INTEGER)
57  . $this->getWhereForFilter($filter)
58  . $order->join(
59  ' ORDER BY ',
60  static fn(string $ret, string $key, string $value): string =>
61  $ret === ' ORDER BY ' ? "{$ret} {$key} {$value}" : "{$ret}, {$key} {$value} "
62  )
63  );
64  $result = [];
65  while ($row = $this->db->fetchAssoc($set)) {
66  $row['data'] = unserialize($row['data'], [false]);
67  $result[] = $row;
68  }
69  return $result;
70  }
71 
72  public function getLogItemsCount(
73  int $ref_id,
74  array $filter
75  ): int {
76  $result = $this->db->fetchObject(
77  $this->db->query(
78  'SELECT COUNT(*) as cnt FROM ' . self::LOG_TABLE_NAME . ' WHERE ref_id = '
79  . $this->db->quote(
80  $ref_id,
82  ) . $this->getWhereForFilter($filter)
83  )
84  );
85  return $result->cnt;
86  }
87 
88  private function getWhereForFilter(?array $filter): string
89  {
90  if ($filter === null) {
91  return '';
92  }
93 
94  $where = [];
95  if (isset($filter['action'])) {
96  $where[] = ' ' . $this->db->in(
97  'action',
98  $filter['action'],
99  false,
101  );
102  }
103  if (isset($filter['from'])) {
104  $where[] = ' created >= ' . $this->db->quote(
105  $filter['from'],
107  );
108  }
109  if (isset($filter['to'])) {
110  $where[] = ' created <= ' . $this->db->quote(
111  $filter['to'],
113  );
114  }
115 
116  if (count($where) > 0) {
117  $where = array_merge([' AND '], [implode(' AND ', $where)]);
118  }
119  return implode('', $where);
120  }
121 
122  public static function isActive(): bool
123  {
124  return ilPrivacySettings::getInstance()->enabledRbacLog();
125  }
126 
127  public static function gatherFaPa(int $ref_id, array $role_ids, bool $add_action = false): array
128  {
129  global $DIC;
130 
131  $rbacreview = $DIC->rbac()->review();
132  $result = [];
133 
134  // #10946 - if result is written to log directly we need to add an "action" dimension
135  // if result is used as input to diffFaPa() we need "raw" data
136 
137  // roles
138  foreach ($role_ids as $role_id) {
139  if ($role_id != SYSTEM_ROLE_ID) {
140  if ($add_action) {
141  $result["ops"][$role_id]["add"] = $rbacreview->getRoleOperationsOnObject($role_id, $ref_id);
142  } else {
143  $result["ops"][$role_id] = $rbacreview->getRoleOperationsOnObject($role_id, $ref_id);
144  }
145  }
146  }
147 
148  // inheritance
149  if ($ref_id && $ref_id != ROLE_FOLDER_ID) {
150  if ($add_action) {
151  $result["inht"]["add"] = $rbacreview->getRolesOfRoleFolder($ref_id);
152  } else {
153  $result["inht"] = $rbacreview->getRolesOfRoleFolder($ref_id);
154  }
155  }
156 
157  return $result;
158  }
159 
160  public static function diffFaPa(array $old, array $new): array
161  {
162  $result = [];
163 
164  // roles
165  foreach ((array) $old["ops"] as $role_id => $ops) {
166  $diff = array_diff($ops, $new["ops"][$role_id]);
167  if ($diff !== []) {
168  $result["ops"][$role_id]["rmv"] = array_values($diff);
169  }
170  $diff = array_diff($new["ops"][$role_id], $ops);
171  if ($diff !== []) {
172  $result["ops"][$role_id]["add"] = array_values($diff);
173  }
174  }
175 
176  if (isset($old["inht"]) || isset($new["inht"])) {
177  if (isset($old["inht"]) && !isset($new["inht"])) {
178  $result["inht"]["rmv"] = $old["inht"];
179  } elseif (!isset($old["inht"]) && isset($new["inht"])) {
180  $result["inht"]["add"] = $new["inht"];
181  } else {
182  $diff = array_diff($old["inht"], $new["inht"]);
183  if ($diff !== []) {
184  $result["inht"]["rmv"] = array_values($diff);
185  }
186  $diff = array_diff($new["inht"], $old["inht"]);
187  if ($diff !== []) {
188  $result["inht"]["add"] = array_values($diff);
189  }
190  }
191  }
192  return $result;
193  }
194 
195  public static function gatherTemplate(int $role_ref_id, int $role_id): array
196  {
197  global $DIC;
198 
199  $rbacreview = $DIC->rbac()->review();
200  return $rbacreview->getAllOperationsOfRole($role_id, $role_ref_id);
201  }
202 
203  public static function diffTemplate(array $old, array $new): array
204  {
205  $result = [];
206  $types = array_unique(array_merge(array_keys($old), array_keys($new)));
207  foreach ($types as $type) {
208  if (!isset($old[$type])) {
209  $result[$type]["add"] = $new[$type];
210  } elseif (!isset($new[$type])) {
211  $result[$type]["rmv"] = $old[$type];
212  } else {
213  $diff = array_diff($old[$type], $new[$type]);
214  if ($diff !== []) {
215  $result[$type]["rmv"] = array_values($diff);
216  }
217  $diff = array_diff($new[$type], $old[$type]);
218  if ($diff !== []) {
219  $result[$type]["add"] = array_values($diff);
220  }
221  }
222  }
223  return $result;
224  }
225 
226  public static function add(int $action, int $ref_id, array $diff, bool $source_ref_id = false): bool
227  {
228  global $DIC;
229 
230  $ilUser = $DIC->user();
231  $ilDB = $DIC->database();
232 
233  if (self::isValidAction($action) && count($diff)) {
234  if ($source_ref_id) {
235  $diff["src"] = $source_ref_id;
236  }
237  $id = $ilDB->nextId(self::LOG_TABLE_NAME);
238 
239  $ilDB->query('INSERT INTO ' . self::LOG_TABLE_NAME . ' (log_id, user_id, created, ref_id, action, data)' .
240  " VALUES (" . $ilDB->quote($id, "integer") . "," . $ilDB->quote($ilUser->getId(), "integer") .
241  "," . $ilDB->quote(time(), "integer") .
242  "," . $ilDB->quote($ref_id, "integer") . "," . $ilDB->quote($action, "integer") .
243  "," . $ilDB->quote(serialize($diff), "text") . ")");
244  return true;
245  }
246  return false;
247  }
248 
249  protected static function isValidAction(int $action): bool
250  {
251  if (in_array(
252  $action,
253  [
254  self::EDIT_PERMISSIONS,
255  self::MOVE_OBJECT,
256  self::LINK_OBJECT,
257  self::COPY_OBJECT,
258  self::CREATE_OBJECT,
259  self::EDIT_TEMPLATE,
260  self::EDIT_TEMPLATE_EXISTING,
261  self::CHANGE_OWNER
262  ]
263  )) {
264  return true;
265  }
266  return false;
267  }
268 
269  public static function delete(int $ref_id): void
270  {
271  global $DIC;
272 
273  $ilDB = $DIC->database();
274  $ilDB->query('DELETE FROM ' . self::LOG_TABLE_NAME . ' WHERE ref_id = ' . $ilDB->quote($ref_id, 'integer'));
275  self::garbageCollection();
276  }
277 
278  public static function garbageCollection(): void
279  {
280  global $DIC;
281 
282  $ilDB = $DIC->database();
283 
284  $settings = ilPrivacySettings::getInstance();
285  $max = $settings->getRbacLogAge();
286 
287  $ilDB->query('DELETE FROM ' . self::LOG_TABLE_NAME . ' WHERE created < ' . $ilDB->quote(
288  strtotime("-" . $max . "months"),
289  "integer"
290  ));
291  }
292 }
const LOG_TABLE_NAME
join($init, callable $fn)
Definition: Order.php:75
static garbageCollection()
getWhereForFilter(?array $filter)
const SYSTEM_ROLE_ID
Definition: constants.php:29
const CHANGE_OWNER
getLogItemsCount(int $ref_id, array $filter)
static isActive()
static isValidAction(int $action)
Both the subject and the direction need to be specified when expressing an order. ...
Definition: Order.php:28
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
const EDIT_PERMISSIONS
static gatherFaPa(int $ref_id, array $role_ids, bool $add_action=false)
const CREATE_OBJECT
getLogItems(int $ref_id, Range $range, Order $order, ?array $filter)
static gatherTemplate(int $role_ref_id, int $role_id)
$ref_id
Definition: ltiauth.php:65
global $DIC
Definition: shib_login.php:22
const COPY_OBJECT
const LINK_OBJECT
const ROLE_FOLDER_ID
Definition: constants.php:34
static add(int $action, int $ref_id, array $diff, bool $source_ref_id=false)
static diffFaPa(array $old, array $new)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
static diffTemplate(array $old, array $new)
const EDIT_TEMPLATE_EXISTING
__construct(private readonly ilDBInterface $db)
const EDIT_TEMPLATE
const MOVE_OBJECT
class ilRbacLog Log changes in Rbac-related settings
A simple class to express a naive range of whole positive numbers.
Definition: Range.php:28