From 22db579973af4db77d91eb362519ac7ae7b43fa0 Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Sat, 17 Jan 2026 22:36:46 +0100 Subject: [PATCH] refactor: filter by org id in all places --- app/server/modules/backups/backups.service.ts | 20 ++++++++++--------- .../notifications/notifications.service.ts | 4 +++- .../repositories/repositories.service.ts | 12 ++++++----- app/server/modules/volumes/volume.service.ts | 19 +++++++++++------- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/app/server/modules/backups/backups.service.ts b/app/server/modules/backups/backups.service.ts index 5292867e..75e26eb2 100644 --- a/app/server/modules/backups/backups.service.ts +++ b/app/server/modules/backups/backups.service.ts @@ -178,7 +178,7 @@ const updateSchedule = async (scheduleId: number, data: UpdateBackupScheduleBody const [updated] = await db .update(backupSchedulesTable) .set({ ...data, nextBackupAt, updatedAt: Date.now() }) - .where(eq(backupSchedulesTable.id, scheduleId)) + .where(and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId))) .returning(); if (!updated) { @@ -197,7 +197,9 @@ const deleteSchedule = async (scheduleId: number, organizationId: string) => { throw new NotFoundError("Backup schedule not found"); } - await db.delete(backupSchedulesTable).where(eq(backupSchedulesTable.id, scheduleId)); + await db + .delete(backupSchedulesTable) + .where(and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId))); }; const executeBackup = async (scheduleId: number, organizationId: string, manual = false) => { @@ -220,7 +222,7 @@ const executeBackup = async (scheduleId: number, organizationId: string, manual } const volume = await db.query.volumesTable.findFirst({ - where: eq(volumesTable.id, schedule.volumeId), + where: and(eq(volumesTable.id, schedule.volumeId), eq(volumesTable.organizationId, organizationId)), }); if (!volume) { @@ -228,7 +230,7 @@ const executeBackup = async (scheduleId: number, organizationId: string, manual } const repository = await db.query.repositoriesTable.findFirst({ - where: eq(repositoriesTable.id, schedule.repositoryId), + where: and(eq(repositoriesTable.id, schedule.repositoryId), eq(repositoriesTable.organizationId, organizationId)), }); if (!repository) { @@ -267,7 +269,7 @@ const executeBackup = async (scheduleId: number, organizationId: string, manual lastBackupError: null, nextBackupAt, }) - .where(eq(backupSchedulesTable.id, scheduleId)); + .where(and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId))); const abortController = new AbortController(); runningBackups.set(scheduleId, abortController); @@ -345,7 +347,7 @@ const executeBackup = async (scheduleId: number, organizationId: string, manual nextBackupAt: nextBackupAt, updatedAt: Date.now(), }) - .where(eq(backupSchedulesTable.id, scheduleId)); + .where(and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId))); if (finalStatus === "warning") { logger.warn( @@ -386,7 +388,7 @@ const executeBackup = async (scheduleId: number, organizationId: string, manual lastBackupError: toMessage(error), updatedAt: Date.now(), }) - .where(eq(backupSchedulesTable.id, scheduleId)); + .where(and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId))); serverEvents.emit("backup:completed", { scheduleId, @@ -466,7 +468,7 @@ const stopBackup = async (scheduleId: number, organizationId: string) => { lastBackupError: "Backup was stopped by user", updatedAt: Date.now(), }) - .where(eq(backupSchedulesTable.id, scheduleId)); + .where(and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId))); } }; @@ -722,7 +724,7 @@ const reorderSchedules = async (scheduleIds: number[], organizationId: string) = tx .update(backupSchedulesTable) .set({ sortOrder: index, updatedAt: now }) - .where(eq(backupSchedulesTable.id, scheduleId)), + .where(and(eq(backupSchedulesTable.id, scheduleId), eq(backupSchedulesTable.organizationId, organizationId))), ), ); }); diff --git a/app/server/modules/notifications/notifications.service.ts b/app/server/modules/notifications/notifications.service.ts index aab17716..cb1201af 100644 --- a/app/server/modules/notifications/notifications.service.ts +++ b/app/server/modules/notifications/notifications.service.ts @@ -219,7 +219,9 @@ const updateDestination = async ( const deleteDestination = async (id: number, organizationId: string) => { await getDestination(id, organizationId); - await db.delete(notificationDestinationsTable).where(eq(notificationDestinationsTable.id, id)); + await db + .delete(notificationDestinationsTable) + .where(and(eq(notificationDestinationsTable.id, id), eq(notificationDestinationsTable.organizationId, organizationId))); }; const testDestination = async (id: number, organizationId: string) => { diff --git a/app/server/modules/repositories/repositories.service.ts b/app/server/modules/repositories/repositories.service.ts index 0777781a..3e653791 100644 --- a/app/server/modules/repositories/repositories.service.ts +++ b/app/server/modules/repositories/repositories.service.ts @@ -124,13 +124,13 @@ const createRepository = async ( await db .update(repositoriesTable) .set({ status: "healthy", lastChecked: Date.now(), lastError: null }) - .where(eq(repositoriesTable.id, id)); + .where(and(eq(repositoriesTable.id, id), eq(repositoriesTable.organizationId, organizationId))); return { repository: created, status: 201 }; } const errorMessage = toMessage(error); - await db.delete(repositoriesTable).where(eq(repositoriesTable.id, id)); + await db.delete(repositoriesTable).where(and(eq(repositoriesTable.id, id), eq(repositoriesTable.organizationId, organizationId))); throw new InternalServerError(`Failed to initialize repository: ${errorMessage}`); }; @@ -154,7 +154,9 @@ const deleteRepository = async (id: string, organizationId: string) => { // TODO: Add cleanup logic for the actual restic repository files - await db.delete(repositoriesTable).where(eq(repositoriesTable.id, repository.id)); + await db + .delete(repositoriesTable) + .where(and(eq(repositoriesTable.id, repository.id), eq(repositoriesTable.organizationId, repository.organizationId))); cache.delByPrefix(`snapshots:${repository.id}:`); cache.delByPrefix(`ls:${repository.id}:`); @@ -325,7 +327,7 @@ const checkHealth = async (repositoryId: string, organizationId: string) => { lastChecked: Date.now(), lastError: error, }) - .where(eq(repositoriesTable.id, repository.id)); + .where(and(eq(repositoriesTable.id, repository.id), eq(repositoriesTable.organizationId, repository.organizationId))); return { lastError: error }; } finally { @@ -414,7 +416,7 @@ const doctorRepository = async (id: string, organizationId: string) => { lastChecked: Date.now(), lastError: doctorError, }) - .where(eq(repositoriesTable.id, repository.id)); + .where(and(eq(repositoriesTable.id, repository.id), eq(repositoriesTable.organizationId, repository.organizationId))); return { success: doctorSucceeded, diff --git a/app/server/modules/volumes/volume.service.ts b/app/server/modules/volumes/volume.service.ts index 5eb5415b..3e450e3d 100644 --- a/app/server/modules/volumes/volume.service.ts +++ b/app/server/modules/volumes/volume.service.ts @@ -85,7 +85,7 @@ const createVolume = async (name: string, backendConfig: BackendConfig, organiza await db .update(volumesTable) .set({ status, lastError: error ?? null, lastHealthCheck: Date.now() }) - .where(eq(volumesTable.name, slug)); + .where(and(eq(volumesTable.id, created.id), eq(volumesTable.organizationId, organizationId))); return { volume: created, status: 201 }; }; @@ -101,7 +101,9 @@ const deleteVolume = async (name: string, organizationId: string) => { const backend = createVolumeBackend(volume); await backend.unmount(); - await db.delete(volumesTable).where(eq(volumesTable.name, name)); + await db + .delete(volumesTable) + .where(and(eq(volumesTable.id, volume.id), eq(volumesTable.organizationId, organizationId))); }; const mountVolume = async (name: string, organizationId: string) => { @@ -119,7 +121,7 @@ const mountVolume = async (name: string, organizationId: string) => { await db .update(volumesTable) .set({ status, lastError: error ?? null, lastHealthCheck: Date.now() }) - .where(eq(volumesTable.name, name)); + .where(and(eq(volumesTable.id, volume.id), eq(volumesTable.organizationId, organizationId))); if (status === "mounted") { serverEvents.emit("volume:mounted", { volumeName: name }); @@ -140,7 +142,10 @@ const unmountVolume = async (name: string, organizationId: string) => { const backend = createVolumeBackend(volume); const { status, error } = await backend.unmount(); - await db.update(volumesTable).set({ status }).where(eq(volumesTable.name, name)); + await db + .update(volumesTable) + .set({ status }) + .where(and(eq(volumesTable.id, volume.id), eq(volumesTable.organizationId, organizationId))); if (status === "unmounted") { serverEvents.emit("volume:unmounted", { volumeName: name }); @@ -218,7 +223,7 @@ const updateVolume = async (name: string, volumeData: UpdateVolumeBody, organiza autoRemount: volumeData.autoRemount, updatedAt: Date.now(), }) - .where(eq(volumesTable.id, existing.id)) + .where(and(eq(volumesTable.id, existing.id), eq(volumesTable.organizationId, organizationId))) .returning(); if (!updated) { @@ -231,7 +236,7 @@ const updateVolume = async (name: string, volumeData: UpdateVolumeBody, organiza await db .update(volumesTable) .set({ status, lastError: error ?? null, lastHealthCheck: Date.now() }) - .where(eq(volumesTable.id, existing.id)); + .where(and(eq(volumesTable.id, existing.id), eq(volumesTable.organizationId, organizationId))); serverEvents.emit("volume:updated", { volumeName: updated.name }); } @@ -291,7 +296,7 @@ const checkHealth = async (name: string, organizationId: string) => { await db .update(volumesTable) .set({ lastHealthCheck: Date.now(), status, lastError: error ?? null }) - .where(eq(volumesTable.name, volume.name)); + .where(and(eq(volumesTable.id, volume.id), eq(volumesTable.organizationId, organizationId))); return { status, error }; };