feat(gro-203): add requireSuperUser() middleware + route guards

- Added requireSuperUser() middleware in apps/api/src/middleware/rbac.ts
  that checks staff.isSuperUser, returns 403 if false
- Wired into index.ts:
  - POST/PATCH/DELETE /api/staff/* → requireSuperUser() after requireRole("manager")
  - /api/admin/settings/* → requireSuperUser() after requireRole("manager")
- resolveStaffMiddleware: inject isSuperUser: true for AUTH_DISABLED dev mode

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
groombook-ci[bot]
2026-03-28 20:50:48 +00:00
committed by Flea Flicker
parent a547931f9b
commit 1c82a75a88
2 changed files with 34 additions and 3 deletions
+27 -3
View File
@@ -42,7 +42,7 @@ export const resolveStaffMiddleware: MiddlewareHandler<AppEnv> = async (
if (!manager) {
return c.json({ error: "Forbidden: no staff records found" }, 403);
}
c.set("staff", manager);
c.set("staff", { ...manager, isSuperUser: true });
await next();
return;
}
@@ -52,7 +52,7 @@ export const resolveStaffMiddleware: MiddlewareHandler<AppEnv> = async (
.from(staff)
.where(eq(staff.userId, devUserId));
if (row) {
c.set("staff", row);
c.set("staff", { ...row, isSuperUser: true });
await next();
return;
}
@@ -68,7 +68,7 @@ export const resolveStaffMiddleware: MiddlewareHandler<AppEnv> = async (
403
);
}
c.set("staff", fallbackRow);
c.set("staff", { ...fallbackRow, isSuperUser: true });
await next();
return;
}
@@ -125,3 +125,27 @@ export function requireRole(
await next();
};
}
/**
* Middleware that enforces the staff member is a super user.
* Must be applied after resolveStaffMiddleware and (typically) after requireRole.
*
* @example
* api.use("/staff/*", requireRole("manager"));
* api.use("/staff/*", requireSuperUser());
*/
export function requireSuperUser(): MiddlewareHandler<AppEnv> {
return async (c, next) => {
const staffRow = c.get("staff");
if (!staffRow) {
return c.json({ error: "Forbidden: staff record not resolved" }, 403);
}
if (!staffRow.isSuperUser) {
return c.json(
{ error: "Forbidden: super user privileges required" },
403
);
}
await next();
};
}
@@ -134,6 +134,13 @@
"when": 1774598400000,
"tag": "0018_backfill_staff_user_id",
"breakpoints": true
},
{
"idx": 19,
"version": "7",
"when": 1774729055924,
"tag": "0019_concerned_sunfire",
"breakpoints": true
}
]
}