Admin → Rust zone presets: named sets of ZoneManager flags and settings for one server, several, or every server (D195), ticked in groups read from each server's own ZoneManager list in its last hello (D211). A flag not on a covered server is refused on save with the server named; two presets of one name may not share a server. rust.zone.open gains options (one line, NoBuild, radiation=10), enterMessage, leaveMessage, delivery, dome and domeStack. The options field's dropdown is rust.options.zone_presets, whose row VALUE is the preset's line, so picking one copies it into the step (D210) and no published event changes when a preset does. The line and the dome are checked against the server's hello on save and in a dry run; bad-option and dome-unavailable are permanent. Schema: rust_zone_presets, rust_zone_preset_servers. Swagger fragment and routes.manifest regenerated against the pinned core f0e7d2a. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
85 lines
5.0 KiB
JavaScript
85 lines
5.0 KiB
JavaScript
// ── Admin · Rust · Zone presets ───────────────────────────────────────────
|
||
//
|
||
// Mounted under the admin tier's `/rust` prefix, so every path here is
|
||
// `/api/v1/admin/rust/zones`. An admin's own named sets of ZoneManager flags and
|
||
// settings (PLAN_REDESIGNS §3.1, D195). A zone step's options field offers them
|
||
// and copies the one picked (D210).
|
||
//
|
||
// **Every route is `requireRole('admin')`,** like every other page under Admin →
|
||
// Rust: a preset decides what a zone does to the players standing in it.
|
||
|
||
const core = require('../../core')
|
||
|
||
const express = core.express
|
||
const zones = require('./zones.controller')
|
||
const { requireRole, validate } = core.middleware
|
||
const { body, param } = core.validator
|
||
|
||
const zonesRouter = express.Router()
|
||
|
||
const presetBody = [
|
||
body('name').isString().trim().isLength({ min: 1, max: 64 }).withMessage('name is 1 to 64 characters'),
|
||
body('flags').optional().isArray({ max: 80 }).withMessage('flags is a list of at most 80 names'),
|
||
body('settings').optional().isObject().withMessage('settings is an object of name and value'),
|
||
body('allServers').optional().isBoolean().withMessage('allServers is true or false'),
|
||
body('servers').optional().isArray().withMessage('servers is a list of server ids'),
|
||
]
|
||
|
||
zonesRouter.get(
|
||
'/',
|
||
// #swagger.tags = ['Admin · Rust']
|
||
// #swagger.summary = 'Zone presets, and what each server said about its zone mods'
|
||
// #swagger.description = 'Everything the zone presets page draws. Each server with what its last hello said about ZoneManager (its version and flag list, D211) and ZoneDomes (loaded, version, the domes helper’s state, and whether a dome may be added now, D194); every server’s flags, grouped as the form draws them (a flag the module does not know is under Other); the settings a zone may carry, with their bounds; and every preset, with `line` — the text a zone step copies when the preset is picked (D210). Read from the stored hello, so it answers while a server is off.'
|
||
/* #swagger.responses[200] = { description: 'The page', content: { "application/json": { schema: { $ref: "#/components/schemas/RustZones" } } } } */
|
||
requireRole('admin'),
|
||
zones.describe,
|
||
)
|
||
|
||
zonesRouter.post(
|
||
'/presets',
|
||
// #swagger.tags = ['Admin · Rust']
|
||
// #swagger.summary = 'Save a new zone preset'
|
||
// #swagger.description = 'A named set of ZoneManager flags and settings for the servers it lists, or for every server (`allServers`). Every flag must be on each listed server that has reported its flags, and is saved as that ZoneManager spells it. Two presets of one name may not share a server; the same name on different servers is allowed (D189). No preset ships with the module (D195).'
|
||
/* #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/RustZonePresetInput" } } } } */
|
||
/* #swagger.responses[201] = { description: 'Saved', content: { "application/json": { schema: { $ref: "#/components/schemas/RustZonePreset" } } } } */
|
||
/* #swagger.responses[400] = { description: 'A flag or setting the servers do not have, or out of range' } */
|
||
/* #swagger.responses[404] = { description: 'A server that does not exist' } */
|
||
/* #swagger.responses[409] = { description: 'A preset of that name is already on one of the servers' } */
|
||
requireRole('admin'),
|
||
...presetBody,
|
||
validate,
|
||
zones.create,
|
||
)
|
||
|
||
zonesRouter.put(
|
||
'/presets/:id',
|
||
// #swagger.tags = ['Admin · Rust']
|
||
// #swagger.summary = 'Change a zone preset'
|
||
// #swagger.description = 'Replaces the preset whole, under the same rules as saving a new one. A zone step already made from it keeps its own copy of the options (D210), so no published event changes.'
|
||
/* #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/RustZonePresetInput" } } } } */
|
||
/* #swagger.responses[200] = { description: 'Saved', content: { "application/json": { schema: { $ref: "#/components/schemas/RustZonePreset" } } } } */
|
||
/* #swagger.responses[400] = { description: 'A flag or setting the servers do not have, or out of range' } */
|
||
/* #swagger.responses[404] = { description: 'No such preset, or a server that does not exist' } */
|
||
/* #swagger.responses[409] = { description: 'A preset of that name is already on one of the servers' } */
|
||
requireRole('admin'),
|
||
param('id').isInt({ min: 1 }).withMessage('id is a preset id'),
|
||
...presetBody,
|
||
validate,
|
||
zones.update,
|
||
)
|
||
|
||
zonesRouter.delete(
|
||
'/presets/:id',
|
||
// #swagger.tags = ['Admin · Rust']
|
||
// #swagger.summary = 'Delete a zone preset'
|
||
// #swagger.description = 'Removes the preset from the zone step’s dropdown. Steps made from it keep their own copy of its options (D210).'
|
||
/* #swagger.responses[200] = { description: 'Deleted' } */
|
||
/* #swagger.responses[404] = { description: 'No such preset' } */
|
||
requireRole('admin'),
|
||
param('id').isInt({ min: 1 }).withMessage('id is a preset id'),
|
||
validate,
|
||
zones.remove,
|
||
)
|
||
|
||
module.exports = zonesRouter
|