feat(auth): role-agnostic self-service surface under /auth/me #76

Merged
whitlocktech merged 1 commits from feat/auth-me-self-surface into main 2026-07-19 16:34:42 +00:00
Member

What & why

Adds /auth/me/account* — the canonical role-agnostic self-service surface for every authenticated role. This is Android-app prerequisite §8 item 1 (docs/android/PLAN.md §6.4): the app wants one "me" surface it can call regardless of role, and it must never touch /admin.

It reuses the existing account.controller handlers verbatim (no logic duplication) behind requireAuth only — any active account, never a specific role. The older /player/account/* and /admin/account/* routes stay for web back-compat.

New routes (cookie- or bearer-auth, any active role):

  • GET /auth/me/account
  • PATCH /auth/me/account/username
  • PATCH /auth/me/account/password
  • POST /auth/me/account/totp/setup|enable|disable
  • GET /auth/me/account/identities
  • DELETE /auth/me/account/identities/:provider

Mounted as a me.routes.js sub-router at /me; the bare GET /auth/me is unchanged. OpenAPI/Swagger regenerated with #swagger annotations.

How it was tested

  • npm test (server) — all tests pass, incl. the new test/authMe.test.js (the /auth/me/* group gate rejects unauthenticated callers with 401 across every verb/route).
  • End-to-end smoketest against the Dockerized MariaDB with the server running, using real mobile bearer tokens:
    • Unauthenticated → 401; player login → GET /auth/me + /auth/me/account (full account incl. has_password, email).
    • PATCH username updates the DB; validation rejects bad username / short password with 400.
    • PATCH password succeeds and revokes the caller's old bearer token (subsequent call → 401); wrong currentPassword → 400.
    • Role-agnostic proven: an editor (staff) drives the same /auth/me/account surface (200, role=editor) and changes its own username — never touching /admin.

Checklist

  • I have read CONTRIBUTING.md.
  • The change builds and existing tests/checks pass locally.
  • I have added or updated tests/docs where it makes sense.
  • My commits are reasonably scoped with clear messages.

AI-assisted contributions (required)

  • No AI tools were used to produce this contribution.
  • AI tools were used. Tool(s): Claude Code (Claude Opus 4.8). I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a Co-Authored-By trailer.

License

  • I agree that my contribution is licensed under this project's license (GNU GPL v3.0 or later), and I have the right to contribute it.

Docs counterpart updates BACKEND_DESIGN.md (the /auth/me/* rows) and marks PLAN §8 item 1 done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr

## What & why Adds `/auth/me/account*` — the canonical **role-agnostic** self-service surface for every authenticated role. This is Android-app prerequisite **§8 item 1** (docs/android/PLAN.md §6.4): the app wants one "me" surface it can call regardless of role, and it must never touch `/admin`. It **reuses the existing `account.controller` handlers verbatim** (no logic duplication) behind `requireAuth` **only** — any active account, never a specific role. The older `/player/account/*` and `/admin/account/*` routes stay for web back-compat. **New routes** (cookie- or bearer-auth, any active role): - `GET /auth/me/account` - `PATCH /auth/me/account/username` - `PATCH /auth/me/account/password` - `POST /auth/me/account/totp/setup|enable|disable` - `GET /auth/me/account/identities` - `DELETE /auth/me/account/identities/:provider` Mounted as a `me.routes.js` sub-router at `/me`; the bare `GET /auth/me` is unchanged. OpenAPI/Swagger regenerated with `#swagger` annotations. ## How it was tested - `npm test` (server) — **all tests pass**, incl. the new `test/authMe.test.js` (the `/auth/me/*` group gate rejects unauthenticated callers with 401 across every verb/route). - **End-to-end smoketest** against the Dockerized MariaDB with the server running, using real mobile bearer tokens: - Unauthenticated → 401; player login → `GET /auth/me` + `/auth/me/account` (full account incl. `has_password`, `email`). - `PATCH username` updates the DB; validation rejects bad username / short password with 400. - `PATCH password` succeeds and **revokes the caller's old bearer token** (subsequent call → 401); wrong `currentPassword` → 400. - **Role-agnostic proven:** an `editor` (staff) drives the *same* `/auth/me/account` surface (200, `role=editor`) and changes its own username — never touching `/admin`. ## Checklist - [x] I have read [CONTRIBUTING.md](CONTRIBUTING.md). - [x] The change builds and existing tests/checks pass locally. - [x] I have added or updated tests/docs where it makes sense. - [x] My commits are reasonably scoped with clear messages. ## AI-assisted contributions (required) - [ ] No AI tools were used to produce this contribution. - [x] AI tools were used. Tool(s): `Claude Code (Claude Opus 4.8)`. I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a `Co-Authored-By` trailer. ## License - [x] I agree that my contribution is licensed under this project's license (**GNU GPL v3.0 or later**), and I have the right to contribute it. --- Docs counterpart updates `BACKEND_DESIGN.md` (the `/auth/me/*` rows) and marks PLAN §8 item 1 done. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
wtclaude added 1 commit 2026-07-19 09:56:28 +00:00
feat(auth): role-agnostic self-service surface under /auth/me
All checks were successful
PR Checks / server-tests (pull_request) Successful in 9m27s
PR Checks / client-build (pull_request) Successful in 10m23s
PR Checks / bot-install (pull_request) Successful in 9m19s
fc5255da99
Add /auth/me/account* — the canonical "me" endpoints for every authenticated
role (Android app §6.4/§8.1). Reuses the existing account.controller handlers
(getAccount, changeUsername, changePassword, TOTP setup/enable/disable, list/
unlink identities) verbatim behind requireAuth (any role) — no logic
duplication. The app gets one self surface and never has to touch /admin; the
old /player/account/* and /admin/account/* routes stay for web back-compat.

New routes (all bearer- or cookie-auth, any active role):
- GET    /auth/me/account
- PATCH  /auth/me/account/username
- PATCH  /auth/me/account/password
- POST   /auth/me/account/totp/setup|enable|disable
- GET    /auth/me/account/identities
- DELETE /auth/me/account/identities/:provider

Mounted as a sub-router; the bare GET /auth/me is unchanged. Swagger
regenerated with #swagger annotations. Adds test/authMe.test.js (the group
gate rejects unauthenticated callers with 401).

Verified end-to-end against MariaDB: a player and an editor both drive the
same surface (role-agnostic), username/password changes work, a password
change revokes the caller's old bearer token, and validation/401 paths behave.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
whitlocktech approved these changes 2026-07-19 16:34:34 +00:00
whitlocktech merged commit 93a2c0d55f into main 2026-07-19 16:34:42 +00:00
whitlocktech deleted branch feat/auth-me-self-surface 2026-07-19 16:34:43 +00:00
Sign in to join this conversation.
No description provided.