authorizedOrder($request, $order); $panelRuntime = (array) data_get($order->meta, 'server_panel_runtime', data_get($order->meta, 'server_order.panel_snapshot', [])); if ((bool) ($panelRuntime['managed_stack_candidate'] ?? false)) { app(ServerAgentBootstrapService::class)->ensureBootstrap($order); $order->refresh(); $panelRuntime = (array) data_get($order->meta, 'server_panel_runtime', data_get($order->meta, 'server_order.panel_snapshot', [])); } return view('hosting.server-panel.show', [ 'order' => $order, 'panelState' => (array) data_get($order->meta, 'server_panel', []), 'panelRuntime' => $panelRuntime, 'selectionSummary' => (array) data_get($order->meta, 'server_order.selection_summary', []), 'serverAgent' => $order->serverAgent, 'serverTasks' => $order->serverTasks()->latest('id')->limit(12)->get(), 'serverSites' => $order->serverSites()->latest('updated_at')->limit(6)->get(), 'serverDatabases' => $order->serverDatabases()->latest('updated_at')->limit(6)->get(), 'serverFiles' => $order->serverFiles()->latest('last_synced_at')->limit(8)->get(), ]); } public function sync(Request $request, CustomerHostingOrder $order, ContaboProvider $provider): RedirectResponse { $order = $this->authorizedOrder($request, $order); $instance = $provider->getInstance($this->providerInstanceId($order)); abort_if($instance === null, 404, 'Server instance not found.'); $this->updateOrderState($order, $instance); return back()->with('success', 'Server status refreshed.'); } public function power(Request $request, CustomerHostingOrder $order, string $action, ContaboProvider $provider): RedirectResponse { $order = $this->authorizedOrder($request, $order); abort_unless(in_array($action, ['start', 'stop', 'reboot'], true), 404); $instanceId = $this->providerInstanceId($order); $success = match ($action) { 'start' => $provider->startInstance($instanceId), 'stop' => $provider->stopInstance($instanceId), 'reboot' => $provider->rebootInstance($instanceId), }; if (! $success) { return back()->with('error', 'Server action failed. Please try again.'); } $meta = (array) ($order->meta ?? []); $panelState = (array) ($meta['server_panel'] ?? []); $panelState['last_action'] = [ 'name' => $action, 'at' => now()->toIso8601String(), ]; $panelState['power_status'] = match ($action) { 'stop' => 'off', default => 'on', }; $order->update([ 'meta' => array_merge($meta, ['server_panel' => $panelState]), ]); return back()->with('success', ucfirst($action).' request sent successfully.'); } public function queueDomain(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'domain' => ['required', 'string', 'max:255', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9-_.]+\.[a-zA-Z]{2,}$/'], 'document_root' => ['nullable', 'string', 'max:255'], 'php_version' => ['nullable', 'string', 'in:8.0,8.1,8.2,8.3,8.4'], ]); $runtime->queueDomainTask( $order, $validated['domain'], $validated['document_root'] ?? null, $validated['php_version'] ?? null, ); return back()->with('success', 'Domain task queued for the server agent.'); } public function queueDatabase(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'name' => ['required', 'string', 'max:32', 'regex:/^[a-zA-Z0-9_]+$/'], ]); $runtime->queueDatabaseTask($order, $validated['name']); return back()->with('success', 'Database task queued for the server agent.'); } public function queueSsl(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'domain' => ['required', 'string', 'max:255', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9-_.]+\.[a-zA-Z]{2,}$/'], ]); $runtime->queueSslTask($order, $validated['domain']); return back()->with('success', 'SSL task queued for the server agent.'); } public function queueFile(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'operation' => ['required', 'string', 'in:list,read,write'], 'path' => ['required', 'string', 'max:1000'], 'content' => ['nullable', 'string'], ]); $runtime->queueFileTask( $order, $validated['operation'], $validated['path'], $validated['content'] ?? null, ); return back()->with('success', 'File task queued for the server agent.'); } public function queueSiteDelete(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'domain' => ['required', 'string', 'max:255', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9-_.]+\.[a-zA-Z]{2,}$/'], ]); $runtime->queueSiteDeleteTask($order, $validated['domain']); return back()->with('success', 'Site removal task queued for the server agent.'); } public function queuePhp(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'domain' => ['required', 'string', 'max:255', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9-_.]+\.[a-zA-Z]{2,}$/'], 'php_version' => ['required', 'string', 'in:8.0,8.1,8.2,8.3,8.4'], ]); $runtime->queuePhpTask($order, $validated['domain'], $validated['php_version']); return back()->with('success', 'PHP configuration task queued for the server agent.'); } public function queueCron(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'operation' => ['required', 'string', 'in:list,upsert,remove'], 'name' => ['nullable', 'string', 'max:80', 'regex:/^[a-zA-Z0-9._-]+$/'], 'expression' => ['nullable', 'string', 'max:120'], 'command' => ['nullable', 'string', 'max:1000'], 'user' => ['nullable', 'string', 'in:web,root,www-data,nginx,wwwrun,apache'], ]); if (($validated['operation'] ?? '') !== 'list') { $request->validate([ 'name' => ['required', 'string', 'max:80', 'regex:/^[a-zA-Z0-9._-]+$/'], ]); } if (($validated['operation'] ?? '') === 'upsert') { $request->validate([ 'expression' => ['required', 'string', 'max:120'], 'command' => ['required', 'string', 'max:1000'], ]); } $runtime->queueCronTask( $order, $validated['operation'], $validated['name'] ?? null, $validated['expression'] ?? null, $validated['command'] ?? null, $validated['user'] ?? 'web', ); return back()->with('success', 'Cron task queued for the server agent.'); } public function queueLog(Request $request, CustomerHostingOrder $order, ServerAgentPanelRuntime $runtime): RedirectResponse { $order = $this->authorizedManagedOrder($request, $order); $validated = $request->validate([ 'target' => ['required', 'string', 'in:nginx_access,nginx_error,php_fpm,mariadb,agent_service'], 'domain' => ['nullable', 'string', 'max:255', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9-_.]*\.[a-zA-Z]{2,}$/'], 'lines' => ['nullable', 'integer', 'min:20', 'max:500'], ]); if (in_array($validated['target'], ['nginx_access', 'nginx_error'], true)) { $request->validate([ 'domain' => ['required', 'string', 'max:255', 'regex:/^[a-zA-Z0-9][a-zA-Z0-9-_.]*\.[a-zA-Z]{2,}$/'], ]); } $runtime->queueLogTask( $order, $validated['target'], $validated['domain'] ?? null, (int) ($validated['lines'] ?? 120), ); return back()->with('success', 'Log read task queued for the server agent.'); } private function authorizedOrder(Request $request, CustomerHostingOrder $order): CustomerHostingOrder { abort_if($order->user_id !== $request->user()->id, 403); $order->load('product'); abort_unless($order->product?->requiresContabo(), 404); abort_unless($this->ladillPanelEnabled($order), 404); return $order; } private function ladillPanelEnabled(CustomerHostingOrder $order): bool { $license = (string) data_get($order->meta, 'server_order.selection.license', ''); return (string) data_get(config('hosting.server_order.licenses'), $license.'.panel') === 'ladill'; } private function providerInstanceId(CustomerHostingOrder $order): string { $instanceId = (string) data_get($order->meta, 'contabo_instance_id', ''); abort_if($instanceId === '', 404, 'Server instance is not provisioned yet.'); return $instanceId; } /** * @param array $instance */ private function updateOrderState(CustomerHostingOrder $order, array $instance): void { $meta = (array) ($order->meta ?? []); $panelState = (array) ($meta['server_panel'] ?? []); $panelState = array_merge($panelState, [ 'instance_status' => $instance['status'] ?? null, 'power_status' => $instance['power_status'] ?? null, 'region' => $instance['region'] ?? null, 'datacenter' => $instance['datacenter'] ?? null, 'image' => $instance['image'] ?? null, 'last_synced_at' => now()->toIso8601String(), ]); $order->update([ 'server_ip' => $instance['ip_address'] ?? $order->server_ip, 'meta' => array_merge($meta, ['server_panel' => $panelState]), ]); } private function authorizedManagedOrder(Request $request, CustomerHostingOrder $order): CustomerHostingOrder { $order = $this->authorizedOrder($request, $order); abort_unless((bool) data_get($order->meta, 'server_panel_runtime.managed_stack_candidate', false), 404); return $order; } }