Skip to content
Snippets Groups Projects
Verified Commit b2e9f0d2 authored by Konstantin Tsabolov's avatar Konstantin Tsabolov
Browse files

Merge remote-tracking branch 'origin/ssi-proof-functionality' into chore/refactor-proof-manager

parents f43a36af 4cf97f96
No related branches found
No related tags found
No related merge requests found
Showing
with 1021 additions and 64 deletions
......@@ -24,15 +24,13 @@
"test:e2e": "jest --config ./test/jest.config.js"
},
"dependencies": {
"@nestjs/axios": "^3.0.1",
"@nestjs/common": "^10.2.10",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.2.10",
"@nestjs/microservices": "^10.2.10",
"@nestjs/platform-express": "^10.2.8",
"@nestjs/swagger": "^7.1.16",
"@nestjs/terminus": "^10.1.1",
"axios": "^1.6.2",
"@ocm/shared": "workspace:*",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"express": "^4.17.3",
......
import type { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { Application } from '../application.js';
describe('Application', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture = await Test.createTestingModule({
imports: [Application],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
it('should be defined', () => {
expect(app).toBeDefined();
});
});
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { httpConfig } from './config/http.config.js';
import { natsConfig } from './config/nats.config.js';
import { ssiConfig } from './config/ssi.config.js';
import { validationSchema } from './config/validation.js';
import { HealthModule } from './health/health.module.js';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [httpConfig, natsConfig, ssiConfig],
cache: true,
expandVariables: true,
validationSchema,
validationOptions: {
allowUnknown: true,
abortEarly: true,
},
}),
HealthModule,
],
})
export default class AppModule {}
import type { ConfigType } from '@nestjs/config';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { RouterModule } from '@nestjs/core';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { HealthModule } from '@ocm/shared';
import { NATS_CLIENT } from './common/constants.js';
import { httpConfig } from './config/http.config.js';
import { natsConfig } from './config/nats.config.js';
import { ssiConfig } from './config/ssi.config.js';
import { validationSchema } from './config/validation.js';
import { CredentialOffersModule } from './credential-offers/credential-offers.module.js';
import { CredentialRequestsModule } from './credential-requests/credential-requests.module.js';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [httpConfig, natsConfig, ssiConfig],
cache: true,
expandVariables: true,
validationSchema,
validationOptions: {
allowUnknown: true,
abortEarly: true,
},
}),
ClientsModule.registerAsync({
isGlobal: true,
clients: [
{
name: NATS_CLIENT,
inject: [natsConfig.KEY],
useFactory: (config: ConfigType<typeof natsConfig>) => ({
transport: Transport.NATS,
options: {
url: config.url as string,
},
}),
},
],
}),
HealthModule.registerAsync({
inject: [natsConfig.KEY],
useFactory: (config: ConfigType<typeof natsConfig>) => {
const options: Parameters<typeof HealthModule.register>[0] = {};
if (config.monitoringUrl) {
options.nats = {
monitoringUrl: config.monitoringUrl as string,
};
}
return options;
},
}),
CredentialOffersModule,
CredentialRequestsModule,
RouterModule.register([
{ module: HealthModule, path: '/health' },
{ module: CredentialOffersModule, path: '/credential-offers' },
{ module: CredentialRequestsModule, path: '/credential-requests' },
]),
],
})
export class Application {}
export const SERVICE_NAME = 'CREDENTIAL_MANAGER_SERVICE';
export const NATS_CLIENT = Symbol('NATS_CLIENT');
import type { TestingModule } from '@nestjs/testing';
import type {
EventAnonCredsCredentialOfferGetAll,
EventAnonCredsCredentialOfferGetById,
} from '@ocm/shared';
import { Test } from '@nestjs/testing';
import { Subject, of, takeUntil } from 'rxjs';
import { NATS_CLIENT } from '../../common/constants.js';
import { CredentialOffersController } from '../credential-offers.controller.js';
import { CredentialOffersService } from '../credential-offers.service.js';
describe('CredentialOffersController', () => {
const natsClientMock = {};
let controller: CredentialOffersController;
let service: CredentialOffersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [CredentialOffersController],
providers: [
{ provide: NATS_CLIENT, useValue: natsClientMock },
CredentialOffersService,
],
}).compile();
controller = module.get<CredentialOffersController>(
CredentialOffersController,
);
service = module.get<CredentialOffersService>(CredentialOffersService);
});
describe('find', () => {
it('should return a list of credential offers', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'exampleTenantId';
const expectedResult: EventAnonCredsCredentialOfferGetAll['data'] = [];
jest
.spyOn(service, 'findCredentialOffers')
.mockReturnValueOnce(of(expectedResult));
controller
.find({ tenantId })
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
describe('getById', () => {
it('should return a credential offer', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'exampleTenantId';
const credentialOfferId = 'exampleCredentialOfferId';
const expectedResult: EventAnonCredsCredentialOfferGetById['data'] = {
cred_def_id: 'exampleCredDefId',
key_correctness_proof: {},
nonce: 'exampleNonce',
schema_id: 'exampleSchemaId',
};
jest
.spyOn(service, 'getCredentialOfferById')
.mockReturnValueOnce(of(expectedResult));
controller
.getById({ credentialOfferId }, { tenantId })
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
});
import { ClientsModule } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import { NATS_CLIENT } from '../../common/constants.js';
import { CredentialOffersController } from '../credential-offers.controller.js';
import { CredentialOffersModule } from '../credential-offers.module.js';
import { CredentialOffersService } from '../credential-offers.service.js';
describe('CredentialOffersModule', () => {
let credentialOffersController: CredentialOffersController;
let credentialOffersService: CredentialOffersService;
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
imports: [
ClientsModule.registerAsync({
isGlobal: true,
clients: [{ name: NATS_CLIENT, useFactory: () => ({}) }],
}),
CredentialOffersModule,
],
}).compile();
credentialOffersController = moduleRef.get<CredentialOffersController>(
CredentialOffersController,
);
credentialOffersService = moduleRef.get<CredentialOffersService>(
CredentialOffersService,
);
});
it('should be defined', () => {
expect(credentialOffersController).toBeDefined();
expect(credentialOffersController).toBeInstanceOf(
CredentialOffersController,
);
expect(credentialOffersService).toBeDefined();
expect(credentialOffersService).toBeInstanceOf(CredentialOffersService);
});
});
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import {
EventAnonCredsCredentialOfferGetAll,
EventAnonCredsCredentialOfferGetById,
} from '@ocm/shared';
import { Subject, of, takeUntil } from 'rxjs';
import { NATS_CLIENT } from '../../common/constants.js';
import { CredentialOffersService } from '../credential-offers.service.js';
describe('CredentialOffersService', () => {
const natsClientMock = { send: jest.fn() };
let service: CredentialOffersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{ provide: NATS_CLIENT, useValue: natsClientMock },
CredentialOffersService,
],
}).compile();
service = module.get<CredentialOffersService>(CredentialOffersService);
});
describe('findCredentialOffers', () => {
it('should call natsClient.send with the correct arguments', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'tenantId';
const expectedResult: EventAnonCredsCredentialOfferGetAll['data'] = [];
natsClientMock.send.mockReturnValueOnce(
of(new EventAnonCredsCredentialOfferGetAll(expectedResult, tenantId)),
);
service
.findCredentialOffers(tenantId)
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(natsClientMock.send).toHaveBeenCalledWith(
EventAnonCredsCredentialOfferGetAll.token,
{ tenantId },
);
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
describe('getCredentialOfferById', () => {
it('should call natsClient.send with the correct arguments', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'tenantId';
const credentialOfferId = 'id';
const expectedResult: EventAnonCredsCredentialOfferGetById['data'] = {
cred_def_id: 'exampleCredDefId',
key_correctness_proof: {},
nonce: 'exampleNonce',
schema_id: 'exampleSchemaId',
};
natsClientMock.send.mockReturnValueOnce(
of(new EventAnonCredsCredentialOfferGetById(expectedResult, tenantId)),
);
service
.getCredentialOfferById(tenantId, credentialOfferId)
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(natsClientMock.send).toHaveBeenCalledWith(
EventAnonCredsCredentialOfferGetById.token,
{ tenantId, credentialOfferId },
);
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
});
import {
Controller,
Get,
HttpStatus,
Param,
Query,
UseInterceptors,
UsePipes,
ValidationPipe,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { MultitenancyParams, ResponseFormatInterceptor } from '@ocm/shared';
import { CredentialOffersService } from './credential-offers.service.js';
import { GetByIdParams } from './dto/get-by-id.dto.js';
@Controller()
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
@UseInterceptors(ResponseFormatInterceptor)
@ApiTags('Credential Offers')
export class CredentialOffersController {
public constructor(private readonly service: CredentialOffersService) {}
@Get()
@ApiOperation({
summary: 'Fetch a list of credential offers',
description:
'This call provides a list of credential offers for a given tenant',
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Credential offers fetched successfully',
content: {
'application/json': {
schema: {},
examples: {
'Credential offers fetched successfully': {
value: {
statusCode: 200,
message: 'Credential offers fetched successfully',
data: [
{
id: '71b784a3',
},
],
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
content: {
'application/json': {
schema: {},
examples: {
'Credential offer not found': {
value: {
statusCode: 404,
message: 'Credential offer not found',
data: null,
},
},
'Tenant not found': {
value: {
statusCode: 404,
message: 'Tenant not found',
data: null,
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'Something went wrong',
content: {
'application/json': {
schema: {},
examples: {
'Something went wrong': {
value: {
statusCode: 500,
message: 'Something went wrong',
error: 'Internal Server Error',
},
},
},
},
},
})
public find(@Query() { tenantId }: MultitenancyParams) {
return this.service.findCredentialOffers(tenantId);
}
@Get(':credentialOfferId')
@ApiOperation({
summary: 'Fetch a credential offer by ID',
description: 'This call provides a credential offer for a given ID',
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Credential offer fetched successfully',
content: {
'application/json': {
schema: {},
examples: {
'Credential offer fetched successfully': {
value: {
statusCode: 200,
message: 'Credential offer fetched successfully',
data: {
id: '71b784a3',
},
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
content: {
'application/json': {
schema: {},
examples: {
'Credential offer not found': {
value: {
statusCode: 404,
message: 'Credential offer not found',
data: null,
},
},
'Tenant not found': {
value: {
statusCode: 404,
message: 'Tenant not found',
data: null,
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'Something went wrong',
content: {
'application/json': {
schema: {},
examples: {
'Something went wrong': {
value: {
statusCode: 500,
message: 'Something went wrong',
error: 'Internal Server Error',
},
},
},
},
},
})
public getById(
@Param() { credentialOfferId }: GetByIdParams,
@Query() { tenantId }: MultitenancyParams,
) {
return this.service.getCredentialOfferById(tenantId, credentialOfferId);
}
}
import { Module } from '@nestjs/common';
import { CredentialOffersController } from './credential-offers.controller.js';
import { CredentialOffersService } from './credential-offers.service.js';
@Module({
providers: [CredentialOffersService],
controllers: [CredentialOffersController],
})
export class CredentialOffersModule {}
import type {
EventAnonCredsCredentialOfferGetAllInput,
EventAnonCredsCredentialOfferGetByIdInput,
} from '@ocm/shared';
import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import {
EventAnonCredsCredentialOfferGetAll,
EventAnonCredsCredentialOfferGetById,
} from '@ocm/shared';
import { map } from 'rxjs';
import { NATS_CLIENT } from '../common/constants.js';
@Injectable()
export class CredentialOffersService {
public constructor(
@Inject(NATS_CLIENT) private readonly natsClient: ClientProxy,
) {}
public findCredentialOffers(tenantId: string) {
return this.natsClient
.send<
EventAnonCredsCredentialOfferGetAll,
EventAnonCredsCredentialOfferGetAllInput
>(EventAnonCredsCredentialOfferGetAll.token, { tenantId })
.pipe(map(({ data }) => data));
}
public getCredentialOfferById(tenantId: string, credentialOfferId: string) {
return this.natsClient
.send<
EventAnonCredsCredentialOfferGetById,
EventAnonCredsCredentialOfferGetByIdInput
>(EventAnonCredsCredentialOfferGetById.token, {
tenantId,
credentialOfferId,
})
.pipe(map(({ data }) => data));
}
}
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class GetByIdParams {
@IsString()
@IsNotEmpty()
@ApiProperty({
description: 'The credential offer ID to retrieve',
format: 'string',
})
public credentialOfferId: string;
}
import type { TestingModule } from '@nestjs/testing';
import type {
EventAnonCredsCredentialRequestGetAll,
EventAnonCredsCredentialRequestGetById,
} from '@ocm/shared';
import { Test } from '@nestjs/testing';
import { Subject, of, takeUntil } from 'rxjs';
import { NATS_CLIENT } from '../../common/constants.js';
import { CredentialRequestsController } from '../credential-requests.controller.js';
import { CredentialRequestsService } from '../credential-requests.service.js';
describe('CredentialRequestsController', () => {
const natsClientMock = {};
let controller: CredentialRequestsController;
let service: CredentialRequestsService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [CredentialRequestsController],
providers: [
{ provide: NATS_CLIENT, useValue: natsClientMock },
CredentialRequestsService,
],
}).compile();
controller = module.get<CredentialRequestsController>(
CredentialRequestsController,
);
service = module.get<CredentialRequestsService>(CredentialRequestsService);
});
describe('find', () => {
it('should return a list of credential requests', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'exampleTenantId';
const expectedResult: EventAnonCredsCredentialRequestGetAll['data'] = [];
jest
.spyOn(service, 'findCredentialRequests')
.mockReturnValueOnce(of(expectedResult));
controller
.find({ tenantId })
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
describe('getById', () => {
it('should return a credential request', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'exampleTenantId';
const credentialRequestId = 'exampleCredentialRequestId';
const expectedResult: EventAnonCredsCredentialRequestGetById['data'] = {
blinded_ms: {},
blinded_ms_correctness_proof: {},
cred_def_id: 'cred_def_id',
nonce: 'nonce',
entropy: 'entropy',
prover_did: 'prover_did',
};
jest
.spyOn(service, 'getCredentialRequestById')
.mockReturnValueOnce(of(expectedResult));
controller
.getById({ credentialRequestId }, { tenantId })
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
});
import { ClientsModule } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import { NATS_CLIENT } from '../../common/constants.js';
import { CredentialRequestsController } from '../credential-requests.controller.js';
import { CredentialRequestsModule } from '../credential-requests.module.js';
import { CredentialRequestsService } from '../credential-requests.service.js';
describe('CredentialRequestsModule', () => {
let credentialRequestsController: CredentialRequestsController;
let credentialRequestsService: CredentialRequestsService;
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
imports: [
ClientsModule.registerAsync({
isGlobal: true,
clients: [{ name: NATS_CLIENT, useFactory: () => ({}) }],
}),
CredentialRequestsModule,
],
}).compile();
credentialRequestsController = moduleRef.get<CredentialRequestsController>(
CredentialRequestsController,
);
credentialRequestsService = moduleRef.get<CredentialRequestsService>(
CredentialRequestsService,
);
});
it('should be defined', () => {
expect(credentialRequestsController).toBeDefined();
expect(credentialRequestsController).toBeInstanceOf(
CredentialRequestsController,
);
expect(credentialRequestsService).toBeDefined();
expect(credentialRequestsService).toBeInstanceOf(CredentialRequestsService);
});
});
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import { EventAnonCredsCredentialRequestGetAll } from '@ocm/shared';
import { Subject, of, takeUntil } from 'rxjs';
import { NATS_CLIENT } from '../../common/constants.js';
import { CredentialRequestsService } from '../credential-requests.service.js';
describe('CredentialRequestsService', () => {
const natsClientMock = { send: jest.fn() };
let service: CredentialRequestsService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{ provide: NATS_CLIENT, useValue: natsClientMock },
CredentialRequestsService,
],
}).compile();
service = module.get<CredentialRequestsService>(CredentialRequestsService);
});
describe('findCredentialRequests', () => {
it('should call the natsClient send method with the correct arguments', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'tenantId';
const expectedResult: EventAnonCredsCredentialRequestGetAll['data'] = [];
natsClientMock.send.mockReturnValueOnce(
of(new EventAnonCredsCredentialRequestGetAll(expectedResult, tenantId)),
);
service
.findCredentialRequests(tenantId)
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(natsClientMock.send).toHaveBeenCalledWith(
EventAnonCredsCredentialRequestGetAll.token,
{ tenantId },
);
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
describe('getCredentialRequestById', () => {
it('should call the natsClient send method with the correct arguments', (done) => {
const unsubscribe$ = new Subject<void>();
const tenantId = 'tenantId';
const credentialRequestId = 'credentialRequestId';
const expectedResult: EventAnonCredsCredentialRequestGetAll['data'] = [];
natsClientMock.send.mockReturnValueOnce(
of(new EventAnonCredsCredentialRequestGetAll(expectedResult, tenantId)),
);
service
.getCredentialRequestById(tenantId, credentialRequestId)
.pipe(takeUntil(unsubscribe$))
.subscribe((result) => {
expect(natsClientMock.send).toHaveBeenCalledWith(
EventAnonCredsCredentialRequestGetAll.token,
{ tenantId, credentialRequestId },
);
expect(result).toStrictEqual(expectedResult);
unsubscribe$.next();
unsubscribe$.complete();
done();
});
});
});
});
import {
Controller,
Get,
HttpStatus,
Param,
Query,
UseInterceptors,
UsePipes,
ValidationPipe,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { MultitenancyParams, ResponseFormatInterceptor } from '@ocm/shared';
import { CredentialRequestsService } from './credential-requests.service.js';
import { GetByIdParams } from './dto/get-by-id.dto.js';
@Controller()
@UsePipes(new ValidationPipe({ transform: true, whitelist: true }))
@UseInterceptors(ResponseFormatInterceptor)
@ApiTags('Credential Requests')
export class CredentialRequestsController {
public constructor(private readonly service: CredentialRequestsService) {}
@Get()
@ApiOperation({
summary: 'Fetch a list of credential requests',
description:
'This call provides a list of credential requests for a given tenant',
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Credential requests fetched successfully',
content: {
'application/json': {
schema: {},
examples: {
'Credential requests fetched successfully': {
value: {
statusCode: 200,
message: 'Credential requests fetched successfully',
data: [
{
id: '71b784a3',
},
],
},
},
'Tenant not found': {
value: {
statusCode: 404,
message: 'Tenant not found',
data: null,
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
content: {
'application/json': {
schema: {},
examples: {
'Credential request not found': {
value: {
statusCode: 404,
message: 'Credential request not found',
data: null,
},
},
'Tenant not found': {
value: {
statusCode: 404,
message: 'Tenant not found',
data: null,
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'Internal server error',
content: {
'application/json': {
schema: {},
examples: {
'Internal server error': {
value: {
statusCode: 500,
message: 'Internal server error',
data: null,
},
},
},
},
},
})
public find(@Query() { tenantId }: MultitenancyParams) {
return this.service.findCredentialRequests(tenantId);
}
@Get(':id')
@ApiOperation({
summary: 'Fetch a credential request by id',
description:
'This call provides a credential request for a given tenant by id',
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Credential request fetched successfully',
content: {
'application/json': {
schema: {},
examples: {
'Credential request fetched successfully': {
value: {
statusCode: 200,
message: 'Credential request fetched successfully',
data: {
id: '71b784a3',
},
},
},
'Tenant not found': {
value: {
statusCode: 404,
message: 'Tenant not found',
data: null,
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
content: {
'application/json': {
schema: {},
examples: {
'Credential request not found': {
value: {
statusCode: 404,
message: 'Credential request not found',
data: null,
},
},
'Tenant not found': {
value: {
statusCode: 404,
message: 'Tenant not found',
data: null,
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'Internal server error',
content: {
'application/json': {
schema: {},
examples: {
'Internal server error': {
value: {
statusCode: 500,
message: 'Internal server error',
data: null,
},
},
},
},
},
})
public getById(
@Param() { credentialRequestId }: GetByIdParams,
@Query() { tenantId }: MultitenancyParams,
) {
return this.service.getCredentialRequestById(tenantId, credentialRequestId);
}
}
import { Module } from '@nestjs/common';
import { CredentialRequestsController } from './credential-requests.controller.js';
import { CredentialRequestsService } from './credential-requests.service.js';
@Module({
providers: [CredentialRequestsService],
controllers: [CredentialRequestsController],
})
export class CredentialRequestsModule {}
import type {
EventAnonCredsCredentialRequestGetAllInput,
EventAnonCredsCredentialRequestGetById,
EventAnonCredsCredentialRequestGetByIdInput,
} from '@ocm/shared';
import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { EventAnonCredsCredentialRequestGetAll } from '@ocm/shared';
import { map } from 'rxjs';
import { NATS_CLIENT } from '../common/constants.js';
@Injectable()
export class CredentialRequestsService {
public constructor(
@Inject(NATS_CLIENT) private readonly natsClient: ClientProxy,
) {}
public findCredentialRequests(tenantId: string) {
return this.natsClient
.send<
EventAnonCredsCredentialRequestGetAll,
EventAnonCredsCredentialRequestGetAllInput
>(EventAnonCredsCredentialRequestGetAll.token, { tenantId })
.pipe(map(({ data }) => data));
}
public getCredentialRequestById(
tenantId: string,
credentialRequestId: string,
) {
return this.natsClient
.send<
EventAnonCredsCredentialRequestGetById,
EventAnonCredsCredentialRequestGetByIdInput
>(EventAnonCredsCredentialRequestGetAll.token, {
tenantId,
credentialRequestId,
})
.pipe(map(({ data }) => data));
}
}
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class GetByIdParams {
@IsString()
@IsNotEmpty()
@ApiProperty({
description: 'The credential request ID to retrieve',
format: 'string',
})
public credentialRequestId: string;
}
import type { HealthIndicatorFunction } from '@nestjs/terminus';
import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
HealthCheck,
HealthCheckService,
HttpHealthIndicator,
} from '@nestjs/terminus';
@Controller('health')
export class HealthController {
public constructor(
private readonly config: ConfigService,
private readonly health: HealthCheckService,
private readonly http: HttpHealthIndicator,
) {}
@Get()
@HealthCheck()
public check() {
const healthIndicators: HealthIndicatorFunction[] = [];
const natsMonitoringUrl = this.config.get('nats.monitoringUrl');
if (typeof natsMonitoringUrl === 'string') {
healthIndicators.push(() =>
this.http.pingCheck('nats', natsMonitoringUrl),
);
} else {
healthIndicators.push(() => ({ nats: { status: 'down' } }));
}
return this.health.check(healthIndicators);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment