Files
stack/apps/api/src/personalities/personalities.controller.ts
Jason Woltje 78b71a0ecc
All checks were successful
ci/woodpecker/push/api Pipeline was successful
feat(api): implement personalities CRUD API (#537)
Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
2026-02-27 10:42:50 +00:00

128 lines
3.7 KiB
TypeScript

import {
Controller,
Get,
Post,
Patch,
Delete,
Body,
Param,
Query,
UseGuards,
HttpCode,
HttpStatus,
} from "@nestjs/common";
import { AuthGuard } from "../auth/guards/auth.guard";
import { WorkspaceGuard, PermissionGuard } from "../common/guards";
import { Workspace, Permission, RequirePermission } from "../common/decorators";
import { PersonalitiesService } from "./personalities.service";
import { CreatePersonalityDto } from "./dto/create-personality.dto";
import { UpdatePersonalityDto } from "./dto/update-personality.dto";
import { PersonalityQueryDto } from "./dto/personality-query.dto";
import type { PersonalityResponse } from "./entities/personality.entity";
/**
* Controller for personality CRUD endpoints.
* Route: /api/personalities
*
* Guards applied in order:
* 1. AuthGuard - verifies the user is authenticated
* 2. WorkspaceGuard - validates workspace access
* 3. PermissionGuard - checks role-based permissions
*/
@Controller("personalities")
@UseGuards(AuthGuard, WorkspaceGuard, PermissionGuard)
export class PersonalitiesController {
constructor(private readonly personalitiesService: PersonalitiesService) {}
/**
* GET /api/personalities
* List all personalities for the workspace.
* Supports ?isActive=true|false filter.
*/
@Get()
@RequirePermission(Permission.WORKSPACE_ANY)
async findAll(
@Workspace() workspaceId: string,
@Query() query: PersonalityQueryDto
): Promise<{ success: true; data: PersonalityResponse[] }> {
const data = await this.personalitiesService.findAll(workspaceId, query);
return { success: true, data };
}
/**
* GET /api/personalities/default
* Get the default personality for the workspace.
* Must be declared before :id to avoid route conflicts.
*/
@Get("default")
@RequirePermission(Permission.WORKSPACE_ANY)
async findDefault(@Workspace() workspaceId: string): Promise<PersonalityResponse> {
return this.personalitiesService.findDefault(workspaceId);
}
/**
* GET /api/personalities/:id
* Get a single personality by ID.
*/
@Get(":id")
@RequirePermission(Permission.WORKSPACE_ANY)
async findOne(
@Workspace() workspaceId: string,
@Param("id") id: string
): Promise<PersonalityResponse> {
return this.personalitiesService.findOne(workspaceId, id);
}
/**
* POST /api/personalities
* Create a new personality.
*/
@Post()
@HttpCode(HttpStatus.CREATED)
@RequirePermission(Permission.WORKSPACE_MEMBER)
async create(
@Workspace() workspaceId: string,
@Body() dto: CreatePersonalityDto
): Promise<PersonalityResponse> {
return this.personalitiesService.create(workspaceId, dto);
}
/**
* PATCH /api/personalities/:id
* Update an existing personality.
*/
@Patch(":id")
@RequirePermission(Permission.WORKSPACE_MEMBER)
async update(
@Workspace() workspaceId: string,
@Param("id") id: string,
@Body() dto: UpdatePersonalityDto
): Promise<PersonalityResponse> {
return this.personalitiesService.update(workspaceId, id, dto);
}
/**
* DELETE /api/personalities/:id
* Delete a personality.
*/
@Delete(":id")
@HttpCode(HttpStatus.NO_CONTENT)
@RequirePermission(Permission.WORKSPACE_MEMBER)
async delete(@Workspace() workspaceId: string, @Param("id") id: string): Promise<void> {
return this.personalitiesService.delete(workspaceId, id);
}
/**
* POST /api/personalities/:id/set-default
* Convenience endpoint to set a personality as the default.
*/
@Post(":id/set-default")
@RequirePermission(Permission.WORKSPACE_MEMBER)
async setDefault(
@Workspace() workspaceId: string,
@Param("id") id: string
): Promise<PersonalityResponse> {
return this.personalitiesService.setDefault(workspaceId, id);
}
}