You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.2 KiB
72 lines
2.2 KiB
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use App\Models\AdminUser;
|
|
use App\Models\OperationLog;
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Str;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class LogAdminOperation
|
|
{
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
$start = microtime(true);
|
|
/** @var Response $response */
|
|
$response = $next($request);
|
|
|
|
$user = $request->user();
|
|
if (! $user instanceof AdminUser) {
|
|
// 登录接口在认证前执行,日志在 AuthController 内单独写入
|
|
return $response;
|
|
}
|
|
|
|
$method = strtoupper($request->method());
|
|
if (! in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE'], true)) {
|
|
return $response;
|
|
}
|
|
|
|
$path = '/'.$request->path();
|
|
if (Str::contains($path, '/operation-logs') && $method === 'GET') {
|
|
return $response;
|
|
}
|
|
if (Str::contains($path, '/auth/me')) {
|
|
return $response;
|
|
}
|
|
|
|
$summary = $this->sanitizeRequest($request);
|
|
|
|
OperationLog::query()->create([
|
|
'admin_user_id' => $user->id,
|
|
'operator_name' => $user->real_name ?: $user->username,
|
|
'operated_at' => now(),
|
|
'http_method' => $method,
|
|
'api_path' => $path,
|
|
'action_label' => $request->route()?->getName() ?? ($method.' '.$path),
|
|
'ip' => $request->ip(),
|
|
'user_agent' => Str::limit((string) $request->userAgent(), 512, ''),
|
|
'request_summary' => $summary,
|
|
'response_code' => $response->getStatusCode(),
|
|
'duration_ms' => (int) round((microtime(true) - $start) * 1000),
|
|
]);
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>|null
|
|
*/
|
|
protected function sanitizeRequest(Request $request): ?array
|
|
{
|
|
$data = $request->except(['password', 'password_hash', 'password_confirmation', 'token', 'current_password', 'file']);
|
|
$encoded = json_encode($data);
|
|
if ($encoded === false) {
|
|
return null;
|
|
}
|
|
|
|
return json_decode(Str::limit($encoded, 4000, '...'), true);
|
|
}
|
|
}
|