From fd910df107cdfa378ce7f69751533449dddc3912 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Mon, 10 Oct 2022 10:47:44 +0200 Subject: [PATCH 1/6] allow maintenance mode to be changed via api, closes #4288 --- app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php index 8c05c5a37e..1d6fd98e31 100644 --- a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php +++ b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php @@ -30,6 +30,7 @@ public function rules(array $rules = null): array 'fqdn', 'scheme', 'behind_proxy', + 'maintenance_mode', 'memory', 'memory_overallocate', 'disk', From e408a51563d60842b8a2b042c02d75172b5bb4be Mon Sep 17 00:00:00 2001 From: Boy132 Date: Mon, 10 Oct 2022 11:08:23 +0200 Subject: [PATCH 2/6] handle maintenance mode frontend-wise --- app/Transformers/Api/Client/ServerTransformer.php | 5 ++++- resources/scripts/api/server/getServer.ts | 10 ++++++++-- .../components/server/ConflictStateRenderer.tsx | 7 +++++++ .../server/console/ServerConsoleContainer.tsx | 7 +++++-- .../components/server/settings/SettingsContainer.tsx | 2 +- resources/scripts/state/server/index.ts | 2 +- 6 files changed, 26 insertions(+), 7 deletions(-) diff --git a/app/Transformers/Api/Client/ServerTransformer.php b/app/Transformers/Api/Client/ServerTransformer.php index 53f4adf4ba..bc5f9c0d37 100644 --- a/app/Transformers/Api/Client/ServerTransformer.php +++ b/app/Transformers/Api/Client/ServerTransformer.php @@ -42,7 +42,10 @@ public function transform(Server $server): array 'internal_id' => $server->id, 'uuid' => $server->uuid, 'name' => $server->name, - 'node' => $server->node->name, + 'node' => [ + 'name' => $server->node->name, + 'maintenance_mode' => $server->node->maintenance_mode, + ], 'sftp_details' => [ 'ip' => $server->node->fqdn, 'port' => $server->node->daemonSFTP, diff --git a/resources/scripts/api/server/getServer.ts b/resources/scripts/api/server/getServer.ts index 5ed92a4270..8e7daf247b 100644 --- a/resources/scripts/api/server/getServer.ts +++ b/resources/scripts/api/server/getServer.ts @@ -16,7 +16,10 @@ export interface Server { internalId: number | string; uuid: string; name: string; - node: string; + node: { + name: string; + maintenanceMode: boolean; + }; status: ServerStatus; sftpDetails: { ip: string; @@ -49,7 +52,10 @@ export const rawDataToServerObject = ({ attributes: data }: FractalResponseData) internalId: data.internal_id, uuid: data.uuid, name: data.name, - node: data.node, + node: { + name: data.node.name, + maintenanceMode: data.node.maintenance_mode, + }, status: data.status, invocation: data.invocation, dockerImage: data.docker_image, diff --git a/resources/scripts/components/server/ConflictStateRenderer.tsx b/resources/scripts/components/server/ConflictStateRenderer.tsx index 70475a4eef..dda85ce03f 100644 --- a/resources/scripts/components/server/ConflictStateRenderer.tsx +++ b/resources/scripts/components/server/ConflictStateRenderer.tsx @@ -8,6 +8,7 @@ import ServerRestoreSvg from '@/assets/images/server_restore.svg'; export default () => { const status = ServerContext.useStoreState((state) => state.server.data?.status || null); const isTransferring = ServerContext.useStoreState((state) => state.server.data?.isTransferring || false); + const isMaintenanceMode = ServerContext.useStoreState((state) => state.server.data?.node.maintenanceMode || false); return status === 'installing' || status === 'install_failed' ? ( { image={ServerErrorSvg} message={'This server is suspended and cannot be accessed.'} /> + ) : isMaintenanceMode ? ( + ) : ( { const isInstalling = ServerContext.useStoreState((state) => state.server.isInstalling); const isTransferring = ServerContext.useStoreState((state) => state.server.data!.isTransferring); const eggFeatures = ServerContext.useStoreState((state) => state.server.data!.eggFeatures, isEqual); + const isMaintenanceMode = ServerContext.useStoreState((state) => state.server.data!.node.maintenanceMode); return ( - {(isInstalling || isTransferring) && ( + {(isMaintenanceMode || isInstalling || isTransferring) && ( - {isInstalling + {isMaintenanceMode + ? 'The node of this server is currently under maintenance and all actions are unavailable.' + : isInstalling ? 'This server is currently running its installation process and most actions are unavailable.' : 'This server is currently being transferred to another node and all actions are unavailable.'} diff --git a/resources/scripts/components/server/settings/SettingsContainer.tsx b/resources/scripts/components/server/settings/SettingsContainer.tsx index bcdc80b8e0..6fd0e8d1c1 100644 --- a/resources/scripts/components/server/settings/SettingsContainer.tsx +++ b/resources/scripts/components/server/settings/SettingsContainer.tsx @@ -60,7 +60,7 @@ export default () => {

Node

- {node} + {node.name}
diff --git a/resources/scripts/state/server/index.ts b/resources/scripts/state/server/index.ts index 8d8eba749f..ba3d5b3964 100644 --- a/resources/scripts/state/server/index.ts +++ b/resources/scripts/state/server/index.ts @@ -30,7 +30,7 @@ const server: ServerDataStore = { return false; } - return state.data.status !== null || state.data.isTransferring; + return state.data.status !== null || state.data.isTransferring || state.data.node.maintenanceMode; }), isInstalling: computed((state) => { From 8b91301e3cfb6e40b7251e216d2ee4721402663e Mon Sep 17 00:00:00 2001 From: Boy132 Date: Mon, 10 Oct 2022 11:21:41 +0200 Subject: [PATCH 3/6] handle maintenance mode backend-wise --- app/Exceptions/Http/Server/ServerStateConflictException.php | 2 ++ .../Api/Client/Server/AuthenticateServerAccess.php | 2 +- app/Models/Server.php | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/Exceptions/Http/Server/ServerStateConflictException.php b/app/Exceptions/Http/Server/ServerStateConflictException.php index f0eb096b16..397fd0674a 100644 --- a/app/Exceptions/Http/Server/ServerStateConflictException.php +++ b/app/Exceptions/Http/Server/ServerStateConflictException.php @@ -17,6 +17,8 @@ public function __construct(Server $server, Throwable $previous = null) $message = 'This server is currently in an unsupported state, please try again later.'; if ($server->isSuspended()) { $message = 'This server is currently suspended and the functionality requested is unavailable.'; + } elseif ($server->isUnderMaintenance()) { + $message = 'The node of this server is currently under maintenance and the functionality requested is unavailable.'; } elseif (!$server->isInstalled()) { $message = 'This server has not yet completed its installation process, please try again later.'; } elseif ($server->status === Server::STATUS_RESTORING_BACKUP) { diff --git a/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php b/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php index 0634e25858..46f31ade9d 100644 --- a/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php +++ b/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php @@ -64,7 +64,7 @@ public function handle(Request $request, Closure $next) // Still allow users to get information about their server if it is installing or // being transferred. if (!$request->routeIs('api:client:server.view')) { - if ($server->isSuspended() && !$request->routeIs('api:client:server.resources')) { + if (($server->isSuspended() || $server->isUnderMaintenance()) && !$request->routeIs('api:client:server.resources')) { throw $exception; } if (!$user->root_admin || !$request->routeIs($this->except)) { diff --git a/app/Models/Server.php b/app/Models/Server.php index b1560bb286..70f8cfa2c9 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -224,6 +224,11 @@ public function isSuspended(): bool return $this->status === self::STATUS_SUSPENDED; } + public function isUnderMaintenance(): bool + { + return $this->node->maintenance_mode; + } + /** * Gets the user who owns the server. * @@ -393,6 +398,7 @@ public function validateCurrentState() { if ( $this->isSuspended() || + $this->isUnderMaintenance() || !$this->isInstalled() || $this->status === self::STATUS_RESTORING_BACKUP || !is_null($this->transfer) From 95f0143335165aa8f45df03eb365c7504661c216 Mon Sep 17 00:00:00 2001 From: Boy132 Date: Mon, 10 Oct 2022 11:46:53 +0200 Subject: [PATCH 4/6] change maintenance box color based on #3661 --- resources/views/admin/nodes/view/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/admin/nodes/view/index.blade.php b/resources/views/admin/nodes/view/index.blade.php index 3cfe903848..7b1a724812 100644 --- a/resources/views/admin/nodes/view/index.blade.php +++ b/resources/views/admin/nodes/view/index.blade.php @@ -98,7 +98,7 @@
@if($node->maintenance_mode)
-
+
This node is under From fa49a9c6380ca8a77cafbaba1bcce4691b3067ab Mon Sep 17 00:00:00 2001 From: Boy132 Date: Mon, 17 Oct 2022 15:03:55 +0200 Subject: [PATCH 5/6] move "isUnderMaintenance" method from Server to Node --- .../Http/Server/ServerStateConflictException.php | 2 +- .../Api/Client/Server/AuthenticateServerAccess.php | 2 +- app/Models/Node.php | 5 +++++ app/Models/Server.php | 7 +------ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/Exceptions/Http/Server/ServerStateConflictException.php b/app/Exceptions/Http/Server/ServerStateConflictException.php index 397fd0674a..ea6a60a559 100644 --- a/app/Exceptions/Http/Server/ServerStateConflictException.php +++ b/app/Exceptions/Http/Server/ServerStateConflictException.php @@ -17,7 +17,7 @@ public function __construct(Server $server, Throwable $previous = null) $message = 'This server is currently in an unsupported state, please try again later.'; if ($server->isSuspended()) { $message = 'This server is currently suspended and the functionality requested is unavailable.'; - } elseif ($server->isUnderMaintenance()) { + } elseif ($server->node->isUnderMaintenance()) { $message = 'The node of this server is currently under maintenance and the functionality requested is unavailable.'; } elseif (!$server->isInstalled()) { $message = 'This server has not yet completed its installation process, please try again later.'; diff --git a/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php b/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php index b8bb312972..358fb6d572 100644 --- a/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php +++ b/app/Http/Middleware/Api/Client/Server/AuthenticateServerAccess.php @@ -53,7 +53,7 @@ public function handle(Request $request, Closure $next): mixed // Still allow users to get information about their server if it is installing or // being transferred. if (!$request->routeIs('api:client:server.view')) { - if (($server->isSuspended() || $server->isUnderMaintenance()) && !$request->routeIs('api:client:server.resources')) { + if (($server->isSuspended() || $server->node->isUnderMaintenance()) && !$request->routeIs('api:client:server.resources')) { throw $exception; } if (!$user->root_admin || !$request->routeIs($this->except)) { diff --git a/app/Models/Node.php b/app/Models/Node.php index 37aec760d6..62ec828712 100644 --- a/app/Models/Node.php +++ b/app/Models/Node.php @@ -186,6 +186,11 @@ public function getDecryptedKey(): string ); } + public function isUnderMaintenance(): bool + { + return $this->maintenance_mode; + } + public function mounts(): HasManyThrough { return $this->hasManyThrough(Mount::class, MountNode::class, 'node_id', 'id', 'id', 'mount_id'); diff --git a/app/Models/Server.php b/app/Models/Server.php index 858bb7b4da..d7cc649c09 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -214,11 +214,6 @@ public function isSuspended(): bool return $this->status === self::STATUS_SUSPENDED; } - public function isUnderMaintenance(): bool - { - return $this->node->maintenance_mode; - } - /** * Gets the user who owns the server. */ @@ -359,7 +354,7 @@ public function validateCurrentState() { if ( $this->isSuspended() || - $this->isUnderMaintenance() || + $this->node->isUnderMaintenance() || !$this->isInstalled() || $this->status === self::STATUS_RESTORING_BACKUP || !is_null($this->transfer) From b1658460fd999c638d5b2c09adc92ff51e1cae0e Mon Sep 17 00:00:00 2001 From: Boy132 Date: Mon, 17 Oct 2022 15:15:57 +0200 Subject: [PATCH 6/6] revert breaking api change --- app/Transformers/Api/Client/ServerTransformer.php | 6 ++---- resources/scripts/api/server/getServer.ts | 12 ++++-------- .../components/server/ConflictStateRenderer.tsx | 6 ++++-- .../server/console/ServerConsoleContainer.tsx | 6 +++--- .../components/server/settings/SettingsContainer.tsx | 2 +- resources/scripts/state/server/index.ts | 2 +- 6 files changed, 15 insertions(+), 19 deletions(-) diff --git a/app/Transformers/Api/Client/ServerTransformer.php b/app/Transformers/Api/Client/ServerTransformer.php index 119ec0a675..9f7bce958a 100644 --- a/app/Transformers/Api/Client/ServerTransformer.php +++ b/app/Transformers/Api/Client/ServerTransformer.php @@ -42,10 +42,8 @@ public function transform(Server $server): array 'internal_id' => $server->id, 'uuid' => $server->uuid, 'name' => $server->name, - 'node' => [ - 'name' => $server->node->name, - 'maintenance_mode' => $server->node->maintenance_mode, - ], + 'node' => $server->node->name, + 'is_node_under_maintenance' => $server->node->isUnderMaintenance(), 'sftp_details' => [ 'ip' => $server->node->fqdn, 'port' => $server->node->daemonSFTP, diff --git a/resources/scripts/api/server/getServer.ts b/resources/scripts/api/server/getServer.ts index 8e7daf247b..d2aa2e0543 100644 --- a/resources/scripts/api/server/getServer.ts +++ b/resources/scripts/api/server/getServer.ts @@ -16,10 +16,8 @@ export interface Server { internalId: number | string; uuid: string; name: string; - node: { - name: string; - maintenanceMode: boolean; - }; + node: string; + isNodeUnderMaintenance: boolean; status: ServerStatus; sftpDetails: { ip: string; @@ -52,10 +50,8 @@ export const rawDataToServerObject = ({ attributes: data }: FractalResponseData) internalId: data.internal_id, uuid: data.uuid, name: data.name, - node: { - name: data.node.name, - maintenanceMode: data.node.maintenance_mode, - }, + node: data.node, + isNodeUnderMaintenance: data.is_node_under_maintenance, status: data.status, invocation: data.invocation, dockerImage: data.docker_image, diff --git a/resources/scripts/components/server/ConflictStateRenderer.tsx b/resources/scripts/components/server/ConflictStateRenderer.tsx index dda85ce03f..95e70bbaa3 100644 --- a/resources/scripts/components/server/ConflictStateRenderer.tsx +++ b/resources/scripts/components/server/ConflictStateRenderer.tsx @@ -8,7 +8,9 @@ import ServerRestoreSvg from '@/assets/images/server_restore.svg'; export default () => { const status = ServerContext.useStoreState((state) => state.server.data?.status || null); const isTransferring = ServerContext.useStoreState((state) => state.server.data?.isTransferring || false); - const isMaintenanceMode = ServerContext.useStoreState((state) => state.server.data?.node.maintenanceMode || false); + const isNodeUnderMaintenance = ServerContext.useStoreState( + (state) => state.server.data?.isNodeUnderMaintenance || false + ); return status === 'installing' || status === 'install_failed' ? ( { image={ServerErrorSvg} message={'This server is suspended and cannot be accessed.'} /> - ) : isMaintenanceMode ? ( + ) : isNodeUnderMaintenance ? ( { const isInstalling = ServerContext.useStoreState((state) => state.server.isInstalling); const isTransferring = ServerContext.useStoreState((state) => state.server.data!.isTransferring); const eggFeatures = ServerContext.useStoreState((state) => state.server.data!.eggFeatures, isEqual); - const isMaintenanceMode = ServerContext.useStoreState((state) => state.server.data!.node.maintenanceMode); + const isNodeUnderMaintenance = ServerContext.useStoreState((state) => state.server.data!.isNodeUnderMaintenance); return ( - {(isMaintenanceMode || isInstalling || isTransferring) && ( + {(isNodeUnderMaintenance || isInstalling || isTransferring) && ( - {isMaintenanceMode + {isNodeUnderMaintenance ? 'The node of this server is currently under maintenance and all actions are unavailable.' : isInstalling ? 'This server is currently running its installation process and most actions are unavailable.' diff --git a/resources/scripts/components/server/settings/SettingsContainer.tsx b/resources/scripts/components/server/settings/SettingsContainer.tsx index 6fd0e8d1c1..bcdc80b8e0 100644 --- a/resources/scripts/components/server/settings/SettingsContainer.tsx +++ b/resources/scripts/components/server/settings/SettingsContainer.tsx @@ -60,7 +60,7 @@ export default () => {

Node

- {node.name} + {node}
diff --git a/resources/scripts/state/server/index.ts b/resources/scripts/state/server/index.ts index ba3d5b3964..f9806b6498 100644 --- a/resources/scripts/state/server/index.ts +++ b/resources/scripts/state/server/index.ts @@ -30,7 +30,7 @@ const server: ServerDataStore = { return false; } - return state.data.status !== null || state.data.isTransferring || state.data.node.maintenanceMode; + return state.data.status !== null || state.data.isTransferring || state.data.isNodeUnderMaintenance; }), isInstalling: computed((state) => {