UNPKG

@sphereon/ssi-sdk.uni-resolver-registrar-api

Version:

428 lines (425 loc) • 14.3 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/api-functions.ts import { getAgentDIDMethods, toDidDocument, toDidResolutionResult } from "@sphereon/ssi-sdk-ext.did-utils"; import { JwkKeyUse } from "@sphereon/ssi-sdk-ext.key-utils"; import { checkAuth, sendErrorResponse } from "@sphereon/ssi-express-support"; import { parseDid } from "@sphereon/ssi-types"; import { v4 } from "uuid"; import Debug from "debug"; var debug = Debug("sphereon:ssi-sdk:uni-resolver-registrar"); function createDidEndpoint(router, context, opts) { if (opts?.enabled === false) { console.log(`create DID endpoint is disabled`); return; } const path = opts?.path ?? "/identifiers"; router.post(path, checkAuth(opts?.endpoint), async (request, response) => { try { const createRequest = request.body; if (!createRequest) { return sendErrorResponse(response, 400, "No DID create request present"); } const did = createRequest.did; const didMethod = request.query.method ?? (did ? parseDid(did).method : opts?.defaultMethod); const allDidMethods = await getAgentDIDMethods(context); if (!didMethod) { return sendErrorResponse(response, 400, "No DID method supplied or deductible"); } else if (did && parseDid(did).method != didMethod) { return sendErrorResponse(response, 400, "DID method did not match method param"); } else if (!allDidMethods.includes(didMethod)) { return sendErrorResponse(response, 400, "DID method not supported"); } const provider = `did:${didMethod}`; const jobId = createRequest.jobId ?? v4(); let alias = void 0; if (didMethod === "web") { if (!did) { return sendErrorResponse(response, 400, 'Please provide a value for "did" in the request body when creating a DID web'); } alias = parseDid(did).id; if (!alias) { return sendErrorResponse(response, 400, "Could not determine alias from did:web DID value: " + did); } } let identifier; let state; if (opts?.noErrorOnExistingDid && did) { try { identifier = await context.agent.didManagerGet({ did }); state = "exists"; } catch (e) { } } if (identifier === void 0) { if (createRequest.options.storeSecrets === false) { return sendErrorResponse(response, 400, "Only storeSecrets mode is supported currently"); } else if (createRequest.options.storeSecrets || opts?.storeSecrets) { identifier = await context.agent.didManagerCreate({ provider, alias, kms: opts?.kms }); state = "finished"; } else { return sendErrorResponse(response, 400, "Only storeSecrets mode is supported currently"); } } if (!identifier || !state) { return sendErrorResponse(response, 400, "An identifier and did state should be present at this point"); } const didDocument = toDidDocument(identifier, { did, use: [ JwkKeyUse.Signature, JwkKeyUse.Encryption ] }); const createState = { jobId, didState: { did: identifier.did, state, didDocument } }; response.statusCode = 200; return response.send(createState); } catch (e) { return sendErrorResponse(response, 500, e.message, e); } }); } __name(createDidEndpoint, "createDidEndpoint"); function getDidMethodsEndpoint(router, context, opts) { if (opts?.enabled === false) { console.log(`Get DID methods endpoint is disabled`); return; } const path = opts?.path ?? "/methods"; router.get(path, checkAuth(opts?.endpoint), async (request, response) => { try { const methods = await getAgentDIDMethods(context); response.statusCode = 200; return response.send(methods); } catch (e) { return sendErrorResponse(response, 500, e.message, e); } }); } __name(getDidMethodsEndpoint, "getDidMethodsEndpoint"); async function agentDidToResolutionResult(context, did) { try { const identifier = await context.agent.didManagerGet({ did }); debug(JSON.stringify(identifier, null, 2)); return toDidResolutionResult(identifier, { did, supportedMethods: await getAgentDIDMethods(context) }); } catch (error) { console.log(JSON.stringify(error.message)); return { didDocument: null, didResolutionMetadata: { error: "notFound" }, didDocumentMetadata: {} }; } } __name(agentDidToResolutionResult, "agentDidToResolutionResult"); function resolveDidEndpoint(router, context, opts) { if (opts?.enabled === false) { console.log(`Resolve DID endpoint is disabled`); return; } const path = opts?.path ?? "/identifiers/:identifier"; router.get(path, checkAuth(opts?.endpoint), async (request, response) => { try { const did = request.params.identifier; if (!did) { return sendErrorResponse(response, 400, "no identifier provided"); } const mode = request.query.mode?.toString().toLowerCase() ?? opts?.mode?.toLowerCase() ?? "hybrid"; let resolutionResult; if (mode === "local" || mode === "hybrid") { resolutionResult = await agentDidToResolutionResult(context, did); } if (mode !== "local" && !resolutionResult?.didDocument) { resolutionResult = await context.agent.resolveDid({ didUrl: did }); } response.statusCode = 200; return response.send(resolutionResult); } catch (e) { return sendErrorResponse(response, 500, e.message, e); } }); } __name(resolveDidEndpoint, "resolveDidEndpoint"); function deleteDidEndpoint(router, context, opts) { if (opts?.enabled === false) { console.log(`Deactivate DID endpoint is disabled`); return; } router.delete(opts?.path ?? "/identifiers/:identifier", checkAuth(opts?.endpoint), async (request, response) => { try { const did = request.params.identifier; if (!did) { return sendErrorResponse(response, 400, "no DID provided"); } const result = await context.agent.didManagerDelete({ did }); if (!result) { return sendErrorResponse(response, 404, `id ${did} not found`); } response.statusCode = 200; return response.send(); } catch (e) { return sendErrorResponse(response, 500, e.message, e); } }); } __name(deleteDidEndpoint, "deleteDidEndpoint"); function deactivateDidEndpoint(router, context, opts) { if (opts?.enabled === false) { console.log("Deactivate DID endpoint is disabled"); return; } router.post(opts?.path ?? "/deactivate", checkAuth(opts?.endpoint), async (request, response) => { try { const deactivateRequest = request.body; if (!deactivateRequest) { return sendErrorResponse(response, 400, "Invalid request body", { state: "failed" }); } const { did, jobId = v4() } = deactivateRequest; if (!did) { return sendErrorResponse(response, 400, "No DID provided", { state: "failed" }); } const result = await context.agent.didManagerDelete({ did }); if (!result) { return sendErrorResponse(response, 404, `DID ${did} not found`, { state: "failed" }); } response.status(200).json({ state: "finished", did, jobId }); return response.send(); } catch (e) { return sendErrorResponse(response, 500, e.message, { state: "failed", errorDetails: e }); } }); } __name(deactivateDidEndpoint, "deactivateDidEndpoint"); function didWebDomainEndpoint(router, context, opts) { if (opts?.enabled === false) { console.log(`DID Web domain resolution endpoint is disabled`); return; } router.get(opts?.path ?? ":path(*)/did.json", checkAuth(opts?.endpoint), async (request, response) => { try { const path = request.params.path; if (!path || path.length === 0) { return sendErrorResponse(response, 404, "Not found"); } let did; did = `did:web:${opts?.hostname?.replace("https://", "")?.replace("http://", "") ?? request.hostname}`; if (path !== "/.well-known") { if (opts?.disableSubPaths) { return sendErrorResponse(response, 404, "Not found"); } const suffix = path.replace(/\//g, ":").replace(/%2F/g, ":"); if (!suffix.startsWith(":")) { did += ":"; } did += suffix; } else if (opts?.disableWellKnown) { return sendErrorResponse(response, 404, "Not found"); } const resolutionResult = await agentDidToResolutionResult(context, did); if (!resolutionResult || !resolutionResult.didDocument || resolutionResult?.didResolutionMetadata?.error === "notFound") { return sendErrorResponse(response, 404, "Not found"); } const serviceEntries = await context.agent.lvpGetServiceEntries({ subjectDid: did }); if (resolutionResult?.didDocument && serviceEntries) { const existingServices = resolutionResult.didDocument.service || []; const nonLVPServices = existingServices.filter((service) => service.type !== "LinkedVerifiablePresentation"); resolutionResult.didDocument.service = [ ...nonLVPServices, ...serviceEntries ]; } const cleanService = /* @__PURE__ */ __name((svc) => { return Object.fromEntries(Object.entries(svc).filter(([_, v]) => v !== null && v !== void 0)); }, "cleanService"); if (resolutionResult?.didDocument?.service && typeof context.agent.getServiceMetadata === "function") { const enrichedServices = await Promise.all(resolutionResult.didDocument.service.map(async (service) => { try { const metadata = await context.agent.getServiceMetadata({ serviceId: service.id, did }); if (metadata?.einvoice) { return cleanService({ ...service, einvoice: metadata.einvoice }); } } catch (e) { debug(`No metadata found for service ${service.id}`); } return cleanService(service); })); resolutionResult.didDocument.service = enrichedServices; } else if (resolutionResult?.didDocument?.service) { resolutionResult.didDocument.service = resolutionResult.didDocument.service.map(cleanService); } response.statusCode = 200; return response.send(resolutionResult.didDocument); } catch (e) { return sendErrorResponse(response, 500, e.message, e); } }); } __name(didWebDomainEndpoint, "didWebDomainEndpoint"); // src/uni-resolver-api-server.ts import { agentContext } from "@sphereon/ssi-sdk.core"; import { copyGlobalAuthToEndpoints } from "@sphereon/ssi-express-support"; import express from "express"; var UniResolverApiServer = class { static { __name(this, "UniResolverApiServer"); } get router() { return this._router; } _express; _agent; _opts; _router; constructor(args) { const { agent, opts } = args; this._agent = agent; copyGlobalAuthToEndpoints({ opts, keys: [ "getDidMethods", "createDid", "resolveDid", "deactivateDid" ] }); this._opts = opts; this._express = args.expressSupport.express; this._router = express.Router(); const context = agentContext(agent); const features = opts?.enableFeatures ?? [ "did-resolve", "did-persist" ]; console.log(`DID Uni Resolver and Registrar API enabled, with features: ${JSON.stringify(features)}}`); if (features.includes("did-resolve")) { resolveDidEndpoint(this.router, context, opts?.endpointOpts?.resolveDid); getDidMethodsEndpoint(this.router, context, opts?.endpointOpts?.getDidMethods); } if (features.includes("did-persist")) { createDidEndpoint(this.router, context, opts?.endpointOpts?.createDid); deleteDidEndpoint(this.router, context, opts?.endpointOpts?.deactivateDid); deactivateDidEndpoint(this.router, context, opts?.endpointOpts?.deactivateDid); } this._express.use(opts?.endpointOpts?.basePath ?? "", this.router); } get agent() { return this._agent; } get opts() { return this._opts; } get express() { return this._express; } }; // src/did-web-server.ts import { agentContext as agentContext2 } from "@sphereon/ssi-sdk.core"; import express2 from "express"; var DidWebServer = class { static { __name(this, "DidWebServer"); } get router() { return this._router; } _express; _agent; _opts; _router; constructor(args) { const { agent, opts } = args; const features = opts?.enableFeatures ?? []; if (!features.includes("did-web-global-resolution")) { console.log("did:web hosting service NOT enabled"); return; } this._agent = agent; if (opts?.globalAuth) { copyGlobalAuthToEndpoint(opts, "endpointOpts"); } this._opts = opts; this._express = args.expressSupport.express; this._router = express2.Router(); const context = agentContext2(agent); console.log(`did:web hosting service enabled`); didWebDomainEndpoint(this.router, context, opts?.endpointOpts); this._express.use(this.router); } get agent() { return this._agent; } get opts() { return this._opts; } get express() { return this._express; } }; function copyGlobalAuthToEndpoint(opts, key) { if (opts?.globalAuth) { opts[key] = { ...opts?.globalAuth, // @ts-ignore ...opts[key] }; } } __name(copyGlobalAuthToEndpoint, "copyGlobalAuthToEndpoint"); export { DidWebServer, UniResolverApiServer, createDidEndpoint, deactivateDidEndpoint, deleteDidEndpoint, didWebDomainEndpoint, getDidMethodsEndpoint, resolveDidEndpoint }; //# sourceMappingURL=index.js.map