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:
@@ -3,7 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|||||||
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { db as prodDb } from "@/db/index.ts";
|
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 { getCollectionSummary } from "./resources/collection.ts";
|
||||||
import {
|
import {
|
||||||
categoryToolDefinitions,
|
categoryToolDefinitions,
|
||||||
@@ -90,13 +90,16 @@ mcpRoutes.use("/*", async (c, next) => {
|
|||||||
const db = c.get("db") ?? prodDb;
|
const db = c.get("db") ?? prodDb;
|
||||||
const apiKey = c.req.header("X-API-Key");
|
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);
|
const valid = await verifyApiKey(db, apiKey);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return c.json({ error: "Invalid API key" }, 401);
|
return c.json({ error: "Invalid API key" }, 401);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If no API key header, allow through (unauthenticated access when auth not configured)
|
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -121,8 +121,15 @@ app.put(
|
|||||||
zValidator("json", changePasswordSchema),
|
zValidator("json", changePasswordSchema),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const db = c.get("db");
|
const db = c.get("db");
|
||||||
const sessionId = getCookie(c, COOKIE_NAME)!;
|
const sessionId = getCookie(c, COOKIE_NAME);
|
||||||
const session = getSession(db, sessionId)!;
|
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
|
const userRecord = db
|
||||||
.select()
|
.select()
|
||||||
|
|||||||
@@ -19,7 +19,14 @@ app.post("/from-url", zValidator("json", fromUrlSchema), async (c) => {
|
|||||||
const result = await fetchImageFromUrl(url);
|
const result = await fetchImageFromUrl(url);
|
||||||
return c.json(result, 201);
|
return c.json(result, 201);
|
||||||
} catch (err) {
|
} 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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user