fix(GRO-1272): auto-provision staff record on first OIDC login #19
@@ -26,14 +26,13 @@ GroomBook API is a Hono-based REST service (TypeScript/Node.js) powering the pet
|
|||||||
| # | Scenario | Steps | Expected |
|
| # | Scenario | Steps | Expected |
|
||||||
|---|----------|-------|----------|
|
|---|----------|-------|----------|
|
||||||
| TC-API-1.1 | Login via OIDC | POST to OIDC provider callback, verify JWT token issued | 200 OK, JWT returned with valid claims |
|
| TC-API-1.1 | Login via OIDC | POST to OIDC provider callback, verify JWT token issued | 200 OK, JWT returned with valid claims |
|
||||||
| TC-API-1.2 | Session persistence | Make authenticated request, verify session token valid | 200 OK, request succeeds |
|
|
||||||
| TC-API-1.3 | Logout | Call logout endpoint, verify token invalidated | 200 OK, subsequent requests return 401 |
|
|
||||||
| TC-API-1.4 | Email+password login (UAT) | POST /api/auth/sign-in/email with uat-super@groombook.dev + SEED_UAT_SUPER_PASSWORD | 200 OK, session cookie returned |
|
| TC-API-1.4 | Email+password login (UAT) | POST /api/auth/sign-in/email with uat-super@groombook.dev + SEED_UAT_SUPER_PASSWORD | 200 OK, session cookie returned |
|
||||||
| TC-API-1.5 | Email+password login — groomer | POST /api/auth/sign-in/email with uat-groomer@groombook.dev + SEED_UAT_GROOMER_PASSWORD | 200 OK, session cookie returned |
|
| TC-API-1.5 | Email+password login — groomer | POST /api/auth/sign-in/email with uat-groomer@groombook.dev + SEED_UAT_GROOMER_PASSWORD | 200 OK, session cookie returned |
|
||||||
| TC-API-1.6 | Email+password login — customer | POST /api/auth/sign-in/email with uat-customer@groombook.dev + SEED_UAT_CUSTOMER_PASSWORD | 200 OK, session cookie returned |
|
| TC-API-1.6 | Email+password login — customer | POST /api/auth/sign-in/email with uat-customer@groombook.dev + SEED_UAT_CUSTOMER_PASSWORD | 200 OK, session cookie returned |
|
||||||
| TC-API-1.7 | Email+password login — tester | POST /api/auth/sign-in/email with uat-tester@groombook.dev + SEED_UAT_TESTER_PASSWORD | 200 OK, session cookie returned |
|
| TC-API-1.7 | Email+password login — tester | POST /api/auth/sign-in/email with uat-tester@groombook.dev + SEED_UAT_TESTER_PASSWORD | 200 OK, session cookie returned |
|
||||||
| TC-API-1.8 | Email+password — invalid password | POST /api/auth/sign-in/email with wrong password | 400 Bad Request, error returned |
|
| TC-API-1.8 | Email+password — invalid password | POST /api/auth/sign-in/email with wrong password | 400 Bad Request, error returned |
|
||||||
| TC-API-1.9 | Email+password — unknown user | POST /api/auth/sign-in/email with non-existent email | 400 Bad Request, error returned |
|
| TC-API-1.9 | Email+password — unknown user | POST /api/auth/sign-in/email with non-existent email | 400 Bad Request, error returned |
|
||||||
|
| TC-API-1.10 | Auto-provision on first OIDC login | First login as a Better-Auth user with no existing staff record | 200 OK, access granted; groomer staff record auto-created with name/email from user table |
|
||||||
|
|
||||||
### 4.2 Client Management
|
### 4.2 Client Management
|
||||||
|
|
||||||
|
|||||||
@@ -45,40 +45,76 @@ const GROOMER: StaffRow = {
|
|||||||
|
|
|||||||
|
|
||||||
let staffLookupResult: StaffRow | null = null;
|
let staffLookupResult: StaffRow | null = null;
|
||||||
let managerFallbackResult: StaffRow | null = MANAGER;
|
let managerFallbackResult: StaffRow | null = MANAGER;
|
||||||
|
let userLookupResult: { id: string; name: string | null; email: string | null } | null = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
let _insertedStaff: StaffRow | null = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
vi.mock("../db", () => {
|
vi.mock("../db", () => {
|
||||||
const staff = new Proxy(
|
const makeTableProxy = (name: string) =>
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
{ _name: "staff" },
|
new Proxy(
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
{
|
{ _name: name },
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
get(target, prop) {
|
{
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
if (prop === "_name") return "staff";
|
get(target, prop) {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
if (prop === "$inferSelect") return {};
|
if (prop === "_name") return name;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
return { table: "staff", column: prop };
|
if (prop === "$inferSelect") return {};
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
},
|
return { table: name, column: prop };
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
}
|
},
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
);
|
}
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
);
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const staff = makeTableProxy("staff");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const user = makeTableProxy("user");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const buildQuery = (result: unknown, fallback: unknown) => ({
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
[Symbol.iterator]: function* () {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
if (result) yield result;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
},
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
limit: (_n: number) => {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const item = result ?? fallback;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
return {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
[Symbol.iterator]: function* () { if (item) yield item; },
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
0: item,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
length: item ? 1 : 0,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
};
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
},
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
});
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
getDb: () => ({
|
getDb: () => ({
|
||||||
select: () => ({
|
select: () => ({
|
||||||
from: () => ({
|
from: (table: unknown) => ({
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
where: () => ({
|
where: () => buildQuery(
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
limit: () => {
|
table === staff ? staffLookupResult : userLookupResult,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
// dev mode fallback to first manager
|
table === staff ? managerFallbackResult : null
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
return managerFallbackResult ? [managerFallbackResult] : [];
|
),
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
},
|
}),
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
[Symbol.iterator]: function* () {
|
}),
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
if (staffLookupResult) yield staffLookupResult;
|
insert: (_table: unknown) => ({
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
},
|
values: (vals: Record<string, unknown>) => ({
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
0: staffLookupResult,
|
returning: () => {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
length: staffLookupResult ? 1 : 0,
|
const newStaff: StaffRow = {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
}),
|
id: "new-staff-id",
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
oidcSub: null,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
userId: vals.userId as string,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
role: vals.role as StaffRow["role"],
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
isSuperUser: false,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
name: vals.name as string,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
email: vals.email as string,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
active: true,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
icalToken: null,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
createdAt: new Date(),
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
updatedAt: new Date(),
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
};
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
_insertedStaff = newStaff;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
return [newStaff];
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
},
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
staff,
|
staff,
|
||||||
|
user,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
eq: vi.fn((_col: unknown, _val: unknown) => ({ col: _col, val: _val })),
|
eq: vi.fn((_col: unknown, _val: unknown) => ({ col: _col, val: _val })),
|
||||||
and: vi.fn((..._clauses: unknown[]) => ({})),
|
and: vi.fn((..._clauses: unknown[]) => ({})),
|
||||||
|
sql: vi.fn((..._args: unknown[]) => ({})),
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -87,6 +123,8 @@ vi.mock("../db", () => {
|
|||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
function resetMocks() {
|
function resetMocks() {
|
||||||
staffLookupResult = null;
|
staffLookupResult = null;
|
||||||
managerFallbackResult = MANAGER;
|
managerFallbackResult = MANAGER;
|
||||||
|
userLookupResult = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
_insertedStaff = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Build a minimal Hono app with jwtPayload pre-set, then apply a middleware. */
|
/** Build a minimal Hono app with jwtPayload pre-set, then apply a middleware. */
|
||||||
@@ -96,7 +134,10 @@ function buildApp(
|
|||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
) {
|
) {
|
||||||
const app = new Hono<AppEnv>();
|
const app = new Hono<AppEnv>();
|
||||||
app.use("*", async (c, next) => {
|
app.use("*", async (c, next) => {
|
||||||
c.set("jwtPayload", { sub: staffLookupResult?.userId ?? "unknown-sub" });
|
c.set("jwtPayload", {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
sub: userLookupResult?.id ?? staffLookupResult?.userId ?? "unknown-sub",
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
email: userLookupResult?.email,
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
});
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
await next();
|
await next();
|
||||||
});
|
});
|
||||||
app.use("*", middleware);
|
app.use("*", middleware);
|
||||||
@@ -202,6 +243,50 @@ describe("resolveStaffMiddleware", () => {
|
|||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
const body = await res.json();
|
const body = await res.json();
|
||||||
expect(body.error).toMatch(/no staff records found/i);
|
expect(body.error).toMatch(/no staff records found/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
it("auto-provision: creates groomer staff record on first login when Better-Auth user exists", async () => {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
staffLookupResult = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
userLookupResult = { id: "ba-user-new", name: "New User", email: "newuser@example.com" };
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
let capturedStaff: StaffRow | null = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const app = buildApp(resolveStaffMiddleware, (c) => {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
capturedStaff = c.get("staff");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
return c.json({ ok: true });
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
});
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const res = await app.request("/test");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(res.status).toBe(200);
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(capturedStaff).not.toBeNull();
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(capturedStaff!.role).toBe("groomer");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(capturedStaff!.userId).toBe("ba-user-new");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(capturedStaff!.name).toBe("New User");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(capturedStaff!.email).toBe("newuser@example.com");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(capturedStaff!.isSuperUser).toBe(false);
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
});
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
it("auto-provision: falls back to email prefix when user has no name", async () => {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
staffLookupResult = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
userLookupResult = { id: "ba-user-noname", name: null, email: "firstlogin@example.com" };
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
let capturedStaff: StaffRow | null = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const app = buildApp(resolveStaffMiddleware, (c) => {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
capturedStaff = c.get("staff");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
return c.json({ ok: true });
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
});
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const res = await app.request("/test");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(res.status).toBe(200);
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(capturedStaff!.name).toBe("firstlogin");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
});
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
it("auto-provision: returns 403 when no staff record and no Better-Auth user exists", async () => {
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
staffLookupResult = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
userLookupResult = null;
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const app = buildApp(resolveStaffMiddleware);
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const res = await app.request("/test");
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(res.status).toBe(403);
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
const body = await res.json();
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
expect(body.error).toMatch(/no staff record found for authenticated user/i);
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
|
});
|
||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ─── requireRole tests ────────────────────────────────────────────────────────
|
// ─── requireRole tests ────────────────────────────────────────────────────────
|
||||||
|
|||||||
|
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
Lint Roller
commented
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null. returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
import type { MiddlewareHandler } from "hono";
|
import type { MiddlewareHandler } from "hono";
|
||||||
import { and, eq, getDb, sql, staff } from "../db/index.js";
|
import { and, eq, getDb, sql, staff, user } from "../db/index.js";
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
|
||||||
export type StaffRole = "groomer" | "receptionist" | "manager";
|
export type StaffRole = "groomer" | "receptionist" | "manager";
|
||||||
export type StaffRow = typeof staff.$inferSelect;
|
export type StaffRow = typeof staff.$inferSelect;
|
||||||
@@ -110,6 +110,33 @@ export const resolveStaffMiddleware: MiddlewareHandler<AppEnv> = async (
|
|||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Auto-provision: no staff record exists for this user at all, but a valid
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
// Better-Auth user session exists (jwt.sub = user.id from user table).
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
// Create a minimal groomer staff record on first login.
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
const [userRow] = await db
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
.select({ id: user.id, name: user.name, email: user.email })
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
.from(user)
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
.where(eq(user.id, jwt.sub))
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
.limit(1);
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
if (userRow) {
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
const [newStaff] = await db
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
.insert(staff)
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
.values({
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
name: userRow.name ?? jwt.email?.split("@")[0] ?? "Unknown",
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
email: userRow.email ?? jwt.email ?? "",
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
userId: jwt.sub,
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
role: "groomer",
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
isSuperUser: false,
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
active: true,
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
})
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
.returning();
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
if (!newStaff) {
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
return c.json({ error: "Internal error: staff record creation failed" }, 500);
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
}
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
c.set("staff", newStaff);
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
await next();
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
return;
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
|
}
|
||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
return c.json(
|
return c.json(
|
||||||
{ error: "Forbidden: no staff record found for authenticated user" },
|
{ error: "Forbidden: no staff record found for authenticated user" },
|
||||||
403
|
403
|
||||||
|
|||||||
|
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
Lint Roller
commented
TS2769: is — add a guard before to avoid passing . TS2769: is — add a guard before to avoid passing .
|
|||||||
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.
returns with no . All non-limit WHERE queries throw TypeError → 500. Add to the returned object, and make fall back to when is null.