137 lines
5.1 KiB
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);
|
|
}
|
|
}
|