feat(oobe): conditional auth provider bootstrap step + fix(rbac): requireRoleOrSuperUser for /admin/* (GRO-392, GRO-412)

Merges GRO-392 (OOBE auth provider bootstrap step) and GRO-412 (fix admin route RBAC to use requireRoleOrSuperUser). QA  CTO . Approved by CEO.
This commit was merged in pull request #214.
This commit is contained in:
groombook-engineer[bot]
2026-04-03 01:55:13 +00:00
committed by GitHub
parent 7e584effaa
commit 2a50850217
5 changed files with 714 additions and 38 deletions
+64 -1
View File
@@ -124,7 +124,7 @@ function buildWithStaff(
// ─── Import middleware ────────────────────────────────────────────────────────
const { resolveStaffMiddleware, requireRole, requireSuperUser } = await import(
const { resolveStaffMiddleware, requireRole, requireSuperUser, requireRoleOrSuperUser } = await import(
"../middleware/rbac.js"
);
@@ -326,3 +326,66 @@ describe("requireSuperUser", () => {
expect(contentType).toContain("application/json");
});
});
// ─── requireRoleOrSuperUser tests ─────────────────────────────────────────────
describe("requireRoleOrSuperUser", () => {
it("allows a manager to access manager-only routes", async () => {
const app = buildWithStaff(MANAGER, requireRoleOrSuperUser("manager"));
const res = await app.request("/test");
expect(res.status).toBe(200);
});
it("allows a super user with receptionist role to access manager-only routes (GRO-412 bug fix)", async () => {
// GRO-412: a receptionist granted super user via Staff UI should access admin routes
const superReceptionist: StaffRow = {
...RECEPTIONIST,
isSuperUser: true,
};
const app = buildWithStaff(superReceptionist, requireRoleOrSuperUser("manager"));
const res = await app.request("/test");
expect(res.status).toBe(200);
});
it("allows a super user with groomer role to access manager-only routes", async () => {
const superGroomer: StaffRow = {
...GROOMER,
isSuperUser: true,
};
const app = buildWithStaff(superGroomer, requireRoleOrSuperUser("manager"));
const res = await app.request("/test");
expect(res.status).toBe(200);
});
it("blocks a non-super-user receptionist from manager-only routes", async () => {
const app = buildWithStaff(RECEPTIONIST, requireRoleOrSuperUser("manager"));
const res = await app.request("/test");
expect(res.status).toBe(403);
const body = await res.json();
expect(body.error).toMatch(/super user privileges required/i);
});
it("blocks a non-super-user groomer from manager-only routes", async () => {
const app = buildWithStaff(GROOMER, requireRoleOrSuperUser("manager"));
const res = await app.request("/test");
expect(res.status).toBe(403);
const body = await res.json();
expect(body.error).toMatch(/super user privileges required/i);
});
it("allows a manager with multiple allowed roles", async () => {
const app = buildWithStaff(MANAGER, requireRoleOrSuperUser("manager", "receptionist"));
const res = await app.request("/test");
expect(res.status).toBe(200);
});
it("allows a super user with disallowed role to access route with multiple allowed roles", async () => {
const superGroomer: StaffRow = {
...GROOMER,
isSuperUser: true,
};
const app = buildWithStaff(superGroomer, requireRoleOrSuperUser("manager", "receptionist"));
const res = await app.request("/test");
expect(res.status).toBe(200);
});
});