Skip to content

Commit

Permalink
Add init script for initialising issuance dids, schemas and credentia…
Browse files Browse the repository at this point in the history
…l definitions (#73)

* Add init script for initialising issuance dids, schemas and credential definitions

* Cache created logger
  • Loading branch information
mattdean-digicatapult authored Jun 26, 2024
1 parent 2ab8070 commit 8df6698
Show file tree
Hide file tree
Showing 20 changed files with 1,295 additions and 66 deletions.
41 changes: 15 additions & 26 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,13 @@ services:
condition: service_healthy
ports:
- 3100:3000
command: --inbound-transport http 5002 ws 5003 --outbound-transport http ws
env_file:
- docker/cloudagent.env
environment:
# - AFJ_REST_INBOUND_TRANSPORT="http 5002 ws 5003"
# - AFJ_REST_OUTBOUND_TRANSPORT="http ws"
- AFJ_REST_ENDPOINT=ws://veritable-cloudagent-alice:5003
- AFJ_REST_ADMIN_PORT=3000
- AFJ_REST_IPFS_ORIGIN=http://ipfs:5001
- AFJ_REST_POSTGRES_HOST=postgres-veritable-cloudagent-alice
- AFJ_REST_POSTGRES_PORT=5432
- AFJ_REST_POSTGRES_USERNAME=postgres
- AFJ_REST_POSTGRES_PASSWORD=postgres
- AFJ_REST_LABEL=vertiable-cloudagent
- AFJ_REST_WALLET_ID=alice
- AFJ_REST_WALLET_KEY=alice-key
- ENDPOINT=ws://veritable-cloudagent-alice:5003
- POSTGRES_HOST=postgres-veritable-cloudagent-alice
- WALLET_ID=alice
- WALLET_KEY=alice-key

# -------------------- bob -------------------------------#
veritable-ui-bob:
Expand Down Expand Up @@ -99,6 +92,9 @@ services:
- IDP_INTERNAL_URL_PREFIX=http://keycloak:8080/realms/veritable/protocol/openid-connect
- INVITATION_FROM_COMPANY_NUMBER=07964699
- INVITATION_PIN_SECRET=secret
- ISSUANCE_DID_POLICY=EXISTING_OR_NEW
- ISSUANCE_SCHEMA_POLICY=EXISTING_OR_NEW
- ISSUANCE_CRED_DEF_POLICY=EXISTING_OR_NEW
postgres-veritable-ui-bob:
image: postgres:16.3-alpine
container_name: postgres-veritable-ui-bob
Expand Down Expand Up @@ -127,20 +123,13 @@ services:
condition: service_healthy
ports:
- 3101:3000
command: --inbound-transport http 5002 ws 5003 --outbound-transport http ws
env_file:
- docker/cloudagent.env
environment:
# - AFJ_REST_INBOUND_TRANSPORT="http 5002 ws 5003"
# - AFJ_REST_OUTBOUND_TRANSPORT="http ws"
- AFJ_REST_ENDPOINT=ws://veritable-cloudagent-bob:5003
- AFJ_REST_ADMIN_PORT=3000
- AFJ_REST_IPFS_ORIGIN=http://ipfs:5001
- AFJ_REST_POSTGRES_HOST=postgres-veritable-cloudagent-bob
- AFJ_REST_POSTGRES_PORT=5432
- AFJ_REST_POSTGRES_USERNAME=postgres
- AFJ_REST_POSTGRES_PASSWORD=postgres
- AFJ_REST_LABEL=vertiable-cloudagent
- AFJ_REST_WALLET_ID=bob
- AFJ_REST_WALLET_KEY=bob-key
- ENDPOINT=ws://veritable-cloudagent-bob:5003
- POSTGRES_HOST=postgres-veritable-cloudagent-bob
- WALLET_ID=bob
- WALLET_KEY=bob-key

volumes:
ipfs:
Expand Down
8 changes: 8 additions & 0 deletions docker/cloudagent.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
INBOUND_TRANSPORT="[{\"transport\": \"http\", \"port\": 5002}, {\"transport\": \"ws\", \"port\": 5003}]"
OUTBOUND_TRANSPORT="http,ws"
ADMIN_PORT=3000
IPFS_ORIGIN=http://ipfs:5001
POSTGRES_PORT=5432
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=postgres
LABEL=vertiable-cloudagent
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "veritable-ui",
"version": "0.5.5",
"version": "0.6.0",
"description": "UI for Veritable",
"main": "src/index.ts",
"type": "module",
Expand All @@ -19,6 +19,8 @@
"tsoa:build": "tsoa spec-and-routes",
"tsoa:watch": "node --watch-path=./src ./node_modules/.bin/tsoa -- spec-and-routes",
"dev": "npm run tsoa:watch & NODE_ENV=dev node --import=tsimp/import --watch src/index.ts | pino-colada",
"dev:init": "NODE_ENV=dev node --import=tsimp/import src/init.ts | pino-colada",
"init": "node build/init.js",
"start": "node build/index.js",
"db:cmd": "node --import=tsimp/import ./node_modules/.bin/knex",
"db:migrate": "npm run db:cmd -- migrate:latest",
Expand Down
3 changes: 2 additions & 1 deletion src/controllers/__tests__/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { Readable } from 'node:stream'
import { pino } from 'pino'

import { Env } from '../../env.js'
import type { ILogger } from '../../logger.js'

export const mockLogger = pino({ level: 'silent' })
export const mockLogger: ILogger = pino({ level: 'silent' })

export const mockEnv = {
get: (name: string) => {
Expand Down
5 changes: 3 additions & 2 deletions src/controllers/connection/__tests__/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Readable } from 'node:stream'
import { pino } from 'pino'

import { Env } from '../../../env.js'
import type { ILogger } from '../../../logger.js'
import CompanyHouseEntity from '../../../models/companyHouseEntity.js'
import Database from '../../../models/db/index.js'
import { ConnectionRow } from '../../../models/db/types.js'
Expand All @@ -22,7 +23,7 @@ export const withConnectionMocks = () => {
listPage: (connections: ConnectionRow[]) =>
templateFake('list', connections[0].company_name, connections[0].status),
} as ConnectionTemplates
const mockLogger = pino({ level: 'silent' })
const mockLogger: ILogger = pino({ level: 'silent' })
const dbMock = {
get: () => Promise.resolve([{ company_name: 'foo', status: 'verified' }]),
} as unknown as Database
Expand All @@ -35,7 +36,7 @@ export const withConnectionMocks = () => {
}

export const withNewConnectionMocks = () => {
const mockLogger = pino({ level: 'silent' })
const mockLogger: ILogger = pino({ level: 'silent' })
const mockTransactionDb = {
insert: () => Promise.resolve([{ id: '42' }]),
}
Expand Down
50 changes: 40 additions & 10 deletions src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ import dotenv from 'dotenv'
import * as envalid from 'envalid'
import { singleton } from 'tsyringe'

if (process.env.NODE_ENV === 'test') {
dotenv.config({ path: 'test/test.env' })
} else {
dotenv.config()
}

const strArrayValidator = envalid.makeValidator((input) => {
const arr = input
.split(',')
Expand All @@ -22,7 +16,30 @@ const strArrayValidator = envalid.makeValidator((input) => {
return res
})

const envConfig = {
const issuanceRecordValidator = envalid.makeValidator((input) => {
if (input === 'CREATE_NEW') {
return 'CREATE_NEW' as const
}

if (input === 'FIND_EXISTING') {
return 'FIND_EXISTING' as const
}

if (input === 'EXISTING_OR_NEW') {
return 'EXISTING_OR_NEW' as const
}

if (input.match(/^did:/)) {
return input as `did:${string}`
}
if (input.match(/^ipfs:\/\//)) {
return input as `ipfs://${string}`
}

throw new Error('must supply a valid issuance policy')
})

export const envConfig = {
PORT: envalid.port({ default: 3000 }),
LOG_LEVEL: envalid.str({ default: 'info', devDefault: 'debug' }),
DB_HOST: envalid.host({ devDefault: 'localhost' }),
Expand Down Expand Up @@ -60,20 +77,33 @@ const envConfig = {
CLOUDAGENT_ADMIN_WS_ORIGIN: envalid.url({ devDefault: 'ws://localhost:3100' }),
INVITATION_PIN_SECRET: envalid.str({ devDefault: 'secret' }),
INVITATION_FROM_COMPANY_NUMBER: envalid.str({ devDefault: '07964699' }),
ISSUANCE_DID_POLICY: issuanceRecordValidator({ devDefault: 'EXISTING_OR_NEW' }),
ISSUANCE_SCHEMA_POLICY: issuanceRecordValidator({ devDefault: 'EXISTING_OR_NEW' }),
ISSUANCE_CRED_DEF_POLICY: issuanceRecordValidator({ devDefault: 'EXISTING_OR_NEW' }),
}

export type ENV_CONFIG = typeof envConfig
export type ENV_KEYS = keyof ENV_CONFIG

export interface PartialEnv<KS extends ENV_KEYS = ENV_KEYS> {
get<K extends KS>(key: K): Pick<envalid.CleanedEnv<typeof envConfig>, KS>[K]
}

@singleton()
export class Env {
private vals: envalid.CleanedEnv<typeof envConfig>
export class Env<KS extends ENV_KEYS = ENV_KEYS> implements PartialEnv<KS> {
private vals: Pick<envalid.CleanedEnv<typeof envConfig>, KS>

constructor() {
if (process.env.NODE_ENV === 'test') {
dotenv.config({ path: 'test/test.env' })
} else {
dotenv.config()
}

this.vals = envalid.cleanEnv(process.env, envConfig)
}

get<K extends ENV_KEYS>(key: K) {
get<K extends KS>(key: K) {
return this.vals[key]
}
}
11 changes: 8 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import { container } from 'tsyringe'
import { Env } from './env.js'
import Server from './server.js'

import { logger } from './logger.js'
import { Logger, type ILogger } from './logger.js'
import { CredentialSchema } from './models/credentialSchema.js'
;(async () => {
const { app } = await Server()

const env = container.resolve(Env)
const logger = container.resolve<ILogger>(Logger)

const schema = container.resolve<CredentialSchema>(CredentialSchema)
await schema.assertIssuanceRecords()

const { app } = await Server()

app.listen(env.get('PORT'), () => {
logger.info(`htmx-tsoa listening on ${env.get('PORT')} port`)
Expand Down
55 changes: 55 additions & 0 deletions src/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import 'reflect-metadata'

import dotenv from 'dotenv'
import envalid from 'envalid'
import { pino } from 'pino'

import { PartialEnv, envConfig } from './env.js'
import { type ILogger } from './logger.js'
import { CredentialSchema } from './models/credentialSchema.js'
import VeritableCloudagent from './models/veritableCloudagent.js'

type InitConfigKeys =
| 'CLOUDAGENT_ADMIN_ORIGIN'
| 'LOG_LEVEL'
| 'ISSUANCE_DID_POLICY'
| 'ISSUANCE_SCHEMA_POLICY'
| 'ISSUANCE_CRED_DEF_POLICY'

class InitEnv implements PartialEnv<InitConfigKeys> {
private values: Pick<envalid.CleanedEnv<typeof envConfig>, InitConfigKeys>

constructor() {
if (process.env.NODE_ENV === 'test') {
dotenv.config({ path: 'test/test.env' })
} else {
dotenv.config()
}

this.values = envalid.cleanEnv(process.env, {
CLOUDAGENT_ADMIN_ORIGIN: envConfig.CLOUDAGENT_ADMIN_ORIGIN,
LOG_LEVEL: envConfig.LOG_LEVEL,
ISSUANCE_DID_POLICY: envConfig.ISSUANCE_DID_POLICY,
ISSUANCE_SCHEMA_POLICY: envConfig.ISSUANCE_SCHEMA_POLICY,
ISSUANCE_CRED_DEF_POLICY: envConfig.ISSUANCE_CRED_DEF_POLICY,
})
}

get<K extends InitConfigKeys>(key: K) {
return this.values[key]
}
}
const env = new InitEnv()

const logger: ILogger = pino(
{
name: 'veritable-ui-init',
timestamp: true,
level: env.get('LOG_LEVEL'),
},
process.stdout
)
const cloudagent = new VeritableCloudagent(env, logger)
const init = new CredentialSchema(env, logger, cloudagent)
const details = await init.assertIssuanceRecords()
logger.info(details, 'Asserted credential issuance records with: %o', details)
31 changes: 18 additions & 13 deletions src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ import { container } from 'tsyringe'

import { Env } from './env.js'

const env = container.resolve(Env)

export const logger = pino(
{
name: 'htmx-tsoa',
timestamp: true,
level: env.get('LOG_LEVEL'),
},
process.stdout
)

export const Logger = Symbol('Logger')
export type ILogger = typeof logger
export type ILogger = ReturnType<typeof pino>

let instance: ILogger | null = null
container.register<ILogger>(Logger, {
useValue: logger,
useFactory: (container) => {
if (instance) {
return instance
}

const env = container.resolve(Env)
instance = pino(
{
name: 'veritable-ui',
timestamp: true,
level: env.get('LOG_LEVEL'),
},
process.stdout
)
return instance
},
})
Loading

0 comments on commit 8df6698

Please sign in to comment.