FRE-592: Fix remaining code review blockers and add tests
- Replace in-memory Maps with Drizzle ORM queries for all CRUD operations - Use integer IDs matching SQLite schema instead of UUIDs - Fix scriptId to projectId inconsistency in characters and scenes - Add project ownership verification on all mutation procedures - Make getCharacter/getScene procedures protected (not public) - Proper JWT-based userId validation via context - Add cascade delete for characters/relationships/scenes on project deletion - Add verifyProjectOwnership helper for authorization checks - Rewrite tests with createCallerFactory pattern for tRPC v11 - Use better-sqlite3 for in-memory test database - Split vitest config into separate file from vite config
This commit is contained in:
@@ -13,22 +13,31 @@ const isAuthenticated = t.middleware(({ ctx, next }) => {
|
||||
return next({ ctx: { ...ctx, userId: ctx.userId } });
|
||||
});
|
||||
|
||||
// Middleware for project authorization
|
||||
const hasProjectAccess = t.middleware(({ ctx, next }) => {
|
||||
const projectId = ctx.projectId;
|
||||
if (!projectId) {
|
||||
throw new TRPCError({ code: 'FORBIDDEN', message: 'Project access required' });
|
||||
// Middleware for database access
|
||||
const hasDb = t.middleware(({ ctx, next }) => {
|
||||
if (!ctx.db) {
|
||||
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Database not available' });
|
||||
}
|
||||
return next({ ctx: { ...ctx, projectId } });
|
||||
return next({ ctx: { ...ctx, db: ctx.db } });
|
||||
});
|
||||
|
||||
// Base router
|
||||
export const baseRouter = t.router;
|
||||
|
||||
// Procedure builders
|
||||
export const publicProcedure = t.procedure;
|
||||
export const protectedProcedure = t.procedure.use(isAuthenticated);
|
||||
export const projectProcedure = t.procedure.use(hasProjectAccess);
|
||||
export const publicProcedure = t.procedure.use(hasDb);
|
||||
export const protectedProcedure = t.procedure.use(isAuthenticated).use(hasDb);
|
||||
const hasProjectAccess = t.middleware(({ ctx, next }) => {
|
||||
if (!ctx.projectId) {
|
||||
throw new TRPCError({ code: 'FORBIDDEN', message: 'Project access required' });
|
||||
}
|
||||
return next({ ctx: { ...ctx, projectId: ctx.projectId } });
|
||||
});
|
||||
|
||||
export const projectProcedure = t.procedure
|
||||
.use(isAuthenticated)
|
||||
.use(hasDb)
|
||||
.use(hasProjectAccess);
|
||||
|
||||
// Validation middleware
|
||||
export const validateInput = <T extends z.ZodTypeAny>(schema: T) => {
|
||||
|
||||
Reference in New Issue
Block a user