feat: swagger document endpoints

This commit is contained in:
Ahmed Bouhuolia
2025-06-19 21:04:54 +02:00
parent 26c1f118c1
commit 4d52059dba
9 changed files with 218 additions and 14 deletions

View File

@@ -139,6 +139,7 @@ export class AccountsController {
@ApiResponse({
status: 200,
description: 'The account details have been successfully retrieved.',
schema: { $ref: getSchemaPath(AccountResponseDto) },
})
@ApiResponse({ status: 404, description: 'The account not found.' })
@ApiParam({
@@ -147,11 +148,6 @@ export class AccountsController {
type: Number,
description: 'The account id',
})
@ApiResponse({
status: 200,
description: 'The account details have been successfully retrieved.',
schema: { $ref: getSchemaPath(AccountResponseDto) },
})
async getAccount(@Param('id', ParseIntPipe) id: number) {
return this.accountsApplication.getAccount(id);
}

View File

@@ -1,16 +1,25 @@
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import {
ApiTags,
ApiOperation,
ApiResponse,
getSchemaPath,
ApiExtraModels,
} from '@nestjs/swagger';
import { Controller, Get } from '@nestjs/common';
import { DashboardService } from './Dashboard.service';
import { GetDashboardBootMetaResponseDto } from './dtos/GetDashboardBootMetaResponse.dto';
@ApiTags('Dashboard')
@Controller('dashboard')
@ApiExtraModels(GetDashboardBootMetaResponseDto)
export class DashboardController {
constructor(private readonly dashboardService: DashboardService) {}
@ApiOperation({ summary: 'Get dashboard boot metadata' })
@ApiResponse({
status: 200,
description: 'Returns dashboard boot metadata including abilities, features, and cloud status',
description: 'The dashboard details have been successfully retrieved.',
schema: { $ref: getSchemaPath(GetDashboardBootMetaResponseDto) },
})
@Get('boot')
getBootMeta() {

View File

@@ -0,0 +1,64 @@
import { ApiExtraModels, ApiProperty } from '@nestjs/swagger';
class RoleAbilityResponseDto {
@ApiProperty({
description: 'The subject of the ability',
example: 'all',
})
subject: string;
@ApiProperty({
description: 'The action permitted for the subject',
example: 'manage',
})
action: string;
}
class DashboardFeatureResponseDto {
@ApiProperty({
description: 'The name of the feature',
example: 'warehouses',
})
name: string;
@ApiProperty({
description: 'Whether the feature is accessible for the tenant',
example: true,
})
isAccessible: boolean;
@ApiProperty({
description: 'The default accessibility of the feature',
example: false,
})
defaultAccessible: boolean;
}
@ApiExtraModels(RoleAbilityResponseDto, DashboardFeatureResponseDto)
export class GetDashboardBootMetaResponseDto {
@ApiProperty({
description: 'List of abilities for the current user',
type: [RoleAbilityResponseDto],
example: [
{ subject: 'all', action: 'manage' },
{ subject: 'invoices', action: 'read' },
],
})
abilities: RoleAbilityResponseDto[];
@ApiProperty({
description: 'List of features and their accessibility',
type: [DashboardFeatureResponseDto],
example: [
{ name: 'warehouses', isAccessible: true, defaultAccessible: false },
{ name: 'branches', isAccessible: false, defaultAccessible: false },
],
})
features: DashboardFeatureResponseDto[];
@ApiProperty({
description: 'Whether the app is running on Bigcapital Cloud',
example: true,
})
isBigcapitalCloud: boolean;
}

View File

@@ -66,7 +66,7 @@ export class RolesApplication {
* Gets the role permissions schema.
* @returns The role permissions schema.
*/
async getRolePermissionsSchema() {
getRolePermissionsSchema() {
return this.getRolePermissionsSchemaService.getRolePermissionsSchema();
}
}

View File

@@ -19,10 +19,14 @@ import {
ApiResponse,
ApiParam,
ApiBody,
getSchemaPath,
ApiExtraModels,
} from '@nestjs/swagger';
import { RoleResponseDto } from './dtos/RoleResponse.dto';
@ApiTags('Roles')
@Controller('roles')
@ApiExtraModels(RoleResponseDto)
export class RolesController {
constructor(private readonly rolesApp: RolesApplication) {}
@@ -88,14 +92,21 @@ export class RolesController {
description: 'Role permissions schema',
})
async getRolePermissionsSchema() {
const schema = await this.rolesApp.getRolePermissionsSchema();
const schema = this.rolesApp.getRolePermissionsSchema();
return schema;
}
@Get()
@ApiOperation({ summary: 'Get all roles' })
@ApiResponse({ status: HttpStatus.OK, description: 'List of all roles' })
@ApiResponse({
status: HttpStatus.OK,
description: 'List of all roles',
schema: {
type: 'array',
items: { $ref: getSchemaPath(RoleResponseDto) },
},
})
async getRoles() {
const roles = await this.rolesApp.getRoles();
@@ -105,7 +116,13 @@ export class RolesController {
@Get(':id')
@ApiOperation({ summary: 'Get a specific role by ID' })
@ApiParam({ name: 'id', description: 'Role ID' })
@ApiResponse({ status: HttpStatus.OK, description: 'Role details' })
@ApiResponse({
status: HttpStatus.OK,
description: 'Role details',
schema: {
$ref: getSchemaPath(RoleResponseDto),
},
})
async getRole(@Param('id', ParseIntPipe) roleId: number) {
const role = await this.rolesApp.getRole(roleId);

View File

@@ -0,0 +1,67 @@
import { ApiProperty, ApiExtraModels } from '@nestjs/swagger';
import { Type } from 'class-transformer';
// RolePermissionResponseDto
export class RolePermissionResponseDto {
@ApiProperty({
example: 'read',
description: 'The action/ability of the permission',
})
ability: string;
@ApiProperty({
example: 'item',
description: 'The subject of the permission',
})
subject: string;
@ApiProperty({
example: true,
description: 'The value of the permission',
})
value: boolean;
}
@ApiExtraModels(RolePermissionResponseDto)
export class RoleResponseDto {
@ApiProperty({
example: 1,
description: 'Unique identifier of the role',
})
id: number;
@ApiProperty({
example: 'admin',
description: 'The slug of the role',
})
slug: string;
@ApiProperty({
example: 'Administrator',
description: 'The name of the role',
})
name: string;
@ApiProperty({
example: 'Administrator role with all permissions',
description: 'The description of the role',
})
description: string;
@ApiProperty({
example: false,
description: 'Indicates if the role is predefined',
})
predefined: boolean;
@ApiProperty({
type: [RolePermissionResponseDto],
description: 'List of permissions associated with the role',
example: [
{ ability: 'read', subject: 'item', value: true },
{ ability: 'edit', subject: 'item', value: false },
],
})
@Type(() => RolePermissionResponseDto)
permissions: RolePermissionResponseDto[];
}

View File

@@ -1,16 +1,37 @@
import { IsEmail, IsNotEmpty } from 'class-validator';
import { IsEmail, IsNotEmpty, IsString, IsNumber } from 'class-validator';
import { ApiProperty, ApiExtraModels } from '@nestjs/swagger';
@ApiExtraModels()
export class EditUserDto {
@ApiProperty({
description: 'First name of the user',
example: 'John',
})
@IsString()
@IsNotEmpty()
firstName: string;
@ApiProperty({
description: 'Last name of the user',
example: 'Doe',
})
@IsString()
@IsNotEmpty()
lastName: string;
@ApiProperty({
description: 'Email address of the user',
example: 'john.doe@example.com',
})
@IsEmail()
@IsNotEmpty()
email: string;
@ApiProperty({
description: 'Role ID assigned to the user',
example: 2,
})
@IsNumber()
@IsNotEmpty()
roleId: number;
}

View File

@@ -1,26 +1,48 @@
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
import { ApiProperty, ApiExtraModels } from '@nestjs/swagger';
@ApiExtraModels()
export class InviteUserDto {
@ApiProperty({
description: 'First name of the user to invite',
example: 'John',
})
@IsString()
@IsNotEmpty()
firstName: string;
@ApiProperty({
description: 'Last name of the user to invite',
example: 'Doe',
})
@IsString()
@IsNotEmpty()
lastName: string;
@ApiProperty({
description: 'Password for the invited user',
example: 'StrongPassword123!',
})
@IsString()
@IsNotEmpty()
password: string;
}
@ApiExtraModels()
export class SendInviteUserDto {
@ApiProperty({
description: 'Email address of the user to invite',
example: 'john.doe@example.com',
})
@IsString()
@IsNotEmpty()
email: string;
@ApiProperty({
description: 'Role ID to assign to the invited user',
example: 2,
})
@IsNumber()
@IsNotEmpty()
roleId: number;
}
}

View File

@@ -60,6 +60,14 @@ export class WarehousesController {
@Get()
@ApiOperation({ summary: 'Get all warehouses' })
@ApiResponse({
status: 200,
description: 'The warehouses have been successfully retrieved.',
schema: {
type: 'array',
items: { $ref: getSchemaPath(WarehouseResponseDto) },
},
})
getWarehouses() {
return this.warehousesApplication.getWarehouses();
}