refactor: deny empty names
This commit is contained in:
parent
779542e8bd
commit
138a63780a
4 changed files with 19 additions and 15 deletions
|
|
@ -87,7 +87,7 @@ export const createApp = () => {
|
||||||
|
|
||||||
const { status, message } = handleServiceError(err);
|
const { status, message } = handleServiceError(err);
|
||||||
|
|
||||||
return c.json({ message }, status);
|
return c.json({ message }, status as 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { eq, and, inArray } from "drizzle-orm";
|
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 { db } from "../../db/db";
|
||||||
import {
|
import {
|
||||||
notificationDestinationsTable,
|
notificationDestinationsTable,
|
||||||
|
|
@ -144,7 +144,7 @@ const createDestination = async (name: string, config: NotificationConfig) => {
|
||||||
const trimmedName = name.trim();
|
const trimmedName = name.trim();
|
||||||
|
|
||||||
if (trimmedName.length === 0) {
|
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);
|
const encryptedConfig = await encryptSensitiveFields(config);
|
||||||
|
|
@ -184,7 +184,7 @@ const updateDestination = async (
|
||||||
if (updates.name !== undefined) {
|
if (updates.name !== undefined) {
|
||||||
const trimmedName = updates.name.trim();
|
const trimmedName = updates.name.trim();
|
||||||
if (trimmedName.length === 0) {
|
if (trimmedName.length === 0) {
|
||||||
throw new InternalServerError("Name cannot be empty or whitespace-only");
|
throw new BadRequestError("Name cannot be empty");
|
||||||
}
|
}
|
||||||
updateData.name = trimmedName;
|
updateData.name = trimmedName;
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +195,7 @@ const updateDestination = async (
|
||||||
|
|
||||||
const newConfig = notificationConfigSchema(updates.config || existing.config);
|
const newConfig = notificationConfigSchema(updates.config || existing.config);
|
||||||
if (newConfig instanceof type.errors) {
|
if (newConfig instanceof type.errors) {
|
||||||
throw new InternalServerError("Invalid notification configuration");
|
throw new BadRequestError("Invalid notification configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
const encryptedConfig = await encryptSensitiveFields(newConfig);
|
const encryptedConfig = await encryptSensitiveFields(newConfig);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import * as fs from "node:fs/promises";
|
||||||
import * as os from "node:os";
|
import * as os from "node:os";
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import { and, eq } from "drizzle-orm";
|
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 { db } from "../../db/db";
|
||||||
import { volumesTable } from "../../db/schema";
|
import { volumesTable } from "../../db/schema";
|
||||||
import { cryptoUtils } from "../../utils/crypto";
|
import { cryptoUtils } from "../../utils/crypto";
|
||||||
|
|
@ -66,6 +66,10 @@ const createVolume = async (name: string, backendConfig: BackendConfig) => {
|
||||||
const organizationId = getOrganizationId();
|
const organizationId = getOrganizationId();
|
||||||
const trimmedName = name.trim();
|
const trimmedName = name.trim();
|
||||||
|
|
||||||
|
if (trimmedName.length === 0) {
|
||||||
|
throw new BadRequestError("Volume name cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
const shortId = generateShortId();
|
const shortId = generateShortId();
|
||||||
const encryptedConfig = await encryptSensitiveFields(backendConfig);
|
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;
|
const newName = volumeData.name !== undefined ? volumeData.name.trim() : existing.name;
|
||||||
|
|
||||||
|
if (newName.length === 0) {
|
||||||
|
throw new BadRequestError("Volume name cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
const configChanged =
|
const configChanged =
|
||||||
JSON.stringify(existing.config) !== JSON.stringify(volumeData.config) && volumeData.config !== undefined;
|
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);
|
const newConfig = volumeConfigSchema(volumeData.config || existing.config);
|
||||||
if (newConfig instanceof type.errors) {
|
if (newConfig instanceof type.errors) {
|
||||||
throw new InternalServerError("Invalid volume configuration");
|
throw new BadRequestError("Invalid volume configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
const encryptedConfig = await encryptSensitiveFields(newConfig);
|
const encryptedConfig = await encryptSensitiveFields(newConfig);
|
||||||
|
|
@ -306,7 +314,7 @@ const listFiles = async (idOrShortId: string | number, subPath?: string) => {
|
||||||
const relative = path.relative(volumePath, normalizedPath);
|
const relative = path.relative(volumePath, normalizedPath);
|
||||||
|
|
||||||
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
||||||
throw new InternalServerError("Invalid path");
|
throw new BadRequestError("Invalid path");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
import { ConflictError, NotFoundError } from "http-errors-enhanced";
|
import { HttpError } from "http-errors-enhanced";
|
||||||
import { sanitizeSensitiveData } from "./sanitize";
|
import { sanitizeSensitiveData } from "./sanitize";
|
||||||
|
|
||||||
export const handleServiceError = (error: unknown) => {
|
export const handleServiceError = (error: unknown) => {
|
||||||
if (error instanceof ConflictError) {
|
if (error instanceof HttpError) {
|
||||||
return { message: sanitizeSensitiveData(error.message), status: 409 as const };
|
return { message: sanitizeSensitiveData(error.message), status: error.statusCode };
|
||||||
}
|
|
||||||
|
|
||||||
if (error instanceof NotFoundError) {
|
|
||||||
return { message: sanitizeSensitiveData(error.message), status: 404 as const };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { message: sanitizeSensitiveData(toMessage(error)), status: 500 as const };
|
return { message: sanitizeSensitiveData(toMessage(error)), status: 500 as const };
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue