123 lines
3.0 KiB
PHP
123 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Audit;
|
|
|
|
use App\Models\SuperAdminActionLog;
|
|
use App\Models\User;
|
|
use Filament\Facades\Filament;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Str;
|
|
|
|
class SuperAdminAuditLogger
|
|
{
|
|
/**
|
|
* @param array<string, array<int, string>> $metadata
|
|
*/
|
|
public function record(
|
|
string $action,
|
|
?Model $subject = null,
|
|
array $metadata = [],
|
|
?User $actor = null,
|
|
?string $source = null
|
|
): ?SuperAdminActionLog {
|
|
$actor = $actor ?? Filament::auth()->user();
|
|
|
|
if (! $this->shouldLog($actor)) {
|
|
return null;
|
|
}
|
|
|
|
$metadata = $this->sanitizeMetadata($metadata);
|
|
|
|
return SuperAdminActionLog::create([
|
|
'actor_id' => $actor?->getKey(),
|
|
'action' => $action,
|
|
'subject_type' => $subject?->getMorphClass(),
|
|
'subject_id' => $subject?->getKey(),
|
|
'source' => $source,
|
|
'metadata' => $metadata ?: null,
|
|
'occurred_at' => now(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, array<int, string>> $metadata
|
|
*/
|
|
public function recordModelMutation(
|
|
string $operation,
|
|
Model $record,
|
|
array $metadata = [],
|
|
?string $source = null,
|
|
?User $actor = null
|
|
): ?SuperAdminActionLog {
|
|
$action = $this->formatAction($record, $operation);
|
|
|
|
return $this->record(
|
|
$action,
|
|
$record,
|
|
$metadata,
|
|
$actor,
|
|
$source
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<int, string>|array<string, mixed> $data
|
|
* @return array<string, array<int, string>>
|
|
*/
|
|
public static function fieldsMetadata(array $data): array
|
|
{
|
|
$fields = array_is_list($data) ? $data : array_keys($data);
|
|
|
|
return ['fields' => array_values(array_unique($fields))];
|
|
}
|
|
|
|
private function shouldLog(?User $actor): bool
|
|
{
|
|
if (! $actor || $actor->role !== 'super_admin') {
|
|
return false;
|
|
}
|
|
|
|
$panel = Filament::getCurrentPanel();
|
|
|
|
if ($panel) {
|
|
return $panel->getId() === 'superadmin';
|
|
}
|
|
|
|
if (app()->runningInConsole()) {
|
|
return false;
|
|
}
|
|
|
|
return request()->is('super-admin*');
|
|
}
|
|
|
|
/**
|
|
* @param array<string, array<int, string>> $metadata
|
|
* @return array<string, array<int, string>>
|
|
*/
|
|
private function sanitizeMetadata(array $metadata): array
|
|
{
|
|
$sanitized = [];
|
|
|
|
foreach ($metadata as $key => $value) {
|
|
if (! is_array($value)) {
|
|
continue;
|
|
}
|
|
|
|
$values = array_values(array_filter($value, fn ($item) => is_string($item) && $item !== ''));
|
|
|
|
if ($values === []) {
|
|
continue;
|
|
}
|
|
|
|
$sanitized[$key] = $values;
|
|
}
|
|
|
|
return $sanitized;
|
|
}
|
|
|
|
private function formatAction(Model $record, string $operation): string
|
|
{
|
|
return Str::kebab(class_basename($record)).'.'.$operation;
|
|
}
|
|
}
|