forked from EduCraft/curriculum-project-hub
feat(hub): add Feishu OAuth session for org admin
Introduce signed cookie sessions, Feishu web OAuth, requireOrgRole guards, and the first org admin APIs (summary + project settings).
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Map domain / HTTP errors to consistent JSON responses.
|
||||
*/
|
||||
import type { FastifyReply } from "fastify";
|
||||
import { HttpError, sendError } from "./auth/guards.js";
|
||||
|
||||
export async function handleRouteError(reply: FastifyReply, err: unknown): Promise<void> {
|
||||
if (err instanceof HttpError) {
|
||||
await sendError(reply, err.statusCode, err.code, err.message);
|
||||
return;
|
||||
}
|
||||
if (err instanceof Error) {
|
||||
const mapped = mapDomainError(err.message);
|
||||
if (mapped !== null) {
|
||||
await sendError(reply, mapped.statusCode, mapped.code, mapped.message);
|
||||
return;
|
||||
}
|
||||
await sendError(reply, 500, "internal_error", "internal error");
|
||||
return;
|
||||
}
|
||||
await sendError(reply, 500, "internal_error", "internal error");
|
||||
}
|
||||
|
||||
function mapDomainError(message: string): { statusCode: number; code: string; message: string } | null {
|
||||
const lower = message.toLowerCase();
|
||||
if (lower.includes("not found")) {
|
||||
return { statusCode: 404, code: "not_found", message };
|
||||
}
|
||||
if (
|
||||
lower.includes("requires") ||
|
||||
lower.includes("forbidden") ||
|
||||
lower.includes("cannot") ||
|
||||
lower.includes("not an active member") ||
|
||||
lower.includes("refused")
|
||||
) {
|
||||
return { statusCode: 403, code: "forbidden", message };
|
||||
}
|
||||
if (
|
||||
lower.includes("is required") ||
|
||||
lower.includes("already") ||
|
||||
lower.includes("invalid") ||
|
||||
lower.includes("accepts only")
|
||||
) {
|
||||
return { statusCode: 400, code: "bad_request", message };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user