180 lines
7.0 KiB
PHP
180 lines
7.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api\Admin\Rebuild;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\ReinstallLog;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
|
|
/**
|
|
* AdminReinstallLogController
|
|
*
|
|
* Admin-facing read API for VM rebuild history. Surfaces:
|
|
* - which customer initiated each rebuild
|
|
* - which service / VM was rebuilt
|
|
* - which OS was chosen
|
|
* - status lifecycle + timestamps
|
|
* - the credential that was applied to the rebuilt VM (decrypted on detail)
|
|
*
|
|
* Routes:
|
|
* GET /v1/administrator/rebuild-logs → paginated index
|
|
* GET /v1/administrator/rebuild-logs/stats → counts by status
|
|
* GET /v1/administrator/rebuild-logs/{id} → full detail (incl. password)
|
|
*/
|
|
final class AdminReinstallLogController extends Controller
|
|
{
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$perPage = min((int) $request->get('per_page', 20), 200);
|
|
|
|
$query = ReinstallLog::query()
|
|
->with([
|
|
'customer:id,fullname,email',
|
|
'service:id,uuid,server_name,status',
|
|
'vm:id,name,vmware_id,ip',
|
|
'os:id,version,os_group_id',
|
|
'os.osGroup:id,name',
|
|
])
|
|
->orderByDesc('id');
|
|
|
|
if ($status = $request->query('status')) {
|
|
$query->where('status', $status);
|
|
}
|
|
if ($customerId = $request->query('customer_id')) {
|
|
$query->where('custome_id', (int) $customerId);
|
|
}
|
|
if ($serviceId = $request->query('service_id')) {
|
|
$query->where('service_id', (int) $serviceId);
|
|
}
|
|
if ($osId = $request->query('os_id')) {
|
|
$query->where('os_id', (int) $osId);
|
|
}
|
|
if ($initiator = $request->query('initiator')) {
|
|
$query->where('initiator', $initiator);
|
|
}
|
|
if ($from = $request->query('date_from')) {
|
|
$query->whereDate('created_at', '>=', $from);
|
|
}
|
|
if ($to = $request->query('date_to')) {
|
|
$query->whereDate('created_at', '<=', $to);
|
|
}
|
|
if ($search = trim((string) $request->query('search', ''))) {
|
|
$query->where(function ($q) use ($search) {
|
|
$q->where('ip_address', 'like', "%{$search}%")
|
|
->orWhere('old_vmware_id', 'like', "%{$search}%")
|
|
->orWhere('new_vmware_id', 'like', "%{$search}%")
|
|
->orWhereHas('customer', function ($cq) use ($search) {
|
|
$cq->where('email', 'like', "%{$search}%")
|
|
->orWhere('fullname', 'like', "%{$search}%");
|
|
})
|
|
->orWhereHas('vm', fn ($vq) => $vq->where('name', 'like', "%{$search}%"));
|
|
});
|
|
}
|
|
|
|
$paginator = $query->paginate($perPage);
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'data' => [
|
|
'items' => collect($paginator->items())->map(fn (ReinstallLog $log) => $this->summarize($log))->values(),
|
|
'total' => $paginator->total(),
|
|
'per_page' => $paginator->perPage(),
|
|
'current_page' => $paginator->currentPage(),
|
|
'last_page' => $paginator->lastPage(),
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function show(int $id): JsonResponse
|
|
{
|
|
$log = ReinstallLog::with([
|
|
'customer:id,fullname,email,phone',
|
|
'service:id,uuid,server_name,status,product_id',
|
|
'service.product:id,name',
|
|
'vm:id,name,vmware_id,ip,port,user,os_id,customer_id',
|
|
'os:id,version,os_group_id,template_id',
|
|
'os.osGroup:id,name,thumbnail',
|
|
])->find($id);
|
|
|
|
if (!$log) {
|
|
return response()->json(['error' => true, 'message' => 'Không tìm thấy log rebuild'], 404);
|
|
}
|
|
|
|
$data = $this->summarize($log);
|
|
$data['password'] = $log->decryptedPassword();
|
|
$data['error_message'] = $log->error_message;
|
|
$data['vm'] = $log->vm ? [
|
|
'id' => $log->vm->id,
|
|
'name' => $log->vm->name,
|
|
'ip' => $log->vm->ip,
|
|
'port' => $log->vm->port,
|
|
'user' => $log->vm->user,
|
|
'vmware_id' => $log->vm->vmware_id,
|
|
] : null;
|
|
|
|
return response()->json([
|
|
'error' => false,
|
|
'data' => $data,
|
|
]);
|
|
}
|
|
|
|
public function stats(): JsonResponse
|
|
{
|
|
return response()->json([
|
|
'error' => false,
|
|
'data' => [
|
|
'total' => ReinstallLog::count(),
|
|
'today' => ReinstallLog::whereDate('created_at', today())->count(),
|
|
'by_status' => ReinstallLog::selectRaw('status, COUNT(*) as count')
|
|
->groupBy('status')->pluck('count', 'status'),
|
|
'by_initiator' => ReinstallLog::selectRaw('initiator, COUNT(*) as count')
|
|
->groupBy('initiator')->pluck('count', 'initiator'),
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Compact list-row projection. Password is intentionally omitted here —
|
|
* detail endpoint is where the decrypted credential is returned.
|
|
*/
|
|
private function summarize(ReinstallLog $log): array
|
|
{
|
|
return [
|
|
'id' => $log->id,
|
|
'status' => $log->status,
|
|
'initiator' => $log->initiator,
|
|
'note' => $log->note,
|
|
'ip_address' => $log->ip_address,
|
|
'old_vmware_id' => $log->old_vmware_id,
|
|
'new_vmware_id' => $log->new_vmware_id,
|
|
'password_supplied_by_customer' => (bool) $log->password_supplied_by_customer,
|
|
'has_credentials' => $log->password !== null || $log->plain_password !== null,
|
|
'created_at' => $log->created_at,
|
|
'started_at' => $log->started_at,
|
|
'completed_at' => $log->completed_at,
|
|
'customer' => $log->customer ? [
|
|
'id' => $log->customer->id,
|
|
'fullname' => $log->customer->fullname,
|
|
'email' => $log->customer->email,
|
|
] : null,
|
|
'service' => $log->service ? [
|
|
'id' => $log->service->id,
|
|
'uuid' => $log->service->uuid,
|
|
'server_name' => $log->service->server_name,
|
|
'status' => $log->service->status,
|
|
] : null,
|
|
'os' => $log->os ? [
|
|
'id' => $log->os->id,
|
|
'version' => $log->os->version,
|
|
'group' => $log->os->osGroup ? [
|
|
'id' => $log->os->osGroup->id,
|
|
'name' => $log->os->osGroup->name,
|
|
] : null,
|
|
] : null,
|
|
];
|
|
}
|
|
}
|