Refactor subject conversion handling and enhance audit logging

- Replaced `Subject|array` return types with `SubjectBag` in `SubjectConverterInterface` for more robust handling.
- Updated `getSubjectsForEntity` to include an optional `$includeAssociated` parameter for finer control over associated subject resolution.
- Refactored `AuditEvent` to differentiate `mainSubject` from associated subjects, improving clarity in audit logging.
- Introduced database schema changes to add `main_subject` and `subjects` columns in the `chill_main_audit_trail` table.
- Added `SubjectBag` class for grouped subject management and implemented deduplication logic.
- Updated all converters and test cases to use the new `SubjectBag` approach, ensuring compatibility.
- Improved event dispatching in controllers to utilize the updated `AuditEvent` structure and refined metadata handling.
This commit is contained in:
2026-02-13 16:56:04 +01:00
parent 443ee4cb1a
commit 32c5f21438
20 changed files with 332 additions and 84 deletions

View File

@@ -26,26 +26,28 @@ class AuditTrail
public function __construct(
#[ORM\Id]
#[ORM\Column(type: 'uuid', unique: true, name: 'id')]
#[ORM\Column(name: 'id', type: 'uuid', unique: true)]
private UuidInterface $id,
#[ORM\Column(type: Types::STRING, length: 255, name: 'action')]
#[ORM\Column(name: 'action', type: Types::STRING, length: 255)]
private string $action,
#[ORM\Column(type: Types::DATETIMETZ_IMMUTABLE, name: 'occurredat')]
#[ORM\Column(name: 'occurredat', type: Types::DATETIMETZ_IMMUTABLE)]
private \DateTimeImmutable $occurredAt,
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(nullable: true, name: 'user_id', referencedColumnName: 'id')]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: true)]
private ?User $user = null,
#[ORM\Column(type: Types::STRING, length: 255, nullable: false, options: ['default' => ''], name: 'description')]
#[ORM\Column(name: 'description', type: Types::STRING, nullable: false, options: ['default' => ''])]
private string $description = '',
#[ORM\Column(name: 'main_subject', type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"])]
private array $mainSubject = [],
/**
* @var list<array<string, mixed>>
*/
#[ORM\Column(type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"], name: 'targets')]
private array $targets = [],
#[ORM\Column(name: 'subjects', type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"])]
private array $subjects = [],
/**
* @var array<array-key, mixed>
*/
#[ORM\Column(type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"], name: 'metadata')]
#[ORM\Column(name: 'metadata', type: Types::JSON, options: ['jsonb' => true, 'default' => "'[]'::jsonb"])]
private array $metadata = [],
) {}
@@ -77,9 +79,17 @@ class AuditTrail
/**
* @return list<array<string, mixed>>
*/
public function getTargets(): array
public function getSubjects(): array
{
return $this->targets;
return $this->subjects;
}
/**
* @return array<string, mixed>
*/
public function getMainSubject(): array
{
return $this->mainSubject;
}
/**