refactor: deny empty names

This commit is contained in:
Nicolas Meienberger 2026-01-29 20:50:06 +01:00
parent 779542e8bd
commit 138a63780a
4 changed files with 19 additions and 15 deletions

View file

@ -87,7 +87,7 @@ export const createApp = () => {
const { status, message } = handleServiceError(err);
return c.json({ message }, status);
return c.json({ message }, status as 500);
});
return app;

View file

@ -1,5 +1,5 @@
import { eq, and, inArray } from "drizzle-orm";
import { ConflictError, InternalServerError, NotFoundError } from "http-errors-enhanced";
import { BadRequestError, ConflictError, InternalServerError, NotFoundError } from "http-errors-enhanced";
import { db } from "../../db/db";
import {
notificationDestinationsTable,
@ -144,7 +144,7 @@ const createDestination = async (name: string, config: NotificationConfig) => {
const trimmedName = name.trim();
if (trimmedName.length === 0) {
throw new InternalServerError("Name cannot be empty or whitespace-only");
throw new BadRequestError("Name cannot be empty");
}
const encryptedConfig = await encryptSensitiveFields(config);
@ -184,7 +184,7 @@ const updateDestination = async (
if (updates.name !== undefined) {
const trimmedName = updates.name.trim();
if (trimmedName.length === 0) {
throw new InternalServerError("Name cannot be empty or whitespace-only");
throw new BadRequestError("Name cannot be empty");
}
updateData.name = trimmedName;
}
@ -195,7 +195,7 @@ const updateDestination = async (
const newConfig = notificationConfigSchema(updates.config || existing.config);
if (newConfig instanceof type.errors) {
throw new InternalServerError("Invalid notification configuration");
throw new BadRequestError("Invalid notification configuration");
}
const encryptedConfig = await encryptSensitiveFields(newConfig);

View file

@ -2,7 +2,7 @@ import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import { and, eq } from "drizzle-orm";
import { InternalServerError, NotFoundError } from "http-errors-enhanced";
import { BadRequestError, InternalServerError, NotFoundError } from "http-errors-enhanced";
import { db } from "../../db/db";
import { volumesTable } from "../../db/schema";
import { cryptoUtils } from "../../utils/crypto";
@ -66,6 +66,10 @@ const createVolume = async (name: string, backendConfig: BackendConfig) => {
const organizationId = getOrganizationId();
const trimmedName = name.trim();
if (trimmedName.length === 0) {
throw new BadRequestError("Volume name cannot be empty");
}
const shortId = generateShortId();
const encryptedConfig = await encryptSensitiveFields(backendConfig);
@ -184,6 +188,10 @@ const updateVolume = async (idOrShortId: string | number, volumeData: UpdateVolu
const newName = volumeData.name !== undefined ? volumeData.name.trim() : existing.name;
if (newName.length === 0) {
throw new BadRequestError("Volume name cannot be empty");
}
const configChanged =
JSON.stringify(existing.config) !== JSON.stringify(volumeData.config) && volumeData.config !== undefined;
@ -195,7 +203,7 @@ const updateVolume = async (idOrShortId: string | number, volumeData: UpdateVolu
const newConfig = volumeConfigSchema(volumeData.config || existing.config);
if (newConfig instanceof type.errors) {
throw new InternalServerError("Invalid volume configuration");
throw new BadRequestError("Invalid volume configuration");
}
const encryptedConfig = await encryptSensitiveFields(newConfig);
@ -306,7 +314,7 @@ const listFiles = async (idOrShortId: string | number, subPath?: string) => {
const relative = path.relative(volumePath, normalizedPath);
if (relative.startsWith("..") || path.isAbsolute(relative)) {
throw new InternalServerError("Invalid path");
throw new BadRequestError("Invalid path");
}
try {

View file

@ -1,13 +1,9 @@
import { ConflictError, NotFoundError } from "http-errors-enhanced";
import { HttpError } from "http-errors-enhanced";
import { sanitizeSensitiveData } from "./sanitize";
export const handleServiceError = (error: unknown) => {
if (error instanceof ConflictError) {
return { message: sanitizeSensitiveData(error.message), status: 409 as const };
}
if (error instanceof NotFoundError) {
return { message: sanitizeSensitiveData(error.message), status: 404 as const };
if (error instanceof HttpError) {
return { message: sanitizeSensitiveData(error.message), status: error.statusCode };
}
return { message: sanitizeSensitiveData(toMessage(error)), status: 500 as const };