Files
stack/apps/api/src/workspaces/workspaces.controller.ts
Jason Woltje 023949f1e0
Some checks failed
ci/woodpecker/push/api Pipeline failed
ci/woodpecker/push/orchestrator Pipeline failed
ci/woodpecker/push/web Pipeline failed
fix(api,web): separate workspace context from auth session (#534)
BetterAuth session responses contain only identity fields — workspace
context (workspaceId, currentWorkspaceId) was never returned, causing
"Workspace ID is required" on every guarded endpoint after login.

Add GET /api/workspaces endpoint (AuthGuard only, no WorkspaceGuard)
that returns user workspace memberships with auto-provisioning for
new users. Frontend auth-context now fetches workspaces after session
check and persists the default to localStorage. Race condition in
auto-provisioning is guarded by re-querying inside the transaction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 09:04:15 -06:00

29 lines
1.0 KiB
TypeScript

import { Controller, Get, UseGuards } from "@nestjs/common";
import { WorkspacesService } from "./workspaces.service";
import { AuthGuard } from "../auth/guards/auth.guard";
import { CurrentUser } from "../auth/decorators/current-user.decorator";
import type { AuthUser } from "@mosaic/shared";
import type { WorkspaceResponseDto } from "./dto";
/**
* User-scoped workspace operations.
*
* Intentionally does NOT use WorkspaceGuard — these routes operate across all
* workspaces the user belongs to, not within a single workspace context.
*/
@Controller("workspaces")
@UseGuards(AuthGuard)
export class WorkspacesController {
constructor(private readonly workspacesService: WorkspacesService) {}
/**
* GET /api/workspaces
* Returns workspaces the authenticated user is a member of.
* Auto-provisions a default workspace if the user has none.
*/
@Get()
async getUserWorkspaces(@CurrentUser() user: AuthUser): Promise<WorkspaceResponseDto[]> {
return this.workspacesService.getUserWorkspaces(user.id);
}
}