Implement superadmin audit log for mutations
This commit is contained in:
122
app/Services/Audit/SuperAdminAuditLogger.php
Normal file
122
app/Services/Audit/SuperAdminAuditLogger.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user