left4me/docs/superpowers/specs/2026-05-13-rcon-password-display-design.md
2026-05-13 11:35:46 +02:00

2.6 KiB

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):

<div>
  <dt>RCON Password</dt>
  <dd>
    <span class="password-mask" data-password-field="{{ server.id }}">••••••••••••</span>
    <span class="password-value" data-password-field="{{ server.id }}" hidden>{{ server.rcon_password }}</span>
    <button class="link-button" data-password-toggle="{{ server.id }}" aria-label="Show RCON password">show</button>
  </dd>
</div>

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.

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.