BastionSSO/app/Http/Controllers/Api/AccessLogController.php

137 lines
5.1 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\LogQueryRequest;
use App\Http\Requests\StoreAccessLogRequest;
use App\Models\AccessLog;
use App\Models\ServerResource;
use App\Models\User;
use hg\apidoc\annotation as Apidoc;
use Illuminate\Http\JsonResponse;
#[Apidoc\Title('访问日志管理')]
class AccessLogController extends Controller
{
public function __construct()
{
$this->middleware('auth:api');
$this->middleware('permission:platform.logs.view,api')->only(['index']);
$this->middleware('permission:platform.logs.manage,api')->only(['store']);
}
#[Apidoc\Title('日志查询'), Apidoc\Method('GET'), Apidoc\Url('/logs')]
public function index(LogQueryRequest $request): JsonResponse
{
$sortBy = $request->string('sort_by')->toString() ?: 'requested_at';
$sortOrder = $request->string('sort_order')->toString() ?: 'desc';
$query = AccessLog::query()->with(['user', 'serverResource', 'bastionAccount']);
if ($request->filled('from')) {
$query->where('requested_at', '>=', $request->date('from'));
}
if ($request->filled('to')) {
$query->where('requested_at', '<=', $request->date('to'));
}
if ($request->filled('action')) {
$query->where('action', 'like', '%'.$request->string('action')->toString().'%');
}
if ($request->filled('actions')) {
$query->whereIn('action', $request->array('actions'));
}
if ($request->filled('user_id')) {
$query->where('user_id', $request->integer('user_id'));
}
if ($request->filled('user_ids')) {
$query->whereIn('user_id', $request->array('user_ids'));
}
if ($request->filled('server_resource_id')) {
$query->where('server_resource_id', $request->integer('server_resource_id'));
}
if ($request->filled('server_resource_ids')) {
$query->whereIn('server_resource_id', $request->array('server_resource_ids'));
}
if ($request->filled('protocol')) {
$query->where('protocol', $request->string('protocol')->toString());
}
if ($sortBy === 'user') {
$query->leftJoin('users', 'users.id', '=', 'access_logs.user_id')
->select('access_logs.*')
->orderBy('users.nickname', $sortOrder);
} elseif ($sortBy === 'resource') {
$query->leftJoin('server_resources', 'server_resources.id', '=', 'access_logs.server_resource_id')
->select('access_logs.*')
->orderBy('server_resources.name', $sortOrder);
} elseif ($sortBy === 'account') {
$query->leftJoin('bastion_accounts', 'bastion_accounts.id', '=', 'access_logs.bastion_account_id')
->select('access_logs.*')
->orderBy('bastion_accounts.name', $sortOrder);
} else {
$column = in_array($sortBy, ['id', 'requested_at', 'action', 'protocol'], true) ? $sortBy : 'requested_at';
$query->orderBy('access_logs.'.$column, $sortOrder);
}
$logs = $query->paginate($request->integer('per_page', 20));
$userIds = AccessLog::query()
->whereNotNull('user_id')
->distinct()
->pluck('user_id')
->map(fn (int $id): int => (int) $id)
->all();
$serverResourceIds = AccessLog::query()
->whereNotNull('server_resource_id')
->distinct()
->pluck('server_resource_id')
->map(fn (int $id): int => (int) $id)
->all();
return response()->json([
'code' => 0,
'message' => 'ok',
'data' => $logs,
'filter_options' => [
'actions' => AccessLog::query()
->whereNotNull('action')
->where('action', '!=', '')
->distinct()
->orderBy('action')
->pluck('action')
->values(),
'users' => User::query()
->select(['id', 'nickname', 'email'])
->whereIn('id', $userIds)
->orderBy('id')
->get(),
'server_resources' => ServerResource::query()
->select(['id', 'name', 'internal_ip'])
->whereIn('id', $serverResourceIds)
->orderBy('id')
->get(),
'protocols' => AccessLog::query()
->whereNotNull('protocol')
->where('protocol', '!=', '')
->distinct()
->orderBy('protocol')
->pluck('protocol')
->values(),
],
]);
}
#[Apidoc\Title('新增日志'), Apidoc\Method('POST'), Apidoc\Url('/logs')]
public function store(StoreAccessLogRequest $request): JsonResponse
{
$log = AccessLog::query()->create($request->validated());
return response()->json(['code' => 0, 'message' => 'ok', 'data' => $log], 201);
}
}