feat: target matrix + reset scores/environment buttons
- /api/targets (admin): matrix of all teams' domain:port targets - /api/reset/scores: wipe leaderboard (admin, confirm dialog) - /api/reset/environment: stop all teams, remove containers+receivers+ team dirs+systemd units, wipe scores, drop domains (admin, confirm) - portal targets now only domain+port (no ssh/labels) - UI: tab Target Matrix, header buttons Reset Skor / Reset Environment with confirm() alerts 'apakah anda yakin ingin mereset...'
This commit is contained in:
@@ -402,6 +402,50 @@ def submit_flag(team_idx: int, chall: str, flag: str, team_name: str = "") -> di
|
||||
lb_path.write_text(json.dumps(lb, indent=2))
|
||||
return {"success": True, "team": team_idx, "challenge": chall}
|
||||
|
||||
def reset_scores() -> dict:
|
||||
"""Wipe the leaderboard (all solves removed)."""
|
||||
lb_path = TEAMS_DIR / "leaderboard.json"
|
||||
lb_path.write_text(json.dumps({"solves": []}, indent=2))
|
||||
return {"ok": True, "cleared": True}
|
||||
|
||||
def reset_environment() -> dict:
|
||||
"""Full env reset: stop all teams, remove containers + receiver services,
|
||||
delete team dirs (fresh for re-create). Keeps panel + images."""
|
||||
results = []
|
||||
for d in sorted(TEAMS_DIR.glob("team*")):
|
||||
sf = d / "state.json"
|
||||
if not sf.exists():
|
||||
continue
|
||||
st = json.loads(sf.read_text())
|
||||
idx = st["index"]
|
||||
try:
|
||||
stop_team(idx) # compose down + stop receiver service + set status
|
||||
except Exception as e:
|
||||
results.append({"team": idx, "ok": False, "err": str(e)})
|
||||
continue
|
||||
# remove the per-team systemd receiver unit
|
||||
subprocess.run(["systemctl", "disable", f"gemastik-receiver-team{idx}.service"],
|
||||
check=False, capture_output=True)
|
||||
subprocess.run(["systemctl", "stop", f"gemastik-receiver-team{idx}.service"],
|
||||
check=False, capture_output=True)
|
||||
unit = Path("/etc/systemd/system") / f"gemastik-receiver-team{idx}.service"
|
||||
if unit.exists():
|
||||
unit.unlink()
|
||||
results.append({"team": idx, "ok": True})
|
||||
subprocess.run(["systemctl", "daemon-reload"], check=False)
|
||||
# remove team dirs entirely (fresh for re-create)
|
||||
for d in sorted(TEAMS_DIR.glob("team*")):
|
||||
shutil.rmtree(d, ignore_errors=True)
|
||||
# wipe leaderboard too
|
||||
reset_scores()
|
||||
# drop team domains from Traefik (regenerate — no teams left)
|
||||
try:
|
||||
ensure_team_domains()
|
||||
except Exception:
|
||||
pass
|
||||
return {"ok": True, "stopped": results, "teams_dir": str(TEAMS_DIR)}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
cmd = sys.argv[1] if len(sys.argv) > 1 else "list"
|
||||
|
||||
Reference in New Issue
Block a user