Commit Graph

2 Commits

Author SHA1 Message Date
401db8f75c refactor(server): dedupe shard-state shaping, upsert builder, and config DB models
All checks were successful
PR Checks / bot-install (pull_request) Successful in 18s
PR Checks / client-build (pull_request) Successful in 26s
PR Checks / server-tests (pull_request) Successful in 11m4s
Address the SonarQube copy-paste findings that reflect real duplication (as
opposed to the intentional cross-package / admin-player mirror copies, which
are by-design and left as-is):

- shardState.model.js: listOnline() re-inlined the exact field mapping that
  shapeOnline() already provides (used by listOnlineLinked). Collapse it onto
  shapeOnline so the two can no longer drift.
- shardState.db.js: extract a single upsertRow(table, pkCol, pk, fields,
  {coalesce}) builder for the five near-identical INSERT ... ON DUPLICATE KEY
  UPDATE bodies (online/houses/champs/guilds/governors). shard_online keeps its
  COALESCE-on-NULL semantics via the coalesce flag.
- botConfig/emailConfig/uoLinkConfig .db.js: generate get()/upsert() from a
  shared singletonConfigDb(table, cols) factory instead of three byte-identical
  copies.

Behavior unchanged; full server suite (381 tests) passes.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-21 12:35:56 -05:00
f8652c2399 Modernize email: Gmail OAuth2 sending, configured under Settings
Retire env-var SMTP basic-auth and send the contact form through Gmail over
OAuth2 (SMTP XOAUTH2), configured in Admin -> Settings -> Email via an in-app
"Connect Gmail" consent flow. Reuses the existing google SSO OAuth client; the
captured refresh token is stored AES-GCM-encrypted (write-only over the API,
never returned), mirroring the auth-provider and Discord-bot secret patterns.

- schema: new email_config singleton table (mirrors bot_config)
- model: emailConfig.{db,model} with encrypted refresh token + getSafe/getWithSecret
- mailer: nodemailer OAuth2 transport (client id/secret from the google provider
  row), contact recipient = contact_email setting, mailto: fallback preserved,
  plus sendTest()
- routes/controller: /admin/email config, connect start+callback (ssoState CSRF
  + PKCE), test, disconnect
- client: EmailDelivery section on the Settings page + api methods; Settings copy
  now spells out that contact_email is the delivery recipient
- docs/env: drop SMTP_*/CONTACT_TO from env examples; update README/BACKEND_DESIGN
- tests: emailConfig.model + mailer suites (8 new; full suite 142 pass)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XKeCQEJZr1AFJN4Bgcmvh3
2026-07-07 22:29:27 -05:00