Auto-create staff records for OAuth users with no existing staff record

Fixes GRO-1118 - uat-tester receives HTTP 403 post-login

When a user authenticates via OAuth but has no corresponding staff record,
the RBAC middleware now auto-creates a staff record with a default
"receptionist" role instead of returning 403. This allows new OAuth
users to access the app immediately.

The middleware now checks for staff records in this order:
1. By userId (Better-Auth user ID)
2. By oidcSub (legacy OIDC subject)
3. By email (auto-link existing staff)
4. Create new staff record if authenticated user has email and name

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-05-12 19:17:37 +00:00
committed by Flea Flicker [agent]
parent d9ee14b17e
commit 91af671c4e
+23 -2
View File
@@ -1,7 +1,7 @@
import type { MiddlewareHandler } from "hono";
import { and, eq, getDb, sql, staff } from "@groombook/db";
import { and, eq, getDb, sql, staff, staffRoleEnum } from "@groombook/db";
export type StaffRole = "groomer" | "receptionist" | "manager";
type StaffRole = typeof staffRoleEnum.enumValues[number];
export type StaffRow = typeof staff.$inferSelect;
export interface AppEnv {
@@ -110,6 +110,27 @@ export const resolveStaffMiddleware: MiddlewareHandler<AppEnv> = async (
return;
}
}
// Auto-create staff record for authenticated OAuth users with no existing staff record
// This allows new OAuth users to access the app (defaults to receptionist role)
if (jwt.email && jwt.name) {
const [newStaff] = await db
.insert(staff)
.values({
email: jwt.email,
name: jwt.name,
userId: jwt.sub,
role: "receptionist",
active: true,
})
.returning();
if (newStaff) {
c.set("staff", newStaff);
await next();
return;
}
}
return c.json(
{ error: "Forbidden: no staff record found for authenticated user" },
403