From fc887d8431056f5ec5eca42011a1e84225089a89 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Tue, 6 Oct 2026 06:40:25 +0200 Subject: [PATCH] fix(ui): encode every id in API paths (client-side path traversal) Follow-up to a7609ff for the whole frontend: all 30 API helpers in src/lib now pass path values through encodeURIComponent, so an id taken from the URL can never leave its own path segment and make the page call another endpoint with the viewer's token. Co-Authored-By: Claude Opus 5.5 (1M context) --- ApiCore-Frontend/src/lib/api-keys/api.ts | 4 ++-- ApiCore-Frontend/src/lib/apiaries/api.ts | 8 ++++---- ApiCore-Frontend/src/lib/automation/api.ts | 4 ++-- ApiCore-Frontend/src/lib/bottling/api.ts | 6 +++--- ApiCore-Frontend/src/lib/colonies/api.ts | 16 +++++++-------- ApiCore-Frontend/src/lib/documents/api.ts | 6 +++--- ApiCore-Frontend/src/lib/equipment/api.ts | 4 ++-- ApiCore-Frontend/src/lib/extractions/api.ts | 4 ++-- ApiCore-Frontend/src/lib/feedings/api.ts | 6 +++--- ApiCore-Frontend/src/lib/harvests/api.ts | 4 ++-- ApiCore-Frontend/src/lib/honey-batches/api.ts | 20 +++++++++---------- ApiCore-Frontend/src/lib/import/api.ts | 2 +- ApiCore-Frontend/src/lib/inspections/api.ts | 6 +++--- .../src/lib/label-templates/api.ts | 6 +++--- ApiCore-Frontend/src/lib/notifications/api.ts | 2 +- ApiCore-Frontend/src/lib/products/api.ts | 4 ++-- ApiCore-Frontend/src/lib/qr/api.ts | 4 ++-- ApiCore-Frontend/src/lib/queens/api.ts | 16 +++++++-------- ApiCore-Frontend/src/lib/roles/api.ts | 6 +++--- ApiCore-Frontend/src/lib/stock/api.ts | 6 +++--- ApiCore-Frontend/src/lib/storage/api.ts | 6 +++--- ApiCore-Frontend/src/lib/swarm-control/api.ts | 4 ++-- .../src/lib/task-templates/api.ts | 4 ++-- ApiCore-Frontend/src/lib/tasks/api.ts | 4 ++-- ApiCore-Frontend/src/lib/treatments/api.ts | 4 ++-- ApiCore-Frontend/src/lib/users/api.ts | 10 +++++----- ApiCore-Frontend/src/lib/varroa/api.ts | 4 ++-- ApiCore-Frontend/src/lib/weather/api.ts | 4 ++-- ApiCore-Frontend/src/lib/webhooks/api.ts | 4 ++-- ApiCore-Frontend/src/lib/winter-checks/api.ts | 2 +- 30 files changed, 90 insertions(+), 90 deletions(-) diff --git a/ApiCore-Frontend/src/lib/api-keys/api.ts b/ApiCore-Frontend/src/lib/api-keys/api.ts index 2c80463..5c74bd2 100644 --- a/ApiCore-Frontend/src/lib/api-keys/api.ts +++ b/ApiCore-Frontend/src/lib/api-keys/api.ts @@ -13,12 +13,12 @@ export function createApiKey(input: CreateApiKeyInput): Promise { } export function updateApiKeyAllowedIps(id: string, allowedIps: string[]): Promise { - return apiFetch(`/api-keys/${id}`, { + return apiFetch(`/api-keys/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify({ allowedIps }), }); } export function revokeApiKey(id: string): Promise { - return apiFetch(`/api-keys/${id}/revoke`, { method: "POST" }); + return apiFetch(`/api-keys/${encodeURIComponent(id)}/revoke`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/apiaries/api.ts b/ApiCore-Frontend/src/lib/apiaries/api.ts index 95f3516..88f7d5a 100644 --- a/ApiCore-Frontend/src/lib/apiaries/api.ts +++ b/ApiCore-Frontend/src/lib/apiaries/api.ts @@ -15,7 +15,7 @@ export function fetchApiaries(filter: ApiaryFilter = {}): Promise { } export function fetchApiary(id: string): Promise { - return apiFetch(`/apiaries/${id}`); + return apiFetch(`/apiaries/${encodeURIComponent(id)}`); } export function createApiary(input: ApiaryInput): Promise { @@ -26,16 +26,16 @@ export function createApiary(input: ApiaryInput): Promise { } export function updateApiary(id: string, input: Partial): Promise { - return apiFetch(`/apiaries/${id}`, { + return apiFetch(`/apiaries/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function deactivateApiary(id: string): Promise { - return apiFetch(`/apiaries/${id}/deactivate`, { method: "POST" }); + return apiFetch(`/apiaries/${encodeURIComponent(id)}/deactivate`, { method: "POST" }); } export function reactivateApiary(id: string): Promise { - return apiFetch(`/apiaries/${id}/reactivate`, { method: "POST" }); + return apiFetch(`/apiaries/${encodeURIComponent(id)}/reactivate`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/automation/api.ts b/ApiCore-Frontend/src/lib/automation/api.ts index e5e6c9d..1aa7abc 100644 --- a/ApiCore-Frontend/src/lib/automation/api.ts +++ b/ApiCore-Frontend/src/lib/automation/api.ts @@ -9,14 +9,14 @@ export function updateAutomationRule( id: string, input: UpdateAutomationRuleInput, ): Promise { - return apiFetch(`/automation-rules/${id}`, { + return apiFetch(`/automation-rules/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function resetAutomationRuleSequence(id: string): Promise { - return apiFetch(`/automation-rules/${id}/reset-sequence`, { + return apiFetch(`/automation-rules/${encodeURIComponent(id)}/reset-sequence`, { method: "POST", }); } diff --git a/ApiCore-Frontend/src/lib/bottling/api.ts b/ApiCore-Frontend/src/lib/bottling/api.ts index f5d4538..c567506 100644 --- a/ApiCore-Frontend/src/lib/bottling/api.ts +++ b/ApiCore-Frontend/src/lib/bottling/api.ts @@ -16,7 +16,7 @@ export function fetchBottlingBatches( } export function fetchBottlingBatch(id: string): Promise { - return apiFetch(`/bottling-batches/${id}`); + return apiFetch(`/bottling-batches/${encodeURIComponent(id)}`); } export function createBottlingBatch( @@ -32,14 +32,14 @@ export function updateBottlingBatch( id: string, input: UpdateBottlingBatchInput, ): Promise { - return apiFetch(`/bottling-batches/${id}`, { + return apiFetch(`/bottling-batches/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function deleteBottlingBatch(id: string): Promise<{ id: string }> { - return apiFetch<{ id: string }>(`/bottling-batches/${id}`, { + return apiFetch<{ id: string }>(`/bottling-batches/${encodeURIComponent(id)}`, { method: "DELETE", }); } diff --git a/ApiCore-Frontend/src/lib/colonies/api.ts b/ApiCore-Frontend/src/lib/colonies/api.ts index 9847414..140cedf 100644 --- a/ApiCore-Frontend/src/lib/colonies/api.ts +++ b/ApiCore-Frontend/src/lib/colonies/api.ts @@ -24,11 +24,11 @@ export function fetchColonies(filter: ColonyFilter = {}): Promise { } export function fetchColony(id: string): Promise { - return apiFetch(`/colonies/${id}`); + return apiFetch(`/colonies/${encodeURIComponent(id)}`); } export function fetchColonyHistory(id: string): Promise { - return apiFetch(`/colonies/${id}/history`); + return apiFetch(`/colonies/${encodeURIComponent(id)}/history`); } export function createColony(input: CreateColonyInput): Promise { @@ -39,37 +39,37 @@ export function createColony(input: CreateColonyInput): Promise { } export function updateColony(id: string, input: UpdateColonyInput): Promise { - return apiFetch(`/colonies/${id}`, { + return apiFetch(`/colonies/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function moveColony(id: string, input: MoveColonyInput): Promise { - return apiFetch(`/colonies/${id}/move`, { + return apiFetch(`/colonies/${encodeURIComponent(id)}/move`, { method: "POST", body: JSON.stringify(input), }); } export function splitColony(id: string, input: SplitColonyInput): Promise { - return apiFetch(`/colonies/${id}/split`, { + return apiFetch(`/colonies/${encodeURIComponent(id)}/split`, { method: "POST", body: JSON.stringify(input), }); } export function mergeColony(id: string, input: MergeColonyInput): Promise { - return apiFetch(`/colonies/${id}/merge`, { + return apiFetch(`/colonies/${encodeURIComponent(id)}/merge`, { method: "POST", body: JSON.stringify(input), }); } export function dissolveColony(id: string): Promise { - return apiFetch(`/colonies/${id}/dissolve`, { method: "POST" }); + return apiFetch(`/colonies/${encodeURIComponent(id)}/dissolve`, { method: "POST" }); } export function reactivateColony(id: string): Promise { - return apiFetch(`/colonies/${id}/reactivate`, { method: "POST" }); + return apiFetch(`/colonies/${encodeURIComponent(id)}/reactivate`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/documents/api.ts b/ApiCore-Frontend/src/lib/documents/api.ts index 3a9edda..cd53d01 100644 --- a/ApiCore-Frontend/src/lib/documents/api.ts +++ b/ApiCore-Frontend/src/lib/documents/api.ts @@ -30,17 +30,17 @@ export function updateDocument( id: string, input: UpdateDocumentInput, ): Promise { - return apiFetch(`/documents/${id}`, { + return apiFetch(`/documents/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function deleteDocument(id: string): Promise { - return apiFetch(`/documents/${id}`, { method: "DELETE" }); + return apiFetch(`/documents/${encodeURIComponent(id)}`, { method: "DELETE" }); } export async function downloadDocument(id: string, fileName: string): Promise { - const { blob, filename } = await apiFetchBlob(`/documents/${id}/download`, fileName); + const { blob, filename } = await apiFetchBlob(`/documents/${encodeURIComponent(id)}/download`, fileName); downloadBlob(blob, filename); } diff --git a/ApiCore-Frontend/src/lib/equipment/api.ts b/ApiCore-Frontend/src/lib/equipment/api.ts index 255f51f..4e2b288 100644 --- a/ApiCore-Frontend/src/lib/equipment/api.ts +++ b/ApiCore-Frontend/src/lib/equipment/api.ts @@ -14,7 +14,7 @@ export function fetchEquipmentList(filter: EquipmentFilter = {}): Promise { - return apiFetch(`/equipment/${id}`); + return apiFetch(`/equipment/${encodeURIComponent(id)}`); } export function createEquipment(input: CreateEquipmentInput): Promise { @@ -28,7 +28,7 @@ export function updateEquipment( id: string, input: UpdateEquipmentInput, ): Promise { - return apiFetch(`/equipment/${id}`, { + return apiFetch(`/equipment/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/extractions/api.ts b/ApiCore-Frontend/src/lib/extractions/api.ts index 17b2b95..1278fad 100644 --- a/ApiCore-Frontend/src/lib/extractions/api.ts +++ b/ApiCore-Frontend/src/lib/extractions/api.ts @@ -6,7 +6,7 @@ export function fetchExtractions(): Promise { } export function fetchExtraction(id: string): Promise { - return apiFetch(`/extractions/${id}`); + return apiFetch(`/extractions/${encodeURIComponent(id)}`); } export function createExtraction(input: CreateExtractionInput): Promise { @@ -20,7 +20,7 @@ export function updateExtraction( id: string, input: UpdateExtractionInput, ): Promise { - return apiFetch(`/extractions/${id}`, { + return apiFetch(`/extractions/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/feedings/api.ts b/ApiCore-Frontend/src/lib/feedings/api.ts index 1e7b217..c04121d 100644 --- a/ApiCore-Frontend/src/lib/feedings/api.ts +++ b/ApiCore-Frontend/src/lib/feedings/api.ts @@ -8,11 +8,11 @@ import { } from "./types"; export function fetchColonyFeedings(colonyId: string): Promise { - return apiFetch(`/colonies/${colonyId}/feedings`); + return apiFetch(`/colonies/${encodeURIComponent(colonyId)}/feedings`); } export function fetchColonyFeedingsSummary(colonyId: string): Promise { - return apiFetch(`/colonies/${colonyId}/feedings/summary`); + return apiFetch(`/colonies/${encodeURIComponent(colonyId)}/feedings/summary`); } export function createFeeding( @@ -30,7 +30,7 @@ export function updateFeeding( id: string, input: UpdateFeedingInput, ): Promise { - return apiFetch(`/feedings/${id}`, { + return apiFetch(`/feedings/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/harvests/api.ts b/ApiCore-Frontend/src/lib/harvests/api.ts index 723e59b..08b6a0b 100644 --- a/ApiCore-Frontend/src/lib/harvests/api.ts +++ b/ApiCore-Frontend/src/lib/harvests/api.ts @@ -7,7 +7,7 @@ export function fetchHarvests(): Promise { } export function fetchHarvest(id: string): Promise { - return apiFetch(`/harvests/${id}`); + return apiFetch(`/harvests/${encodeURIComponent(id)}`); } export function createHarvest( @@ -22,7 +22,7 @@ export function createHarvest( } export function updateHarvest(id: string, input: UpdateHarvestInput): Promise { - return apiFetch(`/harvests/${id}`, { + return apiFetch(`/harvests/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/honey-batches/api.ts b/ApiCore-Frontend/src/lib/honey-batches/api.ts index f9a6a15..6217de9 100644 --- a/ApiCore-Frontend/src/lib/honey-batches/api.ts +++ b/ApiCore-Frontend/src/lib/honey-batches/api.ts @@ -24,11 +24,11 @@ export function fetchHoneyBatches(filter: HoneyBatchFilter = {}): Promise { - return apiFetch(`/honey-batches/${id}`); + return apiFetch(`/honey-batches/${encodeURIComponent(id)}`); } export function fetchHoneyBatchTraceability(id: string): Promise { - return apiFetch(`/honey-batches/${id}/traceability`); + return apiFetch(`/honey-batches/${encodeURIComponent(id)}/traceability`); } export function createHoneyBatch(input: CreateHoneyBatchInput): Promise { @@ -42,7 +42,7 @@ export function updateHoneyBatch( id: string, input: UpdateHoneyBatchInput, ): Promise { - return apiFetch(`/honey-batches/${id}`, { + return apiFetch(`/honey-batches/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); @@ -52,7 +52,7 @@ export function updateHoneyMeasurement( measurementId: string, input: UpdateHoneyMeasurementInput, ): Promise { - return apiFetch(`/honey-batches/measurements/${measurementId}`, { + return apiFetch(`/honey-batches/measurements/${encodeURIComponent(measurementId)}`, { method: "PATCH", body: JSON.stringify(input), }); @@ -62,7 +62,7 @@ export function addHoneyMeasurement( id: string, input: CreateHoneyMeasurementInput, ): Promise { - return apiFetch(`/honey-batches/${id}/measurements`, { + return apiFetch(`/honey-batches/${encodeURIComponent(id)}/measurements`, { method: "POST", body: JSON.stringify(input), }); @@ -72,20 +72,20 @@ export function relocateHoneyBatch( id: string, input: RelocateHoneyBatchInput, ): Promise { - return apiFetch(`/honey-batches/${id}/relocate`, { + return apiFetch(`/honey-batches/${encodeURIComponent(id)}/relocate`, { method: "POST", body: JSON.stringify(input), }); } export function fetchHoneyBatchRelocations(id: string): Promise { - return apiFetch(`/honey-batches/${id}/relocations`); + return apiFetch(`/honey-batches/${encodeURIComponent(id)}/relocations`); } export function fetchHoneyBatchContainerAllocations( id: string, ): Promise { - return apiFetch(`/honey-batches/${id}/containers`); + return apiFetch(`/honey-batches/${encodeURIComponent(id)}/containers`); } export function setHoneyBatchContainerAllocation( @@ -94,7 +94,7 @@ export function setHoneyBatchContainerAllocation( amount: number, ): Promise { return apiFetch( - `/honey-batches/${id}/containers/${containerId}`, + `/honey-batches/${encodeURIComponent(id)}/containers/${encodeURIComponent(containerId)}`, { method: "PUT", body: JSON.stringify({ amount }) }, ); } @@ -103,7 +103,7 @@ export function removeHoneyBatchContainerAllocation( id: string, containerId: string, ): Promise { - return apiFetch(`/honey-batches/${id}/containers/${containerId}`, { + return apiFetch(`/honey-batches/${encodeURIComponent(id)}/containers/${encodeURIComponent(containerId)}`, { method: "DELETE", }); } diff --git a/ApiCore-Frontend/src/lib/import/api.ts b/ApiCore-Frontend/src/lib/import/api.ts index d5e063a..13b31fd 100644 --- a/ApiCore-Frontend/src/lib/import/api.ts +++ b/ApiCore-Frontend/src/lib/import/api.ts @@ -4,5 +4,5 @@ import { ImportEntity, ImportReport } from "./types"; export function importCsv(entity: ImportEntity, file: File): Promise { const formData = new FormData(); formData.append("file", file); - return apiFetchFormData(`/import/${entity}`, formData); + return apiFetchFormData(`/import/${encodeURIComponent(entity)}`, formData); } diff --git a/ApiCore-Frontend/src/lib/inspections/api.ts b/ApiCore-Frontend/src/lib/inspections/api.ts index 3807b71..83b2d0f 100644 --- a/ApiCore-Frontend/src/lib/inspections/api.ts +++ b/ApiCore-Frontend/src/lib/inspections/api.ts @@ -9,7 +9,7 @@ import { } from "./types"; export function fetchColonyInspections(colonyId: string): Promise { - return apiFetch(`/colonies/${colonyId}/inspections`); + return apiFetch(`/colonies/${encodeURIComponent(colonyId)}/inspections`); } export function createInspection( @@ -27,7 +27,7 @@ export function updateInspection( id: string, input: UpdateInspectionInput, ): Promise { - return apiFetch(`/inspections/${id}`, { + return apiFetch(`/inspections/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); @@ -37,7 +37,7 @@ export function createTaskFromInspection( id: string, input: CreateTaskFromInspectionInput, ): Promise { - return apiFetch(`/inspections/${id}/create-task`, { + return apiFetch(`/inspections/${encodeURIComponent(id)}/create-task`, { method: "POST", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/label-templates/api.ts b/ApiCore-Frontend/src/lib/label-templates/api.ts index bb1134d..cc6b269 100644 --- a/ApiCore-Frontend/src/lib/label-templates/api.ts +++ b/ApiCore-Frontend/src/lib/label-templates/api.ts @@ -17,14 +17,14 @@ export function updateLabelTemplate( id: string, input: UpdateLabelTemplateInput, ): Promise { - return apiFetch(`/label-templates/${id}`, { + return apiFetch(`/label-templates/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function deactivateLabelTemplate(id: string): Promise { - return apiFetch(`/label-templates/${id}`, { method: "DELETE" }); + return apiFetch(`/label-templates/${encodeURIComponent(id)}`, { method: "DELETE" }); } export async function printLabels( @@ -34,7 +34,7 @@ export async function printLabels( ): Promise { const query = startPosition && startPosition > 1 ? `?startPosition=${startPosition}` : ""; const { blob, filename } = await apiFetchBlob( - `/label-templates/${templateId}/print/${bottlingBatchId}${query}`, + `/label-templates/${encodeURIComponent(templateId)}/print/${encodeURIComponent(bottlingBatchId)}${query}`, "etiketten.pdf", ); downloadBlob(blob, filename); diff --git a/ApiCore-Frontend/src/lib/notifications/api.ts b/ApiCore-Frontend/src/lib/notifications/api.ts index 6483175..8705bef 100644 --- a/ApiCore-Frontend/src/lib/notifications/api.ts +++ b/ApiCore-Frontend/src/lib/notifications/api.ts @@ -6,5 +6,5 @@ export function fetchNotifications(unreadOnly = false): Promise } export function markNotificationRead(id: string): Promise { - return apiFetch(`/notifications/${id}/read`, { method: "POST" }); + return apiFetch(`/notifications/${encodeURIComponent(id)}/read`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/products/api.ts b/ApiCore-Frontend/src/lib/products/api.ts index 55fe246..7735924 100644 --- a/ApiCore-Frontend/src/lib/products/api.ts +++ b/ApiCore-Frontend/src/lib/products/api.ts @@ -14,7 +14,7 @@ export function fetchProducts(filter: ProductFilter = {}): Promise { } export function fetchProduct(id: string): Promise { - return apiFetch(`/products/${id}`); + return apiFetch(`/products/${encodeURIComponent(id)}`); } export function createProduct(input: CreateProductInput): Promise { @@ -25,7 +25,7 @@ export function createProduct(input: CreateProductInput): Promise { } export function updateProduct(id: string, input: UpdateProductInput): Promise { - return apiFetch(`/products/${id}`, { + return apiFetch(`/products/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/qr/api.ts b/ApiCore-Frontend/src/lib/qr/api.ts index 1850ab0..887f840 100644 --- a/ApiCore-Frontend/src/lib/qr/api.ts +++ b/ApiCore-Frontend/src/lib/qr/api.ts @@ -9,11 +9,11 @@ export type QrEntityType = | "bottling-batches"; export async function fetchQrCodeSvg(entityType: QrEntityType, id: string): Promise { - const { blob } = await apiFetchBlob(`/qr/${entityType}/${id}.svg`, `${entityType}.svg`); + const { blob } = await apiFetchBlob(`/qr/${encodeURIComponent(entityType)}/${encodeURIComponent(id)}.svg`, `${entityType}.svg`); return blob; } export async function fetchQrLink(entityType: QrEntityType, id: string): Promise { - const { url } = await apiFetch<{ url: string }>(`/qr/${entityType}/${id}/link`); + const { url } = await apiFetch<{ url: string }>(`/qr/${encodeURIComponent(entityType)}/${encodeURIComponent(id)}/link`); return url; } diff --git a/ApiCore-Frontend/src/lib/queens/api.ts b/ApiCore-Frontend/src/lib/queens/api.ts index 284f40f..d06c440 100644 --- a/ApiCore-Frontend/src/lib/queens/api.ts +++ b/ApiCore-Frontend/src/lib/queens/api.ts @@ -24,15 +24,15 @@ export function fetchQueens(filter: QueenFilter = {}): Promise { } export function fetchQueen(id: string): Promise { - return apiFetch(`/queens/${id}`); + return apiFetch(`/queens/${encodeURIComponent(id)}`); } export function fetchQueenHistory(id: string): Promise { - return apiFetch(`/queens/${id}/history`); + return apiFetch(`/queens/${encodeURIComponent(id)}/history`); } export function fetchQueenLineage(id: string): Promise { - return apiFetch(`/queens/${id}/lineage`); + return apiFetch(`/queens/${encodeURIComponent(id)}/lineage`); } export function createQueen(input: CreateQueenInput): Promise { @@ -43,28 +43,28 @@ export function createQueen(input: CreateQueenInput): Promise { } export function updateQueen(id: string, input: UpdateQueenInput): Promise { - return apiFetch(`/queens/${id}`, { + return apiFetch(`/queens/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function assignQueenColony(id: string, input: AssignColonyInput): Promise { - return apiFetch(`/queens/${id}/assign-colony`, { + return apiFetch(`/queens/${encodeURIComponent(id)}/assign-colony`, { method: "POST", body: JSON.stringify(input), }); } export function fetchQueenEvaluations(id: string): Promise { - return apiFetch(`/queens/${id}/evaluations`); + return apiFetch(`/queens/${encodeURIComponent(id)}/evaluations`); } export function updateQueenEvaluation( evaluationId: string, input: UpdateQueenEvaluationInput, ): Promise { - return apiFetch(`/queens/evaluations/${evaluationId}`, { + return apiFetch(`/queens/evaluations/${encodeURIComponent(evaluationId)}`, { method: "PATCH", body: JSON.stringify(input), }); @@ -74,7 +74,7 @@ export function addQueenEvaluation( id: string, input: CreateQueenEvaluationInput, ): Promise { - return apiFetch(`/queens/${id}/evaluations`, { + return apiFetch(`/queens/${encodeURIComponent(id)}/evaluations`, { method: "POST", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/roles/api.ts b/ApiCore-Frontend/src/lib/roles/api.ts index c4d1b5c..0c0369f 100644 --- a/ApiCore-Frontend/src/lib/roles/api.ts +++ b/ApiCore-Frontend/src/lib/roles/api.ts @@ -22,16 +22,16 @@ export function createRole(input: CreateRoleInput): Promise { } export function updateRole(id: string, input: UpdateRoleInput): Promise { - return apiFetch(`/roles/${id}`, { + return apiFetch(`/roles/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function deactivateRole(id: string): Promise { - return apiFetch(`/roles/${id}/deactivate`, { method: "POST" }); + return apiFetch(`/roles/${encodeURIComponent(id)}/deactivate`, { method: "POST" }); } export function reactivateRole(id: string): Promise { - return apiFetch(`/roles/${id}/reactivate`, { method: "POST" }); + return apiFetch(`/roles/${encodeURIComponent(id)}/reactivate`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/stock/api.ts b/ApiCore-Frontend/src/lib/stock/api.ts index be1ed4f..53d64b8 100644 --- a/ApiCore-Frontend/src/lib/stock/api.ts +++ b/ApiCore-Frontend/src/lib/stock/api.ts @@ -10,7 +10,7 @@ export function fetchStock( path: StockBatchPath, id: string, ): Promise { - return apiFetch(`/${path}/${encodeURIComponent(id)}/stock`); + return apiFetch(`/${encodeURIComponent(path)}/${encodeURIComponent(id)}/stock`); } export function withdrawStock( @@ -19,7 +19,7 @@ export function withdrawStock( input: WithdrawInput, ): Promise { return apiFetch( - `/${path}/${encodeURIComponent(id)}/withdrawals`, + `/${encodeURIComponent(path)}/${encodeURIComponent(id)}/withdrawals`, { method: "POST", body: JSON.stringify(input), @@ -33,7 +33,7 @@ export function correctStock( input: CorrectInput, ): Promise { return apiFetch( - `/${path}/${encodeURIComponent(id)}/corrections`, + `/${encodeURIComponent(path)}/${encodeURIComponent(id)}/corrections`, { method: "POST", body: JSON.stringify(input), diff --git a/ApiCore-Frontend/src/lib/storage/api.ts b/ApiCore-Frontend/src/lib/storage/api.ts index fd73e0c..ddc8c24 100644 --- a/ApiCore-Frontend/src/lib/storage/api.ts +++ b/ApiCore-Frontend/src/lib/storage/api.ts @@ -26,7 +26,7 @@ export function updateStorageContainer( id: string, input: UpdateStorageContainerInput, ): Promise { - return apiFetch(`/storage-containers/${id}`, { + return apiFetch(`/storage-containers/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); @@ -47,7 +47,7 @@ export function updateStockItem( id: string, input: UpdateStockItemInput, ): Promise { - return apiFetch(`/stock-items/${id}`, { + return apiFetch(`/stock-items/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); @@ -57,7 +57,7 @@ export function addStockMovement( id: string, input: CreateStockMovementInput, ): Promise { - return apiFetch(`/stock-items/${id}/movements`, { + return apiFetch(`/stock-items/${encodeURIComponent(id)}/movements`, { method: "POST", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/swarm-control/api.ts b/ApiCore-Frontend/src/lib/swarm-control/api.ts index b5a5916..a7abcd3 100644 --- a/ApiCore-Frontend/src/lib/swarm-control/api.ts +++ b/ApiCore-Frontend/src/lib/swarm-control/api.ts @@ -7,7 +7,7 @@ import { } from "./types"; export function fetchColonySwarmControlChecks(colonyId: string): Promise { - return apiFetch(`/colonies/${colonyId}/swarm-control-checks`); + return apiFetch(`/colonies/${encodeURIComponent(colonyId)}/swarm-control-checks`); } export function createSwarmControlCheck( @@ -25,7 +25,7 @@ export function updateSwarmControlCheck( id: string, input: UpdateSwarmControlCheckInput, ): Promise { - return apiFetch(`/swarm-control-checks/${id}`, { + return apiFetch(`/swarm-control-checks/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/task-templates/api.ts b/ApiCore-Frontend/src/lib/task-templates/api.ts index e5a8d07..9c043e1 100644 --- a/ApiCore-Frontend/src/lib/task-templates/api.ts +++ b/ApiCore-Frontend/src/lib/task-templates/api.ts @@ -13,12 +13,12 @@ export function createTaskTemplate(input: CreateTaskTemplateInput): Promise { - return apiFetch(`/task-templates/${id}`, { + return apiFetch(`/task-templates/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function deactivateTaskTemplate(id: string): Promise { - return apiFetch(`/task-templates/${id}/deactivate`, { method: "POST" }); + return apiFetch(`/task-templates/${encodeURIComponent(id)}/deactivate`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/tasks/api.ts b/ApiCore-Frontend/src/lib/tasks/api.ts index 649512e..b412657 100644 --- a/ApiCore-Frontend/src/lib/tasks/api.ts +++ b/ApiCore-Frontend/src/lib/tasks/api.ts @@ -17,12 +17,12 @@ export function createTask(input: CreateTaskInput): Promise { } export function updateTask(id: string, input: UpdateTaskInput): Promise { - return apiFetch(`/tasks/${id}`, { + return apiFetch(`/tasks/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function completeTask(id: string): Promise { - return apiFetch(`/tasks/${id}/complete`, { method: "POST" }); + return apiFetch(`/tasks/${encodeURIComponent(id)}/complete`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/treatments/api.ts b/ApiCore-Frontend/src/lib/treatments/api.ts index 2cc45bb..df56056 100644 --- a/ApiCore-Frontend/src/lib/treatments/api.ts +++ b/ApiCore-Frontend/src/lib/treatments/api.ts @@ -8,7 +8,7 @@ import { } from "./types"; export function fetchColonyTreatments(colonyId: string): Promise { - return apiFetch(`/colonies/${colonyId}/treatments`); + return apiFetch(`/colonies/${encodeURIComponent(colonyId)}/treatments`); } export function fetchWithdrawalStatus( @@ -37,7 +37,7 @@ export function updateTreatment( id: string, input: UpdateTreatmentInput, ): Promise { - return apiFetch(`/treatments/${id}`, { + return apiFetch(`/treatments/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/users/api.ts b/ApiCore-Frontend/src/lib/users/api.ts index c908c7b..17d7bfd 100644 --- a/ApiCore-Frontend/src/lib/users/api.ts +++ b/ApiCore-Frontend/src/lib/users/api.ts @@ -13,7 +13,7 @@ export function createUser(input: CreateUserInput): Promise { } export function updateUser(id: string, input: UpdateUserInput): Promise { - return apiFetch(`/users/${id}`, { + return apiFetch(`/users/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); @@ -23,20 +23,20 @@ export function resetUserPassword( id: string, password: string, ): Promise { - return apiFetch(`/users/${id}/reset-password`, { + return apiFetch(`/users/${encodeURIComponent(id)}/reset-password`, { method: "POST", body: JSON.stringify({ password }), }); } export function deactivateUser(id: string): Promise { - return apiFetch(`/users/${id}/deactivate`, { method: "POST" }); + return apiFetch(`/users/${encodeURIComponent(id)}/deactivate`, { method: "POST" }); } export function activateUser(id: string): Promise { - return apiFetch(`/users/${id}/activate`, { method: "POST" }); + return apiFetch(`/users/${encodeURIComponent(id)}/activate`, { method: "POST" }); } export function resetUserMfa(id: string): Promise { - return apiFetch(`/users/${id}/mfa/reset`, { method: "POST" }); + return apiFetch(`/users/${encodeURIComponent(id)}/mfa/reset`, { method: "POST" }); } diff --git a/ApiCore-Frontend/src/lib/varroa/api.ts b/ApiCore-Frontend/src/lib/varroa/api.ts index 89c31c1..f2ece7d 100644 --- a/ApiCore-Frontend/src/lib/varroa/api.ts +++ b/ApiCore-Frontend/src/lib/varroa/api.ts @@ -7,7 +7,7 @@ import { } from "./types"; export function fetchColonyVarroaMeasurements(colonyId: string): Promise { - return apiFetch(`/colonies/${colonyId}/varroa-measurements`); + return apiFetch(`/colonies/${encodeURIComponent(colonyId)}/varroa-measurements`); } export function createVarroaMeasurement( @@ -25,7 +25,7 @@ export function updateVarroaMeasurement( id: string, input: UpdateVarroaMeasurementInput, ): Promise { - return apiFetch(`/varroa-measurements/${id}`, { + return apiFetch(`/varroa-measurements/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); diff --git a/ApiCore-Frontend/src/lib/weather/api.ts b/ApiCore-Frontend/src/lib/weather/api.ts index 850e976..c40f6b7 100644 --- a/ApiCore-Frontend/src/lib/weather/api.ts +++ b/ApiCore-Frontend/src/lib/weather/api.ts @@ -2,9 +2,9 @@ import { apiFetch } from "@/lib/auth/api-client"; import { ApiaryWeather, Trachtprognose } from "./types"; export function fetchApiaryWeather(apiaryId: string): Promise { - return apiFetch(`/apiaries/${apiaryId}/weather`); + return apiFetch(`/apiaries/${encodeURIComponent(apiaryId)}/weather`); } export function fetchTrachtprognose(apiaryId: string): Promise { - return apiFetch(`/apiaries/${apiaryId}/trachtprognose`); + return apiFetch(`/apiaries/${encodeURIComponent(apiaryId)}/trachtprognose`); } diff --git a/ApiCore-Frontend/src/lib/webhooks/api.ts b/ApiCore-Frontend/src/lib/webhooks/api.ts index ecbb0dd..f95339f 100644 --- a/ApiCore-Frontend/src/lib/webhooks/api.ts +++ b/ApiCore-Frontend/src/lib/webhooks/api.ts @@ -21,12 +21,12 @@ export function updateWebhook( id: string, input: UpdateWebhookInput, ): Promise { - return apiFetch(`/webhooks/${id}`, { + return apiFetch(`/webhooks/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), }); } export function deleteWebhook(id: string): Promise { - return apiFetch(`/webhooks/${id}`, { method: "DELETE" }); + return apiFetch(`/webhooks/${encodeURIComponent(id)}`, { method: "DELETE" }); } diff --git a/ApiCore-Frontend/src/lib/winter-checks/api.ts b/ApiCore-Frontend/src/lib/winter-checks/api.ts index f268c08..5de96c0 100644 --- a/ApiCore-Frontend/src/lib/winter-checks/api.ts +++ b/ApiCore-Frontend/src/lib/winter-checks/api.ts @@ -30,7 +30,7 @@ export function updateWinterCheck( id: string, input: Partial, ): Promise { - return apiFetch(`/winter-checks/${id}`, { + return apiFetch(`/winter-checks/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(input), });