78 lines
2.7 KiB
PHP
78 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Http\Request;
|
|
|
|
#[Fillable(['actor_id', 'action', 'subject_type', 'subject_id', 'subject_label', 'metadata', 'ip_address', 'user_agent', 'created_at'])]
|
|
class AuditLog extends Model
|
|
{
|
|
const UPDATED_AT = null;
|
|
|
|
protected $casts = [
|
|
'metadata' => 'array',
|
|
];
|
|
|
|
public function actor(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'actor_id');
|
|
}
|
|
|
|
/**
|
|
* Listado paginado y filtrable — compartido por Admin\AuditLogController
|
|
* (sesión) y Api\AuditLogController (token), igual que AnalyticsSummary.
|
|
*/
|
|
public static function paginatedFor(Request $request)
|
|
{
|
|
$perPage = min(max((int) $request->integer('per_page', 25), 5), 100);
|
|
|
|
return self::query()
|
|
->with('actor:id,name,email')
|
|
->when($request->filled('action'), fn ($q) => $q->where('action', $request->string('action')))
|
|
->when($request->filled('subject_type'), fn ($q) => $q->where('subject_type', $request->string('subject_type')))
|
|
->latest('created_at')
|
|
->paginate($perPage)
|
|
->through(fn ($log) => [
|
|
'id' => $log->id,
|
|
'actor_name' => $log->actor?->name,
|
|
'actor_email' => $log->actor?->email,
|
|
'action' => $log->action,
|
|
'subject_type' => $log->subject_type,
|
|
'subject_id' => $log->subject_id,
|
|
'subject_label' => $log->subject_label,
|
|
'metadata' => $log->metadata,
|
|
'ip_address' => $log->ip_address,
|
|
'created_at' => $log->created_at,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Registra un evento de auditoría. $subjectId se castea a string a propósito:
|
|
* cubre tanto ids autoincrementales (User) como uuid (Client) sin necesitar
|
|
* una relación polimórfica real (que mezclaría tipos de clave entre modelos).
|
|
*/
|
|
public static function record(
|
|
Request $request,
|
|
string $action,
|
|
string $subjectType,
|
|
int|string $subjectId,
|
|
?string $subjectLabel = null,
|
|
?array $metadata = null,
|
|
): void {
|
|
self::create([
|
|
'actor_id' => $request->user()?->id,
|
|
'action' => $action,
|
|
'subject_type' => $subjectType,
|
|
'subject_id' => (string) $subjectId,
|
|
'subject_label' => $subjectLabel,
|
|
'metadata' => $metadata,
|
|
'ip_address' => $request->ip(),
|
|
'user_agent' => $request->userAgent(),
|
|
'created_at' => now(),
|
|
]);
|
|
}
|
|
}
|