88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Get,
|
|
HttpCode,
|
|
HttpStatus,
|
|
Param,
|
|
ParseUUIDPipe,
|
|
Post,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
import { z } from 'zod';
|
|
|
|
import type { NodeListResponse, NodeSummary } from '@hexahost/contracts';
|
|
|
|
import { CurrentUser } from '../auth/decorators/current-user.decorator';
|
|
import { SessionGuard } from '../auth/guards/session.guard';
|
|
import { ZodValidationPipe } from '../common/pipes/zod-validation.pipe';
|
|
|
|
import { AdminNodesService } from './admin-nodes.service';
|
|
import type { CreateNodeResponse } from './admin-nodes.service';
|
|
|
|
const createNodeRequestSchema = z.object({
|
|
name: z.string().min(1).max(64),
|
|
hostname: z.string().min(1).max(255),
|
|
maxServers: z.number().int().min(1).max(1000).optional(),
|
|
maxRamMb: z.number().int().min(2048).max(1048576).optional(),
|
|
platformRamMb: z.number().int().min(512).max(65536).optional(),
|
|
});
|
|
|
|
const maintenanceRequestSchema = z.object({
|
|
enabled: z.boolean(),
|
|
});
|
|
|
|
@ApiTags('admin')
|
|
@Controller('admin/nodes')
|
|
@UseGuards(SessionGuard)
|
|
export class AdminNodesController {
|
|
constructor(private readonly adminNodesService: AdminNodesService) {}
|
|
|
|
@Get()
|
|
@ApiOperation({ summary: 'List game nodes (super admin only)' })
|
|
list(@CurrentUser() user: { roles: string[] }): Promise<NodeListResponse> {
|
|
this.adminNodesService.assertSuperAdmin(user.roles);
|
|
return this.adminNodesService.listNodes();
|
|
}
|
|
|
|
@Post()
|
|
@HttpCode(HttpStatus.CREATED)
|
|
@ApiOperation({ summary: 'Register a new game node (super admin only)' })
|
|
@ApiResponse({ status: 201, description: 'Node created with enrollment token' })
|
|
create(
|
|
@CurrentUser() user: { roles: string[] },
|
|
@Body(new ZodValidationPipe(createNodeRequestSchema)) body: unknown,
|
|
): Promise<CreateNodeResponse> {
|
|
this.adminNodesService.assertSuperAdmin(user.roles);
|
|
|
|
return this.adminNodesService.createNode(
|
|
body as Parameters<AdminNodesService['createNode']>[0],
|
|
);
|
|
}
|
|
|
|
@Post(':id/drain')
|
|
@HttpCode(HttpStatus.OK)
|
|
@ApiOperation({ summary: 'Drain a game node (super admin only)' })
|
|
drain(
|
|
@CurrentUser() user: { roles: string[] },
|
|
@Param('id', ParseUUIDPipe) id: string,
|
|
): Promise<NodeSummary> {
|
|
this.adminNodesService.assertSuperAdmin(user.roles);
|
|
return this.adminNodesService.requestDrain(id);
|
|
}
|
|
|
|
@Post(':id/maintenance')
|
|
@HttpCode(HttpStatus.OK)
|
|
@ApiOperation({ summary: 'Toggle maintenance mode for a node (super admin only)' })
|
|
maintenance(
|
|
@CurrentUser() user: { roles: string[] },
|
|
@Param('id', ParseUUIDPipe) id: string,
|
|
@Body(new ZodValidationPipe(maintenanceRequestSchema)) body: unknown,
|
|
): Promise<NodeSummary> {
|
|
this.adminNodesService.assertSuperAdmin(user.roles);
|
|
const input = body as z.infer<typeof maintenanceRequestSchema>;
|
|
return this.adminNodesService.setMaintenance(id, input.enabled);
|
|
}
|
|
}
|