fix(plan): correct admin role check (roleName not role) + drop stale category casts
isAdminLike read authData.role, which doesn't exist on AuthData (it's roleName; role is on JwtPayload), so admins were always self-scoped on /entries and /overrides. Typed the param (no more any). Also removed 4 'category: input.category as any' casts now that category is a String column. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
|||||||
} from "../../middleware/auth";
|
} from "../../middleware/auth";
|
||||||
import { success, error, parseId } from "../../utils/response";
|
import { success, error, parseId } from "../../utils/response";
|
||||||
import { parseBody } from "../../schemas/common";
|
import { parseBody } from "../../schemas/common";
|
||||||
|
import { AuthData } from "../../types";
|
||||||
import { logAudit } from "../../services/audit";
|
import { logAudit } from "../../services/audit";
|
||||||
import {
|
import {
|
||||||
CreatePlanEntrySchema,
|
CreatePlanEntrySchema,
|
||||||
@@ -40,8 +41,12 @@ import {
|
|||||||
|
|
||||||
const MAX_RANGE_DAYS = 92;
|
const MAX_RANGE_DAYS = 92;
|
||||||
|
|
||||||
function isAdminLike(authData: any): boolean {
|
// NOTE: AuthData carries `roleName` (not `role` — that lives on JwtPayload).
|
||||||
return authData?.role === "admin";
|
// The previous `authData.role` read was always undefined, so admins were
|
||||||
|
// wrongly scoped to their own plan rows on the /entries and /overrides
|
||||||
|
// endpoints. Typed (not `any`) so this can't silently regress.
|
||||||
|
function isAdminLike(authData: AuthData | undefined): boolean {
|
||||||
|
return authData?.roleName === "admin";
|
||||||
}
|
}
|
||||||
|
|
||||||
function forceFromQuery(query: unknown): boolean {
|
function forceFromQuery(query: unknown): boolean {
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ export async function createEntry(
|
|||||||
date_from: toDateOnly(input.date_from),
|
date_from: toDateOnly(input.date_from),
|
||||||
date_to: toDateOnly(input.date_to),
|
date_to: toDateOnly(input.date_to),
|
||||||
project_id: input.project_id ?? null,
|
project_id: input.project_id ?? null,
|
||||||
category: input.category as any,
|
category: input.category,
|
||||||
note: input.note,
|
note: input.note,
|
||||||
created_by: actorUserId,
|
created_by: actorUserId,
|
||||||
},
|
},
|
||||||
@@ -515,7 +515,7 @@ export async function updateEntry(
|
|||||||
date_from: input.date_from ? toDateOnly(input.date_from) : undefined,
|
date_from: input.date_from ? toDateOnly(input.date_from) : undefined,
|
||||||
date_to: input.date_to ? toDateOnly(input.date_to) : undefined,
|
date_to: input.date_to ? toDateOnly(input.date_to) : undefined,
|
||||||
project_id: input.project_id === undefined ? undefined : input.project_id,
|
project_id: input.project_id === undefined ? undefined : input.project_id,
|
||||||
category: input.category as any,
|
category: input.category,
|
||||||
note: input.note,
|
note: input.note,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -636,7 +636,7 @@ export async function createOverride(
|
|||||||
user_id: input.user_id,
|
user_id: input.user_id,
|
||||||
shift_date: date,
|
shift_date: date,
|
||||||
project_id: input.project_id ?? null,
|
project_id: input.project_id ?? null,
|
||||||
category: input.category as any,
|
category: input.category,
|
||||||
note: input.note,
|
note: input.note,
|
||||||
created_by: actorUserId,
|
created_by: actorUserId,
|
||||||
},
|
},
|
||||||
@@ -707,7 +707,7 @@ export async function updateOverride(
|
|||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
project_id: input.project_id === undefined ? undefined : input.project_id,
|
project_id: input.project_id === undefined ? undefined : input.project_id,
|
||||||
category: input.category as any,
|
category: input.category,
|
||||||
note: input.note,
|
note: input.note,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user