Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • eclipse/xfsc/ocm/ocm-engine
  • zdravko61/ocm-engine
  • mjuergenscg/ocm-engine
  • tsabolov/ocm-engine
  • mikesell/ocm-engine
5 results
Show changes
Showing
with 0 additions and 1195 deletions
image:
repository: registry.gitlab.com/gaia-x/data-infrastructure-federation-services/ocm
# -- Image name
name: attestation-manager
attestationManager:
url:
tsa: https://tsa.gxfs.dev/policy/policy/example
connectionManager: https://ocm.gxfs.dev/connection
attestationManager: https://ocm.gxfs.dev/attestation
database:
host: vereign-database1-postgres.gxfs-vereign
user: ENC[AES256_GCM,data:mk+oOKURENM=,iv:COwKJMsdTq5rk0L6bgooO2ZfTUlc1s16KWfPOGlJ1lo=,tag:5OXJ6l8DCvOUhinh922IAw==,type:str]
password: ENC[AES256_GCM,data:2DRvp3NP2KWDABEjRFqlfVPwtxsooDJW357jmJ7KEFURlubs3DGbce+5wLLhG8XbpdFZhCFEoNZivREa4LwhIw==,iv:3hqOlGqAT5/g52nSnqa8/ydUprOtWThT4lcoysmy11Q=,tag:0ZWS2zf5/huwhq9KO2HjoQ==,type:str]
db: vereign-database1-postgres
ingress:
frontendDomain: ocm.gxfs.dev
frontendTlsSecretName: wildcard-gxfs-dev
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1nrk70nevtmrcgzjunsed43ar6dk3e06qt7tryqqprj9axv4e0djqa0n0cg
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBySXY3dzljdWdyamFLNkFW
WHNqeGY3Q09WNnd2blJiTDhhVzdKQ0hjalgwCjR3RGZMdHFyM1lhQXdhcnN5SVE0
NnBwMzlVY2xwTzFQNE5VR3QybnpLb28KLS0tIHU4QVZZRWViNlVKQzg0YVBQWVI5
S3J1amdkVGhBUzhHOEJmWThSbVFNdm8KsBA7cO4f2Zmym8SoIXAzNw0uxaxfDWg9
ryyxpwCjSQD2kuOw9epK/J7DpCkpAmipQSNvmU5ZiNnq9VzdQ8WGEA==
-----END AGE ENCRYPTED FILE-----
lastmodified: '2022-08-04T11:06:04Z'
mac: ENC[AES256_GCM,data:MdbVIQyR5s4efjMB1MIiOJZOueS0R1F4xvoaHEUoWaQ/bIWa3Km/CBijCI4+zqM54tZ3Zs+kMLK0FdHd+TpSujY2Jg6U8JqRHnA4cUEcr1el5pnhqo3lLiSmZXhGJaO9mlPoE/IVDdlrDXgRwexnznvyJn5RUpK1KdTsAU02wBI=,iv:EdCTlV7CDJikksz0HoiShKhKCO6LsOGsTk6GQalw6QA=,tag:QCbYT1Wr3KwcgmR70Qxlvg==,type:str]
pgp: []
encrypted_regex: ^(password|user)$
version: 3.7.3
# -- Default number of instances to start
replicaCount: 1
# -- Application name
name: ssi-abstraction
# -- Ovverwrites application name
nameOverride: ''
image:
repository: eu.gcr.io/vrgn-infra-prj
# -- Image name
name: gaiax/attestation-manager
# -- Image tag
# Uses .Chart.AppVersion if empty
tag: ''
# -- Image sha, usually generated by the CI
# Uses image.tag if empty
sha: ''
# -- Image pull policy
pullPolicy: IfNotPresent
# -- Image pull secret when internal image is used
pullSecrets: deployment-key-light
podAnnotations: {}
##
## Pass extra environment variables to the container.
##
# extraVars:
# - name: EXTRA_VAR_1
# value: extra-var-value-1
# - name: EXTRA_VAR_2
# value: extra-var-value-2
##
## Create new service when true, and use the specified uner name when set to the name specified
##
resources:
requests:
cpu: 25m
memory: 64Mi
limits:
cpu: 150m
memory: 128Mi
## Configure pod autoscaling
##
autoscaling:
# -- Enable autoscaling
enabled: false
# -- Minimum replicas
minReplicas: 1
# -- Maximum replicas
maxReplicas: 3
# -- CPU target for autoscaling trigger
targetCPUUtilizationPercentage: 70
# -- Memory target for autoscaling trigger
targetMemoryUtilizationPercentage: 70
##
## Prometheus Exporter / Metrics
##
metrics:
# -- Enable prometheus metrics
enabled: true
# -- Port for prometheus metrics
port: 2112
log:
level: 'INFO'
encoding: json
##
## Kubernetes [SecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) object.
##
security:
# -- by default, apps run as non-root
runAsNonRoot: false
# -- User used by the apps
runAsUid: 0
# -- Group used by the apps
runAsGid: 0
##
##
service:
port: 3005
attestationManager:
acceptMembershipCredentialsConfig: AUTO
agent:
host: ssi-abstraction
protocol: http
port: 3010
database:
host: postgresql-postgresql-ha-postgresql.infra
user: ocm_attestation_manager
password: ocm_attestation_manager
port: 5432
schema: attestation
db: ocm_attestation_manager
nats:
url: nats
port: 4222
protocol: nats
elastic:
url: elasticsearch
port: 9200
protocol: http
url:
tsa: https://gaiax.vereign.com/tsa/policy/policy/example
connectionManager: https://gaiax.vereign.com/ocm/connection
attestationManager: https://gaiax.vereign.com/ocm/attestation
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
tlsEnabled: true
frontendDomain: gaiax.vereign.com
frontendTlsSecretName: cert-manager-tls
{
"name": "@ocm/attestation-manager",
"version": "0.0.1",
"description": "",
"author": "Shirdhar",
"private": true,
"license": "Apache-2.0",
"type": "module",
"scripts": {
"clean": "rimraf dist coverage *.tsbuildinfo",
"prebuild": "pnpm clean",
"build": "nest build",
"prebuild:production": "pnpm clean",
"build:production": "pnpm prisma:generate && nest build -p tsconfig.production.json",
"prisma:dbpush": "prisma db push --schema=./src/prisma/schema.prisma",
"prisma:generate": "prisma generate --schema=./src/prisma/schema.prisma",
"prisma:migrate": "prisma migrate deploy --schema=./src/prisma/schema.prisma",
"prisma:studio": "prisma studio",
"start": "nest start",
"start:dev": "nest start --watch --preserveWatchOutput",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest.config.js"
},
"dependencies": {
"@elastic/ecs-winston-format": "^1.5.0",
"@nestjs/axios": "^3.0.1",
"@nestjs/common": "^10.2.8",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.2.8",
"@nestjs/mapped-types": "^2.0.3",
"@nestjs/microservices": "^10.2.8",
"@nestjs/platform-express": "^10.2.8",
"@nestjs/swagger": "^7.1.15",
"@nestjs/terminus": "^10.1.1",
"@prisma/client": "^5.6.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"express": "^4.17.3",
"joi": "^17.11.0",
"jsonwebtoken": "^9.0.2",
"jwks-rsa": "^3.1.0",
"liquibase": "^4.4.0",
"moment": "^2.29.4",
"nats": "^2.18.0",
"pg": "^8.11.3",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"swagger-ui-express": "^5.0.0",
"winston": "^3.11.0",
"winston-elasticsearch": "^0.17.4"
},
"devDependencies": {
"@nestjs/cli": "^10.2.1",
"@nestjs/schematics": "^10.0.3",
"@nestjs/testing": "^10.2.8",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.96",
"@swc/jest": "^0.2.29",
"@types/express": "^4.17.21",
"@types/jest": "^29.5.8",
"@types/jsonwebtoken": "^9.0.5",
"@types/node": "^20.9.0",
"@types/supertest": "^2.0.16",
"dotenv-cli": "^7.3.0",
"eslint": "^8.53.0",
"jest": "^29.7.0",
"node-mocks-http": "^1.13.0",
"prisma": "^5.6.0",
"rimraf": "^5.0.5",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
}
}
import {
Module,
RequestMethod,
type MiddlewareConsumer,
type NestModule,
} from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { APP_FILTER } from '@nestjs/core';
import { TerminusModule } from '@nestjs/terminus';
import ExceptionHandler from './common/exception.handler.js';
import config from './config/config.js';
import validationSchema from './config/validation.js';
import CredentialDefModule from './credentialDef/module.js';
import HealthController from './health/health.controller.js';
import AttestationModule from './issue-credential/module.js';
import { AuthMiddleware } from './middleware/auth.middleware.js';
import SchemasModule from './schemas/module.js';
import UserInfoModule from './userInfo/module.js';
@Module({
imports: [
TerminusModule,
ConfigModule.forRoot({
isGlobal: true,
load: [config],
validationSchema,
}),
SchemasModule,
AttestationModule,
CredentialDefModule,
UserInfoModule,
],
controllers: [HealthController],
providers: [
{
provide: APP_FILTER,
useClass: ExceptionHandler,
},
],
})
export default class AppModule implements NestModule {
public configure(consumer: MiddlewareConsumer) {
// eslint-disable-line
consumer
.apply(AuthMiddleware)
.exclude({
path: 'v1/health',
method: RequestMethod.GET,
})
.forRoutes('*');
}
}
import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { lastValueFrom } from 'rxjs';
import { Connection, NATSServices } from '../common/constants.js';
@Injectable()
export default class NatsClientService {
public constructor(
@Inject(NATSServices.SERVICE_NAME) private natsClient: ClientProxy,
) {}
public getConnectionById(connectionId: string) {
const pattern = {
endpoint: `${Connection.NATS_ENDPOINT}/${Connection.GET_CONNECTION_BY_ID}`,
};
const payload = { connectionId };
return lastValueFrom(this.natsClient.send(pattern, payload));
}
public connectionTrusted(connectionId: string) {
const pattern = {
endpoint: `${Connection.NATS_ENDPOINT}/${Connection.MAKE_CONNECTION_TRUSTED}`,
};
const payload = { connectionId };
return lastValueFrom(this.natsClient.send(pattern, payload));
}
public getReceivedConnections() {
const pattern = {
endpoint: `${Connection.NATS_ENDPOINT}/${Connection.GET_RECEIVED_CONNECTIONS}`,
};
const payload = {};
return lastValueFrom(this.natsClient.send(pattern, payload));
}
}
import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { lastValueFrom, map } from 'rxjs';
@Injectable()
export default class RestClientService {
public constructor(private readonly httpService: HttpService) {}
public async delete(url: string) {
return lastValueFrom(
this.httpService.delete(url).pipe(map((response) => response.data)),
);
}
public async post(url: string, payload: object) {
return lastValueFrom(
this.httpService
.post(url, payload)
.pipe(map((response) => response.data)),
);
}
public async get(url: string) {
return lastValueFrom(
this.httpService.get(url).pipe(map((response) => response.data)),
);
}
}
import {
natsAgentResponse,
natsConnectionResponse,
} from '../stubs/nats-response.js';
const NatsClientServiceMock = jest.fn().mockReturnValue({
getAgentByParticipantId: jest.fn().mockReturnValue(natsAgentResponse),
getConnectionById: jest.fn().mockReturnValue(natsConnectionResponse),
});
export default NatsClientServiceMock;
import schemaAgentDto from '../../../schemas/tests/stubs/schema-from-agent-dto.js';
const RestClientServiceMock = jest.fn().mockReturnValue({
post: jest.fn().mockReturnValue({ agent: 'response' }),
get: jest.fn().mockImplementation((url: string) => {
if (url.includes('schemas')) {
return schemaAgentDto;
}
return {};
}),
});
export default RestClientServiceMock;
import type { PolicyReturnType } from '../../tsa.client.js';
import { TSAService } from '../../../common/constants.js';
const TSAClientServiceMock = jest.fn().mockReturnValue({
getPolicy: jest.fn().mockImplementation((url: string) => {
if (url.includes(TSAService.PRINCIPAL_CREDENTIAL_REQUEST)) {
return {
success: true,
returnData: true,
} as PolicyReturnType;
}
return {};
}),
});
export default TSAClientServiceMock;
import type { TestingModule } from '@nestjs/testing';
import { HttpModule, HttpService } from '@nestjs/axios';
import { Test } from '@nestjs/testing';
import HttpServiceMock from '../../tests/__mocks__/http-service.js';
import RestClientService from '../rest.client.js';
describe('RestClientService', () => {
let restClient: RestClientService;
const HttpServiceProvider = {
provide: HttpService,
useFactory: HttpServiceMock,
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [HttpModule],
providers: [RestClientService, HttpServiceProvider],
}).compile();
restClient = module.get<RestClientService>(RestClientService);
});
it('should be defined', () => {
expect(restClient).toBeDefined();
});
describe('post()', () => {
let restClientResponse: unknown;
beforeEach(async () => {
restClientResponse = await restClient.post('test_url', {});
});
it('should call post() from HttpService', async () => {
expect(HttpServiceMock().post).toHaveBeenCalled();
});
it('should retrieve response', async () => {
expect(restClientResponse).not.toBe(null);
});
});
});
import type { ResponseType } from '../../../common/response.js';
import AttestationService from '../../../issue-credential/services/service.js';
const natsAgentResponse: ResponseType = {
statusCode: 200,
data: {
service_endpoint: 'TEST_AGENT_URL',
},
message: 'Agent Details',
};
const natsConnectionResponse = {
status: AttestationService.connectionStatus.TRUSTED,
};
export { natsAgentResponse, natsConnectionResponse };
import { Injectable } from '@nestjs/common';
import RestClientService from './rest.client.js';
export interface PolicyReturnType {
success: boolean;
returnData?: unknown; // replace with actual structure when ready
}
export interface PolicyResult {
allow: boolean;
data?: unknown;
}
@Injectable()
export default class TSAClientService {
public constructor(private readonly restClient: RestClientService) {}
public async getPolicy(policyUrl: string) {
try {
const policyResponse: PolicyResult = await this.restClient.get(policyUrl);
if (
policyResponse &&
policyResponse.allow &&
typeof policyResponse.allow === 'boolean'
) {
return {
success: true,
returnData: Boolean(policyResponse?.allow),
} as PolicyReturnType;
}
// Add condition when policy returns data other than boolean
return {
success: false,
returnData: 'Unable to fetch policy data.',
} as PolicyReturnType;
} catch (error: any /* eslint-disable-line @typescript-eslint/no-explicit-any */) {
let returnData = 'Something went wrong!';
if (error?.isAxiosError) {
returnData = `${error?.response?.status} ${error?.response?.statusText}`;
}
return {
success: false,
returnData,
} as PolicyReturnType;
}
}
}
export enum LoggerConfig {
FILE_PATH = 'logs/log.json',
LOG_DIR = './logs',
}
export enum Connection {
BASE_URL = 'http://3.111.77.38:3003', // TODO Hardcoded IP, move to env variables
CONNECTION = 'v1/connections',
GET_CONNECTION_BY_ID = 'getConnectionById',
NATS_ENDPOINT = 'CONNECTION_MANAGER_SERVICE',
MAKE_CONNECTION_TRUSTED = 'makeConnectionTrusted',
GET_RECEIVED_CONNECTIONS = 'getReceivedConnections',
}
export enum Abstraction {
NATS_ENDPOINT = 'SSI_ABSTRACTION_SERVICE',
CREDENTIAL_STATE_CHANGED = 'CredentialStateChanged',
}
export enum NATSServices {
SERVICE_NAME = 'ATTESTATION_MANAGER_SERVICE',
}
export enum TSAService {
PRINCIPAL_CREDENTIAL_REQUEST = 'PrincipalCredentialRequest',
}
export enum PrismaErrorCode {
RECORD_NOT_FOUND = 'P2025',
}
export const VersionRegex = /^(\d+\.)(\d+\.)?(\d+)$/;
export enum AutoAcceptCredential {
ALWAYS = 'always',
Content_Approved = 'contentApproved',
NEVER = 'never',
}
import moment from 'moment';
const getDate = () => moment().format('MM-DD-YYYY, h:mm:ss a');
export default getDate;
import type { ResponseType } from './response.js';
import {
Catch,
HttpException,
HttpStatus,
type ArgumentsHost,
type ExceptionFilter,
} from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
@Catch()
export default class ExceptionHandler implements ExceptionFilter {
public constructor(private readonly httpAdapterHost: HttpAdapterHost) {}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public catch(exception: any, host: ArgumentsHost): void {
// In certain situations `httpAdapter` might not be available in the
// constructor method, thus we should resolve it here.
const { httpAdapter } = this.httpAdapterHost;
const ctx = host.switchToHttp();
const response = ctx.getResponse();
let statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
let message =
exception.message.error || exception.message || 'Something went wrong!';
if (exception instanceof HttpException) {
const errorResponse: string | object = exception.getResponse();
statusCode = exception.getStatus();
message =
(typeof errorResponse === 'object' &&
Reflect.get(errorResponse, 'error')) ||
message;
}
const responseBody: ResponseType = {
statusCode,
message,
error: exception.message,
};
httpAdapter.reply(response, responseBody, statusCode);
}
}
import { fileURLToPath } from 'node:url';
const parentDirectory = fileURLToPath(new URL('..', import.meta.url));
const config = () => ({
PORT: Number(process.env.PORT),
nats: {
url: process.env.NATS_URL,
},
auth: {
useAuth: process.env.USE_AUTH || 'false',
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
tokenUrl: process.env.OAUTH_TOKEN_URL,
},
agent: {
AGENT_URL: process.env.AGENT_URL,
},
DATABASE: {
type: 'postgres',
port: 5432,
synchronize: false,
logging: false,
entities: [`${parentDirectory}/**/**.model{.ts,.js}`],
},
ECSURL: process.env.ECSURL,
ACCEPT_MEMBERSHIP_CREDENTIALS_CONFIG:
process.env.ACCEPT_MEMBERSHIP_CREDENTIALS_CONFIG,
TSA_URL: process.env.TSA_URL,
});
export default config;
import Joi from 'joi';
const validationSchema = Joi.object({
DATABASE_URL: Joi.string().required(),
AGENT_URL: Joi.string().required(),
NATS_URL: Joi.string().required(),
PORT: Joi.number().required(),
ACCEPT_MEMBERSHIP_CREDENTIALS_CONFIG: Joi.string().required(),
USE_AUTH: Joi.string(),
OAUTH_CLIENT_ID: Joi.string(),
OAUTH_CLIENT_SECRET: Joi.string(),
OAUTH_TOKEN_URL: Joi.string(),
});
export default validationSchema;
import type { ResponseType } from '../../common/response.js';
import type CredentialDefLedgerDto from '../entities/credentialDefLedger-entity.js';
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
import type { Response } from 'express';
import {
Body,
Controller,
Get,
HttpStatus,
InternalServerErrorException,
Param,
Post,
Query,
Res,
Version,
} from '@nestjs/common';
import {
ApiBody,
ApiOperation,
ApiParam,
ApiQuery,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { Prisma } from '@prisma/client';
import logger from '../../utils/logger.js';
import CredentialDefDto from '../entities/credentialDef-entity.js';
import CredentialDefService from '../services/service.js';
@ApiTags('Credential Definitions')
@Controller('credentialDef')
export default class CredentialDefController {
public constructor(
private readonly credentialDefService: CredentialDefService,
) {}
@Version(['1'])
@ApiQuery({ name: 'page', required: false })
@ApiQuery({ name: 'pageSize', required: false })
@ApiQuery({ name: 'schemaID', required: false })
@Get('')
@ApiOperation({
summary: 'Fetch a list of credential definitions',
description:
'This call provides the capability to search created credential definitions by using pagination and filter parameter (schemaID) to select credential definitions. This call returns a list of credential definitions and overall count of records. Using a credential definition from that list you can issue credential so some connection',
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Credential definitions fetched successfully',
content: {
'application/json': {
schema: {},
examples: {
'Credential definitions fetched successfully': {
value: {
statusCode: 200,
message: 'Credential definitions fetched successfully',
data: {
count: 2,
records: [
{
id: '1234abcd',
schemaID: 'loremipsum:test-01-01:1.0',
name: 'test-01-01',
credDefId: 'test-cred-def123',
isAutoIssue: false,
isRevokable: false,
expiryHours: '24',
createdBy: 'acceptsAnyString',
createdDate: '1970-01-01T00:00:28.343Z',
updatedBy: '',
updatedDate: '1970-01-01T00:00:28.343Z',
},
{
id: '5678abcd',
schemaID: 'loremipsum2:test2-01-01:1.0',
name: 'test2-01-01',
credDefId: 'test2-cred-def123',
isAutoIssue: false,
isRevokable: false,
expiryHours: '24',
createdBy: 'acceptsAnyString',
createdDate: '1970-01-01T00:00:28.343Z',
updatedBy: '',
updatedDate: '1970-01-01T00:00:28.343Z',
},
],
},
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
description: 'No Data found.',
content: {
'application/json': {
schema: {},
examples: {
'No Data found.': {
value: {
statusCode: HttpStatus.NOT_FOUND,
message: 'No Data found',
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'Internal Server Error.',
content: {
'application/json': {
schema: {},
examples: {
'Internal Server Error.': {
value: {
statusCode: 500,
timestamp: '1970-01-01T00:00:27.897Z',
message: 'Lorem Ipsum',
},
},
},
},
},
})
public async findCredentialDef(
@Query()
query: {
pageSize: string;
page: string;
schemaID: string;
},
@Res() response: Response,
) {
let res: ResponseType;
try {
logger.info('Credential definitions fetched successfully');
const result = await this.credentialDefService.findCredentialDef(
query.pageSize ? parseInt(query.pageSize, 10) : 10,
query.page ? parseInt(query.page, 10) : 0,
query.schemaID ? query.schemaID : '',
);
if (Array.isArray(result) && result[0] > 0) {
res = {
statusCode: HttpStatus.OK,
message: 'Credential definitions fetched successfully',
data: {
count: result[0],
records: result[1],
},
};
} else {
response.status(HttpStatus.NOT_FOUND);
res = {
statusCode: HttpStatus.NOT_FOUND,
message: 'No Data found',
};
}
return response.send(res);
} catch (error: unknown) {
logger.error(error instanceof Error && error.message);
throw new InternalServerErrorException(
`Error: ${error instanceof Error ? error.message : error}`,
);
}
}
@ApiParam({ name: 'id', type: 'string', description: 'Pass Cred Def id' })
@Version(['1'])
@Get('/:id')
@ApiOperation({
summary: 'Fetch credential definition by id',
description:
'This call provides the capability to get credential definition data by providing id of credential definition. The credential definition data is the same which is returned from /v1/connections endpoint and contains generic information about credential definition like schemaID, name, credDefId, isAutoIssue, isRevokable, expiryHours, createdBy, createdDate, updatedBy, updatedDate',
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Credential definition fetched successfully',
content: {
'application/json': {
schema: {},
examples: {
'Credential definition fetched successfully': {
value: {
statusCode: 200,
message: 'Credential definition fetched successfully',
data: {
count: 1,
records: [
{
id: '1234abcd',
schemaID: 'loremipsum:test-01-01:1.0',
name: 'test-01-01',
credDefId: 'test-cred-def123',
isAutoIssue: false,
isRevokable: false,
expiryHours: '24',
createdBy: 'acceptsAnyString',
createdDate: '1970-01-01T00:00:28.343Z',
updatedBy: '',
updatedDate: '1970-01-01T00:00:28.343Z',
},
],
},
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
description: 'No Data found',
content: {
'application/json': {
schema: {},
examples: {
'No Data found': {
value: {
statusCode: HttpStatus.NOT_FOUND,
message: 'No Data found',
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'Internal Server Error.',
content: {
'application/json': {
schema: {},
examples: {
'Internal Server Error.': {
value: {
statusCode: 500,
timestamp: '1970-01-01T00:00:27.897Z',
message: 'Lorem Ipsum',
},
},
},
},
},
})
public async findCredentialDefById(
@Param('id') id: string,
@Res() response: Response,
) {
let res: ResponseType;
try {
logger.info('Credential definition fetched successfully');
const result = await this.credentialDefService.findCredentialDefById(id);
if (Array.isArray(result) && result[0] > 0) {
res = {
statusCode: HttpStatus.OK,
message: 'Credential definition fetch successfully',
data: {
count: result[0],
records: result[1],
},
};
} else {
response.status(HttpStatus.NOT_FOUND);
res = {
statusCode: HttpStatus.NOT_FOUND,
message: 'No Data found',
};
}
return response.send(res);
} catch (error) {
if (error instanceof Prisma.PrismaClientUnknownRequestError) {
throw new InternalServerErrorException(error.message);
} else {
throw new InternalServerErrorException(error);
}
}
}
@Version(['1'])
@ApiBody({ type: CredentialDefDto })
@Post('')
@ApiOperation({
summary: 'Create a new credential definition',
description:
'This call provides the capability to create new credential definition by providing schema id, name, createdBy, auto-issue and other information required by this method. This call returns an object contains information abut this credential definition (type CredentialDefDto). You can use this credential definition to issue credentials to some connection',
})
@ApiResponse({
status: HttpStatus.CREATED,
description: 'Credential definition created successfully',
content: {
'application/json': {
schema: {},
examples: {
'Credential definition created successfully': {
value: {
statusCode: 201,
message: 'Credential definition created successfully',
data: {
id: '71b784a3',
schemaID: '7KuDTpQh3:test-schema',
name: 'test',
credDefId: '7KuDTpQh3:test',
isAutoIssue: false,
isRevokable: false,
expiryHours: '23',
createdBy: 'vocm',
createdDate: '1970-01-01T00:00:28.343Z',
updatedBy: '',
updatedDate: '1970-01-01T00:00:28.343Z',
},
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description:
'Credential definition required following attributes ( schemaID, name, isRevokable, isAutoIssue, createdBy, expiryHours )',
content: {
'application/json': {
schema: {},
examples: {
'Credential definition required following attributes ( schemaID, name, isRevokable, isAutoIssue, createdBy, expiryHours )':
{
value: {
statusCode: 400,
message:
'Credential definition required following attributes ( schemaID, name, isRevokable, isAutoIssue, createdBy, expiryHours )',
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description:
'Could not get credential definition details. Please try again.',
content: {
'application/json': {
schema: {},
examples: {
'Could not get credential definition details. Please try again.': {
value: {
statusCode: 400,
message:
'Could not get credential definition details. Please try again.',
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.CONFLICT,
description: 'Credential definition already exists',
content: {
'application/json': {
schema: {},
examples: {
'Credential definition already exists': {
value: {
statusCode: 409,
message: 'Credential definition already exists',
},
},
},
},
},
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: 'Internal Server Error.',
content: {
'application/json': {
schema: {},
examples: {
'Internal Server Error.': {
value: {
statusCode: 500,
timestamp: '1970-01-01T00:00:27.897Z',
message: 'Lorem Ipsum',
},
},
},
},
},
})
public async createCredentialDef(
@Body() credentialDefDto: CredentialDefDto,
@Res() response: Response,
) {
try {
let res: ResponseType = {
statusCode: HttpStatus.OK,
message: 'Something went wrong please try again.',
};
if (
!(
credentialDefDto.schemaID &&
typeof credentialDefDto.schemaID === 'string' &&
credentialDefDto.name &&
typeof credentialDefDto.name === 'string' &&
credentialDefDto.createdBy &&
typeof credentialDefDto.createdBy === 'string' &&
(credentialDefDto.isRevokable === false ||
credentialDefDto.isRevokable === true) &&
(credentialDefDto.isAutoIssue === false ||
credentialDefDto.isAutoIssue === true) &&
credentialDefDto.expiryHours &&
typeof credentialDefDto.expiryHours === 'string' &&
parseFloat(credentialDefDto.expiryHours) >= -1
)
) {
res = {
statusCode: HttpStatus.BAD_REQUEST,
message:
'Credential definition required following attributes ( schemaID, name, isRevokable, isAutoIssue, createdBy, expiryHours )',
};
return response.status(HttpStatus.BAD_REQUEST).send(res);
}
const credDefResponse =
await this.credentialDefService.checkCredDefByNameAndSchemaID(
credentialDefDto,
);
if (credDefResponse[0] === 0) {
const credentialDefLedgerDto: CredentialDefLedgerDto = {
tag: credentialDefDto.name,
supportRevocation: credentialDefDto.isRevokable,
schemaId: credentialDefDto.schemaID,
};
const resp = await this.credentialDefService.createCredDefOnLedger(
credentialDefLedgerDto,
);
if (resp?.id) {
const credentialDefIDRes: CredentialDefDto = credentialDefDto;
credentialDefIDRes.credDefId = resp.id;
response.status(HttpStatus.CREATED);
res = {
statusCode: HttpStatus.CREATED,
message: 'Credential definition created successfully',
data: await this.credentialDefService.createCredDef(
credentialDefIDRes,
),
};
logger.info('Credential definition created successfully');
} else {
response.status(HttpStatus.BAD_REQUEST);
res = {
statusCode: HttpStatus.BAD_REQUEST,
message:
'Could not get credential definition details. Please try again.',
};
}
} else {
response.status(HttpStatus.CONFLICT);
res = {
statusCode: HttpStatus.CONFLICT,
message: 'Credential definition already exists',
};
}
return response.send(res);
} catch (error) {
if (error instanceof Prisma.PrismaClientUnknownRequestError) {
throw new InternalServerErrorException(error.message);
} else {
throw new InternalServerErrorException(error);
}
}
}
}
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
export default class CredentialDefDto {
@IsString()
public id: string;
@IsString()
@IsNotEmpty()
@ApiProperty()
public schemaID: string;
@IsString()
@IsNotEmpty()
@ApiProperty()
public name: string;
@IsString()
public credDefId: string;
@IsBoolean()
public supportRevocation?: boolean;
@IsBoolean()
@ApiProperty()
public isRevokable: boolean;
@IsBoolean()
@ApiProperty()
public isAutoIssue: boolean;
@IsString()
@ApiProperty()
// Number of hours of Credential validity
public expiryHours: string;
@IsString()
@ApiProperty()
public createdBy: string;
@IsString()
public createdDate: Date;
@IsString()
public updatedBy: string;
@IsString()
public updatedDate: Date;
@IsString()
public tag?: string;
@IsString()
@ApiPropertyOptional()
public type?: string;
}
import { IsString, IsBoolean } from 'class-validator';
export default class CredentialDefLedgerDto {
@IsString()
public schemaId: string;
@IsBoolean()
public supportRevocation?: boolean;
@IsString()
public tag?: string;
}