collabcentral/lib
Joseph B. McQueen 44568044e8 Phase R1: split per-user data into gitignored authorized.json
Every add/remove of a favorite group or authorized user was rewriting
config.json — the same file that carries structural bot metadata and
was committed to git. This split ends the git-noise and lets ops
deploy fresh installs without a pre-populated user list.

Split
- config.json (committed) stays structural: server, per-bot labels,
  integration + service-account ids, languages.
- config/authorized.json (gitignored) is the new mutable source of
  truth: { admins: [personId...], bot: { <appName>: { <personId>:
  { id, displayName, email, avatar, groups: [...] } } } }.
- Seeded authorized.json with the current admins list and all
  authorized users (3 on novi, 4 on techupdates) so this commit is
  a pure move — no data lost, no downtime.

Helpers (lib/helpers.js)
- New getAuthorizedEntry(authorized, app, id) as the single lookup
  point every consumer goes through, so nullability is uniform.
- isAuthorized() gains an authorized-doc arg (pure signature stays
  testable): fails closed when the doc is missing / partially
  loaded, so a broken deploy grants no access.
- isAdmin() now reads authorized.admins instead of config.admins.

Runtime (index.js)
- loadAuthorized() with an ENOENT fallback to { admins: [], bot: {} }
  so a fresh deploy can bootstrap via the admin page instead of
  requiring a hand-crafted authorized.json.
- All 8 previous config.webex.bot[app].authorized sites (favorites
  read/add/remove, admin list/add/delete, isAuthorized) now go
  through the authorized doc.
- Every mutation writes to config/authorized.json instead of
  config/config.json.

Latent-bug fixup (uncovered while smoke-testing this refactor)
- The /user/:scope/:action fallthroughs used res.status(4xx)
  without .send(...), so unknown scopes / unauthorized callers got
  a hung request instead of a response. Added ".send(...)" bodies
  so the response actually completes.

Docs + tests
- README updated: new "Authorized users" step in "Adding a new bot",
  updated file-layout section, docker mount list adds
  authorized.json.
- Test suite expanded from 48 → 53 with a new getAuthorizedEntry
  group and the existing isAuthorized/isAdmin cases reshaped for
  the new signatures.

Smoke tested the auth matrix end-to-end (admin + non-admin + signed-
out across /info, /admin/users, /user/groups/list): every path
returns the expected code and body.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-01 21:06:44 -04:00
..
helpers.js Phase R1: split per-user data into gitignored authorized.json 2026-07-01 21:06:44 -04:00