diff --git a/packages/server/src/modules/Accounts/Accounts.controller.ts b/packages/server/src/modules/Accounts/Accounts.controller.ts index a9a6b0e88..8cb887027 100644 --- a/packages/server/src/modules/Accounts/Accounts.controller.ts +++ b/packages/server/src/modules/Accounts/Accounts.controller.ts @@ -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); } diff --git a/packages/server/src/modules/Dashboard/Dashboard.controller.ts b/packages/server/src/modules/Dashboard/Dashboard.controller.ts index 0d7634ec4..ae0d3e4b0 100644 --- a/packages/server/src/modules/Dashboard/Dashboard.controller.ts +++ b/packages/server/src/modules/Dashboard/Dashboard.controller.ts @@ -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() { diff --git a/packages/server/src/modules/Dashboard/dtos/GetDashboardBootMetaResponse.dto.ts b/packages/server/src/modules/Dashboard/dtos/GetDashboardBootMetaResponse.dto.ts new file mode 100644 index 000000000..9f65e8356 --- /dev/null +++ b/packages/server/src/modules/Dashboard/dtos/GetDashboardBootMetaResponse.dto.ts @@ -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; +} diff --git a/packages/server/src/modules/Roles/Roles.application.ts b/packages/server/src/modules/Roles/Roles.application.ts index 296854f12..5523d7b96 100644 --- a/packages/server/src/modules/Roles/Roles.application.ts +++ b/packages/server/src/modules/Roles/Roles.application.ts @@ -66,7 +66,7 @@ export class RolesApplication { * Gets the role permissions schema. * @returns The role permissions schema. */ - async getRolePermissionsSchema() { + getRolePermissionsSchema() { return this.getRolePermissionsSchemaService.getRolePermissionsSchema(); } } diff --git a/packages/server/src/modules/Roles/Roles.controller.ts b/packages/server/src/modules/Roles/Roles.controller.ts index b1e68aad0..a80accf12 100644 --- a/packages/server/src/modules/Roles/Roles.controller.ts +++ b/packages/server/src/modules/Roles/Roles.controller.ts @@ -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); diff --git a/packages/server/src/modules/Roles/dtos/RoleResponse.dto.ts b/packages/server/src/modules/Roles/dtos/RoleResponse.dto.ts new file mode 100644 index 000000000..8a519740e --- /dev/null +++ b/packages/server/src/modules/Roles/dtos/RoleResponse.dto.ts @@ -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[]; +} diff --git a/packages/server/src/modules/UsersModule/dtos/EditUser.dto.ts b/packages/server/src/modules/UsersModule/dtos/EditUser.dto.ts index cd67b8acb..27caecbc7 100644 --- a/packages/server/src/modules/UsersModule/dtos/EditUser.dto.ts +++ b/packages/server/src/modules/UsersModule/dtos/EditUser.dto.ts @@ -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; } diff --git a/packages/server/src/modules/UsersModule/dtos/InviteUser.dto.ts b/packages/server/src/modules/UsersModule/dtos/InviteUser.dto.ts index e3e9dffa7..302997c5b 100644 --- a/packages/server/src/modules/UsersModule/dtos/InviteUser.dto.ts +++ b/packages/server/src/modules/UsersModule/dtos/InviteUser.dto.ts @@ -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; -} \ No newline at end of file +} diff --git a/packages/server/src/modules/Warehouses/Warehouses.controller.ts b/packages/server/src/modules/Warehouses/Warehouses.controller.ts index dc529b38d..848ba273c 100644 --- a/packages/server/src/modules/Warehouses/Warehouses.controller.ts +++ b/packages/server/src/modules/Warehouses/Warehouses.controller.ts @@ -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(); }