AuditService.php
- Pfad:
src/Infrastructure/Audit/AuditService.php - Namespace: Infrastructure\Audit
- Zeilen: 220 | Größe: 7,251 Bytes
- Geändert: 2025-12-24 20:19:03 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 93
- Dependencies: 100 (25%)
- LOC: 65 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 2
- constructor PDO
- use PDO
Klassen 1
-
AuditServiceclass Zeile 21
Funktionen 7
-
__construct()public Zeile 28 -
log()public Zeile 45 -
logCreate()public Zeile 96 -
logUpdate()public Zeile 123 -
logDelete()public Zeile 152 -
logMerge()public Zeile 181 -
getCorrelationId()Zeile 204
Verwendet von 7
- AssignChunkTaxonomyUseCase.php constructor
- AssignChunkTaxonomyUseCase.php use
- AssignEntityTaxonomyUseCase.php constructor
- AssignEntityTaxonomyUseCase.php use
- InfrastructureServiceProvider.php use
- OntologyController.php constructor
- OntologyController.php use
Code
<?php
declare(strict_types=1);
namespace Infrastructure\Audit;
// @responsibility: Zentrales Audit-Logging für kritische Operationen
use PDO;
/**
* Audit service for logging critical operations.
*
* Logs to ki_dev.audit_log table with structured data for:
* - Ontology/Taxonomy changes
* - Entity merges
* - DSGVO deletions
* - Schema migrations
* - Pipeline configuration changes
*/
final class AuditService
{
private const TABLE = 'ki_dev.audit_log';
/**
* @param PDO $pdo Database connection to ki_dev
*/
public function __construct(private PDO $pdo)
{
}
/**
* Log an audit event.
*
* @param string $event Event name (e.g., 'entity.merge', 'ontology.update')
* @param string $targetTable Target table name (e.g., 'entities', 'ontology_classes')
* @param int|null $targetId Target entity/record ID
* @param array<string, mixed> $oldValue Previous state (will be JSON encoded)
* @param array<string, mixed> $newValue New state (will be JSON encoded)
* @param string|null $reason Optional reason for the change
* @param string $actor Who performed the action (username or 'system')
* @param string $actorType Actor type: 'user', 'system', 'pipeline'
* @param string $level Log level: 'debug', 'info', 'warning', 'error'
*/
public function log(
string $event,
string $targetTable,
?int $targetId = null,
array $oldValue = [],
array $newValue = [],
?string $reason = null,
string $actor = 'system',
string $actorType = 'system',
string $level = 'info'
): void {
$correlationId = $this->getCorrelationId();
$stmt = $this->pdo->prepare(
'INSERT INTO ' . self::TABLE . '
(correlation_id, event, entity_type, entity_id, context, level,
actor, actor_type, target_table, target_id, old_value, new_value, reason,
ip_address, created_at)
VALUES
(:correlation_id, :event, :entity_type, :entity_id, :context, :level,
:actor, :actor_type, :target_table, :target_id, :old_value, :new_value, :reason,
:ip_address, NOW())'
);
$stmt->execute([
'correlation_id' => $correlationId,
'event' => $event,
'entity_type' => $targetTable,
'entity_id' => $targetId,
'context' => json_encode(['target_table' => $targetTable, 'target_id' => $targetId]),
'level' => $level,
'actor' => $actor,
'actor_type' => $actorType,
'target_table' => $targetTable,
'target_id' => $targetId,
'old_value' => $oldValue !== [] ? json_encode($oldValue) : null,
'new_value' => $newValue !== [] ? json_encode($newValue) : null,
'reason' => $reason,
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1',
]);
}
/**
* Log an entity creation.
*
* @param string $table Table name
* @param int $id Created entity ID
* @param array<string, mixed> $data Created data
* @param string $actor Who created it
* @param string $actorType Actor type
*/
public function logCreate(
string $table,
int $id,
array $data,
string $actor = 'system',
string $actorType = 'system'
): void {
$this->log(
event: $table . '.create',
targetTable: $table,
targetId: $id,
newValue: $data,
actor: $actor,
actorType: $actorType
);
}
/**
* Log an entity update.
*
* @param string $table Table name
* @param int $id Updated entity ID
* @param array<string, mixed> $oldData Previous state
* @param array<string, mixed> $newData New state
* @param string $actor Who updated it
* @param string $actorType Actor type
*/
public function logUpdate(
string $table,
int $id,
array $oldData,
array $newData,
string $actor = 'system',
string $actorType = 'system'
): void {
$this->log(
event: $table . '.update',
targetTable: $table,
targetId: $id,
oldValue: $oldData,
newValue: $newData,
actor: $actor,
actorType: $actorType
);
}
/**
* Log an entity deletion.
*
* @param string $table Table name
* @param int $id Deleted entity ID
* @param array<string, mixed> $data Deleted data (for recovery)
* @param string|null $reason Reason for deletion (e.g., 'DSGVO request')
* @param string $actor Who deleted it
* @param string $actorType Actor type
*/
public function logDelete(
string $table,
int $id,
array $data,
?string $reason = null,
string $actor = 'system',
string $actorType = 'system'
): void {
$this->log(
event: $table . '.delete',
targetTable: $table,
targetId: $id,
oldValue: $data,
reason: $reason,
actor: $actor,
actorType: $actorType,
level: 'warning'
);
}
/**
* Log an entity merge operation.
*
* @param int $sourceId Source entity ID (merged into target)
* @param int $targetId Target entity ID (kept)
* @param array<string, mixed> $sourceData Source entity data
* @param array<string, mixed> $targetData Target entity data after merge
* @param string $actor Who performed the merge
*/
public function logMerge(
int $sourceId,
int $targetId,
array $sourceData,
array $targetData,
string $actor = 'system'
): void {
$this->log(
event: 'entity.merge',
targetTable: 'entities',
targetId: $targetId,
oldValue: ['source_id' => $sourceId, 'source_data' => $sourceData],
newValue: ['target_id' => $targetId, 'merged_data' => $targetData],
reason: "Merged entity #{$sourceId} into #{$targetId}",
actor: $actor,
actorType: 'user',
level: 'warning'
);
}
/**
* Get or generate correlation ID for request tracing.
*/
private function getCorrelationId(): string
{
// Check for existing correlation ID from middleware
if (isset($_SERVER['HTTP_X_CORRELATION_ID'])) {
return $_SERVER['HTTP_X_CORRELATION_ID'];
}
// Check session
if (isset($_SESSION['correlation_id'])) {
return $_SESSION['correlation_id'];
}
// Generate new one
return bin2hex(random_bytes(16));
}
}