tRPC Authorization 미들웨어 구현

This commit is contained in:
static
2025-12-25 16:50:41 +09:00
parent 7779910949
commit 640e12d2c3
4 changed files with 109 additions and 38 deletions

View File

@@ -1,9 +1,25 @@
import type { RequestEvent } from "@sveltejs/kit";
import { initTRPC } from "@trpc/server";
import { initTRPC, TRPCError } from "@trpc/server";
import { authorizeMiddleware, authorizeClientMiddleware } from "./middlewares/authorize";
export const createContext = (event: RequestEvent) => event;
const t = initTRPC.context<Awaited<ReturnType<typeof createContext>>>().create();
export const t = initTRPC.context<Awaited<ReturnType<typeof createContext>>>().create();
export const router = t.router;
export const publicProcedure = t.procedure;
const authedProcedure = publicProcedure.use(async ({ ctx, next }) => {
if (!ctx.locals.session) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next();
});
export const roleProcedure = {
any: authedProcedure.use(authorizeMiddleware("any")),
notClient: authedProcedure.use(authorizeMiddleware("notClient")),
anyClient: authedProcedure.use(authorizeClientMiddleware("anyClient")),
pendingClient: authedProcedure.use(authorizeClientMiddleware("pendingClient")),
activeClient: authedProcedure.use(authorizeClientMiddleware("activeClient")),
};

View File

@@ -0,0 +1,36 @@
import { TRPCError } from "@trpc/server";
import {
AuthorizationError,
authorizeInternal,
type ClientSession,
type SessionPermission,
} from "$lib/server/modules/auth";
import { t } from "../init.server";
const authorize = async (locals: App.Locals, requiredPermission: SessionPermission) => {
try {
return await authorizeInternal(locals, requiredPermission);
} catch (e) {
if (e instanceof AuthorizationError) {
throw new TRPCError({
code: e.status === 403 ? "FORBIDDEN" : "INTERNAL_SERVER_ERROR",
message: e.message,
});
}
throw e;
}
};
export const authorizeMiddleware = (requiredPermission: "any" | "notClient") =>
t.middleware(async ({ ctx, next }) => {
const session = await authorize(ctx.locals, requiredPermission);
return next({ ctx: { session } });
});
export const authorizeClientMiddleware = (
requiredPermission: "anyClient" | "pendingClient" | "activeClient",
) =>
t.middleware(async ({ ctx, next }) => {
const session = (await authorize(ctx.locals, requiredPermission)) as ClientSession;
return next({ ctx: { session } });
});