Index

src/auth/auth-validation.schema.ts

AUTH_VALIDATION_SCHEMA
Type : Joi.ObjectSchema
Default value : Joi.object({ OIDC: Joi.string() .description("Enable OIDC mode") .meta({ group: "auth", order: 10 }), OIDC_INTERNAL_ISSUER_URL: Joi.string() .uri() .when("OIDC", { is: Joi.exist(), then: Joi.string().default((config) => config.OIDC), otherwise: Joi.optional(), }) .description("Internal issuer URL in OIDC mode") .meta({ group: "auth", order: 20 }), OIDC_CLIENT_ID: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().required(), otherwise: Joi.optional(), }) .description("Client ID for OIDC") .meta({ group: "auth", order: 25 }), OIDC_CLIENT_SECRET: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().required(), otherwise: Joi.optional(), }) .description("Client secret for OIDC") .meta({ group: "auth", order: 26 }), OIDC_SUB: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().default("tenant_id"), otherwise: Joi.optional(), }) .description("Claim to use as subject") .meta({ group: "auth", order: 30 }), OIDC_ALGORITHM: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().valid("RS256", "PS256", "ES256").default("RS256"), otherwise: Joi.optional(), }) .description("Expected JWT alg") .meta({ group: "auth", order: 40 }), JWT_SECRET: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().optional(), otherwise: Joi.string().min(32).default(DEFAULT_JWT_SECRET), }) .description("Local JWT secret (when OIDC is off)") .meta({ group: "auth", order: 50 }), JWT_ISSUER: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().optional(), otherwise: Joi.string().default("eudiplo-service"), }) .description("Local JWT issuer") .meta({ group: "auth", order: 60 }), JWT_EXPIRES_IN: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().optional(), otherwise: Joi.string().default("24h"), }) .description("Local JWT expiration") .meta({ group: "auth", order: 70 }), AUTH_CLIENT_SECRET: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().optional(), otherwise: Joi.string().default(DEFAULT_AUTH_CLIENT_SECRET), }) .description("Client secret (local auth)") .meta({ group: "auth", order: 80 }), AUTH_CLIENT_ID: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string().optional(), otherwise: Joi.string().default(DEFAULT_AUTH_CLIENT_ID), }) .description("Client ID (local auth)") .meta({ group: "auth", order: 90 }), //TODO: logic has to be challenged AUTH_CLIENT_TENANT: Joi.string() .optional() .description("Tenant to which this client should be added") .meta({ group: "auth", order: 100 }), AUTH_CLIENT_ROLES: Joi.when("OIDC", { is: Joi.exist(), then: Joi.string(), otherwise: Joi.string().default("all"), }) .description("Roles assigned to this client") .meta({ group: "auth", order: 110 }), }).unknown(true)
DEFAULT_AUTH_CLIENT_ID
Type : string
Default value : "root"
DEFAULT_AUTH_CLIENT_SECRET
Type : string
Default value : "root"
DEFAULT_JWT_SECRET
Type : string
Default value : "supersecret"

src/utils/config-printer/validation.schema.ts

BASE_VALIDATION_SCHEMA
Default value : Joi.object({ FOLDER: Joi.string() .default("../../tmp") .description("Root working folder for temp files") .meta({ group: "general", order: 10 }), }).unknown(true)

Validation schema for base configuration

src/auth/client/client.provider.ts

CLIENTS_PROVIDER
Type : string
Default value : "CLIENTS_PROVIDER"

src/utils/config-printer/config-validation.schema.ts

CONFIG_VALIDATION_SCHEMA
Default value : Joi.object({ CONFIG_IMPORT: Joi.boolean() .default(false) .description("Run one-off config import on startup") .meta({ group: "config", order: 10 }), CONFIG_IMPORT_FORCE: Joi.boolean() .default(false) .description("Force overwrite on config import") .meta({ group: "config", order: 20 }), CONFIG_FOLDER: Joi.string() .default("../../assets/config") .description("Path to config import folder") .meta({ group: "config", order: 30 }), })

Validation schema for configuration

src/utils/mediaType/media-type.decorator.ts

ContentType
Default value : createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.headers["accept"] as string | undefined; }, )

Decorator to extract the content type from the request headers. This decorator can be used to determine the media type of the request.

src/utils/logger/logger.factory.ts

createLoggerOptions
Default value : (configService: ConfigService) => { const enableHttpLogger = configService.get<boolean>( "LOG_ENABLE_HTTP_LOGGER", false, ); // Check if file logging is enabled const logToFile = configService.get<boolean>("LOG_TO_FILE"); const logFilePath = configService.get<string>("LOG_FILE_PATH"); let transportConfig; if (logToFile) { // Configure both console and file logging transportConfig = { targets: [ // Console pretty logging { target: "pino-pretty", level: configService.get("LOG_LEVEL", "info"), options: { colorize: true, singleLine: false, translateTime: "yyyy-mm-dd HH:MM:ss", ignore: "pid,hostname", }, }, // File logging - ensure order is maintained with sync: true { target: "pino/file", level: configService.get("LOG_LEVEL", "info"), options: { destination: logFilePath, mkdir: true, sync: true, // Use synchronous writes to ensure message order }, }, ], }; } else { // Console logging only transportConfig = { target: "pino-pretty", options: { colorize: true, singleLine: false, translateTime: "yyyy-mm-dd HH:MM:ss", ignore: "pid,hostname", }, }; } return { pinoHttp: { level: configService.get("LOG_LEVEL", "info"), autoLogging: enableHttpLogger, transport: transportConfig, formatters: { log: (object) => { object.hostname = undefined; return object; }, }, customProps: (req: any) => ({ sessionId: req.params?.session, }), serializers: { req: (req: any) => ({ method: req.method, url: req.url, headers: { "user-agent": req.headers["user-agent"], "content-type": req.headers["content-type"], }, sessionId: req.params?.session, tenantId: req.params?.tenantId, }), res: (res: any) => ({ statusCode: res.statusCode, }), }, }, }; }

Factory function for configuring the logger module

src/utils/serve-static.factory.ts

createServeStaticOptions
Default value : ( configService: ConfigService, ): ServeStaticModuleOptions[] => { const folder = configService.getOrThrow<string>("FOLDER"); const rootPath = isAbsolute(folder) ? join(folder, "public") : join(__dirname, "../", folder, "public"); return [ { rootPath, }, ]; }

Factory function for configuring the serve static module

src/crypto/key/crypto-implementation/crypto-validation.schema.ts

CRYPTO_VALIDATION_SCHEMA
Default value : Joi.object({ CRYPTO_ALG: Joi.string() .valid("ES256") .default("ES256") .description("The signing algorithm to use") .meta({ group: "crypto", order: 10 }), })

src/database/database-validation.schema.ts

DB_VALIDATION_SCHEMA
Default value : Joi.object({ DB_TYPE: Joi.string() .valid("sqlite", "postgres") .default("sqlite") .description("Database type") .meta({ group: "database", order: 10 }), DB_HOST: Joi.string() .when("DB_TYPE", { is: "sqlite", then: Joi.optional(), otherwise: Joi.required(), }) .description("Database host") .meta({ group: "database", order: 15 }), DB_PORT: Joi.number() .when("DB_TYPE", { is: "sqlite", then: Joi.optional(), otherwise: Joi.required(), }) .description("Database port") .meta({ group: "database", order: 20 }), DB_USERNAME: Joi.string() .when("DB_TYPE", { is: "sqlite", then: Joi.optional(), otherwise: Joi.required(), }) .description("Database username") .meta({ group: "database", order: 30 }), DB_PASSWORD: Joi.string() .when("DB_TYPE", { is: "sqlite", then: Joi.optional(), otherwise: Joi.required(), }) .description("Database password") .meta({ group: "database", order: 40 }), DB_DATABASE: Joi.string() .when("DB_TYPE", { is: "sqlite", then: Joi.optional(), otherwise: Joi.required(), }) .description("Database name") .meta({ group: "database", order: 50 }), })

src/crypto/crypto.service.ts

ECDSA_P256
Type : object
Default value : { name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" as const, }

src/crypto/key/crypto-implementation/ed25519.ts

ED25519
Type : CryptoImplementation
Default value : { alg: "EdDSA", async generateKeyPair() { const keyPair = await crypto.webcrypto.subtle.generateKey( { name: "EdDSA", namedCurve: "Ed25519", }, true, ["sign", "verify"], ); const publicKey = await crypto.webcrypto.subtle.exportKey( "jwk", keyPair.publicKey, ); const privateKey = await crypto.webcrypto.subtle.exportKey( "jwk", keyPair.privateKey, ); return { publicKey, privateKey }; }, async getSigner(privateKeyJWK: object) { const privateKey = await crypto.webcrypto.subtle.importKey( "jwk", privateKeyJWK, { name: "EdDSA", namedCurve: "Ed25519", }, false, ["sign"], ); return async (data: string) => { const signature = await crypto.webcrypto.subtle.sign( "EdDSA", privateKey, new TextEncoder().encode(data), ); return Buffer.from(signature).toString("base64url"); }; }, async getVerifier(publicKeyJWK: object) { const publicKey = await crypto.webcrypto.subtle.importKey( "jwk", publicKeyJWK, { name: "EdDSA", namedCurve: "Ed25519", }, false, ["verify"], ); return async (data: string, signatureBase64url: string) => { const signature = Buffer.from(signatureBase64url, "base64url"); const isVerified = await crypto.webcrypto.subtle.verify( "EdDSA", publicKey, signature, new TextEncoder().encode(data), ); return isVerified; }; }, }

src/storage/storage.types.ts

FILE_STORAGE
Default value : Symbol("FILE_STORAGE")

src/auth/public.decorator.ts

IS_PUBLIC_KEY
Type : string
Default value : "isPublic"
Public
Default value : () => SetMetadata(IS_PUBLIC_KEY, true)

src/issuer/issuer-validation.schema.ts

ISSUER_VALIDATION_SCHEMA
Default value : Joi.object({ PUBLIC_URL: Joi.string() .default("http://localhost:3000") .description("The public URL of the issuer") .meta({ group: "general", order: 10 }), })

src/crypto/key/key-validation.schema.ts

KEY_VALIDATION_SCHEMA
Default value : Joi.object({ KM_TYPE: Joi.string() .valid("db", "vault") .default("db") .description("The key management type") .meta({ group: "key", order: 10 }), // Vault-related config VAULT_URL: Joi.string() .uri() .when("KM_TYPE", { is: "vault", then: Joi.required(), otherwise: Joi.optional(), }) .description("The URL of the Vault server") .meta({ group: "key", order: 20 }), VAULT_TOKEN: Joi.string() .when("KM_TYPE", { is: "vault", then: Joi.required(), otherwise: Joi.optional(), }) .description("The token for accessing the Vault") .meta({ group: "key", order: 30 }), })

src/utils/logger/log-validation.schema.ts

LOG_VALIDATION_SCHEMA
Default value : Joi.object({ LOG_LEVEL: Joi.string() .valid("trace", "debug", "info", "warn", "error", "fatal") .default(process.env.NODE_ENV === "production" ? "warn" : "debug") .description("Application log level") .meta({ group: "log", order: 10 }), LOG_ENABLE_HTTP_LOGGER: Joi.boolean() .default(false) .description("Enable HTTP request logging") .meta({ group: "log", order: 20 }), LOG_ENABLE_SESSION_LOGGER: Joi.boolean() .default(false) .description("Enable session flow logging") .meta({ group: "log", order: 30 }), LOG_DEBUG_MODE: Joi.boolean() .default(false) .description("Enable verbose debug logs") .meta({ group: "log", order: 40 }), LOG_FORMAT: Joi.string() .valid("json", "pretty") .default(process.env.NODE_ENV === "production" ? "json" : "pretty") .description("Log output format") .meta({ group: "log", order: 50 }), LOG_TO_FILE: Joi.boolean() .default(false) .description("Enable logging to file in addition to console") .meta({ group: "log", order: 60 }), LOG_FILE_PATH: Joi.string() .default("./logs/session.log") .description("File path for log output when LOG_TO_FILE is enabled") .meta({ group: "log", order: 70 }), })

Validation schema for logging configuration

src/registrar/registrar-validation.schema.ts

REGISTRAR_VALIDATION_SCHEMA
Default value : Joi.object({ REGISTRAR_URL: Joi.string() .description("The URL of the registrar") .meta({ group: "registrar", order: 10 }), REGISTRAR_OIDC_URL: Joi.string() .when("REGISTRAR_URL", { is: Joi.exist(), then: Joi.required(), }) .description("The OIDC URL of the registrar") .meta({ group: "registrar", order: 20 }), REGISTRAR_OIDC_CLIENT_ID: Joi.string() .when("REGISTRAR_URL", { is: Joi.exist(), then: Joi.required(), }) .description("The OIDC client ID of the registrar") .meta({ group: "registrar", order: 30 }), REGISTRAR_OIDC_CLIENT_SECRET: Joi.string() .when("REGISTRAR_URL", { is: Joi.exist(), then: Joi.required(), }) .description("The OIDC client secret of the registrar") .meta({ group: "registrar", order: 40 }), })

Validation schema for the registrar module. Defines the required environment variables and their types.

src/auth/roles/roles.decorator.ts

Roles
Default value : (...roles: Role[]) => SetMetadata(ROLES_KEY, roles)
ROLES_KEY
Type : string
Default value : "roles"

src/utils/logger/session-logger.decorator.ts

SESSION_LOGGER_KEY
Type : string
Default value : "session-logger"

Key for session logger metadata.

SessionLogger
Default value : ( sessionIdParam: string, flowType: "OID4VCI" | "OID4VP", ) => SetMetadata(SESSION_LOGGER_KEY, { sessionIdParam, flowType })

Decorator to mark methods that should have session-based logging

src/session/session-validation.schema.ts

SESSION_VALIDATION_SCHEMA
Default value : Joi.object({ SESSION_TIDY_UP_INTERVAL: Joi.number() .default(60 * 60) .description("Interval in seconds to run session tidy up") .meta({ group: "session", order: 10 }), SESSION_TTL: Joi.number() .default(24 * 60 * 60) .description("Time to live for sessions in seconds") .meta({ group: "session", order: 20 }), })

Module for managing user sessions.

src/storage/storage-validation.schema.ts

STORAGE_VALIDATION_SCHEMA
Default value : Joi.object({ STORAGE_DRIVER: Joi.string() .valid("local", "s3") .default("local") .description("The storage driver to use") .meta({ group: "storage", order: 10 }), LOCAL_STORAGE_DIR: Joi.string() .when(Joi.ref("STORAGE_DRIVER"), { is: "local", then: Joi.string().default((parent) => join(parent.FOLDER, "uploads"), ), }) .description("The directory to store files in when using local storage") .meta({ group: "storage", order: 20 }), S3_REGION: Joi.string() .when(Joi.ref("STORAGE_DRIVER"), { is: "s3", then: Joi.required(), }) .description("The AWS region for the S3 bucket") .meta({ group: "storage", order: 30 }), S3_BUCKET: Joi.string() .when(Joi.ref("STORAGE_DRIVER"), { is: "s3", then: Joi.required(), }) .description("The name of the S3 bucket") .meta({ group: "storage", order: 40 }), S3_ACCESS_KEY_ID: Joi.string() .when(Joi.ref("STORAGE_DRIVER"), { is: "s3", then: Joi.required(), }) .description("The access key ID for the S3 bucket") .meta({ group: "storage", order: 50 }), S3_SECRET_ACCESS_KEY: Joi.string() .when(Joi.ref("STORAGE_DRIVER"), { is: "s3", then: Joi.required(), }) .description("The secret access key for the S3 bucket") .meta({ group: "storage", order: 60 }), S3_ENDPOINT: Joi.string() .when(Joi.ref("STORAGE_DRIVER"), { is: "s3", then: Joi.optional(), }) .description( "The endpoint URL for the S3 service (for S3-compatible services)", ) .meta({ group: "storage", order: 70 }), S3_FORCE_PATH_STYLE: Joi.boolean() .when(Joi.ref("STORAGE_DRIVER"), { is: "s3", then: Joi.boolean().default(false), }) .description("Whether to force path-style URLs for S3") .meta({ group: "storage", order: 80 }), S3_PUBLIC_BASE_URL: Joi.string() .when(Joi.ref("STORAGE_DRIVER"), { is: "s3", then: Joi.required(), }) .description("The public base URL for the S3 bucket") .meta({ group: "storage", order: 90 }), })

src/auth/token.decorator.ts

Token
Default value : createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user as TokenPayload; // Access the token payload on the request object }, )

Token decorator

src/utils/config-printer/combined.schema.ts

VALIDATION_SCHEMA
Default value : BASE_VALIDATION_SCHEMA.concat( AUTH_VALIDATION_SCHEMA, ) .concat(DB_VALIDATION_SCHEMA) .concat(CONFIG_VALIDATION_SCHEMA) .concat(LOG_VALIDATION_SCHEMA) .concat(REGISTRAR_VALIDATION_SCHEMA) .concat(KEY_VALIDATION_SCHEMA) .concat(CRYPTO_VALIDATION_SCHEMA) .concat(ISSUER_VALIDATION_SCHEMA) .concat(SESSION_VALIDATION_SCHEMA) .concat(STORAGE_VALIDATION_SCHEMA)

Combined validation schema for the application configuration

results matching ""

    No results matching ""