mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: make all hardcoded limits configurable via env vars
- bodyLimit: conditional on MAX_UPLOAD_SIZE_MB (0 = 1GB practical max) - rate limiting: disabled when RATE_LIMIT_PER_MIN=0 - shutdown timeout: 8s → 30s - upload plugin: no fileSize/files cap when env=0 - session duration: configurable via SESSION_DURATION_HOURS (default 168h) - login attempts: configurable via LOGIN_ATTEMPT_LIMIT - batch/pipeline/svg-to-raster: skip guard when MAX_BATCH_SIZE=0 - pipeline steps: configurable via MAX_PIPELINE_STEPS (0 = unlimited) - user-files: remove 200 hard cap - stitch canvas: configurable via MAX_CANVAS_PIXELS (0 = unlimited) - PDF pages: configurable via MAX_PDF_PAGES (0 = unlimited) - SVG size: configurable via MAX_SVG_SIZE_MB (0 = unlimited) - logo size: configurable via MAX_LOGO_SIZE_KB (default 2048) - worker threads: auto-detect via resolveWorkerThreads (0 = auto) - megapixels: skip validation when MAX_MEGAPIXELS=0 - seam carving: remove 1200px dimension cap - concurrency: auto-detect via resolveConcurrency (0 = auto)
This commit is contained in:
@@ -7,6 +7,7 @@ import type { FastifyInstance } from "fastify";
|
||||
import * as mupdf from "mupdf";
|
||||
import sharp from "sharp";
|
||||
import { z } from "zod";
|
||||
import { env } from "../../config.js";
|
||||
import { formatZodErrors } from "../../lib/errors.js";
|
||||
import { encodeHeic } from "../../lib/heic-converter.js";
|
||||
import { createWorkspace } from "../../lib/workspace.js";
|
||||
@@ -229,7 +230,7 @@ export function registerPdfToImage(app: FastifyInstance) {
|
||||
return reply.status(400).send({ error: "Password-protected PDFs are not supported" });
|
||||
}
|
||||
const pageCount = doc.countPages();
|
||||
const maxPages = Math.min(pageCount, 200);
|
||||
const maxPages = env.MAX_PDF_PAGES > 0 ? Math.min(pageCount, env.MAX_PDF_PAGES) : pageCount;
|
||||
const thumbnails: Array<{
|
||||
page: number;
|
||||
dataUrl: string;
|
||||
|
||||
@@ -4,14 +4,13 @@ import { basename, join } from "node:path";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import sharp from "sharp";
|
||||
import { z } from "zod";
|
||||
import { env } from "../../config.js";
|
||||
import { autoOrient } from "../../lib/auto-orient.js";
|
||||
import { formatZodErrors } from "../../lib/errors.js";
|
||||
import { validateImageBuffer } from "../../lib/file-validation.js";
|
||||
import { ensureSharpCompat } from "../../lib/heic-converter.js";
|
||||
import { createWorkspace } from "../../lib/workspace.js";
|
||||
|
||||
const MAX_CANVAS_PIXELS = 100_000_000;
|
||||
|
||||
const settingsSchema = z.object({
|
||||
direction: z.enum(["horizontal", "vertical", "grid"]).default("horizontal"),
|
||||
gridColumns: z.number().int().min(2).max(100).default(2),
|
||||
@@ -180,9 +179,10 @@ export function registerStitch(app: FastifyInstance) {
|
||||
}
|
||||
}
|
||||
|
||||
if (canvasWidth * canvasHeight > MAX_CANVAS_PIXELS) {
|
||||
const maxCanvasPixels = env.MAX_CANVAS_PIXELS > 0 ? env.MAX_CANVAS_PIXELS : Infinity;
|
||||
if (canvasWidth * canvasHeight > maxCanvasPixels) {
|
||||
return reply.status(422).send({
|
||||
error: `Canvas too large: ${canvasWidth}x${canvasHeight} (${Math.round((canvasWidth * canvasHeight) / 1_000_000)}MP exceeds 100MP limit)`,
|
||||
error: `Canvas too large: ${canvasWidth}x${canvasHeight} (${Math.round((canvasWidth * canvasHeight) / 1_000_000)}MP exceeds ${Math.round(maxCanvasPixels / 1_000_000)}MP limit)`,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import PQueue from "p-queue";
|
||||
import sharp from "sharp";
|
||||
import { z } from "zod";
|
||||
import { env } from "../../config.js";
|
||||
import { resolveConcurrency } from "../../lib/env.js";
|
||||
import { formatZodErrors } from "../../lib/errors.js";
|
||||
import { sanitizeFilename } from "../../lib/filename.js";
|
||||
import { decodeHeic, encodeHeic } from "../../lib/heic-converter.js";
|
||||
@@ -135,7 +136,7 @@ export function registerSvgToRaster(app: FastifyInstance) {
|
||||
return reply.status(400).send({ error: "No SVG files provided" });
|
||||
}
|
||||
|
||||
if (files.length > env.MAX_BATCH_SIZE) {
|
||||
if (env.MAX_BATCH_SIZE > 0 && files.length > env.MAX_BATCH_SIZE) {
|
||||
return reply.status(400).send({
|
||||
error: `Too many files. Maximum batch size is ${env.MAX_BATCH_SIZE}`,
|
||||
});
|
||||
@@ -157,7 +158,7 @@ export function registerSvgToRaster(app: FastifyInstance) {
|
||||
}
|
||||
|
||||
const jobId = clientJobId || randomUUID();
|
||||
const queue = new PQueue({ concurrency: env.CONCURRENT_JOBS });
|
||||
const queue = new PQueue({ concurrency: resolveConcurrency(env) });
|
||||
const results: ({ buffer: Buffer; filename: string } | null)[] = new Array(files.length).fill(
|
||||
null,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user