diff --git a/apps/frontend/src/pages/admin.vue b/apps/frontend/src/pages/admin.vue index 1244396e9bb..76ecb41b588 100644 --- a/apps/frontend/src/pages/admin.vue +++ b/apps/frontend/src/pages/admin.vue @@ -43,6 +43,12 @@ icon: TransferIcon, shown: admin, }, + { + link: '/admin/servers/locks', + label: 'Server locks', + icon: LockIcon, + shown: admin, + }, { type: 'heading', label: 'Management', @@ -85,6 +91,7 @@ import { ChartIcon, FileSearchCornerIcon, IssuesIcon, + LockIcon, MailIcon, ServerSearchIcon, TransferIcon, diff --git a/apps/frontend/src/pages/admin/servers/locks.vue b/apps/frontend/src/pages/admin/servers/locks.vue new file mode 100644 index 00000000000..9c4e923fb63 --- /dev/null +++ b/apps/frontend/src/pages/admin/servers/locks.vue @@ -0,0 +1,155 @@ + + + diff --git a/packages/api-client/src/modules/archon/servers/internal.ts b/packages/api-client/src/modules/archon/servers/internal.ts index 2be3033882b..44911c265a4 100644 --- a/packages/api-client/src/modules/archon/servers/internal.ts +++ b/packages/api-client/src/modules/archon/servers/internal.ts @@ -20,4 +20,59 @@ export class ArchonServersInternalModule extends AbstractModule { }, ) } + + /** + * List all locked servers. + * GET /_internal/admin/server-locks + */ + public async getLocks(): Promise { + return this.client.request('/admin/server-locks', { + api: 'archon', + version: 'internal', + method: 'GET', + }) + } + + /** + * Get the lock on a server. + * GET /_internal/admin/server/:server_id/lock + */ + public async getLock(serverId: string): Promise { + return this.client.request( + `/admin/server/${serverId}/lock`, + { + api: 'archon', + version: 'internal', + method: 'GET', + }, + ) + } + + /** + * Lock a server. + * PUT /_internal/admin/server/:server_id/lock + */ + public async lock( + serverId: string, + request: Archon.Servers.Internal.LockServerRequest, + ): Promise { + return this.client.request(`/admin/server/${serverId}/lock`, { + api: 'archon', + version: 'internal', + method: 'PUT', + body: request, + }) + } + + /** + * Unlock a server. + * DELETE /_internal/admin/server/:server_id/lock + */ + public async unlock(serverId: string): Promise { + return this.client.request(`/admin/server/${serverId}/lock`, { + api: 'archon', + version: 'internal', + method: 'DELETE', + }) + } } diff --git a/packages/api-client/src/modules/archon/types.ts b/packages/api-client/src/modules/archon/types.ts index e0a95cc5836..3270ceb8da1 100644 --- a/packages/api-client/src/modules/archon/types.ts +++ b/packages/api-client/src/modules/archon/types.ts @@ -577,6 +577,17 @@ export namespace Archon { export type Lookup = { id: string } + + export type ServerLock = { + server_id: string + reason: string + locked_by?: string + created: string + } + + export type LockServerRequest = { + reason: string + } } export namespace v0 { @@ -645,6 +656,7 @@ export namespace Archon { flows: Flows is_medal: boolean current_user_permissions: UserScope + locked_since: string | null medal_expires?: string } diff --git a/packages/ui/src/components/servers/LockServerModal.vue b/packages/ui/src/components/servers/LockServerModal.vue new file mode 100644 index 00000000000..ac5fe0703d5 --- /dev/null +++ b/packages/ui/src/components/servers/LockServerModal.vue @@ -0,0 +1,160 @@ +