feat(api): add workspace member management endpoints (#556)
Some checks are pending
ci/woodpecker/push/api Pipeline is running

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #556.
This commit is contained in:
2026-02-28 18:01:05 +00:00
committed by jason.woltje
parent 20f914ea85
commit 8388d49786
9 changed files with 718 additions and 8 deletions

View File

@@ -1,9 +1,12 @@
import { Controller, Get, UseGuards } from "@nestjs/common";
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 type { AuthUser } from "@mosaic/shared";
import type { WorkspaceResponseDto } from "./dto";
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 type { AddMemberDto, UpdateMemberRoleDto, WorkspaceResponseDto } from "./dto";
/**
* User-scoped workspace operations.
@@ -22,7 +25,61 @@ export class WorkspacesController {
* Auto-provisions a default workspace if the user has none.
*/
@Get()
async getUserWorkspaces(@CurrentUser() user: AuthUser): Promise<WorkspaceResponseDto[]> {
async getUserWorkspaces(@CurrentUser() user: AuthenticatedUser): Promise<WorkspaceResponseDto[]> {
return this.workspacesService.getUserWorkspaces(user.id);
}
/**
* 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);
}
}