fix(api,web): resolve RLS context SQL error, workspace guard crash, and projects response unwrapping #531
@@ -110,10 +110,10 @@ export class WorkspaceGuard implements CanActivate {
|
|||||||
return paramWorkspaceId;
|
return paramWorkspaceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Check request body
|
// 3. Check request body (body may be undefined for GET requests despite Express typings)
|
||||||
const bodyWorkspaceId = request.body.workspaceId;
|
const body = request.body as Record<string, unknown> | undefined;
|
||||||
if (typeof bodyWorkspaceId === "string") {
|
if (body && typeof body.workspaceId === "string") {
|
||||||
return bodyWorkspaceId;
|
return body.workspaceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Check query string (backward compatibility for existing clients)
|
// 4. Check query string (backward compatibility for existing clients)
|
||||||
|
|||||||
@@ -140,8 +140,11 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModul
|
|||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
client: PrismaClient = this
|
client: PrismaClient = this
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await client.$executeRaw`SET LOCAL app.current_user_id = ${userId}`;
|
// Use set_config() instead of SET LOCAL so values are safely parameterized.
|
||||||
await client.$executeRaw`SET LOCAL app.current_workspace_id = ${workspaceId}`;
|
// SET LOCAL with Prisma's tagged template produces invalid SQL (bind parameter $1
|
||||||
|
// is not supported in SET statements by PostgreSQL).
|
||||||
|
await client.$executeRaw`SELECT set_config('app.current_user_id', ${userId}, true)`;
|
||||||
|
await client.$executeRaw`SELECT set_config('app.current_workspace_id', ${workspaceId}, true)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,8 +154,8 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModul
|
|||||||
* @param client - Optional Prisma client (uses 'this' if not provided)
|
* @param client - Optional Prisma client (uses 'this' if not provided)
|
||||||
*/
|
*/
|
||||||
async clearWorkspaceContext(client: PrismaClient = this): Promise<void> {
|
async clearWorkspaceContext(client: PrismaClient = this): Promise<void> {
|
||||||
await client.$executeRaw`SET LOCAL app.current_user_id = NULL`;
|
await client.$executeRaw`SELECT set_config('app.current_user_id', '', true)`;
|
||||||
await client.$executeRaw`SET LOCAL app.current_workspace_id = NULL`;
|
await client.$executeRaw`SELECT set_config('app.current_workspace_id', '', true)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ export interface UpdateProjectDto {
|
|||||||
* Fetch all projects for a workspace
|
* Fetch all projects for a workspace
|
||||||
*/
|
*/
|
||||||
export async function fetchProjects(workspaceId?: string): Promise<Project[]> {
|
export async function fetchProjects(workspaceId?: string): Promise<Project[]> {
|
||||||
return apiGet<Project[]>("/api/projects", workspaceId);
|
const response = await apiGet<{ data: Project[]; meta?: unknown }>("/api/projects", workspaceId);
|
||||||
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user