diff --git a/apps/schema-manager/src/schemas/__tests__/schemas.service.spec.ts b/apps/schema-manager/src/schemas/__tests__/schemas.service.spec.ts index 8d91e99bfc4eee6f589870eca88e6f648311b2a6..0c41559ada6e5b472ea7616885e084cdcdea59a7 100644 --- a/apps/schema-manager/src/schemas/__tests__/schemas.service.spec.ts +++ b/apps/schema-manager/src/schemas/__tests__/schemas.service.spec.ts @@ -1,4 +1,5 @@ import type { TestingModule } from '@nestjs/testing'; +import type { EventAnonCredsSchemasRegisterInput } from '@ocm/shared'; import { Test } from '@nestjs/testing'; import { @@ -31,23 +32,20 @@ describe('SchemasService', () => { describe('getAll', () => { it('should return the data from NATS client', (done) => { const unsubscribe$ = new Subject<void>(); - const payload = { - tenantId: 'mocked tenantId', - endpoint: EventAnonCredsSchemasGetAll.token, - }; + const tenantId = 'mocked tenantId'; const expectedResult: EventAnonCredsSchemasGetAll['data'] = []; natsClientMock.send.mockReturnValueOnce( - of(new EventAnonCredsSchemasGetAll([], payload.tenantId)), + of(new EventAnonCredsSchemasGetAll([], tenantId)), ); service - .getAll(payload) + .getAll(tenantId) .pipe(takeUntil(unsubscribe$)) .subscribe((result) => { expect(natsClientMock.send).toHaveBeenCalledWith( - { endpoint: EventAnonCredsSchemasGetAll.token }, - payload, + EventAnonCredsSchemasGetAll.token, + { tenantId }, ); expect(result).toStrictEqual(expectedResult); @@ -63,10 +61,8 @@ describe('SchemasService', () => { describe('getById', () => { it('should return the data from NATS client', (done) => { const unsubscribe$ = new Subject<void>(); - const payload = { - tenantId: 'mocked tenantId', - schemaId: 'mocked id', - }; + const tenantId = 'mocked tenantId'; + const schemaId = 'mocked id'; const expectedResult: EventAnonCredsSchemasGetById['data'] = { issuerId: 'mocked issuerDid', name: 'mocked name', @@ -75,16 +71,16 @@ describe('SchemasService', () => { }; natsClientMock.send.mockReturnValueOnce( - of(new EventAnonCredsSchemasGetById(expectedResult, payload.tenantId)), + of(new EventAnonCredsSchemasGetById(expectedResult, tenantId)), ); service - .getById(payload) + .getById(tenantId, schemaId) .pipe(takeUntil(unsubscribe$)) .subscribe((result) => { expect(natsClientMock.send).toHaveBeenCalledWith( - { endpoint: EventAnonCredsSchemasGetById.token }, - payload, + EventAnonCredsSchemasGetById.token, + { tenantId, schemaId }, ); expect(result).toStrictEqual(expectedResult); @@ -100,31 +96,31 @@ describe('SchemasService', () => { describe('register', () => { it('should return the data from NATS client', (done) => { const unsubscribe$ = new Subject<void>(); - const payload = { - tenantId: 'mocked tenantId', + const tenantId = 'mocked tenantId'; + const payload: Omit<EventAnonCredsSchemasRegisterInput, 'tenantId'> = { issuerDid: 'mocked issuerDid', name: 'mocked name', version: '1.0.0', attributeNames: ['mocked attribute1', 'mocked attribute2'], }; const expectedResult: EventAnonCredsSchemasRegister['data'] = { - issuerId: 'mocked issuerDid', + issuerId: 'mocked issuerId', name: 'mocked name', version: '1.0.0', attrNames: ['mocked attribute1', 'mocked attribute2'], }; natsClientMock.send.mockReturnValueOnce( - of(new EventAnonCredsSchemasRegister(expectedResult, payload.tenantId)), + of(new EventAnonCredsSchemasRegister(expectedResult, tenantId)), ); service - .register(payload) + .register(tenantId, payload) .pipe(takeUntil(unsubscribe$)) .subscribe((result) => { expect(natsClientMock.send).toHaveBeenCalledWith( - { endpoint: EventAnonCredsSchemasRegister.token }, - payload, + EventAnonCredsSchemasRegister.token, + { ...payload, tenantId }, ); expect(result).toStrictEqual(expectedResult); diff --git a/apps/schema-manager/src/schemas/dto/tenant-id.dto.ts b/apps/schema-manager/src/schemas/dto/tenant-id.dto.ts deleted file mode 100644 index 5498941a40eec9bd127a0d50512227c9526d5dcf..0000000000000000000000000000000000000000 --- a/apps/schema-manager/src/schemas/dto/tenant-id.dto.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsString } from 'class-validator'; - -export class TenantIdParam { - @IsString() - @IsNotEmpty() - @ApiProperty({ - description: 'The tenant ID to use for the request', - format: 'string', - }) - public tenantId: string; -} diff --git a/apps/schema-manager/src/schemas/schemas.controller.ts b/apps/schema-manager/src/schemas/schemas.controller.ts index 8c52ef1e7689c995286438c27ac02bfaa5dd6942..2436a2af94d5604b45988374330b9cc50d3ce327 100644 --- a/apps/schema-manager/src/schemas/schemas.controller.ts +++ b/apps/schema-manager/src/schemas/schemas.controller.ts @@ -13,27 +13,24 @@ import { Param, Post, Query, + UseInterceptors, UsePipes, ValidationPipe, Version, } from '@nestjs/common'; -import { - ApiBody, - ApiOperation, - ApiParam, - ApiQuery, - ApiResponse, - ApiTags, -} from '@nestjs/swagger'; +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { MultitenancyParams } from '@ocm/shared'; import { Observable, of, switchMap } from 'rxjs'; +import { ResponseFormatInterceptor } from '../common/response-format.interceptor.js'; + import { GetByIdParams } from './dto/get-by-id.dto.js'; import { RegisterSchemaPayload } from './dto/register-schema.dto.js'; -import { TenantIdParam } from './dto/tenant-id.dto.js'; import { SchemasService } from './schemas.service.js'; -@Controller('schemas') +@Controller() @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) +@UseInterceptors(ResponseFormatInterceptor) @ApiTags('Schemas') export class SchemasController { public constructor(private readonly schemasService: SchemasService) {} @@ -44,34 +41,64 @@ export class SchemasController { summary: 'Fetch a list of schemas', description: 'This call provides a list of schemas for a given tenant', }) - @ApiQuery({ name: 'tenantId', required: true }) @ApiResponse({ status: HttpStatus.OK, description: 'Schemas fetched successfully', content: { - // TBD + 'application/json': { + schema: {}, + examples: { + 'Schemas fetched successfully': { + value: { + statusCode: 200, + message: 'Schemas fetched successfully', + data: [], + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Tenant not found', content: { - // TBD + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error', content: { - // TBD + 'application/json': { + schema: {}, + examples: { + 'Internal server error': { + value: { + statusCode: 500, + message: 'Internal server error', + error: 'Internal Server Error', + }, + }, + }, + }, }, }) public getAll( - @Query() { tenantId }: TenantIdParam, + @Query() { tenantId }: MultitenancyParams, ): Observable<EventAnonCredsSchemasGetAll['data']> { - return this.schemasService.getAll({ - tenantId, - }); + return this.schemasService.getAll(tenantId); } @Version('1') @@ -81,53 +108,92 @@ export class SchemasController { description: 'This call allows you to retrieve schema data for a given tenant by specifying the `schemaId`.', }) - @ApiParam({ name: 'schemaId', required: true }) - @ApiQuery({ name: 'tenantId', required: true }) @ApiResponse({ status: HttpStatus.OK, description: 'Schema fetched successfully', content: { - // TBD + 'application/json': { + schema: {}, + examples: { + 'Schema fetched successfully': { + value: { + statusCode: 200, + message: 'Schema fetched successfully', + data: { + id: '71b784a3', + }, + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Tenant not found', content: { - // TBD + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Schema not found', content: { - // TBD + 'application/json': { + schema: {}, + examples: { + 'Schema not found': { + value: { + statusCode: 404, + message: 'Schema not found', + data: null, + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error', content: { - // TBD + 'application/json': { + schema: {}, + examples: { + 'Internal server error': { + value: { + statusCode: 500, + message: 'Internal server error', + error: 'Internal Server Error', + }, + }, + }, + }, }, }) public getById( @Param() { schemaId }: GetByIdParams, - @Query() { tenantId }: TenantIdParam, + @Query() { tenantId }: MultitenancyParams, ): Observable<EventAnonCredsSchemasGetById['data']> { - return this.schemasService - .getById({ - tenantId, - schemaId, - }) - .pipe( - switchMap((schema) => { - if (schema === null) { - throw new NotFoundException(`Schema with id ${schemaId} not found`); - } - return of(schema); - }), - ); + return this.schemasService.getById(tenantId, schemaId).pipe( + switchMap((schema) => { + if (schema === null) { + throw new NotFoundException(`Schema with id ${schemaId} not found`); + } + return of(schema); + }), + ); } @Version('1') @@ -137,50 +203,102 @@ export class SchemasController { description: 'This call provides the capability to create new schema on ledger by name, author, version, schema attributes and type. Later this schema can be used to issue new credential definition. This call returns an information about created schema.', }) - @ApiQuery({ name: 'tenantId', required: true }) - @ApiBody({ type: RegisterSchemaPayload }) @ApiResponse({ status: HttpStatus.CREATED, description: 'Schema registered successfully', content: { - 'application/json': {}, + 'application/json': { + schema: {}, + examples: { + 'Schema registered successfully': { + value: { + statusCode: 201, + message: 'Schema registered successfully', + data: { + id: '71b784a3', + }, + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Tenant not found', content: { - 'application/json': {}, + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'All fields are required for schema registration', content: { - 'application/json': {}, + 'application/json': { + schema: {}, + examples: { + 'All fields are required for schema registration': { + value: { + statusCode: 400, + message: 'All fields are required for schema registration', + error: 'Bad Request', + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.CONFLICT, description: 'Schema already exists', content: { - 'application/json': {}, + 'application/json': { + schema: {}, + examples: { + 'Schema already exists': { + value: { + statusCode: 409, + message: 'Schema already exists', + error: 'Conflict', + }, + }, + }, + }, }, }) @ApiResponse({ status: HttpStatus.INTERNAL_SERVER_ERROR, description: 'Internal server error', content: { - 'application/json': {}, + 'application/json': { + schema: {}, + examples: { + 'Internal server error': { + value: { + statusCode: 500, + message: 'Internal server error', + error: 'Internal Server Error', + }, + }, + }, + }, }, }) public register( - @Query() { tenantId }: TenantIdParam, + @Query() { tenantId }: MultitenancyParams, @Body() payload: RegisterSchemaPayload, ): Observable<EventAnonCredsSchemasRegister['data']> { - return this.schemasService.register({ - ...payload, - tenantId, - }); + return this.schemasService.register(tenantId, payload); } } diff --git a/apps/schema-manager/src/schemas/schemas.service.ts b/apps/schema-manager/src/schemas/schemas.service.ts index 6a630e99aa9fbce641fabd27a05fc981056809b1..b6fd0cbd9f85ee084e437ef80f845012ac125dc2 100644 --- a/apps/schema-manager/src/schemas/schemas.service.ts +++ b/apps/schema-manager/src/schemas/schemas.service.ts @@ -22,40 +22,36 @@ export class SchemasService { ) {} public getAll( - payload: EventAnonCredsSchemasGetAllInput, + tenantId: string, ): Observable<EventAnonCredsSchemasGetAll['data']> { - const pattern = { endpoint: EventAnonCredsSchemasGetAll.token }; - return this.natsClient .send<EventAnonCredsSchemasGetAll, EventAnonCredsSchemasGetAllInput>( - pattern, - payload, + EventAnonCredsSchemasGetAll.token, + { tenantId }, ) .pipe(map((result) => result.data)); } public getById( - payload: EventAnonCredsSchemasGetByIdInput, + tenantId: string, + schemaId: EventAnonCredsSchemasGetByIdInput['schemaId'], ): Observable<EventAnonCredsSchemasGetById['data']> { - const pattern = { endpoint: EventAnonCredsSchemasGetById.token }; - return this.natsClient .send<EventAnonCredsSchemasGetById, EventAnonCredsSchemasGetByIdInput>( - pattern, - payload, + EventAnonCredsSchemasGetById.token, + { tenantId, schemaId }, ) .pipe(map((result) => result.data)); } public register( - payload: EventAnonCredsSchemasRegisterInput, + tenantId: string, + payload: Omit<EventAnonCredsSchemasRegisterInput, 'tenantId'>, ): Observable<EventAnonCredsSchemasRegister['data']> { - const pattern = { endpoint: EventAnonCredsSchemasRegister.token }; - return this.natsClient .send<EventAnonCredsSchemasRegister, EventAnonCredsSchemasRegisterInput>( - pattern, - payload, + EventAnonCredsSchemasRegister.token, + { ...payload, tenantId }, ) .pipe(map((result) => result.data)); }