feat: add tools:use permission check to tool, batch, pipeline, and upload routes

This commit is contained in:
Siddharth Kumar Sah
2026-04-10 21:25:30 +08:00
parent 49431772ec
commit 885ace54f0
5 changed files with 254 additions and 13 deletions
+4
View File
@@ -16,6 +16,7 @@ import { autoOrient } from "../lib/auto-orient.js";
import { validateImageBuffer } from "../lib/file-validation.js";
import { sanitizeFilename } from "../lib/filename.js";
import { decodeHeic } from "../lib/heic-converter.js";
import { requirePermission } from "../permissions.js";
import { type JobProgress, updateJobProgress } from "./progress.js";
import { getToolConfig } from "./tool-factory.js";
@@ -28,6 +29,9 @@ export async function registerBatchRoutes(app: FastifyInstance): Promise<void> {
app.post(
"/api/v1/tools/:toolId/batch",
async (request: FastifyRequest<{ Params: { toolId: string } }>, reply: FastifyReply) => {
const user = requirePermission("tools:use")(request, reply);
if (!user) return;
const { toolId } = request.params;
// Look up the tool config from the registry
+4
View File
@@ -5,6 +5,7 @@ import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import { validateImageBuffer } from "../lib/file-validation.js";
import { sanitizeFilename } from "../lib/filename.js";
import { createWorkspace, getWorkspacePath } from "../lib/workspace.js";
import { requirePermission } from "../permissions.js";
/**
* Guard against path traversal in URL params.
@@ -21,6 +22,9 @@ function isPathTraversal(segment: string): boolean {
export async function fileRoutes(app: FastifyInstance): Promise<void> {
// ── POST /api/v1/upload ────────────────────────────────────────
app.post("/api/v1/upload", async (request: FastifyRequest, reply: FastifyReply) => {
const user = requirePermission("tools:use")(request, reply);
if (!user) return;
const jobId = randomUUID();
const workspacePath = await createWorkspace(jobId);
const inputDir = join(workspacePath, "input");
+4
View File
@@ -17,6 +17,7 @@ import { validateImageBuffer } from "../lib/file-validation.js";
import { sanitizeFilename } from "../lib/filename.js";
import { decodeHeic } from "../lib/heic-converter.js";
import { createWorkspace } from "../lib/workspace.js";
import { requirePermission } from "../permissions.js";
import { requireAuth } from "../plugins/auth.js";
import { getRegisteredToolIds, getToolConfig } from "./tool-factory.js";
@@ -57,6 +58,9 @@ export async function registerPipelineRoutes(app: FastifyInstance): Promise<void
* Returns the final processed image for download.
*/
app.post("/api/v1/pipeline/execute", async (request: FastifyRequest, reply: FastifyReply) => {
const user = requirePermission("tools:use")(request, reply);
if (!user) return;
let fileBuffer: Buffer | null = null;
let filename = "image";
let pipelineRaw: string | null = null;
+4
View File
@@ -14,6 +14,7 @@ import type { WorkerInput, WorkerOutput } from "../lib/image-worker.js";
import { sanitizeSvg } from "../lib/svg-sanitize.js";
import { getWorkerPool } from "../lib/worker-pool.js";
import { createWorkspace } from "../lib/workspace.js";
import { requirePermission } from "../permissions.js";
export interface ToolRouteConfig<T> {
/** Unique tool identifier, used as the URL path segment. */
@@ -102,6 +103,9 @@ export function createToolRoute<T>(app: FastifyInstance, config: ToolRouteConfig
app.post(
`/api/v1/tools/${config.toolId}`,
async (request: FastifyRequest, reply: FastifyReply) => {
const user = requirePermission("tools:use")(request, reply);
if (!user) return;
let fileBuffer: Buffer | null = null;
let filename = "image";
let settingsRaw: string | null = null;