-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathAuditTrail.php
More file actions
485 lines (439 loc) · 15.5 KB
/
AuditTrail.php
File metadata and controls
485 lines (439 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
<?php
/**
* OpenRegister Audit Trail
*
* This file contains the class for handling audit trail related operations
* in the OpenRegister application.
*
* @category Database
* @package OCA\OpenRegister\Db
*
* @author Conduction Development Team <dev@conductio.nl>
* @copyright 2024 Conduction B.V.
* @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* @version GIT: <git-id>
*
* @link https://OpenRegister.app
*/
namespace OCA\OpenRegister\Db;
use DateTime;
use JsonSerializable;
use OCP\AppFramework\Db\Entity;
/**
* Entity class representing an Audit Trail entry
*
* Manages audit trail data and operations
*
* @package OCA\OpenRegister\Db
*
* @method string|null getUuid()
* @method void setUuid(?string $uuid)
* @method int|null getSchema()
* @method void setSchema(?int $schema)
* @method int|null getRegister()
* @method void setRegister(?int $register)
* @method int|null getObject()
* @method void setObject(?int $object)
* @method int|null getSize()
* @method void setSize(?int $size)
* @method string|null getObjectUuid()
* @method void setObjectUuid(?string $objectUuid)
* @method string|null getRegisterUuid()
* @method void setRegisterUuid(?string $registerUuid)
* @method string|null getSchemaUuid()
* @method void setSchemaUuid(?string $schemaUuid)
* @method string|null getAction()
* @method void setAction(?string $action)
* @method array|null getChanged()
* @method void setChanged(?array $changed)
* @method string|null getUser()
* @method void setUser(?string $user)
* @method string|null getUserName()
* @method void setUserName(?string $userName)
* @method DateTime|null getCreated()
* @method void setCreated(?DateTime $created)
* @method string|null getOrganisation()
* @method void setOrganisation(?string $organisation)
* @method DateTime|null getExpires()
* @method void setExpires(?DateTime $expires)
* @method string|null getHash()
* @method void setHash(?string $hash)
* @method string|null getPreviousHash()
* @method void setPreviousHash(?string $previousHash)
*
* @psalm-suppress PossiblyUnusedMethod
* @psalm-suppress PropertyNotSetInConstructor $id is set by Nextcloud's Entity base class
*
* @SuppressWarnings(PHPMD.TooManyFields) Domain entity requires many fields for complete audit trail data
*/
class AuditTrail extends Entity implements JsonSerializable
{
/**
* Unique identifier for the audit trail entry
*
* @var string|null Unique identifier for the audit trail entry
*/
protected ?string $uuid = null;
/**
* Schema ID associated with the audit trail entry
*
* @var integer|null Schema ID associated with the audit trail entry
*/
protected ?int $schema = null;
/**
* Register ID associated with the audit trail entry
*
* @var integer|null Register ID associated with the audit trail entry
*/
protected ?int $register = null;
/**
* Object ID associated with the audit trail entry
*
* @var integer|null Object ID associated with the audit trail entry
*/
protected ?int $object = null;
/**
* Size of the log in byte
*
* @var integer|null
*/
protected ?int $size = null;
/**
* UUID of the object associated with the audit trail entry
*
* @var string|null UUID of the object associated with the audit trail entry
*/
protected ?string $objectUuid = null;
/**
* UUID of the register associated with the audit trail entry
*
* @var string|null UUID of the register associated with the audit trail entry
*/
protected ?string $registerUuid = null;
/**
* UUID of the schema associated with the audit trail entry
*
* @var string|null UUID of the schema associated with the audit trail entry
*/
protected ?string $schemaUuid = null;
/**
* Action performed in the audit trail entry
*
* @var string|null Action performed in the audit trail entry
*/
protected ?string $action = null;
/**
* Changed data in the audit trail entry
*
* @var array|null Changed data in the audit trail entry
*/
protected ?array $changed = null;
/**
* User ID associated with the audit trail entry
*
* @var string|null User ID associated with the audit trail entry
*/
protected ?string $user = null;
/**
* Username associated with the audit trail entry
*
* @var string|null Username associated with the audit trail entry
*/
protected ?string $userName = null;
/**
* Session ID associated with the audit trail entry
*
* @var string|null Session ID associated with the audit trail entry
*/
protected ?string $session = null;
/**
* Request data associated with the audit trail entry
*
* @var string|null Request data associated with the audit trail entry
*/
protected ?string $request = null;
/**
* IP address associated with the audit trail entry
*
* @var string|null IP address associated with the audit trail entry
*/
protected ?string $ipAddress = null;
/**
* Version of the audit trail entry
*
* @var string|null Version of the audit trail entry
*/
protected ?string $version = null;
/**
* Creation timestamp of the audit trail entry
*
* @var DateTime|null Creation timestamp of the audit trail entry
*/
protected ?DateTime $created = null;
/**
* The unique identifier of the organization processing personal data
*
* This can be an OIN (Organisatie Identificatie Nummer), RSIN (Rechtspersonen en Samenwerkingsverbanden
* Informatienummer), KVK (Kamer van Koophandel) number, or any other official organization identifier.
*
* @var string|null The unique identifier of the organization processing personal data
*/
protected ?string $organisationId = null;
/**
* The type of organization identifier used
*
* Common values include:
* - 'OIN': Organisatie Identificatie Nummer
* - 'RSIN': Rechtspersonen en Samenwerkingsverbanden Informatienummer
* - 'KVK': Kamer van Koophandel
* - 'OTHER': Other type of organization identifier
*
* @var string|null The type of organization identifier used
*/
protected ?string $organisationIdType = null;
/**
* The Processing Activity ID that identifies the specific processing operation
*
* @var string|null The Processing Activity ID that identifies the specific processing operation
*/
protected ?string $processingActivityId = null;
/**
* The URL where the processing activity is registered
*
* @var string|null The URL where the processing activity is registered
*/
protected ?string $processingActivityUrl = null;
/**
* The unique identifier for this specific processing operation
*
* @var string|null The unique identifier for this specific processing operation
*/
protected ?string $processingId = null;
/**
* The confidentiality level of the processed data
*
* @var string|null The confidentiality level of the processed data (e.g., 'public', 'internal', 'confidential')
*/
protected ?string $confidentiality = null;
/**
* The retention period for the processed data in ISO 8601 duration format
*
* @var string|null The retention period for the processed data in ISO 8601 duration format
*/
protected ?string $retentionPeriod = null;
/**
* The expiration timestamp for this audit trail entry
*
* When this timestamp is reached, the audit trail entry can be safely removed
* from the database during cleanup operations.
*
* @var DateTime|null The expiration timestamp for this audit trail entry
*/
protected ?DateTime $expires = null;
/**
* SHA-256 hash of this entry chained to the previous entry
*
* @var string|null SHA-256 hash of this entry chained to the previous entry
*/
protected ?string $hash = null;
/**
* SHA-256 hash of the previous audit trail entry in the chain
*
* @var string|null SHA-256 hash of the previous audit trail entry
*/
protected ?string $previousHash = null;
/**
* Constructor for the AuditTrail class
*
* Sets up field types for all properties
*/
public function __construct()
{
$this->addType(fieldName: 'uuid', type: 'string');
$this->addType(fieldName: 'schema', type: 'integer');
$this->addType(fieldName: 'register', type: 'integer');
$this->addType(fieldName: 'object', type: 'integer');
$this->addType(fieldName: 'objectUuid', type: 'string');
$this->addType(fieldName: 'registerUuid', type: 'string');
$this->addType(fieldName: 'schemaUuid', type: 'string');
$this->addType(fieldName: 'action', type: 'string');
$this->addType(fieldName: 'changed', type: 'json');
$this->addType(fieldName: 'user', type: 'string');
$this->addType(fieldName: 'userName', type: 'string');
$this->addType(fieldName: 'session', type: 'string');
$this->addType(fieldName: 'request', type: 'string');
$this->addType(fieldName: 'ipAddress', type: 'string');
$this->addType(fieldName: 'version', type: 'string');
$this->addType(fieldName: 'created', type: 'datetime');
$this->addType(fieldName: 'organisationId', type: 'string');
$this->addType(fieldName: 'organisationIdType', type: 'string');
$this->addType(fieldName: 'processingActivityId', type: 'string');
$this->addType(fieldName: 'processingActivityUrl', type: 'string');
$this->addType(fieldName: 'processingId', type: 'string');
$this->addType(fieldName: 'confidentiality', type: 'string');
$this->addType(fieldName: 'retentionPeriod', type: 'string');
$this->addType(fieldName: 'size', type: 'integer');
$this->addType(fieldName: 'expires', type: 'datetime');
$this->addType(fieldName: 'hash', type: 'string');
$this->addType(fieldName: 'previousHash', type: 'string');
}//end __construct()
/**
* Get the changed data
*
* @return array The changed data or empty array if null
*/
public function getChanged(): array
{
return ($this->changed ?? []);
}//end getChanged()
/**
* Get JSON fields from the entity
*
* Returns all fields that are of type 'json'
*
* @return string[] List of JSON field names
*
* @psalm-return list<string>
*/
public function getJsonFields(): array
{
return array_keys(
array_filter(
$this->getFieldTypes(),
function ($field) {
return $field === 'json';
}
)
);
}//end getJsonFields()
/**
* Hydrate the entity with data from an array
*
* Sets entity properties based on input array values
*
* @param array $object The data array to hydrate from
*
* @return static Returns $this for method chaining
*/
public function hydrate(array $object): static
{
$jsonFields = $this->getJsonFields();
foreach ($object as $key => $value) {
if (in_array($key, $jsonFields) === true && $value === []) {
$value = null;
}
$method = 'set'.ucfirst($key);
try {
$this->$method($value);
} catch (\Exception $exception) {
// Silently ignore invalid properties.
}
}
return $this;
}//end hydrate()
/**
* Convert entity to JSON serializable array
*
* Prepares the entity data for JSON serialization
*
* @return (array|int|null|string)[] Array of serializable entity data
*
* @psalm-return array{
* id: int,
* uuid: null|string,
* schema: int|null,
* register: int|null,
* object: int|null,
* objectUuid: null|string,
* registerUuid: null|string,
* schemaUuid: null|string,
* action: null|string,
* changed: array|null,
* user: null|string,
* userName: null|string,
* session: null|string,
* request: null|string,
* ipAddress: null|string,
* version: null|string,
* created: null|string,
* organisationId: null|string,
* organisationIdType: null|string,
* processingActivityId: null|string,
* processingActivityUrl: null|string,
* processingId: null|string,
* confidentiality: null|string,
* retentionPeriod: null|string,
* size: int|null,
* expires: null|string,
* hash: null|string,
* previousHash: null|string
* }
*/
public function jsonSerialize(): array
{
$created = null;
if ($this->created !== null) {
$created = $this->created->format('c');
}
$expires = null;
if ($this->expires !== null) {
$expires = $this->expires->format('c');
}
return [
'id' => $this->id,
'uuid' => $this->uuid,
'schema' => $this->schema,
'register' => $this->register,
'object' => $this->object,
'objectUuid' => $this->objectUuid,
'registerUuid' => $this->registerUuid,
'schemaUuid' => $this->schemaUuid,
'action' => $this->action,
'changed' => $this->changed,
'user' => $this->user,
'userName' => $this->userName,
'session' => $this->session,
'request' => $this->request,
'ipAddress' => $this->ipAddress,
'version' => $this->version,
'created' => $created,
'organisationId' => $this->organisationId,
'organisationIdType' => $this->organisationIdType,
'processingActivityId' => $this->processingActivityId,
'processingActivityUrl' => $this->processingActivityUrl,
'processingId' => $this->processingId,
'confidentiality' => $this->confidentiality,
'retentionPeriod' => $this->retentionPeriod,
'size' => $this->size,
'expires' => $expires,
'hash' => $this->hash,
'previousHash' => $this->previousHash,
];
}//end jsonSerialize()
/**
* String representation of the audit trail
*
* This magic method is required for proper entity handling in Nextcloud
* when the framework needs to convert the object to a string.
*
* @return string String representation of the audit trail
*/
public function __toString(): string
{
// Return the UUID if available, otherwise return a descriptive string.
if ($this->uuid !== null && $this->uuid !== '') {
return $this->uuid;
}
// Fallback to action if available.
if ($this->action !== null && $this->action !== '') {
return 'Audit: '.$this->action;
}
// Fallback to ID if available.
if ($this->id !== null) {
return 'AuditTrail #'.$this->id;
}
// Final fallback.
return 'Audit Trail';
}//end __toString()
}//end class