Files

2.6 KiB

plan, phase, title, status, completed
plan phase title status completed
36-01 36 isAdmin schema, requireAdmin middleware, /api/auth/me surface, grant script complete 2026-04-19

What Was Built

Server-side admin foundation for Phase 36:

  1. isAdmin column added to the users pgTable in src/db/schema.tsboolean("is_admin").notNull().default(false).
  2. Drizzle migration generated (drizzle-pg/0009_spotty_lord_tyger.sql) with ALTER TABLE "users" ADD COLUMN "is_admin" boolean DEFAULT false NOT NULL. DB push could not be applied (DB not reachable with default credentials — requires DATABASE_URL env var pointing to the running Postgres instance).
  3. requireAdmin middleware added to src/server/middleware/auth.ts — reads userId from context (set by requireAuth), queries users.isAdmin, returns 401 if userId missing, 403 if !user.isAdmin, calls next() for admins.
  4. isAdmin in /api/auth/mesrc/server/routes/auth.ts now includes isAdmin: fullUser?.isAdmin ?? false in the returned user object.
  5. /api/admin/ placeholder routesrc/server/routes/admin.ts applies requireAuth + requireAdmin middleware on /* and returns { ok: true } on GET /.
  6. Route registrationsrc/server/index.ts imports and registers app.route("/api/admin", adminRoutes).
  7. grant-admin scriptscripts/grant-admin.ts grants or revokes isAdmin by logto_sub. Accepts --revoke flag. Exits 1 on missing sub or user not found.

Key Files

  • src/db/schema.ts — isAdmin column added to users table
  • drizzle-pg/0009_spotty_lord_tyger.sql — migration file
  • src/server/middleware/auth.ts — requireAdmin exported
  • src/server/routes/auth.ts — isAdmin in /me response
  • src/server/routes/admin.ts — new placeholder admin route
  • src/server/index.ts — adminRoutes registered
  • scripts/grant-admin.ts — admin grant/revoke script

Deviations

  • DB push could not be applied — the default PostgreSQL credentials (gearbox:gearbox@localhost:5432/gearbox) don't match the running instance. The migration file is generated and correct. Apply manually with the correct DATABASE_URL:
    DATABASE_URL=<connection-string> bun run db:push
    
    This is a deployment/environment concern, not a code defect.

Self-Check: PASSED

  • isAdmin column in schema.ts
  • Migration file generated with correct SQL
  • requireAdmin middleware exported from auth.ts
  • isAdmin in /api/auth/me response
  • /api/admin route protected by requireAuth + requireAdmin
  • grant-admin.ts script created
  • bun run build exits 0