From 358a835d652e76e749bc07b3309d94520051945c Mon Sep 17 00:00:00 2001 From: mwiegand Date: Wed, 13 May 2026 11:35:46 +0200 Subject: [PATCH] docs: add rcon password display design spec --- ...2026-05-13-rcon-password-display-design.md | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-13-rcon-password-display-design.md diff --git a/docs/superpowers/specs/2026-05-13-rcon-password-display-design.md b/docs/superpowers/specs/2026-05-13-rcon-password-display-design.md new file mode 100644 index 0000000..b65986f --- /dev/null +++ b/docs/superpowers/specs/2026-05-13-rcon-password-display-design.md @@ -0,0 +1,61 @@ +# RCON Password Display on Server Detail Page — Design + +**Goal:** Show the RCON password on the server detail page with a show/hide toggle. + +**Architecture:** Presentational change only. The `server.rcon_password` field already exists in the database and is rendered via Jinja2 autoescaping into the template. A small external JS file provides the reveal/hide interaction via delegated click on `[data-password-toggle]` attributes — no inline handlers. + +**Files touched:** +- `l4d2web/static/js/password-reveal.js` — new, ~15 lines +- `l4d2web/templates/server_detail.html` — add one row to `.server-info` DL +- `l4d2web/templates/base.html` — add script include +- `l4d2web/static/css/components.css` — optional, add `.password-mask` letter-spacing if default renders poorly + +--- + +## Template + +Add after the blueprint row in `server_detail.html` (line 13): + +```html +
+
RCON Password
+
+ •••••••••••• + + +
+
+``` + +## JavaScript (`password-reveal.js`) + +Delegated click listener on `[data-password-toggle]`. Toggles `hidden` between the mask span and value span, updates button text and aria-label. + +```js +document.addEventListener('click', (e) => { + const btn = e.target.closest('[data-password-toggle]'); + if (!btn) return; + const id = btn.dataset.passwordToggle; + const mask = document.querySelector(`[data-password-field="${id}"].password-mask`); + const value = document.querySelector(`[data-password-field="${id}"].password-value`); + const hidden = value.hidden; + value.hidden = !hidden; + mask.hidden = hidden; + btn.textContent = hidden ? 'hide' : 'show'; + btn.setAttribute('aria-label', hidden ? 'Hide RCON password' : 'Show RCON password'); +}); +``` + +## CSS + +Reuse existing `.link-button` for the toggle button. If the bullet characters render inconsistently across browsers (spacing, baseline), add a simple `.password-mask { letter-spacing: 0.15em; }` class — but likely unnecessary. + +## Security + +- Password is server-rendered via Jinja2 autoescaping — no XSS vector. +- Visible in page source to the server owner (consistent with existing auth model: user must own the server). +- No copy-to-clipboard functionality (per requirements). + +## Testing + +No new tests required — purely presentational change. Existing `test_create_server_generates_rcon_password` in `test_servers.py` already covers password generation.