Some checks failed
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
import { Body, Controller, Delete, Get, Param, Patch, Post, 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 { WorkspaceGuard, PermissionGuard } from "../common/guards";
|
|
import { Permission, RequirePermission } from "../common/decorators";
|
|
import type { WorkspaceMember } from "@prisma/client";
|
|
import type { AuthenticatedUser } from "../common/types/user.types";
|
|
import { AddMemberDto, UpdateMemberRoleDto, 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: AuthenticatedUser): Promise<WorkspaceResponseDto[]> {
|
|
return this.workspacesService.getUserWorkspaces(user.id);
|
|
}
|
|
|
|
/**
|
|
* GET /api/workspaces/:workspaceId/stats
|
|
* Returns member, project, and domain counts for a workspace.
|
|
*/
|
|
@Get(":workspaceId/stats")
|
|
async getStats(@Param("workspaceId") workspaceId: string) {
|
|
return this.workspacesService.getStats(workspaceId);
|
|
}
|
|
|
|
/**
|
|
* GET /api/workspaces/:workspaceId/members
|
|
* Returns the list of members for a workspace.
|
|
*/
|
|
@Get(":workspaceId/members")
|
|
@UseGuards(WorkspaceGuard)
|
|
async getMembers(@Param("workspaceId") workspaceId: string) {
|
|
return this.workspacesService.getMembers(workspaceId);
|
|
}
|
|
|
|
/**
|
|
* POST /api/workspaces/:workspaceId/members
|
|
* Add a member to a workspace with the specified role.
|
|
* Requires: ADMIN role or higher.
|
|
*/
|
|
@Post(":workspaceId/members")
|
|
@UseGuards(WorkspaceGuard, PermissionGuard)
|
|
@RequirePermission(Permission.WORKSPACE_ADMIN)
|
|
async addMember(
|
|
@Param("workspaceId") workspaceId: string,
|
|
@Body() addMemberDto: AddMemberDto,
|
|
@CurrentUser() user: AuthenticatedUser
|
|
): Promise<WorkspaceMember> {
|
|
return this.workspacesService.addMember(workspaceId, user.id, addMemberDto);
|
|
}
|
|
|
|
/**
|
|
* PATCH /api/workspaces/:workspaceId/members/:userId
|
|
* Change a member role in a workspace.
|
|
* Requires: ADMIN role or higher.
|
|
*/
|
|
@Patch(":workspaceId/members/:userId")
|
|
@UseGuards(WorkspaceGuard, PermissionGuard)
|
|
@RequirePermission(Permission.WORKSPACE_ADMIN)
|
|
async updateMemberRole(
|
|
@Param("workspaceId") workspaceId: string,
|
|
@Param("userId") targetUserId: string,
|
|
@Body() updateMemberRoleDto: UpdateMemberRoleDto,
|
|
@CurrentUser() user: AuthenticatedUser
|
|
): Promise<WorkspaceMember> {
|
|
return this.workspacesService.updateMemberRole(
|
|
workspaceId,
|
|
user.id,
|
|
targetUserId,
|
|
updateMemberRoleDto
|
|
);
|
|
}
|
|
|
|
/**
|
|
* DELETE /api/workspaces/:workspaceId/members/:userId
|
|
* Remove a member from a workspace.
|
|
* Requires: ADMIN role or higher.
|
|
*/
|
|
@Delete(":workspaceId/members/:userId")
|
|
@UseGuards(WorkspaceGuard, PermissionGuard)
|
|
@RequirePermission(Permission.WORKSPACE_ADMIN)
|
|
async removeMember(
|
|
@Param("workspaceId") workspaceId: string,
|
|
@Param("userId") targetUserId: string,
|
|
@CurrentUser() user: AuthenticatedUser
|
|
): Promise<void> {
|
|
await this.workspacesService.removeMember(workspaceId, user.id, targetUserId);
|
|
}
|
|
}
|