diff --git a/frontends/nextjs/src/app/api/v1/[...slug]/route.ts b/frontends/nextjs/src/app/api/v1/[...slug]/route.ts index e4019ba44..c002c097c 100644 --- a/frontends/nextjs/src/app/api/v1/[...slug]/route.ts +++ b/frontends/nextjs/src/app/api/v1/[...slug]/route.ts @@ -54,7 +54,7 @@ async function handleRequest( const { route, operation, dbalOp } = context // 2. Get current user session (may be null for public routes) - const { user } = getSessionUser() + const { user } = await getSessionUser() // 3. Validate package exists and user has required level const packageResult = validatePackageRoute(route.package, route.entity, user) diff --git a/frontends/nextjs/src/lib/routing/index.ts b/frontends/nextjs/src/lib/routing/index.ts index 9bdbef3a9..77b3200db 100644 --- a/frontends/nextjs/src/lib/routing/index.ts +++ b/frontends/nextjs/src/lib/routing/index.ts @@ -67,9 +67,34 @@ export interface SessionUser { user: Record | null } -export function getSessionUser(_req?: Request): SessionUser { - // TODO: Implement session user retrieval - return { user: null } +export async function getSessionUser(_req?: Request): Promise { + try { + // Use fetchSession to get current user from cookies + const { fetchSession } = await import('@/lib/auth/api/fetch-session') + const user = await fetchSession() + + if (user === null) { + return { user: null } + } + + // Convert User to Record for compatibility + return { + user: { + id: user.id, + username: user.username, + email: user.email, + role: user.role, + tenantId: user.tenantId ?? null, + createdAt: user.createdAt, + profilePicture: user.profilePicture ?? null, + bio: user.bio ?? null, + isInstanceOwner: user.isInstanceOwner ?? false, + } + } + } catch (error) { + console.error('Error getting session user:', error) + return { user: null } + } } export interface RestfulContext { @@ -85,11 +110,70 @@ export interface RestfulContext { } export function parseRestfulRequest( - _req: Request, - _params: { slug: string[] } + req: Request, + params: { slug: string[] } ): RestfulContext | { error: string; status: number } { - // TODO: Implement RESTful request parsing - return { error: 'Not implemented', status: 500 } + const { slug } = params + const method = req.method + + // Validate minimum path segments: tenant, package, entity + if (slug.length < 3) { + return { + error: 'Invalid route: expected /api/v1/{tenant}/{package}/{entity}[/{id}[/{action}]]', + status: STATUS.BAD_REQUEST + } + } + + const [tenant, packageId, entity, id, action] = slug + + if (tenant === undefined || tenant.length === 0) { + return { error: 'Tenant is required', status: STATUS.BAD_REQUEST } + } + + if (packageId === undefined || packageId.length === 0) { + return { error: 'Package is required', status: STATUS.BAD_REQUEST } + } + + if (entity === undefined || entity.length === 0) { + return { error: 'Entity is required', status: STATUS.BAD_REQUEST } + } + + // Determine operation from HTTP method and path structure + let operation = 'unknown' + + if (action !== undefined && action.length > 0) { + // Custom action like POST /posts/123/like + operation = action + } else if (id !== undefined && id.length > 0) { + // Operation on specific record + if (method === 'GET') operation = 'read' + else if (method === 'PUT' || method === 'PATCH') operation = 'update' + else if (method === 'DELETE') operation = 'delete' + } else { + // Collection operation + if (method === 'GET') operation = 'list' + else if (method === 'POST') operation = 'create' + } + + // Build DBAL operation object + const dbalOp = { + entity, + operation, + id, + action, + } + + return { + route: { + tenant, + package: packageId, + entity, + id, + action, + }, + operation, + dbalOp, + } } export function executeDbalOperation(