diff --git a/public/index.html b/public/index.html index b4d6f75..e3e87e6 100644 --- a/public/index.html +++ b/public/index.html @@ -56,16 +56,6 @@
Statut synchronise toutes les 5 minutes.
- diff --git a/public/styles/app.css b/public/styles/app.css index 1dc9dfa..46a5b82 100644 --- a/public/styles/app.css +++ b/public/styles/app.css @@ -253,36 +253,6 @@ button { margin-bottom: 1.2rem; } -.info-banner { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 0.85rem; - margin: -0.25rem 0 1rem; -} - -.info-banner > div { - background: linear-gradient(135deg, rgba(123, 92, 255, 0.14), rgba(0, 132, 255, 0.08)); - border: 1px solid rgba(123, 92, 255, 0.28); - border-radius: 7px; - padding: 0.85rem 0.95rem; -} - -.info-banner strong { - display: block; - color: var(--text); - font-family: var(--font-display); - font-size: 0.76rem; - letter-spacing: 0.1em; - margin-bottom: 0.38rem; - text-transform: uppercase; -} - -.info-banner p { - color: var(--muted); - font-size: 0.9rem; - margin: 0; -} - h2, h3 { margin: 0; @@ -734,10 +704,6 @@ code { max-width: none; } - .info-banner { - grid-template-columns: 1fr; - } - .inline-form { width: 100%; } diff --git a/src/routes/servers.js b/src/routes/servers.js index 93a3003..5c1543d 100644 --- a/src/routes/servers.js +++ b/src/routes/servers.js @@ -5,17 +5,10 @@ import { mergeServersWithStatus } from "../services/status.js"; import { getStartProfile, launchServer } from "../services/serverLauncher.js"; const router = express.Router(); -let launchInProgress = false; router.get("/servers", (req, res) => { - const allServers = serversWithImages(); - const anyServerActive = allServers.some((server) => server.active); - const servers = allServers.filter((server) => canAccessServer(req.group, server.id)); - return res.json({ - servers: servers.map((server) => - serializeServerForGroup(server, req.group, { anyServerActive }) - ), - }); + const servers = visibleServers(req.group); + return res.json({ servers: servers.map((server) => serializeServerForGroup(server, req.group)) }); }); router.post("/servers/:serverId/start", async (req, res) => { @@ -30,20 +23,10 @@ router.post("/servers/:serverId/start", async (req, res) => { return res.status(409).json({ error: "Le serveur est deja en ligne" }); } - if (servers.some((entry) => entry.active)) { - return res.status(409).json({ error: "Un serveur est deja en cours" }); - } - - if (launchInProgress) { - return res.status(409).json({ error: "Un lancement est deja en cours" }); - } - if (!getStartProfile(server)) { return res.status(400).json({ error: "Aucun profil de lancement configure" }); } - launchInProgress = true; - try { const { stdout, stderr } = await launchServer(server); @@ -57,24 +40,24 @@ router.post("/servers/:serverId/start", async (req, res) => { return res.json({ status: "started", - server: serializeServerForGroup(server, req.group, { anyServerActive: true }), + server: serializeServerForGroup(server, req.group), stdout: stdout?.trim() || "", stderr: stderr?.trim() || "", }); } catch (error) { console.error(`[servers] Failed to start ${server.id}:`, error); return res.status(500).json({ error: "Impossible de lancer le serveur" }); - } finally { - launchInProgress = false; } }); -function serversWithImages() { +function visibleServers(group) { const images = readServerImages(); - return mergeServersWithStatus(readServers()).map((server) => ({ - ...server, - heroImage: images[server.id]?.url || null, - })); + return mergeServersWithStatus(readServers()) + .map((server) => ({ + ...server, + heroImage: images[server.id]?.url || null, + })) + .filter((server) => canAccessServer(group, server.id)); } export { router as serversRouter }; diff --git a/src/services/permissions.js b/src/services/permissions.js index 999d0d9..934915c 100644 --- a/src/services/permissions.js +++ b/src/services/permissions.js @@ -48,7 +48,7 @@ function getPublicSecrets(secrets = {}) { ); } -function serializeServerForGroup(server, group, { anyServerActive = false } = {}) { +function serializeServerForGroup(server, group) { const publicSecrets = getPublicSecrets(server.secrets); const startProfile = getStartProfile(server); const serialized = { @@ -58,8 +58,7 @@ function serializeServerForGroup(server, group, { anyServerActive = false } = {} port: server.port, heroImage: server.heroImage || null, active: Boolean(server.active), - canStart: - canAccessServer(group, server.id) && !server.active && !anyServerActive && Boolean(startProfile), + canStart: canAccessServer(group, server.id) && !server.active && Boolean(startProfile), hasSecrets: Object.keys(publicSecrets).length > 0, }; diff --git a/test/api.test.js b/test/api.test.js index 8635815..ea4e134 100644 --- a/test/api.test.js +++ b/test/api.test.js @@ -125,7 +125,6 @@ test("filters servers and shows secrets for visible non-admin servers", async () assert.equal(response.body.servers[0].id, "offline-server"); assert.equal(response.body.servers[0].secrets.password, "secret-1"); assert.equal(response.body.servers[0].hasSecrets, true); - assert.equal(response.body.servers[0].canStart, false); }); test("admin sees all servers and secrets", async () => { @@ -180,50 +179,20 @@ test("status file is authoritative for server list and names", async () => { }); test("starts an offline authorized server and writes a log", async () => { - try { - fs.writeFileSync( - process.env.GAMESERVERS_STATUS_FILE, - `${JSON.stringify( - { - servers: [ - { - id: "offline-server", - game: "Offline Server", - address: "games.example:1111", - port: 1111, - active: false, - }, - { - id: "online-server", - game: "Online Server", - address: "games.example:2222", - port: 2222, - active: false, - }, - ], - }, - null, - 2 - )}\n` - ); + const token = await login(playerPassword); + const start = await request("/api/servers/offline-server/start", { + method: "POST", + token, + }); - const token = await login(playerPassword); - const start = await request("/api/servers/offline-server/start", { - method: "POST", - token, - }); + assert.equal(start.status, 200); + assert.equal(start.body.status, "started"); - assert.equal(start.status, 200); - assert.equal(start.body.status, "started"); - - const adminToken = await login(adminLoginPassword); - const logs = await request("/api/logs", { token: adminToken }); - assert.equal(logs.status, 200); - assert.equal(logs.body.logs[0].groupId, "players"); - assert.equal(logs.body.logs[0].serverId, "offline-server"); - } finally { - fs.writeFileSync(process.env.GAMESERVERS_STATUS_FILE, originalStatus); - } + const adminToken = await login(adminLoginPassword); + const logs = await request("/api/logs", { token: adminToken }); + assert.equal(logs.status, 200); + assert.equal(logs.body.logs[0].groupId, "players"); + assert.equal(logs.body.logs[0].serverId, "offline-server"); }); test("refuses to start online or unauthorized servers", async () => { @@ -235,13 +204,6 @@ test("refuses to start online or unauthorized servers", async () => { assert.equal(unauthorized.status, 404); const adminToken = await login(adminLoginPassword); - const blockedByActiveServer = await request("/api/servers/offline-server/start", { - method: "POST", - token: adminToken, - }); - assert.equal(blockedByActiveServer.status, 409); - assert.equal(blockedByActiveServer.body.error, "Un serveur est deja en cours"); - const online = await request("/api/servers/online-server/start", { method: "POST", token: adminToken,