Skip to content

feat(admins): configurable password generator - #48

Merged
Rushaway merged 1 commit into
mainfrom
feat/configurable-password-generator
Oct 5, 2026
Merged

Rushaway merged 1 commit into
mainfrom
feat/configurable-password-generator

Conversation

@Rushaway

@Rushaway Rushaway commented Oct 1, 2026

Copy link
Copy Markdown
Member

Summary

Adds a configurable password generator to every panel form that sets a credential:

  • Add admin: web password + in-game admin password
  • Edit admin: web password + in-game admin password
  • Your account: new password + new server password (only shown to web admins, matching the existing admins.generate_password gate)
  • Add / Edit server: RCON password

Each generate button opens one shared dialog. It shows a random password and lets the admin:

  • change the length (slider or exact number)
  • turn lowercase, uppercase, digits, symbols, and look-alike filtering (0 O 1 l I) on or off
  • copy the value
  • click Use password to fill the field and its confirmation

Owners set the starting options under Settings > Main > Password generator defaults.

Implementation

  • Sbpp\Security\PasswordGenerator (new): the only place passwords get generated.
    • Uses random_int, puts at least one character from every enabled set, then runs a Fisher-Yates shuffle.
    • Clamps length to [max(8, config.password.minlength), 128], so a generated password always passes the panel's own minimum.
    • Symbols leave out quotes, backslash, ;, space, and backtick, so values are safe in server.cfg and SourceMod configs.
  • Settings: six new config.password.generator.* rows. They are seeded in data.sql and backfilled for upgraded installs by updater migration 813 (INSERT IGNORE, idempotent). REST PATCH /settings types the new keys as bool / int.
  • admins.generate_password: now accepts optional length / lowercase / uppercase / digits / symbols / exclude_ambiguous. Missing options fall back to the defaults. The response echoes the effective options plus min_length / max_length. If every character set is off, it returns a validation error on field charset. The permission gate is unchanged. api-contract.js is regenerated.
  • web/scripts/password-generator.js (new, // @ts-check): one document-level delegate for [data-password-generator][data-password-targets="id,id2"], loaded from core/footer.tpl. It replaces the page-local generator handler on Add admin.
  • REST POST /admins now builds its fallback password with the same generator. Crypto::genPassword() had no callers left and is removed.
  • Docs: added a "Generating passwords" section to docs/.../setup/admins-and-groups.md, a namespacing row and a "Where to find what" row in AGENTS.md, and a directory-layout line in ARCHITECTURE.md.

Test plan

  • PHPStan: no errors
  • ts-check: passes
  • API contract regenerated
  • PHPUnit:
    • new PasswordGeneratorTest: length clamping, per-set guarantee, look-alike exclusion, console-safe symbols, empty-set rejection, plus a check that the keys and defaults match between data.sql and 813.php
    • new AdminsTest::testGeneratePassword*: request options, length clamp, empty charset, configured defaults
    • updated snapshots: generate_password_success, youraccount_owner
    • the remaining failures in AdminsTest are the local CRLF snapshot baseline and also fail on main
  • Playwright (chromium, workers: 1):
    • new password-generator.spec.ts: options shape the output, empty charset blocks "Use password", configured defaults seed the dialog, Settings save round-trip, Edit admin, Your account, axe check
    • updated admins-add-form.spec.ts
    • settings / account / a11y specs still pass, except the SMTP happy path, which needs a mailpit container that wasn't running locally
  • Manual: open the dialog on each surface in light and dark mode (checked locally on Your account)

🤖 Generated with Claude Code

Every password field that sets a credential (Add admin, Edit admin,
Your account, server RCON) gets a "Generate password" button that
opens one shared dialog. The admin can tweak length and character
sets, copy the value, and fill the field + its confirmation.

- Sbpp\Security\PasswordGenerator: random_int based, guarantees one
  character per enabled set, shuffles, clamps length to
  [max(8, config.password.minlength), 128], optional look-alike
  exclusion. Symbols skip quotes/backslash/;/space/backtick so values
  are safe in server.cfg and SourceMod configs.
- Owner defaults in Settings > Main (config.password.generator.*),
  seeded by data.sql and backfilled by updater migration 813.
- admins.generate_password accepts per-request options, falls back to
  the defaults, and echoes the effective options + bounds.
- web/scripts/password-generator.js replaces the page-local Add admin
  handler; loaded once from core/footer.tpl.
- REST POST /admins fallback password uses the same generator;
  the now-unused Crypto::genPassword() is removed.
- REST PATCH /settings types the new keys as bool/int.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rushaway
Rushaway requested review from cmer81 and maxijabase October 1, 2026 16:01
@Rushaway
Rushaway merged commit 157763e into main Oct 5, 2026
6 checks passed
@Rushaway
Rushaway deleted the feat/configurable-password-generator branch October 5, 2026 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants