Rollback: Runden aus CS2-Sicherungen zurückspielen (nur Admin)
Beim Konfigurieren aktiviert CS2 Mapveto die Rundensicherung des Servers (mp_backup_round_auto, Präfix mit Match-ID). Im Admin-Modus lassen sich die Sicherungen der laufenden Map auflisten und zurückspielen. Der Live-Stand wird auf die Runden bis zur Sicherung gekürzt. Organisatoren haben keinen Zugang zu den Rollback-Routen. Sicherheit: Dateinamen werden gegen Match-ID und Muster geprüft, damit keine fremden Dateien oder Befehle in die RCON-Zeile gelangen. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
22996cc4e4
commit
a4218c47d1
13 files changed
+327
-5
No files matched your search
@@ -412,6 +412,40 @@ test('Admin-Modus: Anmeldung, Verwaltung aller Matches, Sperre ohne Anmeldung',
|
||||
}
|
||||
});
|
||||
|
||||
test('Rollback: nur mit Admin-Anmeldung, nur für die laufende Map, Dateiname wird geprüft', async () => {
|
||||
const { app, call, close } = await setup({ adminPassword: 'Admin123', demo: { startSeconds: 0, failFirstConfigure: false, roundSeconds: 600 } });
|
||||
try {
|
||||
const { id, org, tokens } = await readyWingmanMatch(call, 'bo3');
|
||||
await call('POST', `/matches/${id}/veto/start`, { token: org });
|
||||
await playVeto(call, id, { A: tokens.a1, B: tokens.b1 });
|
||||
await app.manager.poll();
|
||||
await waitFor(() => app.service.getMatch(id).status === 'live', { label: 'live' });
|
||||
await call('POST', `/matches/${id}/server/warmup-end`, { token: org });
|
||||
|
||||
// Organisator sieht keine Rollback-Funktion
|
||||
assert.equal((await call('GET', `/admin/matches/${id}/rollback-points`, { token: org })).status, 401);
|
||||
assert.equal((await call('POST', `/matches/${id}/rollback`, { token: org, body: { file: 'x.txt' } })).status, 404);
|
||||
|
||||
const login = (await call('POST', '/admin/login', { body: { password: 'Admin123' } })).body;
|
||||
const admin = { token: login.token };
|
||||
const points = (await call('GET', `/admin/matches/${id}/rollback-points`, admin)).body.points;
|
||||
assert.equal(points.length, 3, 'Demo liefert drei Sicherungen der aktuellen Map');
|
||||
const map = app.service.seriesMaps(id)[0].map;
|
||||
assert.ok(points.every((p) => p.map === map));
|
||||
|
||||
// Dateien, die nicht zu diesem Match gehören, werden abgelehnt
|
||||
assert.equal((await call('POST', `/admin/matches/${id}/rollback`, { ...admin, body: { file: '../../x.txt' } })).status, 400);
|
||||
|
||||
const ok = await call('POST', `/admin/matches/${id}/rollback`, { ...admin, body: { file: points[0].file } });
|
||||
assert.equal(ok.status, 200);
|
||||
const log = app.service.db.prepare("SELECT message FROM events WHERE match_id = ? AND type = 'rollback'").all(id);
|
||||
assert.equal(log.length, 1);
|
||||
assert.match(log[0].message, /zurückgespielt/);
|
||||
} finally {
|
||||
await close();
|
||||
}
|
||||
});
|
||||
|
||||
test('Admin-Modus ohne ADMIN_PASSWORD ist komplett aus', async () => {
|
||||
const { call, close } = await setup({ adminPassword: '' });
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user