fix(api): replace ctx.session.user lookups with ctx.dbUser
Procedures were re-fetching the acting user from DB using the session email, which breaks if email changes between session creation and request. ctx.dbUser is populated by protectedProcedure and is always current. Also removed the now-unused findVacationActor helper function. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,21 +42,11 @@ const BatchCreatePublicHolidaysSchema = z.object({
|
|||||||
replaceExisting: z.boolean().default(false),
|
replaceExisting: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
async function findVacationActor(
|
|
||||||
db: Parameters<Parameters<typeof protectedProcedure["query"]>[0]>[0]["ctx"]["db"],
|
|
||||||
email: string | null | undefined,
|
|
||||||
) {
|
|
||||||
return db.user.findUnique({
|
|
||||||
where: { email: email ?? "" },
|
|
||||||
select: { id: true, systemRole: true },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const vacationManagementProcedures = {
|
export const vacationManagementProcedures = {
|
||||||
approve: managerProcedure
|
approve: managerProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(z.object({ id: z.string() }))
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const userRecord = await findVacationActor(ctx.db, ctx.session.user?.email);
|
const userRecord = ctx.dbUser;
|
||||||
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
||||||
|
|
||||||
const result = await approveVacation(
|
const result = await approveVacation(
|
||||||
@@ -117,7 +107,7 @@ export const vacationManagementProcedures = {
|
|||||||
|
|
||||||
emitVacationUpdated({ id: updated.id, resourceId: updated.resourceId, status: updated.status });
|
emitVacationUpdated({ id: updated.id, resourceId: updated.resourceId, status: updated.status });
|
||||||
|
|
||||||
const userRecord = await findVacationActor(ctx.db, ctx.session.user?.email);
|
const userRecord = ctx.dbUser;
|
||||||
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
||||||
await completeVacationApprovalTasks(ctx.db, input.id, userRecord?.id);
|
await completeVacationApprovalTasks(ctx.db, input.id, userRecord?.id);
|
||||||
|
|
||||||
@@ -144,7 +134,7 @@ export const vacationManagementProcedures = {
|
|||||||
batchApprove: managerProcedure
|
batchApprove: managerProcedure
|
||||||
.input(z.object({ ids: z.array(z.string()).min(1).max(100) }))
|
.input(z.object({ ids: z.array(z.string()).min(1).max(100) }))
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const userRecord = await findVacationActor(ctx.db, ctx.session.user?.email);
|
const userRecord = ctx.dbUser;
|
||||||
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
||||||
|
|
||||||
const result = await batchApproveVacations(
|
const result = await batchApproveVacations(
|
||||||
@@ -187,7 +177,7 @@ export const vacationManagementProcedures = {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const userRecord = await findVacationActor(ctx.db, ctx.session.user?.email);
|
const userRecord = ctx.dbUser;
|
||||||
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
||||||
|
|
||||||
const result = await batchRejectVacations(
|
const result = await batchRejectVacations(
|
||||||
@@ -224,7 +214,7 @@ export const vacationManagementProcedures = {
|
|||||||
cancel: protectedProcedure
|
cancel: protectedProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(z.object({ id: z.string() }))
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const userRecord = await findVacationActor(ctx.db, ctx.session.user?.email);
|
const userRecord = ctx.dbUser;
|
||||||
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
||||||
if (!userRecord) {
|
if (!userRecord) {
|
||||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||||
@@ -274,10 +264,7 @@ export const vacationManagementProcedures = {
|
|||||||
batchCreatePublicHolidays: adminProcedure
|
batchCreatePublicHolidays: adminProcedure
|
||||||
.input(BatchCreatePublicHolidaysSchema)
|
.input(BatchCreatePublicHolidaysSchema)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const adminUser = await ctx.db.user.findUnique({
|
const adminUser = ctx.dbUser;
|
||||||
where: { email: ctx.session.user?.email ?? "" },
|
|
||||||
select: { id: true },
|
|
||||||
});
|
|
||||||
if (!adminUser) {
|
if (!adminUser) {
|
||||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||||
}
|
}
|
||||||
@@ -309,7 +296,7 @@ export const vacationManagementProcedures = {
|
|||||||
throw new TRPCError({ code: "NOT_FOUND", message: "Vacation not found" });
|
throw new TRPCError({ code: "NOT_FOUND", message: "Vacation not found" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const userRecord = await findVacationActor(ctx.db, ctx.session.user?.email);
|
const userRecord = ctx.dbUser;
|
||||||
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
const audit = makeAuditLogger(ctx.db, userRecord?.id);
|
||||||
if (!userRecord) {
|
if (!userRecord) {
|
||||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||||
|
|||||||
Reference in New Issue
Block a user