'Snapshot', 'change-password' => 'Đổi mật khẩu', 'change-ip' => 'Đổi IP', 'change-port' => 'Đổi Remote Port', 'renew' => 'Gia hạn', 'console' => 'Truy cập console', 'rebuild' => 'Rebuild máy chủ', 'addons' => 'Addons', ]; public function actionClick(Request $request): JsonResponse { $data = $request->validate([ 'product' => 'required', 'action' => ['required', 'string', Rule::in(array_keys(self::CLICK_LABELS))], ]); $vm = $this->resolveVmById($data['product'], $request); if ($vm instanceof JsonResponse) { return $vm; } $this->activityLogger->log( event: 'click_' . str_replace('-', '_', $data['action']), logName: 'VM', description: "Customer {$request->user()->email} bấm \"" . self::CLICK_LABELS[$data['action']] . "\" trên VM: {$vm->name} (ID: {$vm->vmware_id})", subject: $vm, newValues: ['action' => $data['action']], ); return response()->json(['success' => true]); } public function consoleTicket(Request $request, vCenter $serviceVCenter): JsonResponse { $productId = $request->get('product'); if (!$productId) { return response()->json(['error' => true, 'message' => 'Please choose product']); } $vm = $this->resolveVmById($productId, $request); if ($vm instanceof JsonResponse) { return $vm; } $result = $this->getConsoleTicket($serviceVCenter, $vm); if ($result instanceof JsonResponse) { return $result; } $this->activityLogger->log( event: 'console_access', logName: 'VM', description: "Customer {$request->user()->email} truy cập console VM: {$vm->name} (ID: {$vm->vmware_id})", subject: $vm, newValues: ['product_id' => $productId, 'vm_name' => $vm->name], ); return response()->json([ 'error' => false, 'data' => $result['data'], ]); } /** * POST /v1/system/vm-change-password * * Body: { product, current_password, new_password } * Dispatches ChangeVmPasswordJob — returns immediately, runs async. */ public function changePassword(Request $request): JsonResponse { $validated = $request->validate([ 'product' => ['required'], 'current_password' => ['required', 'string'], 'new_password' => ['required', 'string', 'min:12', 'max:64', 'regex:/^[A-Za-z0-9!@#^*_+=?.,:~]+$/'], ]); $vm = $this->resolveVmById($validated['product'], $request); if ($vm instanceof JsonResponse) { return $vm; } // ponytail: don't release — lock expires after 5 min while the async job runs $lock = $this->acquireVmLock($vm, 300); if (!$lock) { return $this->vmLocked(); } // Detect OS family from VM's os_id record $os = $vm->os_id ? Os::with('osGroup')->find($vm->os_id) : null; $osGroupName = strtolower($os?->osGroup?->name ?? ''); $osFamily = str_contains($osGroupName, 'windows') ? VmProvisionService::OS_WINDOWS : VmProvisionService::OS_LINUX; ChangeVmPasswordJob::dispatch( $vm->id, $vm->vmware_id, $osFamily, $validated['new_password'], $validated['current_password'], ); $this->activityLogger->log( event: 'change_password', logName: 'VM', description: "Customer {$request->user()->email} yêu cầu đổi mật khẩu VM: {$vm->name}", subject: $vm, newValues: ['os_family' => $osFamily], ); return response()->json([ 'success' => true, 'message' => 'Yêu cầu đổi mật khẩu đã được ghi nhận. Hệ thống sẽ xử lý trong vài phút.', ]); } }