@sphereon/ssi-sdk.vc-status-list-issuer-rest-api 0.34.1-next.6 → 0.34.1-next.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +47 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +47 -16
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
- package/src/api-functions.ts +42 -10
package/dist/index.cjs
CHANGED
|
@@ -54,16 +54,16 @@ var import_ssi_sdk2 = require("@sphereon/ssi-sdk.vc-status-list-issuer-drivers")
|
|
|
54
54
|
var import_debug = __toESM(require("debug"), 1);
|
|
55
55
|
|
|
56
56
|
// src/types.ts
|
|
57
|
-
var StatusListIdType = /* @__PURE__ */ function(StatusListIdType2) {
|
|
57
|
+
var StatusListIdType = /* @__PURE__ */ (function(StatusListIdType2) {
|
|
58
58
|
StatusListIdType2["StatusListId"] = "StatusListId";
|
|
59
59
|
StatusListIdType2["StatusListCorrelationId"] = "StatusListCorrelationId";
|
|
60
60
|
return StatusListIdType2;
|
|
61
|
-
}({});
|
|
62
|
-
var EntryIdType = /* @__PURE__ */ function(EntryIdType2) {
|
|
61
|
+
})({});
|
|
62
|
+
var EntryIdType = /* @__PURE__ */ (function(EntryIdType2) {
|
|
63
63
|
EntryIdType2["StatusListIndex"] = "StatusListIndex";
|
|
64
64
|
EntryIdType2["EntryCorrelationId"] = "StatusListCorrelationId";
|
|
65
65
|
return EntryIdType2;
|
|
66
|
-
}({});
|
|
66
|
+
})({});
|
|
67
67
|
|
|
68
68
|
// src/api-functions.ts
|
|
69
69
|
var import_ssi_types = require("@sphereon/ssi-types");
|
|
@@ -139,6 +139,17 @@ function getStatusListCredentialEndpoint(router, context, opts) {
|
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
__name(getStatusListCredentialEndpoint, "getStatusListCredentialEndpoint");
|
|
142
|
+
function lookupType(details) {
|
|
143
|
+
switch (details.type) {
|
|
144
|
+
case import_ssi_types.StatusListType.StatusList2021:
|
|
145
|
+
return "StatusList2021Entry";
|
|
146
|
+
case import_ssi_types.StatusListType.BitstringStatusList:
|
|
147
|
+
return "BitstringStatusListEntry";
|
|
148
|
+
default:
|
|
149
|
+
return details.type;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
__name(lookupType, "lookupType");
|
|
142
153
|
function getStatusListCredentialIndexStatusEndpoint(router, context, opts) {
|
|
143
154
|
if (opts?.enabled === false) {
|
|
144
155
|
console.log(`Get statusList credential index status endpoint is disabled`);
|
|
@@ -191,16 +202,20 @@ function getStatusListCredentialIndexStatusEndpoint(router, context, opts) {
|
|
|
191
202
|
},
|
|
192
203
|
errorOnNotFound: false
|
|
193
204
|
});
|
|
194
|
-
const type = details
|
|
205
|
+
const type = lookupType(details);
|
|
195
206
|
const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0;
|
|
196
207
|
const status = await (0, import_ssi_sdk.checkStatusIndexFromStatusListCredential)({
|
|
197
208
|
statusListCredential: details.statusListCredential,
|
|
198
|
-
...details.type === import_ssi_types.StatusListType.StatusList2021 ? {
|
|
199
|
-
statusPurpose: details.statusList2021?.statusPurpose
|
|
200
|
-
} : {},
|
|
201
209
|
type,
|
|
202
210
|
id: details.id,
|
|
203
|
-
statusListIndex: resultStatusIndex
|
|
211
|
+
statusListIndex: resultStatusIndex,
|
|
212
|
+
...details.type === import_ssi_types.StatusListType.StatusList2021 && {
|
|
213
|
+
statusPurpose: details.statusList2021?.statusPurpose
|
|
214
|
+
},
|
|
215
|
+
...details.type === import_ssi_types.StatusListType.BitstringStatusList && {
|
|
216
|
+
statusPurpose: details.bitstringStatusList?.statusPurpose,
|
|
217
|
+
bitsPerStatus: details.bitstringStatusList?.bitsPerStatus
|
|
218
|
+
}
|
|
204
219
|
});
|
|
205
220
|
if (!entry) {
|
|
206
221
|
entry = {
|
|
@@ -210,10 +225,12 @@ function getStatusListCredentialIndexStatusEndpoint(router, context, opts) {
|
|
|
210
225
|
};
|
|
211
226
|
}
|
|
212
227
|
response.statusCode = 200;
|
|
213
|
-
|
|
228
|
+
const result = {
|
|
214
229
|
...entry,
|
|
215
230
|
status
|
|
216
|
-
}
|
|
231
|
+
};
|
|
232
|
+
delete result.statusList;
|
|
233
|
+
return response.json(result);
|
|
217
234
|
} catch (e) {
|
|
218
235
|
return (0, import_ssi_express_support.sendErrorResponse)(response, 500, e.message, e);
|
|
219
236
|
}
|
|
@@ -264,9 +281,13 @@ function getStatusListCredentialIndexStatusEndpointLegacy(router, context, opts)
|
|
|
264
281
|
const type = details.type === import_ssi_types.StatusListType.StatusList2021 ? "StatusList2021Entry" : details.type;
|
|
265
282
|
const status = await (0, import_ssi_sdk.checkStatusIndexFromStatusListCredential)({
|
|
266
283
|
statusListCredential: details.statusListCredential,
|
|
267
|
-
...details.type === import_ssi_types.StatusListType.StatusList2021
|
|
284
|
+
...details.type === import_ssi_types.StatusListType.StatusList2021 && {
|
|
268
285
|
statusPurpose: details.statusList2021?.statusPurpose
|
|
269
|
-
}
|
|
286
|
+
},
|
|
287
|
+
...details.type === import_ssi_types.StatusListType.BitstringStatusList && {
|
|
288
|
+
statusPurpose: details.bitstringStatusList?.statusPurpose,
|
|
289
|
+
bitsPerStatus: details.bitstringStatusList?.bitsPerStatus
|
|
290
|
+
},
|
|
270
291
|
type,
|
|
271
292
|
id: details.id,
|
|
272
293
|
statusListIndex
|
|
@@ -279,10 +300,12 @@ function getStatusListCredentialIndexStatusEndpointLegacy(router, context, opts)
|
|
|
279
300
|
};
|
|
280
301
|
}
|
|
281
302
|
response.statusCode = 200;
|
|
282
|
-
|
|
303
|
+
const result = {
|
|
283
304
|
...entry,
|
|
284
305
|
status
|
|
285
|
-
}
|
|
306
|
+
};
|
|
307
|
+
delete result.statusList;
|
|
308
|
+
return response.json(result);
|
|
286
309
|
} catch (e) {
|
|
287
310
|
return (0, import_ssi_express_support.sendErrorResponse)(response, 500, e.message, e);
|
|
288
311
|
}
|
|
@@ -363,7 +386,7 @@ function updateStatusEndpoint(router, context, opts) {
|
|
|
363
386
|
}
|
|
364
387
|
value = `${parseInt(updateItem.status)}`;
|
|
365
388
|
}
|
|
366
|
-
const updStatusListId = statusListId ?? statusListEntry.statusList?.id;
|
|
389
|
+
const updStatusListId = statusListId ?? ("statusList" in statusListEntry && statusListEntry.statusList?.id) ?? statusListEntry?.statusListId;
|
|
367
390
|
if (!updStatusListId) {
|
|
368
391
|
return (0, import_ssi_express_support.sendErrorResponse)(response, 400, "statuslist id could not be determined");
|
|
369
392
|
}
|
|
@@ -372,13 +395,21 @@ function updateStatusEndpoint(router, context, opts) {
|
|
|
372
395
|
statusListId: updStatusListId,
|
|
373
396
|
value
|
|
374
397
|
});
|
|
398
|
+
const bitsPerStatus = "bitsPerStatus" in statusListEntry && typeof statusListEntry.bitsPerStatus === "number" ? statusListEntry.bitsPerStatus : void 0;
|
|
375
399
|
statusListResult = await (0, import_ssi_sdk.updateStatusIndexFromStatusListCredential)({
|
|
376
400
|
statusListCredential,
|
|
377
401
|
statusListIndex: statusListEntry.statusListIndex,
|
|
402
|
+
...bitsPerStatus && {
|
|
403
|
+
bitsPerStatus
|
|
404
|
+
},
|
|
378
405
|
value: parseInt(value),
|
|
379
406
|
keyRef: opts.keyRef
|
|
380
407
|
}, context);
|
|
408
|
+
if (!statusListResult.correlationId) {
|
|
409
|
+
return Promise.reject(Error("Cannot update the statuslist, correlationId is missing from the status list result"));
|
|
410
|
+
}
|
|
381
411
|
statusListResult = await driver.updateStatusList({
|
|
412
|
+
correlationId: statusListResult.correlationId,
|
|
382
413
|
statusListCredential: statusListResult.statusListCredential
|
|
383
414
|
});
|
|
384
415
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/statuslist-management-api-server.ts","../src/api-functions.ts","../src/types.ts"],"sourcesContent":["/**\n * @public\n */\nexport * from './statuslist-management-api-server'\nexport * from './types'\nexport * from './api-functions'\n","import { copyGlobalAuthToEndpoint, ExpressSupport } from '@sphereon/ssi-express-support'\nimport { agentContext } from '@sphereon/ssi-sdk.core'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { TAgent } from '@veramo/core'\n\nimport express, { Express, Router } from 'express'\nimport {\n createNewStatusListEndpoint,\n getStatusListCredentialEndpoint,\n getStatusListCredentialIndexStatusEndpoint,\n getStatusListCredentialIndexStatusEndpointLegacy,\n updateStatusEndpoint,\n} from './api-functions'\nimport { IStatusListOpts } from './types'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\n\nexport class StatuslistManagementApiServer {\n get router(): express.Router {\n return this._router\n }\n\n private readonly _express: Express\n private readonly _agent: TAgent<IRequiredPlugins>\n private readonly _opts?: IStatusListOpts\n private readonly _router: Router\n\n constructor(args: { agent: TAgent<IRequiredPlugins & IStatusListPlugin>; expressSupport: ExpressSupport; opts: IStatusListOpts }) {\n const { agent, opts } = args\n this._agent = agent\n if (opts?.endpointOpts?.globalAuth) {\n copyGlobalAuthToEndpoint({ opts, key: 'vcApiCredentialStatus' })\n copyGlobalAuthToEndpoint({ opts, key: 'createStatusList' })\n copyGlobalAuthToEndpoint({ opts, key: 'getStatusList' })\n }\n\n this._opts = opts\n this._express = args.expressSupport.express\n this._router = express.Router()\n\n const context = agentContext(agent)\n\n const features = opts?.enableFeatures ?? ['status-list-management', 'status-list-hosting', 'w3c-vc-api-credential-status']\n console.log(`Status List API enabled, with features: ${JSON.stringify(features)}`)\n\n // Credential Status (List) endpoints\n if (features.includes('status-list-management')) {\n createNewStatusListEndpoint(this.router, context, opts.endpointOpts.createStatusList)\n }\n if (features.includes('status-list-hosting')) {\n getStatusListCredentialEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpointLegacy(this.router, context, opts.endpointOpts.getStatusList)\n }\n if (features.includes('w3c-vc-api-credential-status')) {\n updateStatusEndpoint(this.router, context, opts.endpointOpts.vcApiCredentialStatus)\n }\n this._express.use(opts?.endpointOpts?.basePath ?? '', this.router)\n }\n\n get agent(): TAgent<IRequiredPlugins> {\n return this._agent\n }\n\n get opts(): IStatusListOpts | undefined {\n return this._opts\n }\n\n get express(): Express {\n return this._express\n }\n}\n\n/*\nfunction copyGlobalAuthToEndpoint(opts: IStatusListOpts, key: string) {\n if (opts?.endpointOpts?.globalAuth) {\n // @ts-ignore\n opts.endpointOpts[key] = {\n // @ts-ignore\n ...opts.endpointOpts[key],\n // @ts-ignore\n endpoint: {...opts.endpointOpts.globalAuth, ...opts.endpointOpts[key]?.endpoint},\n }\n }\n}\n*/\n","import { checkAuth, sendErrorResponse } from '@sphereon/ssi-express-support'\nimport {\n checkStatusIndexFromStatusListCredential,\n CreateNewStatusListFuncArgs,\n StatusListResult,\n updateStatusIndexFromStatusListCredential,\n} from '@sphereon/ssi-sdk.vc-status-list'\nimport { getDriver } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport Debug from 'debug'\nimport { Request, Response, Router } from 'express'\nimport {\n EntryIdType,\n ICredentialStatusListEndpointOpts,\n IRequiredContext,\n IW3CredentialStatusEndpointOpts,\n StatusListIdType,\n UpdateIndexedCredentialStatusRequest,\n UpdateW3cCredentialStatusRequest,\n} from './types'\nimport { StatusListCredential, StatusListType } from '@sphereon/ssi-types'\nimport { IStatusListEntryEntity } from '@sphereon/ssi-sdk.data-store'\n\nconst debug = Debug('sphereon:ssi-sdk:status-list')\n\nfunction sendStatuslistResponse(details: StatusListResult, statuslistPayload: StatusListCredential, response: Response) {\n let payload: Buffer | StatusListCredential\n\n switch (details.proofFormat) {\n case 'jwt':\n case 'cbor':\n payload = Buffer.from(statuslistPayload as string, 'ascii')\n break\n default:\n payload = statuslistPayload\n }\n\n return response.status(200).setHeader('Content-Type', details.statuslistContentType).send(payload)\n}\n\nfunction buildStatusListId(request: Request): string {\n const protocol = request.headers['x-forwarded-proto']?.toString() ?? request.protocol\n let host = request.headers['x-forwarded-host']?.toString() ?? request.get('host')\n const forwardedPort = request.headers['x-forwarded-port']?.toString()\n\n if (forwardedPort && !(protocol === 'https' && forwardedPort === '443') && !(protocol === 'http' && forwardedPort === '80')) {\n host += `:${forwardedPort}`\n }\n\n const forwardedPrefix = request.headers['x-forwarded-prefix']?.toString() ?? ''\n\n return `${protocol}://${host}${forwardedPrefix}${request.originalUrl.split('?')[0].replace(/\\/status\\/index\\/.*/, '')}`\n}\n\nexport function createNewStatusListEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Create new status list endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists'\n\n router.post(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListArgs: CreateNewStatusListFuncArgs = request.body.statusList\n if (!statusListArgs) {\n return sendErrorResponse(response, 400, 'No statusList details supplied')\n }\n const details = await context.agent.slCreateStatusList(statusListArgs)\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const correlationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(correlationId ? { correlationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialIndexStatusEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n\n const path = opts?.path ?? '/status-lists/:statusListId/status/entry-by-id/:entryId'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListIdType = (request.query.statusListIdType as StatusListIdType) ?? StatusListIdType.StatusListId\n const entryIdType = (request.query.entryIdType as EntryIdType) ?? EntryIdType.StatusListIndex\n\n let statusListIndex: number | undefined\n let entityCorrelationId: string | undefined\n let statusListId: string | undefined\n let statusListCorrelationId: string | undefined\n\n if (entryIdType === EntryIdType.StatusListIndex) {\n try {\n statusListIndex = Number.parseInt(request.params.entryId)\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } else {\n entityCorrelationId = request.params.entryId\n }\n\n if (statusListIdType === StatusListIdType.StatusListId) {\n statusListId = request.params.statusListId\n } else {\n statusListCorrelationId = request.params.statusListId\n }\n\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: statusListId }),\n dbName: opts.dbName,\n })\n\n const details = await driver.getStatusList()\n if (statusListIndex && statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex }),\n errorOnNotFound: false,\n })\n\n const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type\n const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n ...(details.type === StatusListType.StatusList2021 ? { statusPurpose: details.statusList2021?.statusPurpose } : {}),\n type,\n id: details.id,\n statusListIndex: resultStatusIndex,\n })\n\n if (!entry) {\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex: resultStatusIndex,\n }\n }\n\n response.statusCode = 200\n return response.json({ ...entry, status })\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialIndexStatusEndpointLegacy(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index/status/index/:statusListIndex'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n const statusListIndexStr = request.params.statusListIndex\n let statusListIndex: number\n try {\n statusListIndex = Number.parseInt(statusListIndexStr)\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const statusListCorrelationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n if (statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n const entityCorrelationId = request.query.entityCorrelationId?.toString()\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex: statusListIndex }),\n errorOnNotFound: false,\n })\n const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n ...(details.type === StatusListType.StatusList2021 ? { statusPurpose: details.statusList2021?.statusPurpose } : {}),\n type,\n id: details.id,\n statusListIndex,\n })\n if (!entry) {\n // The fact we have nothing on it means the status is okay\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex,\n }\n }\n response.statusCode = 200\n return response.json({ ...entry, status })\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function updateStatusEndpoint(router: Router, context: IRequiredContext, opts: IW3CredentialStatusEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Update credential status endpoint is disabled`)\n return\n }\n router.post(opts?.path ?? '/credentials/status', checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n debug(JSON.stringify(request.body, null, 2))\n const updateRequest = request.body as UpdateW3cCredentialStatusRequest | UpdateIndexedCredentialStatusRequest\n const statusListId = updateRequest.statusListId ?? request.query.statusListId?.toString() ?? opts.statusListId // TODO why query params when we have a JSON body ??\n const statusListCorrelationId = updateRequest.statusListCorrelationId ?? request.query.statusListrelationId?.toString() ?? opts.correlationId\n const entryCorrelationId = updateRequest.entryCorrelationId ?? request.query.entryCorrelationId?.toString()\n\n // TODO: Move mostly to driver\n if (!statusListId && !statusListCorrelationId) {\n return sendErrorResponse(response, 400, 'No statusList id or correlation Id provided or deduced for the API or in the request')\n } else if (!updateRequest.credentialStatus || updateRequest.credentialStatus.length === 0) {\n return sendErrorResponse(response, 400, 'No statusList updates supplied')\n }\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n let statusListResult: StatusListResult = await driver.getStatusList()\n\n // Get status list entry based on request type\n let statusListEntry: IStatusListEntryEntity | undefined\n if ('credentialId' in updateRequest) {\n if (!updateRequest.credentialId) {\n return sendErrorResponse(response, 400, 'No credentialId supplied')\n }\n // unfortunately the W3C API works by credentialId. Which means you will have to map listIndices during issuance\n statusListEntry = await driver.getStatusListEntryByCredentialId({\n statusListId,\n statusListCorrelationId,\n entryCorrelationId,\n credentialId: updateRequest.credentialId,\n errorOnNotFound: true,\n })\n } else {\n statusListEntry = await driver.getStatusListEntryByIndex({\n ...(statusListResult.id && { statusListId: statusListResult.id }),\n ...(statusListResult.correlationId && { statusListCorrelationId: statusListResult.correlationId }),\n ...(entryCorrelationId ? { entryCorrelationId } : { statusListIndex: updateRequest.statusListIndex }),\n errorOnNotFound: true,\n })\n }\n\n if (!statusListEntry) {\n const identifier = 'credentialId' in updateRequest ? updateRequest.credentialId : `index ${updateRequest.statusListIndex}`\n return sendErrorResponse(response, 404, `Status list entry for ${identifier} not found for ${statusListId}`)\n }\n\n let statusListCredential = statusListResult.statusListCredential\n for (const updateItem of updateRequest.credentialStatus) {\n if (!updateItem.status) {\n return sendErrorResponse(response, 400, `Required 'status' value was missing in the credentialStatus array`)\n }\n\n let value: string = '1'\n if (updateItem.status === '0' || updateItem.status.toLowerCase() === 'false') {\n value = '0'\n } else if (updateItem.status !== '1' && updateItem.status.toLowerCase() !== 'true') {\n if (updateItem.type === StatusListType.StatusList2021) {\n // 2021 only allows 0 and 1\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n } else if (parseInt(updateItem.status) < 0 || parseInt(updateItem.status) > 255) {\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n }\n value = `${parseInt(updateItem.status)}`\n }\n\n const updStatusListId = statusListId ?? statusListEntry.statusList?.id // When input was statusListCorrelationId the statusList id should come from statusListEntry\n if (!updStatusListId) {\n return sendErrorResponse(response, 400, 'statuslist id could not be determined')\n }\n await driver.updateStatusListEntry({ ...statusListEntry, statusListId: updStatusListId, value })\n\n // todo: optimize. We are now creating a new VC for every item passed in. Probably wise to look at DB as well\n statusListResult = await updateStatusIndexFromStatusListCredential(\n {\n statusListCredential: statusListCredential,\n statusListIndex: statusListEntry.statusListIndex,\n value: parseInt(value),\n keyRef: opts.keyRef,\n },\n context,\n )\n statusListResult = await driver.updateStatusList({ statusListCredential: statusListResult.statusListCredential })\n }\n\n return sendStatuslistResponse(statusListResult, statusListResult.statusListCredential, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n","import { GenericAuthArgs, ISingleEndpointOpts } from '@sphereon/ssi-express-support'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport { StatusListType } from '@sphereon/ssi-types'\nimport { IAgentContext } from '@veramo/core'\n\nexport type IRequiredContext = IAgentContext<IRequiredPlugins & IStatusListPlugin>\n\nexport interface IStatusListOpts {\n endpointOpts: IStatusListEndpointOpts\n enableFeatures?: statusListFeatures[] // Feature to enable. If not defined or empty, all features will be enabled\n}\n\nexport interface IStatusListEndpointOpts {\n basePath?: string\n globalAuth?: GenericAuthArgs\n vcApiCredentialStatus: IW3CredentialStatusEndpointOpts\n createStatusList: ICredentialStatusListEndpointOpts\n getStatusList: ICredentialStatusListEndpointOpts\n}\n\nexport type statusListFeatures = 'w3c-vc-api-credential-status' | 'status-list-management' | 'status-list-hosting'\n\nexport interface ICredentialStatusListEndpointOpts extends ISingleEndpointOpts {\n dbName: string\n}\n\nexport interface IW3CredentialStatusEndpointOpts extends ICredentialStatusListEndpointOpts {\n statusListId?: string\n correlationId?: string\n keyRef?: string\n}\n\nexport interface UpdateW3cCredentialStatusRequest extends UpdateCredentialStatusRequest {\n credentialId: string\n}\n\nexport interface UpdateIndexedCredentialStatusRequest extends UpdateCredentialStatusRequest {\n statusListIndex?: number\n}\n\ninterface UpdateCredentialStatusRequest {\n credentialStatus: UpdateCredentialStatusItem[]\n statusListId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n statusListCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n entryCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n}\n\nexport interface UpdateCredentialStatusItem {\n type?: StatusListType // makes very little sense, but listed in the spec. Would expect a purpose\n status: string\n}\n\nexport enum StatusListIdType {\n StatusListId = 'StatusListId',\n StatusListCorrelationId = 'StatusListCorrelationId',\n}\n\nexport enum EntryIdType {\n StatusListIndex = 'StatusListIndex',\n EntryCorrelationId = 'StatusListCorrelationId',\n}\n"],"mappings":"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","names":["import_ssi_express_support","import_ssi_sdk","import_ssi_sdk","StatusListIdType","EntryIdType","debug","Debug","sendStatuslistResponse","details","statuslistPayload","response","payload","proofFormat","Buffer","from","status","setHeader","statuslistContentType","send","buildStatusListId","request","protocol","headers","toString","host","get","forwardedPort","forwardedPrefix","originalUrl","split","replace","createNewStatusListEndpoint","router","context","opts","enabled","console","log","path","post","checkAuth","endpoint","statusListArgs","body","statusList","sendErrorResponse","agent","slCreateStatusList","statusListCredential","e","message","getStatusListCredentialEndpoint","correlationId","query","driver","getDriver","id","dbName","getStatusList","getStatusListCredentialIndexStatusEndpoint","statusListIdType","StatusListIdType","StatusListId","entryIdType","EntryIdType","StatusListIndex","statusListIndex","entityCorrelationId","statusListId","statusListCorrelationId","Number","parseInt","params","entryId","error","length","entry","getStatusListEntryByIndex","errorOnNotFound","type","StatusListType","StatusList2021","resultStatusIndex","checkStatusIndexFromStatusListCredential","statusPurpose","statusList2021","value","statusCode","json","getStatusListCredentialIndexStatusEndpointLegacy","statusListIndexStr","updateStatusEndpoint","JSON","stringify","updateRequest","statusListrelationId","entryCorrelationId","credentialStatus","statusListResult","statusListEntry","credentialId","getStatusListEntryByCredentialId","identifier","updateItem","toLowerCase","updStatusListId","updateStatusListEntry","updateStatusIndexFromStatusListCredential","keyRef","updateStatusList","StatuslistManagementApiServer","router","_router","_express","_agent","_opts","args","agent","opts","endpointOpts","globalAuth","copyGlobalAuthToEndpoint","key","expressSupport","express","Router","context","agentContext","features","enableFeatures","console","log","JSON","stringify","includes","createNewStatusListEndpoint","createStatusList","getStatusListCredentialEndpoint","getStatusList","getStatusListCredentialIndexStatusEndpoint","getStatusListCredentialIndexStatusEndpointLegacy","updateStatusEndpoint","vcApiCredentialStatus","use","basePath"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/statuslist-management-api-server.ts","../src/api-functions.ts","../src/types.ts"],"sourcesContent":["/**\n * @public\n */\nexport * from './statuslist-management-api-server'\nexport * from './types'\nexport * from './api-functions'\n","import { copyGlobalAuthToEndpoint, ExpressSupport } from '@sphereon/ssi-express-support'\nimport { agentContext } from '@sphereon/ssi-sdk.core'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { TAgent } from '@veramo/core'\n\nimport express, { Express, Router } from 'express'\nimport {\n createNewStatusListEndpoint,\n getStatusListCredentialEndpoint,\n getStatusListCredentialIndexStatusEndpoint,\n getStatusListCredentialIndexStatusEndpointLegacy,\n updateStatusEndpoint,\n} from './api-functions'\nimport { IStatusListOpts } from './types'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\n\nexport class StatuslistManagementApiServer {\n get router(): express.Router {\n return this._router\n }\n\n private readonly _express: Express\n private readonly _agent: TAgent<IRequiredPlugins>\n private readonly _opts?: IStatusListOpts\n private readonly _router: Router\n\n constructor(args: { agent: TAgent<IRequiredPlugins & IStatusListPlugin>; expressSupport: ExpressSupport; opts: IStatusListOpts }) {\n const { agent, opts } = args\n this._agent = agent\n if (opts?.endpointOpts?.globalAuth) {\n copyGlobalAuthToEndpoint({ opts, key: 'vcApiCredentialStatus' })\n copyGlobalAuthToEndpoint({ opts, key: 'createStatusList' })\n copyGlobalAuthToEndpoint({ opts, key: 'getStatusList' })\n }\n\n this._opts = opts\n this._express = args.expressSupport.express\n this._router = express.Router()\n\n const context = agentContext(agent)\n\n const features = opts?.enableFeatures ?? ['status-list-management', 'status-list-hosting', 'w3c-vc-api-credential-status']\n console.log(`Status List API enabled, with features: ${JSON.stringify(features)}`)\n\n // Credential Status (List) endpoints\n if (features.includes('status-list-management')) {\n createNewStatusListEndpoint(this.router, context, opts.endpointOpts.createStatusList)\n }\n if (features.includes('status-list-hosting')) {\n getStatusListCredentialEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpointLegacy(this.router, context, opts.endpointOpts.getStatusList)\n }\n if (features.includes('w3c-vc-api-credential-status')) {\n updateStatusEndpoint(this.router, context, opts.endpointOpts.vcApiCredentialStatus)\n }\n this._express.use(opts?.endpointOpts?.basePath ?? '', this.router)\n }\n\n get agent(): TAgent<IRequiredPlugins> {\n return this._agent\n }\n\n get opts(): IStatusListOpts | undefined {\n return this._opts\n }\n\n get express(): Express {\n return this._express\n }\n}\n\n/*\nfunction copyGlobalAuthToEndpoint(opts: IStatusListOpts, key: string) {\n if (opts?.endpointOpts?.globalAuth) {\n // @ts-ignore\n opts.endpointOpts[key] = {\n // @ts-ignore\n ...opts.endpointOpts[key],\n // @ts-ignore\n endpoint: {...opts.endpointOpts.globalAuth, ...opts.endpointOpts[key]?.endpoint},\n }\n }\n}\n*/\n","import { checkAuth, sendErrorResponse } from '@sphereon/ssi-express-support'\nimport {\n checkStatusIndexFromStatusListCredential,\n CreateNewStatusListFuncArgs,\n StatusListResult,\n updateStatusIndexFromStatusListCredential,\n} from '@sphereon/ssi-sdk.vc-status-list'\nimport { getDriver } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport Debug from 'debug'\nimport { Request, Response, Router } from 'express'\nimport {\n EntryIdType,\n ICredentialStatusListEndpointOpts,\n IRequiredContext,\n IW3CredentialStatusEndpointOpts,\n StatusListIdType,\n UpdateIndexedCredentialStatusRequest,\n UpdateW3cCredentialStatusRequest,\n} from './types'\nimport { StatusListCredential, StatusListType } from '@sphereon/ssi-types'\nimport { IBitstringStatusListEntryEntity, IStatusListEntryEntity } from '@sphereon/ssi-sdk.data-store'\n\nconst debug = Debug('sphereon:ssi-sdk:status-list')\n\nfunction sendStatuslistResponse(details: StatusListResult, statuslistPayload: StatusListCredential, response: Response) {\n let payload: Buffer | StatusListCredential\n\n switch (details.proofFormat) {\n case 'jwt':\n case 'cbor':\n payload = Buffer.from(statuslistPayload as string, 'ascii')\n break\n default:\n payload = statuslistPayload\n }\n\n return response.status(200).setHeader('Content-Type', details.statuslistContentType).send(payload)\n}\n\nfunction buildStatusListId(request: Request): string {\n const protocol = request.headers['x-forwarded-proto']?.toString() ?? request.protocol\n let host = request.headers['x-forwarded-host']?.toString() ?? request.get('host')\n const forwardedPort = request.headers['x-forwarded-port']?.toString()\n\n if (forwardedPort && !(protocol === 'https' && forwardedPort === '443') && !(protocol === 'http' && forwardedPort === '80')) {\n host += `:${forwardedPort}`\n }\n\n const forwardedPrefix = request.headers['x-forwarded-prefix']?.toString() ?? ''\n\n return `${protocol}://${host}${forwardedPrefix}${request.originalUrl.split('?')[0].replace(/\\/status\\/index\\/.*/, '')}`\n}\n\nexport function createNewStatusListEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Create new status list endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists'\n\n router.post(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListArgs: CreateNewStatusListFuncArgs = request.body.statusList\n if (!statusListArgs) {\n return sendErrorResponse(response, 400, 'No statusList details supplied')\n }\n const details = await context.agent.slCreateStatusList(statusListArgs)\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const correlationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(correlationId ? { correlationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nfunction lookupType(details: StatusListResult) {\n switch (details.type) {\n case StatusListType.StatusList2021:\n return 'StatusList2021Entry'\n case StatusListType.BitstringStatusList:\n return 'BitstringStatusListEntry'\n default:\n return details.type\n }\n}\n\nexport function getStatusListCredentialIndexStatusEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n\n const path = opts?.path ?? '/status-lists/:statusListId/status/entry-by-id/:entryId'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListIdType = (request.query.statusListIdType as StatusListIdType) ?? StatusListIdType.StatusListId\n const entryIdType = (request.query.entryIdType as EntryIdType) ?? EntryIdType.StatusListIndex\n\n let statusListIndex: number | undefined\n let entityCorrelationId: string | undefined\n let statusListId: string | undefined\n let statusListCorrelationId: string | undefined\n\n if (entryIdType === EntryIdType.StatusListIndex) {\n try {\n statusListIndex = Number.parseInt(request.params.entryId)\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } else {\n entityCorrelationId = request.params.entryId\n }\n\n if (statusListIdType === StatusListIdType.StatusListId) {\n statusListId = request.params.statusListId\n } else {\n statusListCorrelationId = request.params.statusListId\n }\n\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: statusListId }),\n dbName: opts.dbName,\n })\n\n const details = await driver.getStatusList()\n if (statusListIndex && statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex }),\n errorOnNotFound: false,\n })\n\n const type = lookupType(details)\n const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n type,\n id: details.id,\n statusListIndex: resultStatusIndex,\n ...(details.type === StatusListType.StatusList2021 && { statusPurpose: details.statusList2021?.statusPurpose }),\n ...(details.type === StatusListType.BitstringStatusList && {\n statusPurpose: details.bitstringStatusList?.statusPurpose,\n bitsPerStatus: details.bitstringStatusList?.bitsPerStatus,\n }),\n })\n if (!entry) {\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex: resultStatusIndex,\n }\n }\n\n response.statusCode = 200\n const result = { ...entry, status }\n delete result.statusList // the API caller requested the index status, not the entire status list which may be big. Filter it out\n return response.json(result)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialIndexStatusEndpointLegacy(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index/status/index/:statusListIndex'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n const statusListIndexStr = request.params.statusListIndex\n let statusListIndex: number\n try {\n statusListIndex = Number.parseInt(statusListIndexStr)\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const statusListCorrelationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n if (statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n const entityCorrelationId = request.query.entityCorrelationId?.toString()\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex: statusListIndex }),\n errorOnNotFound: false,\n })\n const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n ...(details.type === StatusListType.StatusList2021 && { statusPurpose: details.statusList2021?.statusPurpose }),\n ...(details.type === StatusListType.BitstringStatusList && {\n statusPurpose: details.bitstringStatusList?.statusPurpose,\n bitsPerStatus: details.bitstringStatusList?.bitsPerStatus,\n }),\n type,\n id: details.id,\n statusListIndex,\n })\n if (!entry) {\n // The fact we have nothing on it means the status is okay\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex,\n }\n }\n response.statusCode = 200\n const result = { ...entry, status }\n delete result.statusList // we asked for the status, not the entire list\n return response.json(result)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function updateStatusEndpoint(router: Router, context: IRequiredContext, opts: IW3CredentialStatusEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Update credential status endpoint is disabled`)\n return\n }\n router.post(opts?.path ?? '/credentials/status', checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n debug(JSON.stringify(request.body, null, 2))\n const updateRequest = request.body as UpdateW3cCredentialStatusRequest | UpdateIndexedCredentialStatusRequest\n const statusListId = updateRequest.statusListId ?? request.query.statusListId?.toString() ?? opts.statusListId // TODO why query params when we have a JSON body ??\n const statusListCorrelationId = updateRequest.statusListCorrelationId ?? request.query.statusListrelationId?.toString() ?? opts.correlationId\n const entryCorrelationId = updateRequest.entryCorrelationId ?? request.query.entryCorrelationId?.toString()\n\n // TODO: Move mostly to driver\n if (!statusListId && !statusListCorrelationId) {\n return sendErrorResponse(response, 400, 'No statusList id or correlation Id provided or deduced for the API or in the request')\n } else if (!updateRequest.credentialStatus || updateRequest.credentialStatus.length === 0) {\n return sendErrorResponse(response, 400, 'No statusList updates supplied')\n }\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n let statusListResult: StatusListResult = await driver.getStatusList()\n\n // Get status list entry based on request type\n let statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity | undefined\n if ('credentialId' in updateRequest) {\n if (!updateRequest.credentialId) {\n return sendErrorResponse(response, 400, 'No credentialId supplied')\n }\n // unfortunately the W3C API works by credentialId. Which means you will have to map listIndices during issuance\n statusListEntry = await driver.getStatusListEntryByCredentialId({\n statusListId,\n statusListCorrelationId,\n entryCorrelationId,\n credentialId: updateRequest.credentialId,\n errorOnNotFound: true,\n })\n } else {\n statusListEntry = await driver.getStatusListEntryByIndex({\n ...(statusListResult.id && { statusListId: statusListResult.id }),\n ...(statusListResult.correlationId && { statusListCorrelationId: statusListResult.correlationId }),\n ...(entryCorrelationId ? { entryCorrelationId } : { statusListIndex: updateRequest.statusListIndex }),\n errorOnNotFound: true,\n })\n }\n\n if (!statusListEntry) {\n const identifier = 'credentialId' in updateRequest ? updateRequest.credentialId : `index ${updateRequest.statusListIndex}`\n return sendErrorResponse(response, 404, `Status list entry for ${identifier} not found for ${statusListId}`)\n }\n\n let statusListCredential = statusListResult.statusListCredential\n for (const updateItem of updateRequest.credentialStatus) {\n if (!updateItem.status) {\n return sendErrorResponse(response, 400, `Required 'status' value was missing in the credentialStatus array`)\n }\n\n let value: string = '1'\n if (updateItem.status === '0' || updateItem.status.toLowerCase() === 'false') {\n value = '0'\n } else if (updateItem.status !== '1' && updateItem.status.toLowerCase() !== 'true') {\n if (updateItem.type === StatusListType.StatusList2021) {\n // 2021 only allows 0 and 1\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n } else if (parseInt(updateItem.status) < 0 || parseInt(updateItem.status) > 255) {\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n }\n value = `${parseInt(updateItem.status)}`\n }\n\n const updStatusListId = statusListId ?? ('statusList' in statusListEntry && statusListEntry.statusList?.id) ?? statusListEntry?.statusListId // When input was statusListCorrelationId the statusList id should come from statusListEntry\n if (!updStatusListId) {\n return sendErrorResponse(response, 400, 'statuslist id could not be determined')\n }\n await driver.updateStatusListEntry({ ...statusListEntry, statusListId: updStatusListId, value })\n const bitsPerStatus =\n 'bitsPerStatus' in statusListEntry && typeof statusListEntry.bitsPerStatus === 'number' ? statusListEntry.bitsPerStatus : undefined\n\n // todo: optimize. We are now creating a new VC for every item passed in. Probably wise to look at DB as well\n statusListResult = await updateStatusIndexFromStatusListCredential(\n {\n statusListCredential: statusListCredential,\n statusListIndex: statusListEntry.statusListIndex,\n ...(bitsPerStatus && { bitsPerStatus }),\n value: parseInt(value),\n keyRef: opts.keyRef,\n },\n context,\n )\n\n if (!statusListResult.correlationId) {\n return Promise.reject(Error('Cannot update the statuslist, correlationId is missing from the status list result'))\n }\n statusListResult = await driver.updateStatusList({\n correlationId: statusListResult.correlationId,\n statusListCredential: statusListResult.statusListCredential,\n })\n }\n\n return sendStatuslistResponse(statusListResult, statusListResult.statusListCredential, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n","import { GenericAuthArgs, ISingleEndpointOpts } from '@sphereon/ssi-express-support'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport { StatusListType } from '@sphereon/ssi-types'\nimport { IAgentContext } from '@veramo/core'\n\nexport type IRequiredContext = IAgentContext<IRequiredPlugins & IStatusListPlugin>\n\nexport interface IStatusListOpts {\n endpointOpts: IStatusListEndpointOpts\n enableFeatures?: statusListFeatures[] // Feature to enable. If not defined or empty, all features will be enabled\n}\n\nexport interface IStatusListEndpointOpts {\n basePath?: string\n globalAuth?: GenericAuthArgs\n vcApiCredentialStatus: IW3CredentialStatusEndpointOpts\n createStatusList: ICredentialStatusListEndpointOpts\n getStatusList: ICredentialStatusListEndpointOpts\n}\n\nexport type statusListFeatures = 'w3c-vc-api-credential-status' | 'status-list-management' | 'status-list-hosting'\n\nexport interface ICredentialStatusListEndpointOpts extends ISingleEndpointOpts {\n dbName: string\n}\n\nexport interface IW3CredentialStatusEndpointOpts extends ICredentialStatusListEndpointOpts {\n statusListId?: string\n correlationId?: string\n keyRef?: string\n}\n\nexport interface UpdateW3cCredentialStatusRequest extends UpdateCredentialStatusRequest {\n credentialId: string\n}\n\nexport interface UpdateIndexedCredentialStatusRequest extends UpdateCredentialStatusRequest {\n statusListIndex?: number\n}\n\ninterface UpdateCredentialStatusRequest {\n credentialStatus: UpdateCredentialStatusItem[]\n statusListId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n statusListCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n entryCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n}\n\nexport interface UpdateCredentialStatusItem {\n type?: StatusListType // makes very little sense, but listed in the spec. Would expect a purpose\n status: string\n}\n\nexport enum StatusListIdType {\n StatusListId = 'StatusListId',\n StatusListCorrelationId = 'StatusListCorrelationId',\n}\n\nexport enum EntryIdType {\n StatusListIndex = 'StatusListIndex',\n EntryCorrelationId = 'StatusListCorrelationId',\n}\n"],"mappings":"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","names":["import_ssi_express_support","import_ssi_sdk","import_ssi_sdk","StatusListIdType","EntryIdType","debug","Debug","sendStatuslistResponse","details","statuslistPayload","response","payload","proofFormat","Buffer","from","status","setHeader","statuslistContentType","send","buildStatusListId","request","protocol","headers","toString","host","get","forwardedPort","forwardedPrefix","originalUrl","split","replace","createNewStatusListEndpoint","router","context","opts","enabled","console","log","path","post","checkAuth","endpoint","statusListArgs","body","statusList","sendErrorResponse","agent","slCreateStatusList","statusListCredential","e","message","getStatusListCredentialEndpoint","correlationId","query","driver","getDriver","id","dbName","getStatusList","lookupType","type","StatusListType","StatusList2021","BitstringStatusList","getStatusListCredentialIndexStatusEndpoint","statusListIdType","StatusListIdType","StatusListId","entryIdType","EntryIdType","StatusListIndex","statusListIndex","entityCorrelationId","statusListId","statusListCorrelationId","Number","parseInt","params","entryId","error","length","entry","getStatusListEntryByIndex","errorOnNotFound","resultStatusIndex","checkStatusIndexFromStatusListCredential","statusPurpose","statusList2021","bitstringStatusList","bitsPerStatus","value","statusCode","result","json","getStatusListCredentialIndexStatusEndpointLegacy","statusListIndexStr","updateStatusEndpoint","JSON","stringify","updateRequest","statusListrelationId","entryCorrelationId","credentialStatus","statusListResult","statusListEntry","credentialId","getStatusListEntryByCredentialId","identifier","updateItem","toLowerCase","updStatusListId","updateStatusListEntry","undefined","updateStatusIndexFromStatusListCredential","keyRef","Promise","reject","Error","updateStatusList","StatuslistManagementApiServer","router","_router","_express","_agent","_opts","args","agent","opts","endpointOpts","globalAuth","copyGlobalAuthToEndpoint","key","expressSupport","express","Router","context","agentContext","features","enableFeatures","console","log","JSON","stringify","includes","createNewStatusListEndpoint","createStatusList","getStatusListCredentialEndpoint","getStatusList","getStatusListCredentialIndexStatusEndpoint","getStatusListCredentialIndexStatusEndpointLegacy","updateStatusEndpoint","vcApiCredentialStatus","use","basePath"]}
|
package/dist/index.js
CHANGED
|
@@ -13,16 +13,16 @@ import { getDriver } from "@sphereon/ssi-sdk.vc-status-list-issuer-drivers";
|
|
|
13
13
|
import Debug from "debug";
|
|
14
14
|
|
|
15
15
|
// src/types.ts
|
|
16
|
-
var StatusListIdType = /* @__PURE__ */ function(StatusListIdType2) {
|
|
16
|
+
var StatusListIdType = /* @__PURE__ */ (function(StatusListIdType2) {
|
|
17
17
|
StatusListIdType2["StatusListId"] = "StatusListId";
|
|
18
18
|
StatusListIdType2["StatusListCorrelationId"] = "StatusListCorrelationId";
|
|
19
19
|
return StatusListIdType2;
|
|
20
|
-
}({});
|
|
21
|
-
var EntryIdType = /* @__PURE__ */ function(EntryIdType2) {
|
|
20
|
+
})({});
|
|
21
|
+
var EntryIdType = /* @__PURE__ */ (function(EntryIdType2) {
|
|
22
22
|
EntryIdType2["StatusListIndex"] = "StatusListIndex";
|
|
23
23
|
EntryIdType2["EntryCorrelationId"] = "StatusListCorrelationId";
|
|
24
24
|
return EntryIdType2;
|
|
25
|
-
}({});
|
|
25
|
+
})({});
|
|
26
26
|
|
|
27
27
|
// src/api-functions.ts
|
|
28
28
|
import { StatusListType } from "@sphereon/ssi-types";
|
|
@@ -98,6 +98,17 @@ function getStatusListCredentialEndpoint(router, context, opts) {
|
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
__name(getStatusListCredentialEndpoint, "getStatusListCredentialEndpoint");
|
|
101
|
+
function lookupType(details) {
|
|
102
|
+
switch (details.type) {
|
|
103
|
+
case StatusListType.StatusList2021:
|
|
104
|
+
return "StatusList2021Entry";
|
|
105
|
+
case StatusListType.BitstringStatusList:
|
|
106
|
+
return "BitstringStatusListEntry";
|
|
107
|
+
default:
|
|
108
|
+
return details.type;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
__name(lookupType, "lookupType");
|
|
101
112
|
function getStatusListCredentialIndexStatusEndpoint(router, context, opts) {
|
|
102
113
|
if (opts?.enabled === false) {
|
|
103
114
|
console.log(`Get statusList credential index status endpoint is disabled`);
|
|
@@ -150,16 +161,20 @@ function getStatusListCredentialIndexStatusEndpoint(router, context, opts) {
|
|
|
150
161
|
},
|
|
151
162
|
errorOnNotFound: false
|
|
152
163
|
});
|
|
153
|
-
const type = details
|
|
164
|
+
const type = lookupType(details);
|
|
154
165
|
const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0;
|
|
155
166
|
const status = await checkStatusIndexFromStatusListCredential({
|
|
156
167
|
statusListCredential: details.statusListCredential,
|
|
157
|
-
...details.type === StatusListType.StatusList2021 ? {
|
|
158
|
-
statusPurpose: details.statusList2021?.statusPurpose
|
|
159
|
-
} : {},
|
|
160
168
|
type,
|
|
161
169
|
id: details.id,
|
|
162
|
-
statusListIndex: resultStatusIndex
|
|
170
|
+
statusListIndex: resultStatusIndex,
|
|
171
|
+
...details.type === StatusListType.StatusList2021 && {
|
|
172
|
+
statusPurpose: details.statusList2021?.statusPurpose
|
|
173
|
+
},
|
|
174
|
+
...details.type === StatusListType.BitstringStatusList && {
|
|
175
|
+
statusPurpose: details.bitstringStatusList?.statusPurpose,
|
|
176
|
+
bitsPerStatus: details.bitstringStatusList?.bitsPerStatus
|
|
177
|
+
}
|
|
163
178
|
});
|
|
164
179
|
if (!entry) {
|
|
165
180
|
entry = {
|
|
@@ -169,10 +184,12 @@ function getStatusListCredentialIndexStatusEndpoint(router, context, opts) {
|
|
|
169
184
|
};
|
|
170
185
|
}
|
|
171
186
|
response.statusCode = 200;
|
|
172
|
-
|
|
187
|
+
const result = {
|
|
173
188
|
...entry,
|
|
174
189
|
status
|
|
175
|
-
}
|
|
190
|
+
};
|
|
191
|
+
delete result.statusList;
|
|
192
|
+
return response.json(result);
|
|
176
193
|
} catch (e) {
|
|
177
194
|
return sendErrorResponse(response, 500, e.message, e);
|
|
178
195
|
}
|
|
@@ -223,9 +240,13 @@ function getStatusListCredentialIndexStatusEndpointLegacy(router, context, opts)
|
|
|
223
240
|
const type = details.type === StatusListType.StatusList2021 ? "StatusList2021Entry" : details.type;
|
|
224
241
|
const status = await checkStatusIndexFromStatusListCredential({
|
|
225
242
|
statusListCredential: details.statusListCredential,
|
|
226
|
-
...details.type === StatusListType.StatusList2021
|
|
243
|
+
...details.type === StatusListType.StatusList2021 && {
|
|
227
244
|
statusPurpose: details.statusList2021?.statusPurpose
|
|
228
|
-
}
|
|
245
|
+
},
|
|
246
|
+
...details.type === StatusListType.BitstringStatusList && {
|
|
247
|
+
statusPurpose: details.bitstringStatusList?.statusPurpose,
|
|
248
|
+
bitsPerStatus: details.bitstringStatusList?.bitsPerStatus
|
|
249
|
+
},
|
|
229
250
|
type,
|
|
230
251
|
id: details.id,
|
|
231
252
|
statusListIndex
|
|
@@ -238,10 +259,12 @@ function getStatusListCredentialIndexStatusEndpointLegacy(router, context, opts)
|
|
|
238
259
|
};
|
|
239
260
|
}
|
|
240
261
|
response.statusCode = 200;
|
|
241
|
-
|
|
262
|
+
const result = {
|
|
242
263
|
...entry,
|
|
243
264
|
status
|
|
244
|
-
}
|
|
265
|
+
};
|
|
266
|
+
delete result.statusList;
|
|
267
|
+
return response.json(result);
|
|
245
268
|
} catch (e) {
|
|
246
269
|
return sendErrorResponse(response, 500, e.message, e);
|
|
247
270
|
}
|
|
@@ -322,7 +345,7 @@ function updateStatusEndpoint(router, context, opts) {
|
|
|
322
345
|
}
|
|
323
346
|
value = `${parseInt(updateItem.status)}`;
|
|
324
347
|
}
|
|
325
|
-
const updStatusListId = statusListId ?? statusListEntry.statusList?.id;
|
|
348
|
+
const updStatusListId = statusListId ?? ("statusList" in statusListEntry && statusListEntry.statusList?.id) ?? statusListEntry?.statusListId;
|
|
326
349
|
if (!updStatusListId) {
|
|
327
350
|
return sendErrorResponse(response, 400, "statuslist id could not be determined");
|
|
328
351
|
}
|
|
@@ -331,13 +354,21 @@ function updateStatusEndpoint(router, context, opts) {
|
|
|
331
354
|
statusListId: updStatusListId,
|
|
332
355
|
value
|
|
333
356
|
});
|
|
357
|
+
const bitsPerStatus = "bitsPerStatus" in statusListEntry && typeof statusListEntry.bitsPerStatus === "number" ? statusListEntry.bitsPerStatus : void 0;
|
|
334
358
|
statusListResult = await updateStatusIndexFromStatusListCredential({
|
|
335
359
|
statusListCredential,
|
|
336
360
|
statusListIndex: statusListEntry.statusListIndex,
|
|
361
|
+
...bitsPerStatus && {
|
|
362
|
+
bitsPerStatus
|
|
363
|
+
},
|
|
337
364
|
value: parseInt(value),
|
|
338
365
|
keyRef: opts.keyRef
|
|
339
366
|
}, context);
|
|
367
|
+
if (!statusListResult.correlationId) {
|
|
368
|
+
return Promise.reject(Error("Cannot update the statuslist, correlationId is missing from the status list result"));
|
|
369
|
+
}
|
|
340
370
|
statusListResult = await driver.updateStatusList({
|
|
371
|
+
correlationId: statusListResult.correlationId,
|
|
341
372
|
statusListCredential: statusListResult.statusListCredential
|
|
342
373
|
});
|
|
343
374
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/statuslist-management-api-server.ts","../src/api-functions.ts","../src/types.ts"],"sourcesContent":["import { copyGlobalAuthToEndpoint, ExpressSupport } from '@sphereon/ssi-express-support'\nimport { agentContext } from '@sphereon/ssi-sdk.core'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { TAgent } from '@veramo/core'\n\nimport express, { Express, Router } from 'express'\nimport {\n createNewStatusListEndpoint,\n getStatusListCredentialEndpoint,\n getStatusListCredentialIndexStatusEndpoint,\n getStatusListCredentialIndexStatusEndpointLegacy,\n updateStatusEndpoint,\n} from './api-functions'\nimport { IStatusListOpts } from './types'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\n\nexport class StatuslistManagementApiServer {\n get router(): express.Router {\n return this._router\n }\n\n private readonly _express: Express\n private readonly _agent: TAgent<IRequiredPlugins>\n private readonly _opts?: IStatusListOpts\n private readonly _router: Router\n\n constructor(args: { agent: TAgent<IRequiredPlugins & IStatusListPlugin>; expressSupport: ExpressSupport; opts: IStatusListOpts }) {\n const { agent, opts } = args\n this._agent = agent\n if (opts?.endpointOpts?.globalAuth) {\n copyGlobalAuthToEndpoint({ opts, key: 'vcApiCredentialStatus' })\n copyGlobalAuthToEndpoint({ opts, key: 'createStatusList' })\n copyGlobalAuthToEndpoint({ opts, key: 'getStatusList' })\n }\n\n this._opts = opts\n this._express = args.expressSupport.express\n this._router = express.Router()\n\n const context = agentContext(agent)\n\n const features = opts?.enableFeatures ?? ['status-list-management', 'status-list-hosting', 'w3c-vc-api-credential-status']\n console.log(`Status List API enabled, with features: ${JSON.stringify(features)}`)\n\n // Credential Status (List) endpoints\n if (features.includes('status-list-management')) {\n createNewStatusListEndpoint(this.router, context, opts.endpointOpts.createStatusList)\n }\n if (features.includes('status-list-hosting')) {\n getStatusListCredentialEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpointLegacy(this.router, context, opts.endpointOpts.getStatusList)\n }\n if (features.includes('w3c-vc-api-credential-status')) {\n updateStatusEndpoint(this.router, context, opts.endpointOpts.vcApiCredentialStatus)\n }\n this._express.use(opts?.endpointOpts?.basePath ?? '', this.router)\n }\n\n get agent(): TAgent<IRequiredPlugins> {\n return this._agent\n }\n\n get opts(): IStatusListOpts | undefined {\n return this._opts\n }\n\n get express(): Express {\n return this._express\n }\n}\n\n/*\nfunction copyGlobalAuthToEndpoint(opts: IStatusListOpts, key: string) {\n if (opts?.endpointOpts?.globalAuth) {\n // @ts-ignore\n opts.endpointOpts[key] = {\n // @ts-ignore\n ...opts.endpointOpts[key],\n // @ts-ignore\n endpoint: {...opts.endpointOpts.globalAuth, ...opts.endpointOpts[key]?.endpoint},\n }\n }\n}\n*/\n","import { checkAuth, sendErrorResponse } from '@sphereon/ssi-express-support'\nimport {\n checkStatusIndexFromStatusListCredential,\n CreateNewStatusListFuncArgs,\n StatusListResult,\n updateStatusIndexFromStatusListCredential,\n} from '@sphereon/ssi-sdk.vc-status-list'\nimport { getDriver } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport Debug from 'debug'\nimport { Request, Response, Router } from 'express'\nimport {\n EntryIdType,\n ICredentialStatusListEndpointOpts,\n IRequiredContext,\n IW3CredentialStatusEndpointOpts,\n StatusListIdType,\n UpdateIndexedCredentialStatusRequest,\n UpdateW3cCredentialStatusRequest,\n} from './types'\nimport { StatusListCredential, StatusListType } from '@sphereon/ssi-types'\nimport { IStatusListEntryEntity } from '@sphereon/ssi-sdk.data-store'\n\nconst debug = Debug('sphereon:ssi-sdk:status-list')\n\nfunction sendStatuslistResponse(details: StatusListResult, statuslistPayload: StatusListCredential, response: Response) {\n let payload: Buffer | StatusListCredential\n\n switch (details.proofFormat) {\n case 'jwt':\n case 'cbor':\n payload = Buffer.from(statuslistPayload as string, 'ascii')\n break\n default:\n payload = statuslistPayload\n }\n\n return response.status(200).setHeader('Content-Type', details.statuslistContentType).send(payload)\n}\n\nfunction buildStatusListId(request: Request): string {\n const protocol = request.headers['x-forwarded-proto']?.toString() ?? request.protocol\n let host = request.headers['x-forwarded-host']?.toString() ?? request.get('host')\n const forwardedPort = request.headers['x-forwarded-port']?.toString()\n\n if (forwardedPort && !(protocol === 'https' && forwardedPort === '443') && !(protocol === 'http' && forwardedPort === '80')) {\n host += `:${forwardedPort}`\n }\n\n const forwardedPrefix = request.headers['x-forwarded-prefix']?.toString() ?? ''\n\n return `${protocol}://${host}${forwardedPrefix}${request.originalUrl.split('?')[0].replace(/\\/status\\/index\\/.*/, '')}`\n}\n\nexport function createNewStatusListEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Create new status list endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists'\n\n router.post(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListArgs: CreateNewStatusListFuncArgs = request.body.statusList\n if (!statusListArgs) {\n return sendErrorResponse(response, 400, 'No statusList details supplied')\n }\n const details = await context.agent.slCreateStatusList(statusListArgs)\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const correlationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(correlationId ? { correlationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialIndexStatusEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n\n const path = opts?.path ?? '/status-lists/:statusListId/status/entry-by-id/:entryId'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListIdType = (request.query.statusListIdType as StatusListIdType) ?? StatusListIdType.StatusListId\n const entryIdType = (request.query.entryIdType as EntryIdType) ?? EntryIdType.StatusListIndex\n\n let statusListIndex: number | undefined\n let entityCorrelationId: string | undefined\n let statusListId: string | undefined\n let statusListCorrelationId: string | undefined\n\n if (entryIdType === EntryIdType.StatusListIndex) {\n try {\n statusListIndex = Number.parseInt(request.params.entryId)\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } else {\n entityCorrelationId = request.params.entryId\n }\n\n if (statusListIdType === StatusListIdType.StatusListId) {\n statusListId = request.params.statusListId\n } else {\n statusListCorrelationId = request.params.statusListId\n }\n\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: statusListId }),\n dbName: opts.dbName,\n })\n\n const details = await driver.getStatusList()\n if (statusListIndex && statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex }),\n errorOnNotFound: false,\n })\n\n const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type\n const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n ...(details.type === StatusListType.StatusList2021 ? { statusPurpose: details.statusList2021?.statusPurpose } : {}),\n type,\n id: details.id,\n statusListIndex: resultStatusIndex,\n })\n\n if (!entry) {\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex: resultStatusIndex,\n }\n }\n\n response.statusCode = 200\n return response.json({ ...entry, status })\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialIndexStatusEndpointLegacy(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index/status/index/:statusListIndex'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n const statusListIndexStr = request.params.statusListIndex\n let statusListIndex: number\n try {\n statusListIndex = Number.parseInt(statusListIndexStr)\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const statusListCorrelationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n if (statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n const entityCorrelationId = request.query.entityCorrelationId?.toString()\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex: statusListIndex }),\n errorOnNotFound: false,\n })\n const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n ...(details.type === StatusListType.StatusList2021 ? { statusPurpose: details.statusList2021?.statusPurpose } : {}),\n type,\n id: details.id,\n statusListIndex,\n })\n if (!entry) {\n // The fact we have nothing on it means the status is okay\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex,\n }\n }\n response.statusCode = 200\n return response.json({ ...entry, status })\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function updateStatusEndpoint(router: Router, context: IRequiredContext, opts: IW3CredentialStatusEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Update credential status endpoint is disabled`)\n return\n }\n router.post(opts?.path ?? '/credentials/status', checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n debug(JSON.stringify(request.body, null, 2))\n const updateRequest = request.body as UpdateW3cCredentialStatusRequest | UpdateIndexedCredentialStatusRequest\n const statusListId = updateRequest.statusListId ?? request.query.statusListId?.toString() ?? opts.statusListId // TODO why query params when we have a JSON body ??\n const statusListCorrelationId = updateRequest.statusListCorrelationId ?? request.query.statusListrelationId?.toString() ?? opts.correlationId\n const entryCorrelationId = updateRequest.entryCorrelationId ?? request.query.entryCorrelationId?.toString()\n\n // TODO: Move mostly to driver\n if (!statusListId && !statusListCorrelationId) {\n return sendErrorResponse(response, 400, 'No statusList id or correlation Id provided or deduced for the API or in the request')\n } else if (!updateRequest.credentialStatus || updateRequest.credentialStatus.length === 0) {\n return sendErrorResponse(response, 400, 'No statusList updates supplied')\n }\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n let statusListResult: StatusListResult = await driver.getStatusList()\n\n // Get status list entry based on request type\n let statusListEntry: IStatusListEntryEntity | undefined\n if ('credentialId' in updateRequest) {\n if (!updateRequest.credentialId) {\n return sendErrorResponse(response, 400, 'No credentialId supplied')\n }\n // unfortunately the W3C API works by credentialId. Which means you will have to map listIndices during issuance\n statusListEntry = await driver.getStatusListEntryByCredentialId({\n statusListId,\n statusListCorrelationId,\n entryCorrelationId,\n credentialId: updateRequest.credentialId,\n errorOnNotFound: true,\n })\n } else {\n statusListEntry = await driver.getStatusListEntryByIndex({\n ...(statusListResult.id && { statusListId: statusListResult.id }),\n ...(statusListResult.correlationId && { statusListCorrelationId: statusListResult.correlationId }),\n ...(entryCorrelationId ? { entryCorrelationId } : { statusListIndex: updateRequest.statusListIndex }),\n errorOnNotFound: true,\n })\n }\n\n if (!statusListEntry) {\n const identifier = 'credentialId' in updateRequest ? updateRequest.credentialId : `index ${updateRequest.statusListIndex}`\n return sendErrorResponse(response, 404, `Status list entry for ${identifier} not found for ${statusListId}`)\n }\n\n let statusListCredential = statusListResult.statusListCredential\n for (const updateItem of updateRequest.credentialStatus) {\n if (!updateItem.status) {\n return sendErrorResponse(response, 400, `Required 'status' value was missing in the credentialStatus array`)\n }\n\n let value: string = '1'\n if (updateItem.status === '0' || updateItem.status.toLowerCase() === 'false') {\n value = '0'\n } else if (updateItem.status !== '1' && updateItem.status.toLowerCase() !== 'true') {\n if (updateItem.type === StatusListType.StatusList2021) {\n // 2021 only allows 0 and 1\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n } else if (parseInt(updateItem.status) < 0 || parseInt(updateItem.status) > 255) {\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n }\n value = `${parseInt(updateItem.status)}`\n }\n\n const updStatusListId = statusListId ?? statusListEntry.statusList?.id // When input was statusListCorrelationId the statusList id should come from statusListEntry\n if (!updStatusListId) {\n return sendErrorResponse(response, 400, 'statuslist id could not be determined')\n }\n await driver.updateStatusListEntry({ ...statusListEntry, statusListId: updStatusListId, value })\n\n // todo: optimize. We are now creating a new VC for every item passed in. Probably wise to look at DB as well\n statusListResult = await updateStatusIndexFromStatusListCredential(\n {\n statusListCredential: statusListCredential,\n statusListIndex: statusListEntry.statusListIndex,\n value: parseInt(value),\n keyRef: opts.keyRef,\n },\n context,\n )\n statusListResult = await driver.updateStatusList({ statusListCredential: statusListResult.statusListCredential })\n }\n\n return sendStatuslistResponse(statusListResult, statusListResult.statusListCredential, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n","import { GenericAuthArgs, ISingleEndpointOpts } from '@sphereon/ssi-express-support'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport { StatusListType } from '@sphereon/ssi-types'\nimport { IAgentContext } from '@veramo/core'\n\nexport type IRequiredContext = IAgentContext<IRequiredPlugins & IStatusListPlugin>\n\nexport interface IStatusListOpts {\n endpointOpts: IStatusListEndpointOpts\n enableFeatures?: statusListFeatures[] // Feature to enable. If not defined or empty, all features will be enabled\n}\n\nexport interface IStatusListEndpointOpts {\n basePath?: string\n globalAuth?: GenericAuthArgs\n vcApiCredentialStatus: IW3CredentialStatusEndpointOpts\n createStatusList: ICredentialStatusListEndpointOpts\n getStatusList: ICredentialStatusListEndpointOpts\n}\n\nexport type statusListFeatures = 'w3c-vc-api-credential-status' | 'status-list-management' | 'status-list-hosting'\n\nexport interface ICredentialStatusListEndpointOpts extends ISingleEndpointOpts {\n dbName: string\n}\n\nexport interface IW3CredentialStatusEndpointOpts extends ICredentialStatusListEndpointOpts {\n statusListId?: string\n correlationId?: string\n keyRef?: string\n}\n\nexport interface UpdateW3cCredentialStatusRequest extends UpdateCredentialStatusRequest {\n credentialId: string\n}\n\nexport interface UpdateIndexedCredentialStatusRequest extends UpdateCredentialStatusRequest {\n statusListIndex?: number\n}\n\ninterface UpdateCredentialStatusRequest {\n credentialStatus: UpdateCredentialStatusItem[]\n statusListId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n statusListCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n entryCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n}\n\nexport interface UpdateCredentialStatusItem {\n type?: StatusListType // makes very little sense, but listed in the spec. Would expect a purpose\n status: string\n}\n\nexport enum StatusListIdType {\n StatusListId = 'StatusListId',\n StatusListCorrelationId = 'StatusListCorrelationId',\n}\n\nexport enum EntryIdType {\n StatusListIndex = 'StatusListIndex',\n EntryCorrelationId = 'StatusListCorrelationId',\n}\n"],"mappings":"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","names":["copyGlobalAuthToEndpoint","agentContext","express","checkAuth","sendErrorResponse","checkStatusIndexFromStatusListCredential","updateStatusIndexFromStatusListCredential","getDriver","Debug","StatusListIdType","EntryIdType","StatusListType","debug","Debug","sendStatuslistResponse","details","statuslistPayload","response","payload","proofFormat","Buffer","from","status","setHeader","statuslistContentType","send","buildStatusListId","request","protocol","headers","toString","host","get","forwardedPort","forwardedPrefix","originalUrl","split","replace","createNewStatusListEndpoint","router","context","opts","enabled","console","log","path","post","checkAuth","endpoint","statusListArgs","body","statusList","sendErrorResponse","agent","slCreateStatusList","statusListCredential","e","message","getStatusListCredentialEndpoint","correlationId","query","driver","getDriver","id","dbName","getStatusList","getStatusListCredentialIndexStatusEndpoint","statusListIdType","StatusListIdType","StatusListId","entryIdType","EntryIdType","StatusListIndex","statusListIndex","entityCorrelationId","statusListId","statusListCorrelationId","Number","parseInt","params","entryId","error","length","entry","getStatusListEntryByIndex","errorOnNotFound","type","StatusListType","StatusList2021","resultStatusIndex","checkStatusIndexFromStatusListCredential","statusPurpose","statusList2021","value","statusCode","json","getStatusListCredentialIndexStatusEndpointLegacy","statusListIndexStr","updateStatusEndpoint","JSON","stringify","updateRequest","statusListrelationId","entryCorrelationId","credentialStatus","statusListResult","statusListEntry","credentialId","getStatusListEntryByCredentialId","identifier","updateItem","toLowerCase","updStatusListId","updateStatusListEntry","updateStatusIndexFromStatusListCredential","keyRef","updateStatusList","StatuslistManagementApiServer","router","_router","_express","_agent","_opts","args","agent","opts","endpointOpts","globalAuth","copyGlobalAuthToEndpoint","key","expressSupport","express","Router","context","agentContext","features","enableFeatures","console","log","JSON","stringify","includes","createNewStatusListEndpoint","createStatusList","getStatusListCredentialEndpoint","getStatusList","getStatusListCredentialIndexStatusEndpoint","getStatusListCredentialIndexStatusEndpointLegacy","updateStatusEndpoint","vcApiCredentialStatus","use","basePath"]}
|
|
1
|
+
{"version":3,"sources":["../src/statuslist-management-api-server.ts","../src/api-functions.ts","../src/types.ts"],"sourcesContent":["import { copyGlobalAuthToEndpoint, ExpressSupport } from '@sphereon/ssi-express-support'\nimport { agentContext } from '@sphereon/ssi-sdk.core'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { TAgent } from '@veramo/core'\n\nimport express, { Express, Router } from 'express'\nimport {\n createNewStatusListEndpoint,\n getStatusListCredentialEndpoint,\n getStatusListCredentialIndexStatusEndpoint,\n getStatusListCredentialIndexStatusEndpointLegacy,\n updateStatusEndpoint,\n} from './api-functions'\nimport { IStatusListOpts } from './types'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\n\nexport class StatuslistManagementApiServer {\n get router(): express.Router {\n return this._router\n }\n\n private readonly _express: Express\n private readonly _agent: TAgent<IRequiredPlugins>\n private readonly _opts?: IStatusListOpts\n private readonly _router: Router\n\n constructor(args: { agent: TAgent<IRequiredPlugins & IStatusListPlugin>; expressSupport: ExpressSupport; opts: IStatusListOpts }) {\n const { agent, opts } = args\n this._agent = agent\n if (opts?.endpointOpts?.globalAuth) {\n copyGlobalAuthToEndpoint({ opts, key: 'vcApiCredentialStatus' })\n copyGlobalAuthToEndpoint({ opts, key: 'createStatusList' })\n copyGlobalAuthToEndpoint({ opts, key: 'getStatusList' })\n }\n\n this._opts = opts\n this._express = args.expressSupport.express\n this._router = express.Router()\n\n const context = agentContext(agent)\n\n const features = opts?.enableFeatures ?? ['status-list-management', 'status-list-hosting', 'w3c-vc-api-credential-status']\n console.log(`Status List API enabled, with features: ${JSON.stringify(features)}`)\n\n // Credential Status (List) endpoints\n if (features.includes('status-list-management')) {\n createNewStatusListEndpoint(this.router, context, opts.endpointOpts.createStatusList)\n }\n if (features.includes('status-list-hosting')) {\n getStatusListCredentialEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpoint(this.router, context, opts.endpointOpts.getStatusList)\n getStatusListCredentialIndexStatusEndpointLegacy(this.router, context, opts.endpointOpts.getStatusList)\n }\n if (features.includes('w3c-vc-api-credential-status')) {\n updateStatusEndpoint(this.router, context, opts.endpointOpts.vcApiCredentialStatus)\n }\n this._express.use(opts?.endpointOpts?.basePath ?? '', this.router)\n }\n\n get agent(): TAgent<IRequiredPlugins> {\n return this._agent\n }\n\n get opts(): IStatusListOpts | undefined {\n return this._opts\n }\n\n get express(): Express {\n return this._express\n }\n}\n\n/*\nfunction copyGlobalAuthToEndpoint(opts: IStatusListOpts, key: string) {\n if (opts?.endpointOpts?.globalAuth) {\n // @ts-ignore\n opts.endpointOpts[key] = {\n // @ts-ignore\n ...opts.endpointOpts[key],\n // @ts-ignore\n endpoint: {...opts.endpointOpts.globalAuth, ...opts.endpointOpts[key]?.endpoint},\n }\n }\n}\n*/\n","import { checkAuth, sendErrorResponse } from '@sphereon/ssi-express-support'\nimport {\n checkStatusIndexFromStatusListCredential,\n CreateNewStatusListFuncArgs,\n StatusListResult,\n updateStatusIndexFromStatusListCredential,\n} from '@sphereon/ssi-sdk.vc-status-list'\nimport { getDriver } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport Debug from 'debug'\nimport { Request, Response, Router } from 'express'\nimport {\n EntryIdType,\n ICredentialStatusListEndpointOpts,\n IRequiredContext,\n IW3CredentialStatusEndpointOpts,\n StatusListIdType,\n UpdateIndexedCredentialStatusRequest,\n UpdateW3cCredentialStatusRequest,\n} from './types'\nimport { StatusListCredential, StatusListType } from '@sphereon/ssi-types'\nimport { IBitstringStatusListEntryEntity, IStatusListEntryEntity } from '@sphereon/ssi-sdk.data-store'\n\nconst debug = Debug('sphereon:ssi-sdk:status-list')\n\nfunction sendStatuslistResponse(details: StatusListResult, statuslistPayload: StatusListCredential, response: Response) {\n let payload: Buffer | StatusListCredential\n\n switch (details.proofFormat) {\n case 'jwt':\n case 'cbor':\n payload = Buffer.from(statuslistPayload as string, 'ascii')\n break\n default:\n payload = statuslistPayload\n }\n\n return response.status(200).setHeader('Content-Type', details.statuslistContentType).send(payload)\n}\n\nfunction buildStatusListId(request: Request): string {\n const protocol = request.headers['x-forwarded-proto']?.toString() ?? request.protocol\n let host = request.headers['x-forwarded-host']?.toString() ?? request.get('host')\n const forwardedPort = request.headers['x-forwarded-port']?.toString()\n\n if (forwardedPort && !(protocol === 'https' && forwardedPort === '443') && !(protocol === 'http' && forwardedPort === '80')) {\n host += `:${forwardedPort}`\n }\n\n const forwardedPrefix = request.headers['x-forwarded-prefix']?.toString() ?? ''\n\n return `${protocol}://${host}${forwardedPrefix}${request.originalUrl.split('?')[0].replace(/\\/status\\/index\\/.*/, '')}`\n}\n\nexport function createNewStatusListEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Create new status list endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists'\n\n router.post(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListArgs: CreateNewStatusListFuncArgs = request.body.statusList\n if (!statusListArgs) {\n return sendErrorResponse(response, 400, 'No statusList details supplied')\n }\n const details = await context.agent.slCreateStatusList(statusListArgs)\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const correlationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(correlationId ? { correlationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n const statuslistPayload = details.statusListCredential\n return sendStatuslistResponse(details, statuslistPayload, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nfunction lookupType(details: StatusListResult) {\n switch (details.type) {\n case StatusListType.StatusList2021:\n return 'StatusList2021Entry'\n case StatusListType.BitstringStatusList:\n return 'BitstringStatusListEntry'\n default:\n return details.type\n }\n}\n\nexport function getStatusListCredentialIndexStatusEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n\n const path = opts?.path ?? '/status-lists/:statusListId/status/entry-by-id/:entryId'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n const statusListIdType = (request.query.statusListIdType as StatusListIdType) ?? StatusListIdType.StatusListId\n const entryIdType = (request.query.entryIdType as EntryIdType) ?? EntryIdType.StatusListIndex\n\n let statusListIndex: number | undefined\n let entityCorrelationId: string | undefined\n let statusListId: string | undefined\n let statusListCorrelationId: string | undefined\n\n if (entryIdType === EntryIdType.StatusListIndex) {\n try {\n statusListIndex = Number.parseInt(request.params.entryId)\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n } else {\n entityCorrelationId = request.params.entryId\n }\n\n if (statusListIdType === StatusListIdType.StatusListId) {\n statusListId = request.params.statusListId\n } else {\n statusListCorrelationId = request.params.statusListId\n }\n\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: statusListId }),\n dbName: opts.dbName,\n })\n\n const details = await driver.getStatusList()\n if (statusListIndex && statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex }),\n errorOnNotFound: false,\n })\n\n const type = lookupType(details)\n const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n type,\n id: details.id,\n statusListIndex: resultStatusIndex,\n ...(details.type === StatusListType.StatusList2021 && { statusPurpose: details.statusList2021?.statusPurpose }),\n ...(details.type === StatusListType.BitstringStatusList && {\n statusPurpose: details.bitstringStatusList?.statusPurpose,\n bitsPerStatus: details.bitstringStatusList?.bitsPerStatus,\n }),\n })\n if (!entry) {\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex: resultStatusIndex,\n }\n }\n\n response.statusCode = 200\n const result = { ...entry, status }\n delete result.statusList // the API caller requested the index status, not the entire status list which may be big. Filter it out\n return response.json(result)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function getStatusListCredentialIndexStatusEndpointLegacy(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Get statusList credential index status endpoint is disabled`)\n return\n }\n const path = opts?.path ?? '/status-lists/:index/status/index/:statusListIndex'\n router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n //todo: Check index against correlationId first. Then match originalUrl against statusList id\n const statusListIndexStr = request.params.statusListIndex\n let statusListIndex: number\n try {\n statusListIndex = Number.parseInt(statusListIndexStr)\n } catch (error) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n if (!statusListIndex || statusListIndex < 0) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n //const correlationId = request.query.correlationId?.toString() ?? request.params.index?.toString() ?? request.originalUrl TODO I so not get these\n const statusListCorrelationId = request.query.correlationId?.toString()\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n const details = await driver.getStatusList()\n if (statusListIndex > details.length) {\n return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)\n }\n\n const entityCorrelationId = request.query.entityCorrelationId?.toString()\n let entry = await driver.getStatusListEntryByIndex({\n statusListId: details.id,\n ...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex: statusListIndex }),\n errorOnNotFound: false,\n })\n const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type\n const status = await checkStatusIndexFromStatusListCredential({\n statusListCredential: details.statusListCredential,\n ...(details.type === StatusListType.StatusList2021 && { statusPurpose: details.statusList2021?.statusPurpose }),\n ...(details.type === StatusListType.BitstringStatusList && {\n statusPurpose: details.bitstringStatusList?.statusPurpose,\n bitsPerStatus: details.bitstringStatusList?.bitsPerStatus,\n }),\n type,\n id: details.id,\n statusListIndex,\n })\n if (!entry) {\n // The fact we have nothing on it means the status is okay\n entry = {\n statusListId: details.id,\n value: '0',\n statusListIndex,\n }\n }\n response.statusCode = 200\n const result = { ...entry, status }\n delete result.statusList // we asked for the status, not the entire list\n return response.json(result)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n\nexport function updateStatusEndpoint(router: Router, context: IRequiredContext, opts: IW3CredentialStatusEndpointOpts) {\n if (opts?.enabled === false) {\n console.log(`Update credential status endpoint is disabled`)\n return\n }\n router.post(opts?.path ?? '/credentials/status', checkAuth(opts?.endpoint), async (request: Request, response: Response) => {\n try {\n debug(JSON.stringify(request.body, null, 2))\n const updateRequest = request.body as UpdateW3cCredentialStatusRequest | UpdateIndexedCredentialStatusRequest\n const statusListId = updateRequest.statusListId ?? request.query.statusListId?.toString() ?? opts.statusListId // TODO why query params when we have a JSON body ??\n const statusListCorrelationId = updateRequest.statusListCorrelationId ?? request.query.statusListrelationId?.toString() ?? opts.correlationId\n const entryCorrelationId = updateRequest.entryCorrelationId ?? request.query.entryCorrelationId?.toString()\n\n // TODO: Move mostly to driver\n if (!statusListId && !statusListCorrelationId) {\n return sendErrorResponse(response, 400, 'No statusList id or correlation Id provided or deduced for the API or in the request')\n } else if (!updateRequest.credentialStatus || updateRequest.credentialStatus.length === 0) {\n return sendErrorResponse(response, 400, 'No statusList updates supplied')\n }\n const driver = await getDriver({\n ...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),\n dbName: opts.dbName,\n })\n let statusListResult: StatusListResult = await driver.getStatusList()\n\n // Get status list entry based on request type\n let statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity | undefined\n if ('credentialId' in updateRequest) {\n if (!updateRequest.credentialId) {\n return sendErrorResponse(response, 400, 'No credentialId supplied')\n }\n // unfortunately the W3C API works by credentialId. Which means you will have to map listIndices during issuance\n statusListEntry = await driver.getStatusListEntryByCredentialId({\n statusListId,\n statusListCorrelationId,\n entryCorrelationId,\n credentialId: updateRequest.credentialId,\n errorOnNotFound: true,\n })\n } else {\n statusListEntry = await driver.getStatusListEntryByIndex({\n ...(statusListResult.id && { statusListId: statusListResult.id }),\n ...(statusListResult.correlationId && { statusListCorrelationId: statusListResult.correlationId }),\n ...(entryCorrelationId ? { entryCorrelationId } : { statusListIndex: updateRequest.statusListIndex }),\n errorOnNotFound: true,\n })\n }\n\n if (!statusListEntry) {\n const identifier = 'credentialId' in updateRequest ? updateRequest.credentialId : `index ${updateRequest.statusListIndex}`\n return sendErrorResponse(response, 404, `Status list entry for ${identifier} not found for ${statusListId}`)\n }\n\n let statusListCredential = statusListResult.statusListCredential\n for (const updateItem of updateRequest.credentialStatus) {\n if (!updateItem.status) {\n return sendErrorResponse(response, 400, `Required 'status' value was missing in the credentialStatus array`)\n }\n\n let value: string = '1'\n if (updateItem.status === '0' || updateItem.status.toLowerCase() === 'false') {\n value = '0'\n } else if (updateItem.status !== '1' && updateItem.status.toLowerCase() !== 'true') {\n if (updateItem.type === StatusListType.StatusList2021) {\n // 2021 only allows 0 and 1\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n } else if (parseInt(updateItem.status) < 0 || parseInt(updateItem.status) > 255) {\n return sendErrorResponse(response, 400, `Invalid 'status' value in the credentialStatus array: ${updateItem.status}`)\n }\n value = `${parseInt(updateItem.status)}`\n }\n\n const updStatusListId = statusListId ?? ('statusList' in statusListEntry && statusListEntry.statusList?.id) ?? statusListEntry?.statusListId // When input was statusListCorrelationId the statusList id should come from statusListEntry\n if (!updStatusListId) {\n return sendErrorResponse(response, 400, 'statuslist id could not be determined')\n }\n await driver.updateStatusListEntry({ ...statusListEntry, statusListId: updStatusListId, value })\n const bitsPerStatus =\n 'bitsPerStatus' in statusListEntry && typeof statusListEntry.bitsPerStatus === 'number' ? statusListEntry.bitsPerStatus : undefined\n\n // todo: optimize. We are now creating a new VC for every item passed in. Probably wise to look at DB as well\n statusListResult = await updateStatusIndexFromStatusListCredential(\n {\n statusListCredential: statusListCredential,\n statusListIndex: statusListEntry.statusListIndex,\n ...(bitsPerStatus && { bitsPerStatus }),\n value: parseInt(value),\n keyRef: opts.keyRef,\n },\n context,\n )\n\n if (!statusListResult.correlationId) {\n return Promise.reject(Error('Cannot update the statuslist, correlationId is missing from the status list result'))\n }\n statusListResult = await driver.updateStatusList({\n correlationId: statusListResult.correlationId,\n statusListCredential: statusListResult.statusListCredential,\n })\n }\n\n return sendStatuslistResponse(statusListResult, statusListResult.statusListCredential, response)\n } catch (e) {\n return sendErrorResponse(response, 500, (e as Error).message, e)\n }\n })\n}\n","import { GenericAuthArgs, ISingleEndpointOpts } from '@sphereon/ssi-express-support'\nimport { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'\nimport { IRequiredPlugins } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'\nimport { StatusListType } from '@sphereon/ssi-types'\nimport { IAgentContext } from '@veramo/core'\n\nexport type IRequiredContext = IAgentContext<IRequiredPlugins & IStatusListPlugin>\n\nexport interface IStatusListOpts {\n endpointOpts: IStatusListEndpointOpts\n enableFeatures?: statusListFeatures[] // Feature to enable. If not defined or empty, all features will be enabled\n}\n\nexport interface IStatusListEndpointOpts {\n basePath?: string\n globalAuth?: GenericAuthArgs\n vcApiCredentialStatus: IW3CredentialStatusEndpointOpts\n createStatusList: ICredentialStatusListEndpointOpts\n getStatusList: ICredentialStatusListEndpointOpts\n}\n\nexport type statusListFeatures = 'w3c-vc-api-credential-status' | 'status-list-management' | 'status-list-hosting'\n\nexport interface ICredentialStatusListEndpointOpts extends ISingleEndpointOpts {\n dbName: string\n}\n\nexport interface IW3CredentialStatusEndpointOpts extends ICredentialStatusListEndpointOpts {\n statusListId?: string\n correlationId?: string\n keyRef?: string\n}\n\nexport interface UpdateW3cCredentialStatusRequest extends UpdateCredentialStatusRequest {\n credentialId: string\n}\n\nexport interface UpdateIndexedCredentialStatusRequest extends UpdateCredentialStatusRequest {\n statusListIndex?: number\n}\n\ninterface UpdateCredentialStatusRequest {\n credentialStatus: UpdateCredentialStatusItem[]\n statusListId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n statusListCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n entryCorrelationId?: string // Non spec compliant. Allows us to manage multiple status lists. The VC API endpoint also has this config option, allowing for a default\n}\n\nexport interface UpdateCredentialStatusItem {\n type?: StatusListType // makes very little sense, but listed in the spec. Would expect a purpose\n status: string\n}\n\nexport enum StatusListIdType {\n StatusListId = 'StatusListId',\n StatusListCorrelationId = 'StatusListCorrelationId',\n}\n\nexport enum EntryIdType {\n StatusListIndex = 'StatusListIndex',\n EntryCorrelationId = 'StatusListCorrelationId',\n}\n"],"mappings":"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","names":["copyGlobalAuthToEndpoint","agentContext","express","checkAuth","sendErrorResponse","checkStatusIndexFromStatusListCredential","updateStatusIndexFromStatusListCredential","getDriver","Debug","StatusListIdType","EntryIdType","StatusListType","debug","Debug","sendStatuslistResponse","details","statuslistPayload","response","payload","proofFormat","Buffer","from","status","setHeader","statuslistContentType","send","buildStatusListId","request","protocol","headers","toString","host","get","forwardedPort","forwardedPrefix","originalUrl","split","replace","createNewStatusListEndpoint","router","context","opts","enabled","console","log","path","post","checkAuth","endpoint","statusListArgs","body","statusList","sendErrorResponse","agent","slCreateStatusList","statusListCredential","e","message","getStatusListCredentialEndpoint","correlationId","query","driver","getDriver","id","dbName","getStatusList","lookupType","type","StatusListType","StatusList2021","BitstringStatusList","getStatusListCredentialIndexStatusEndpoint","statusListIdType","StatusListIdType","StatusListId","entryIdType","EntryIdType","StatusListIndex","statusListIndex","entityCorrelationId","statusListId","statusListCorrelationId","Number","parseInt","params","entryId","error","length","entry","getStatusListEntryByIndex","errorOnNotFound","resultStatusIndex","checkStatusIndexFromStatusListCredential","statusPurpose","statusList2021","bitstringStatusList","bitsPerStatus","value","statusCode","result","json","getStatusListCredentialIndexStatusEndpointLegacy","statusListIndexStr","updateStatusEndpoint","JSON","stringify","updateRequest","statusListrelationId","entryCorrelationId","credentialStatus","statusListResult","statusListEntry","credentialId","getStatusListEntryByCredentialId","identifier","updateItem","toLowerCase","updStatusListId","updateStatusListEntry","undefined","updateStatusIndexFromStatusListCredential","keyRef","Promise","reject","Error","updateStatusList","StatuslistManagementApiServer","router","_router","_express","_agent","_opts","args","agent","opts","endpointOpts","globalAuth","copyGlobalAuthToEndpoint","key","expressSupport","express","Router","context","agentContext","features","enableFeatures","console","log","JSON","stringify","includes","createNewStatusListEndpoint","createStatusList","getStatusListCredentialEndpoint","getStatusList","getStatusListCredentialIndexStatusEndpoint","getStatusListCredentialIndexStatusEndpointLegacy","updateStatusEndpoint","vcApiCredentialStatus","use","basePath"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/ssi-sdk.vc-status-list-issuer-rest-api",
|
|
3
3
|
"description": "Sphereon SSI-SDK plugin for Status List management, like StatusList2021. Issuer drivers module",
|
|
4
|
-
"version": "0.34.1-next.
|
|
4
|
+
"version": "0.34.1-next.85+019802c5",
|
|
5
5
|
"source": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.cjs",
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
"start:dev2": "node --experimental-specifier-resolution=node --loader ts-node/esm __tests__/agent.ts"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@sphereon/ssi-express-support": "0.34.1-next.
|
|
28
|
-
"@sphereon/ssi-sdk-ext.did-utils": "0.
|
|
29
|
-
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.
|
|
30
|
-
"@sphereon/ssi-sdk-ext.jwt-service": "0.
|
|
31
|
-
"@sphereon/ssi-sdk.core": "0.34.1-next.
|
|
32
|
-
"@sphereon/ssi-sdk.data-store": "0.34.1-next.
|
|
33
|
-
"@sphereon/ssi-sdk.vc-status-list": "0.34.1-next.
|
|
34
|
-
"@sphereon/ssi-sdk.vc-status-list-issuer-drivers": "0.34.1-next.
|
|
35
|
-
"@sphereon/ssi-types": "0.34.1-next.
|
|
27
|
+
"@sphereon/ssi-express-support": "0.34.1-next.85+019802c5",
|
|
28
|
+
"@sphereon/ssi-sdk-ext.did-utils": "0.34.1-next.85+019802c5",
|
|
29
|
+
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-next.85+019802c5",
|
|
30
|
+
"@sphereon/ssi-sdk-ext.jwt-service": "0.34.1-next.85+019802c5",
|
|
31
|
+
"@sphereon/ssi-sdk.core": "0.34.1-next.85+019802c5",
|
|
32
|
+
"@sphereon/ssi-sdk.data-store": "0.34.1-next.85+019802c5",
|
|
33
|
+
"@sphereon/ssi-sdk.vc-status-list": "0.34.1-next.85+019802c5",
|
|
34
|
+
"@sphereon/ssi-sdk.vc-status-list-issuer-drivers": "0.34.1-next.85+019802c5",
|
|
35
|
+
"@sphereon/ssi-types": "0.34.1-next.85+019802c5",
|
|
36
36
|
"@sphereon/vc-status-list": "7.0.0-next.0",
|
|
37
37
|
"@veramo/core": "4.2.0",
|
|
38
38
|
"debug": "^4.3.5",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@sphereon/did-uni-client": "^0.6.3",
|
|
47
|
-
"@sphereon/ssi-sdk-ext.did-provider-jwk": "0.
|
|
48
|
-
"@sphereon/ssi-sdk-ext.did-resolver-jwk": "0.
|
|
49
|
-
"@sphereon/ssi-sdk.agent-config": "0.34.1-next.
|
|
50
|
-
"@sphereon/ssi-sdk.credential-vcdm-jsonld-provider": "0.34.1-next.
|
|
47
|
+
"@sphereon/ssi-sdk-ext.did-provider-jwk": "0.34.1-next.85+019802c5",
|
|
48
|
+
"@sphereon/ssi-sdk-ext.did-resolver-jwk": "0.34.1-next.85+019802c5",
|
|
49
|
+
"@sphereon/ssi-sdk.agent-config": "0.34.1-next.85+019802c5",
|
|
50
|
+
"@sphereon/ssi-sdk.credential-vcdm-jsonld-provider": "0.34.1-next.85+019802c5",
|
|
51
51
|
"@sphereon/ssi-sdk.data-store": "workspace:*",
|
|
52
52
|
"@types/body-parser": "^1.19.5",
|
|
53
53
|
"@types/cookie-parser": "^1.4.7",
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"SSI",
|
|
92
92
|
"StatusList2021"
|
|
93
93
|
],
|
|
94
|
-
"gitHead": "
|
|
94
|
+
"gitHead": "019802c57e9c1f9e3df4ecbb1d6a17f49e8fdbeb"
|
|
95
95
|
}
|
package/src/api-functions.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
UpdateW3cCredentialStatusRequest,
|
|
19
19
|
} from './types'
|
|
20
20
|
import { StatusListCredential, StatusListType } from '@sphereon/ssi-types'
|
|
21
|
-
import { IStatusListEntryEntity } from '@sphereon/ssi-sdk.data-store'
|
|
21
|
+
import { IBitstringStatusListEntryEntity, IStatusListEntryEntity } from '@sphereon/ssi-sdk.data-store'
|
|
22
22
|
|
|
23
23
|
const debug = Debug('sphereon:ssi-sdk:status-list')
|
|
24
24
|
|
|
@@ -97,6 +97,17 @@ export function getStatusListCredentialEndpoint(router: Router, context: IRequir
|
|
|
97
97
|
})
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
function lookupType(details: StatusListResult) {
|
|
101
|
+
switch (details.type) {
|
|
102
|
+
case StatusListType.StatusList2021:
|
|
103
|
+
return 'StatusList2021Entry'
|
|
104
|
+
case StatusListType.BitstringStatusList:
|
|
105
|
+
return 'BitstringStatusListEntry'
|
|
106
|
+
default:
|
|
107
|
+
return details.type
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
100
111
|
export function getStatusListCredentialIndexStatusEndpoint(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {
|
|
101
112
|
if (opts?.enabled === false) {
|
|
102
113
|
console.log(`Get statusList credential index status endpoint is disabled`)
|
|
@@ -149,16 +160,19 @@ export function getStatusListCredentialIndexStatusEndpoint(router: Router, conte
|
|
|
149
160
|
errorOnNotFound: false,
|
|
150
161
|
})
|
|
151
162
|
|
|
152
|
-
const type = details
|
|
163
|
+
const type = lookupType(details)
|
|
153
164
|
const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0
|
|
154
165
|
const status = await checkStatusIndexFromStatusListCredential({
|
|
155
166
|
statusListCredential: details.statusListCredential,
|
|
156
|
-
...(details.type === StatusListType.StatusList2021 ? { statusPurpose: details.statusList2021?.statusPurpose } : {}),
|
|
157
167
|
type,
|
|
158
168
|
id: details.id,
|
|
159
169
|
statusListIndex: resultStatusIndex,
|
|
170
|
+
...(details.type === StatusListType.StatusList2021 && { statusPurpose: details.statusList2021?.statusPurpose }),
|
|
171
|
+
...(details.type === StatusListType.BitstringStatusList && {
|
|
172
|
+
statusPurpose: details.bitstringStatusList?.statusPurpose,
|
|
173
|
+
bitsPerStatus: details.bitstringStatusList?.bitsPerStatus,
|
|
174
|
+
}),
|
|
160
175
|
})
|
|
161
|
-
|
|
162
176
|
if (!entry) {
|
|
163
177
|
entry = {
|
|
164
178
|
statusListId: details.id,
|
|
@@ -168,7 +182,9 @@ export function getStatusListCredentialIndexStatusEndpoint(router: Router, conte
|
|
|
168
182
|
}
|
|
169
183
|
|
|
170
184
|
response.statusCode = 200
|
|
171
|
-
|
|
185
|
+
const result = { ...entry, status }
|
|
186
|
+
delete result.statusList // the API caller requested the index status, not the entire status list which may be big. Filter it out
|
|
187
|
+
return response.json(result)
|
|
172
188
|
} catch (e) {
|
|
173
189
|
return sendErrorResponse(response, 500, (e as Error).message, e)
|
|
174
190
|
}
|
|
@@ -214,7 +230,11 @@ export function getStatusListCredentialIndexStatusEndpointLegacy(router: Router,
|
|
|
214
230
|
const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type
|
|
215
231
|
const status = await checkStatusIndexFromStatusListCredential({
|
|
216
232
|
statusListCredential: details.statusListCredential,
|
|
217
|
-
...(details.type === StatusListType.StatusList2021
|
|
233
|
+
...(details.type === StatusListType.StatusList2021 && { statusPurpose: details.statusList2021?.statusPurpose }),
|
|
234
|
+
...(details.type === StatusListType.BitstringStatusList && {
|
|
235
|
+
statusPurpose: details.bitstringStatusList?.statusPurpose,
|
|
236
|
+
bitsPerStatus: details.bitstringStatusList?.bitsPerStatus,
|
|
237
|
+
}),
|
|
218
238
|
type,
|
|
219
239
|
id: details.id,
|
|
220
240
|
statusListIndex,
|
|
@@ -228,7 +248,9 @@ export function getStatusListCredentialIndexStatusEndpointLegacy(router: Router,
|
|
|
228
248
|
}
|
|
229
249
|
}
|
|
230
250
|
response.statusCode = 200
|
|
231
|
-
|
|
251
|
+
const result = { ...entry, status }
|
|
252
|
+
delete result.statusList // we asked for the status, not the entire list
|
|
253
|
+
return response.json(result)
|
|
232
254
|
} catch (e) {
|
|
233
255
|
return sendErrorResponse(response, 500, (e as Error).message, e)
|
|
234
256
|
}
|
|
@@ -261,7 +283,7 @@ export function updateStatusEndpoint(router: Router, context: IRequiredContext,
|
|
|
261
283
|
let statusListResult: StatusListResult = await driver.getStatusList()
|
|
262
284
|
|
|
263
285
|
// Get status list entry based on request type
|
|
264
|
-
let statusListEntry: IStatusListEntryEntity | undefined
|
|
286
|
+
let statusListEntry: IStatusListEntryEntity | IBitstringStatusListEntryEntity | undefined
|
|
265
287
|
if ('credentialId' in updateRequest) {
|
|
266
288
|
if (!updateRequest.credentialId) {
|
|
267
289
|
return sendErrorResponse(response, 400, 'No credentialId supplied')
|
|
@@ -307,23 +329,33 @@ export function updateStatusEndpoint(router: Router, context: IRequiredContext,
|
|
|
307
329
|
value = `${parseInt(updateItem.status)}`
|
|
308
330
|
}
|
|
309
331
|
|
|
310
|
-
const updStatusListId = statusListId ?? statusListEntry.statusList?.id // When input was statusListCorrelationId the statusList id should come from statusListEntry
|
|
332
|
+
const updStatusListId = statusListId ?? ('statusList' in statusListEntry && statusListEntry.statusList?.id) ?? statusListEntry?.statusListId // When input was statusListCorrelationId the statusList id should come from statusListEntry
|
|
311
333
|
if (!updStatusListId) {
|
|
312
334
|
return sendErrorResponse(response, 400, 'statuslist id could not be determined')
|
|
313
335
|
}
|
|
314
336
|
await driver.updateStatusListEntry({ ...statusListEntry, statusListId: updStatusListId, value })
|
|
337
|
+
const bitsPerStatus =
|
|
338
|
+
'bitsPerStatus' in statusListEntry && typeof statusListEntry.bitsPerStatus === 'number' ? statusListEntry.bitsPerStatus : undefined
|
|
315
339
|
|
|
316
340
|
// todo: optimize. We are now creating a new VC for every item passed in. Probably wise to look at DB as well
|
|
317
341
|
statusListResult = await updateStatusIndexFromStatusListCredential(
|
|
318
342
|
{
|
|
319
343
|
statusListCredential: statusListCredential,
|
|
320
344
|
statusListIndex: statusListEntry.statusListIndex,
|
|
345
|
+
...(bitsPerStatus && { bitsPerStatus }),
|
|
321
346
|
value: parseInt(value),
|
|
322
347
|
keyRef: opts.keyRef,
|
|
323
348
|
},
|
|
324
349
|
context,
|
|
325
350
|
)
|
|
326
|
-
|
|
351
|
+
|
|
352
|
+
if (!statusListResult.correlationId) {
|
|
353
|
+
return Promise.reject(Error('Cannot update the statuslist, correlationId is missing from the status list result'))
|
|
354
|
+
}
|
|
355
|
+
statusListResult = await driver.updateStatusList({
|
|
356
|
+
correlationId: statusListResult.correlationId,
|
|
357
|
+
statusListCredential: statusListResult.statusListCredential,
|
|
358
|
+
})
|
|
327
359
|
}
|
|
328
360
|
|
|
329
361
|
return sendStatuslistResponse(statusListResult, statusListResult.statusListCredential, response)
|