refactor: migrate backend to pnpm monorepo with Hono module architecture
- Replace Bun with pnpm 9 + Turborepo + tsx; apps/api renamed to apps/backend - Split backend into http/, modules/, lib/ layers mirroring tai-specguard - Add use-case + Result pattern, Problem Details RFC 7807, basePath /api/v1 - Mount Better Auth at /api/v1/auth, keep session-auth whitelist - Split Prisma schema into prisma/models/*, generate into generated/ - Rework packages/shared into lib/ + schemas/ with pagination DTOs - Implement health, groups, students, payments, waitlist modules - Add vitest suite with prisma mocks (21 tests), biome lint - Point web client to /api/v1/auth and /api/v1/groups/from-organization
This commit is contained in:
43
apps/backend/src/http/session-auth.ts
Normal file
43
apps/backend/src/http/session-auth.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { MiddlewareHandler } from 'hono';
|
||||
import { auth } from '@/modules/auth/auth';
|
||||
import type { BackendEnv } from './env';
|
||||
import { problemJson, unauthorizedProblem } from './problem-details';
|
||||
|
||||
export const sessionAuthMiddleware: MiddlewareHandler<BackendEnv> = async (c, next) => {
|
||||
if (isPublicApiRequest(c.req.method, c.req.path)) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
const session = await auth.api.getSession({ headers: c.req.raw.headers });
|
||||
if (!session) {
|
||||
return problemJson(c, unauthorizedProblem(c.req.path));
|
||||
}
|
||||
|
||||
c.set('user', session.user);
|
||||
c.set('session', session.session);
|
||||
|
||||
await next();
|
||||
};
|
||||
|
||||
export function isPublicApiRequest(method: string, path: string): boolean {
|
||||
if (method === 'OPTIONS') {
|
||||
return true;
|
||||
}
|
||||
|
||||
const normalizedPath = normalizePath(path);
|
||||
|
||||
return (
|
||||
normalizedPath === '/api/v1/health'
|
||||
|| matchesPublicPrefix(normalizedPath, '/api/v1/auth')
|
||||
|| matchesPublicPrefix(normalizedPath, '/api/auth')
|
||||
);
|
||||
}
|
||||
|
||||
function matchesPublicPrefix(path: string, prefix: string): boolean {
|
||||
return path === prefix || path.startsWith(`${prefix}/`);
|
||||
}
|
||||
|
||||
function normalizePath(path: string): string {
|
||||
return path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path;
|
||||
}
|
||||
Reference in New Issue
Block a user