fix(api): auto-link staff to Better-Auth user via email on first SSO login (GRO-480) #231

Merged
groombook-engineer[bot] merged 3 commits from fix/gro-478-auto-link-staff-user into main 2026-04-05 15:05:51 +00:00
2 changed files with 21 additions and 2 deletions
+20 -1
View File
@@ -1,5 +1,5 @@
import type { MiddlewareHandler } from "hono";
import { eq, getDb, staff } from "@groombook/db";
import { and, eq, getDb, isNull, staff } from "@groombook/db";
export type StaffRole = "groomer" | "receptionist" | "manager";
export type StaffRow = typeof staff.$inferSelect;
@@ -89,6 +89,25 @@ export const resolveStaffMiddleware: MiddlewareHandler<AppEnv> = async (
.from(staff)
.where(eq(staff.oidcSub, jwt.sub));
if (!fallbackRow) {
// Auto-link: staff record exists with matching email but no userId — link it now
if (jwt.email) {
const [linkedStaff] = await db
.select()
.from(staff)
.where(and(eq(staff.email, jwt.email), isNull(staff.userId)));
if (linkedStaff) {
await db
.update(staff)
.set({ userId: jwt.sub })
.where(eq(staff.id, linkedStaff.id));
console.log(
`[rbac] Auto-linked staff ${linkedStaff.id} to Better-Auth user ${jwt.sub} via email ${jwt.email}`
);
c.set("staff", linkedStaff);
await next();
return;
}
}
return c.json(
{ error: "Forbidden: no staff record found for authenticated user" },
403
+1 -1
View File
@@ -4,7 +4,7 @@ import * as schema from "./schema.js";
export * from "./schema.js";
export { encryptSecret, decryptSecret } from "./crypto.js";
export { and, asc, desc, eq, exists, gte, gt, ilike, inArray, lt, lte, ne, or, sql } from "drizzle-orm";
export { and, asc, desc, eq, exists, gte, gt, ilike, inArray, isNull, lt, lte, ne, or, sql } from "drizzle-orm";
let _db: ReturnType<typeof drizzle> | null = null;