feat(import): harden untrusted spreadsheet boundaries
This commit is contained in:
@@ -23,6 +23,13 @@ const paginationSchema = z.object({
|
||||
const importBatchStatusSchema = z.nativeEnum(ImportBatchStatus);
|
||||
const stagedRecordStatusSchema = z.nativeEnum(StagedRecordStatus);
|
||||
const stagedRecordTypeSchema = z.nativeEnum(DispoStagedRecordType);
|
||||
const workbookPathSchema = z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, "Workbook path is required.")
|
||||
.refine((value) => value.toLowerCase().endsWith(".xlsx"), {
|
||||
message: "Only .xlsx workbook paths are supported.",
|
||||
});
|
||||
|
||||
// ─── Router ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -32,12 +39,12 @@ export const dispoRouter = createTRPCRouter({
|
||||
stageImportBatch: adminProcedure
|
||||
.input(
|
||||
z.object({
|
||||
chargeabilityWorkbookPath: z.string(),
|
||||
costWorkbookPath: z.string().optional(),
|
||||
chargeabilityWorkbookPath: workbookPathSchema,
|
||||
costWorkbookPath: workbookPathSchema.optional(),
|
||||
notes: z.string().nullish(),
|
||||
planningWorkbookPath: z.string(),
|
||||
referenceWorkbookPath: z.string(),
|
||||
rosterWorkbookPath: z.string().optional(),
|
||||
planningWorkbookPath: workbookPathSchema,
|
||||
referenceWorkbookPath: workbookPathSchema,
|
||||
rosterWorkbookPath: workbookPathSchema.optional(),
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
@@ -56,13 +63,13 @@ export const dispoRouter = createTRPCRouter({
|
||||
validateImportBatch: adminProcedure
|
||||
.input(
|
||||
z.object({
|
||||
chargeabilityWorkbookPath: z.string(),
|
||||
costWorkbookPath: z.string().optional(),
|
||||
chargeabilityWorkbookPath: workbookPathSchema,
|
||||
costWorkbookPath: workbookPathSchema.optional(),
|
||||
importBatchId: z.string().optional(),
|
||||
notes: z.string().nullish(),
|
||||
planningWorkbookPath: z.string(),
|
||||
referenceWorkbookPath: z.string(),
|
||||
rosterWorkbookPath: z.string().optional(),
|
||||
planningWorkbookPath: workbookPathSchema,
|
||||
referenceWorkbookPath: workbookPathSchema,
|
||||
rosterWorkbookPath: workbookPathSchema.optional(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ input }) => {
|
||||
|
||||
Reference in New Issue
Block a user