getUserPermissionsService = $getUserPermissionsService; $this->nodeJWTService = $nodeJWTService; } protected function getToken(): string { if (!$this->user || !$this->server || $this->user->cannot(Permission::ACTION_WEBSOCKET_CONNECT, $this->server)) { throw new HttpForbiddenException('You do not have permission to connect to this server\'s websocket.'); } $permissions = $this->getUserPermissionsService->handle($this->server, $this->user); return $this->nodeJWTService ->setExpiresAt(now()->addMinutes(10)->toImmutable()) ->setUser($this->user) ->setClaims([ 'server_uuid' => $this->server->uuid, 'permissions' => $permissions, ]) ->handle($this->server->node, $this->user->id . $this->server->uuid)->toString(); } protected function getSocket(): string { $socket = str_replace(['https://', 'http://'], ['wss://', 'ws://'], $this->server->node->getConnectionAddress()); $socket .= sprintf('/api/servers/%s/ws', $this->server->uuid); return $socket; } protected function authorizeSendCommand(): bool { return $this->user->can(Permission::ACTION_CONTROL_CONSOLE, $this->server); } protected function canSendCommand(): bool { return $this->authorizeSendCommand() && !$this->server->isInConflictState() && $this->server->retrieveStatus()->isStartingOrRunning(); } public function up(): void { $this->historyIndex = min($this->historyIndex + 1, count($this->history) - 1); $this->input = $this->history[$this->historyIndex] ?? ''; } public function down(): void { $this->historyIndex = max($this->historyIndex - 1, -1); $this->input = $this->history[$this->historyIndex] ?? ''; } public function enter(): void { if (!empty($this->input) && $this->canSendCommand()) { $this->dispatch('sendServerCommand', command: $this->input); $this->history = Arr::prepend($this->history, $this->input); $this->historyIndex = -1; $this->input = ''; } } #[On('token-request')] public function tokenRequest(): void { $this->dispatch('sendAuthRequest', token: $this->getToken()); } #[On('store-stats')] public function storeStats(string $data): void { $data = json_decode($data); $timestamp = now()->getTimestamp(); foreach ($data as $key => $value) { $cacheKey = "servers.{$this->server->id}.$key"; $data = cache()->get($cacheKey, []); $data[$timestamp] = $value; cache()->put($cacheKey, $data, now()->addMinute()); } } #[On('websocket-error')] public function websocketError(): void { AlertBanner::make('websocket_error') ->title('Could not connect to websocket!') ->body('Check your browser console for more details.') ->danger() ->send(); } }