feat(database): reject soft-deleted databases in single-row lookups

This commit is contained in:
charles-gauthereau
2026-07-05 18:31:52 +02:00
parent 8f2d6f0b01
commit 20636bf6f2
5 changed files with 24 additions and 9 deletions
@@ -2,7 +2,7 @@
import {userAction} from "@/lib/safe-actions/actions";
import {z} from "zod";
import {db} from "@/db";
import {eq} from "drizzle-orm";
import {and, eq, isNull} from "drizzle-orm";
import * as drizzleDb from "@/db";
import {BackupWith, RestorationWith} from "@/db/schema/07_database";
import {getOrganizationChannels} from "@/db/services/notification-channel";
@@ -19,7 +19,10 @@ export const getDatabaseDataAction = userAction
const {databaseId} = parsedInput;
const database = await db.query.database.findFirst({
where: eq(drizzleDb.schemas.database.id, databaseId),
where: and(
eq(drizzleDb.schemas.database.id, databaseId),
isNull(drizzleDb.schemas.database.deletedAt),
),
with: {
project: true,
retentionPolicy: true,
@@ -5,7 +5,7 @@ import {db} from "@/db";
import * as drizzleDb from "@/db";
import {Backup} from "@/db/schema/07_database";
import {v4 as uuidv4} from "uuid";
import {eq} from "drizzle-orm";
import {and, eq, isNull} from "drizzle-orm";
import {z} from "zod";
import {storeBackupFiles} from "@/features/storages/utils/storages.helpers";
import {getFileExtension} from "@/utils/common";
@@ -19,7 +19,10 @@ export const uploadBackupAction = userAction
const databaseId = formData.get("databaseId") as string;
const database = await db.query.database.findFirst({
where: eq(drizzleDb.schemas.database.id, databaseId),
where: and(
eq(drizzleDb.schemas.database.id, databaseId),
isNull(drizzleDb.schemas.database.deletedAt),
),
with: {
project: true,
alertPolicies: true,
@@ -4,7 +4,7 @@ import {ServerActionResult} from "@/types/action-type";
import {z} from "zod";
import {db} from "@/db";
import * as drizzleDb from "@/db";
import {eq, inArray} from "drizzle-orm";
import {and, eq, inArray, isNull} from "drizzle-orm";
import {dispatchStorage} from "@/features/storages/utils/storages.dispatch";
import {v4 as uuidv4} from "uuid";
import {getTodayISODate} from "@/utils/date-formatting";
@@ -24,7 +24,10 @@ export const migrationAction = userAction.schema(
try {
const targetDatabase = await db.query.database.findFirst({
where: eq(drizzleDb.schemas.database.id, targetDatabaseId),
where: and(
eq(drizzleDb.schemas.database.id, targetDatabaseId),
isNull(drizzleDb.schemas.database.deletedAt),
),
with: {
project: true,
retentionPolicy: true,
+5 -2
View File
@@ -1,14 +1,17 @@
import {ApiKeyContextUser} from "@/lib/api-v1/types";
import {getAccessibleDatabaseIds} from "@/lib/api-v1/services/databases";
import {db} from "@/db";
import {eq} from "drizzle-orm";
import {and, eq, isNull} from "drizzle-orm";
import * as drizzleDb from "@/db";
export async function resolveDatabaseAccess(id: string, user: ApiKeyContextUser) {
const accessibleIds = await getAccessibleDatabaseIds(user);
if (accessibleIds.includes(id)) return "ok";
const exists = await db.query.database.findFirst({
where: eq(drizzleDb.schemas.database.id, id),
where: and(
eq(drizzleDb.schemas.database.id, id),
isNull(drizzleDb.schemas.database.deletedAt),
),
columns: { id: true },
});
return exists ? "forbidden" : "not_found";
+4 -1
View File
@@ -44,7 +44,10 @@ export const backupCleanTask = async () => {
try {
const database = await db.query.database.findFirst({
where: eq(drizzleDb.schemas.database.id, backup.databaseId),
where: and(
eq(drizzleDb.schemas.database.id, backup.databaseId),
isNull(drizzleDb.schemas.database.deletedAt),
),
with: {alertPolicies: true},
});
if (database) {