import { initTRPC } from "@trpc/server"; import type { CreateHTTPContextOptions } from "@trpc/server/adapters/standalone"; import { db } from "./db"; import * as jwt from "jsonwebtoken"; import { Config } from "./config"; import { z } from "zod"; const t = initTRPC.context().create(); export const router = t.router; export const publicProcedure = t.procedure; export const protectedProcedure = t.procedure.use(async (opts) => { const { ctx } = opts; if (ctx.user === undefined) { throw new Error("Unauthorized"); } else { return opts.next({ ctx: { ...ctx, user: ctx.user, }, }); } }); export const verifiedPhone = t.procedure.use(async (opts) => { const { ctx } = opts; if (ctx.phone === undefined) { throw new Error("Unauthorized"); } else { return opts.next({ ctx: { phone: ctx.phone, }, }); } }); type Context = Awaited>; export const createContext = async (opts: CreateHTTPContextOptions) => { const authorizationHeader = opts.req.headers.authorization || ""; const bearerToken = authorizationHeader.split(" ")[1]; const phone = await verifyToken(bearerToken); if (phone !== null) { const user = await db.query.user.findFirst({ where: (user, { eq }) => eq(user.phone, phone), }); return { phone, user: user, }; } else { return { phone: undefined, user: undefined, }; } }; async function verifyToken(token: string): Promise { try { const rs = await new Promise((resolve, reject) => { jwt.verify(token, Config.jwt_secret, (err, decoded) => { if (err) { reject(err); } else { resolve(decoded); } }); }); const data = z .object({ phone: z.string(), }) .safeParse(rs); if (data.success) { return data.data.phone; } else { return null; } } catch (e) { return null; } }