fix: address code review issues — MCP auth, error handling, password route

- MCP auth middleware now rejects requests without API key when users exist
- Image /from-url route distinguishes validation errors (400) from server errors (500)
- Password change route returns 401 when no session cookie instead of crashing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 13:42:34 +02:00
parent ba9662aeaf
commit 17d76761bb
3 changed files with 23 additions and 6 deletions

View File

@@ -3,7 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { Hono } from "hono";
import { db as prodDb } from "@/db/index.ts";
import { verifyApiKey } from "../services/auth.service.ts";
import { getUserCount, verifyApiKey } from "../services/auth.service.ts";
import { getCollectionSummary } from "./resources/collection.ts";
import {
categoryToolDefinitions,
@@ -90,13 +90,16 @@ mcpRoutes.use("/*", async (c, next) => {
const db = c.get("db") ?? prodDb;
const apiKey = c.req.header("X-API-Key");
if (apiKey) {
// Require API key when auth is configured (users exist)
if (getUserCount(db) > 0) {
if (!apiKey) {
return c.json({ error: "API key required" }, 401);
}
const valid = await verifyApiKey(db, apiKey);
if (!valid) {
return c.json({ error: "Invalid API key" }, 401);
}
}
// If no API key header, allow through (unauthenticated access when auth not configured)
return next();
});

View File

@@ -121,8 +121,15 @@ app.put(
zValidator("json", changePasswordSchema),
async (c) => {
const db = c.get("db");
const sessionId = getCookie(c, COOKIE_NAME)!;
const session = getSession(db, sessionId)!;
const sessionId = getCookie(c, COOKIE_NAME);
if (!sessionId) {
return c.json({ error: "Session required for password change" }, 401);
}
const session = getSession(db, sessionId);
if (!session) {
return c.json({ error: "Session required for password change" }, 401);
}
const userRecord = db
.select()

View File

@@ -19,7 +19,14 @@ app.post("/from-url", zValidator("json", fromUrlSchema), async (c) => {
const result = await fetchImageFromUrl(url);
return c.json(result, 201);
} catch (err) {
return c.json({ error: (err as Error).message }, 400);
const message = (err as Error).message;
// Known validation errors from the service
const isValidationError =
message.startsWith("Invalid") ||
message.startsWith("URL must") ||
message.startsWith("File too") ||
message.startsWith("HTTP ");
return c.json({ error: message }, isValidationError ? 400 : 500);
}
});