Skip to content

Commit

Permalink
chore: REST API tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sanderPostma committed Feb 5, 2025
1 parent 2a07c66 commit f6539aa
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 13 deletions.
94 changes: 82 additions & 12 deletions packages/vc-status-list-issuer-rest-api/src/api-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import { getDriver } from '@sphereon/ssi-sdk.vc-status-list-issuer-drivers'
import Debug from 'debug'
import { Request, Response, Router } from 'express'
import {
EntryIdType,
ICredentialStatusListEndpointOpts,
IRequiredContext,
IW3CredentialStatusEndpointOpts,
StatusListIdType,
UpdateIndexedCredentialStatusRequest,
UpdateW3cCredentialStatusRequest,
} from './types'
Expand Down Expand Up @@ -100,6 +102,84 @@ export function getStatusListCredentialIndexStatusEndpoint(router: Router, conte
console.log(`Get statusList credential index status endpoint is disabled`)
return
}

const path = opts?.path ?? '/query/status-list/:statusListId/entry/:entryId'
router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {
try {
const statusListIdType = (request.query.statusListIdType as StatusListIdType) ?? StatusListIdType.StatusListId
const entryIdType = (request.query.entryIdType as EntryIdType) ?? EntryIdType.StatusListIndex

let statusListIndex: number | undefined
let entityCorrelationId: string | undefined
let statusListId: string | undefined
let statusListCorrelationId: string | undefined

if (entryIdType === EntryIdType.StatusListIndex) {
try {
statusListIndex = Number.parseInt(request.params.entryId)
if (!statusListIndex || statusListIndex < 0) {
return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)
}
} catch (error) {
return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)
}
} else {
entityCorrelationId = request.params.entryId
}

if (statusListIdType === StatusListIdType.StatusListId) {
statusListId = request.params.statusListId
} else {
statusListCorrelationId = request.params.statusListId
}

const driver = await getDriver({
...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: statusListId }),
dbName: opts.dbName,
})

const details = await driver.getStatusList()
if (statusListIndex && statusListIndex > details.length) {
return sendErrorResponse(response, 400, `Please provide a proper statusListIndex`)
}

let entry = await driver.getStatusListEntryByIndex({
statusListId: details.id,
...(entityCorrelationId ? { correlationId: entityCorrelationId } : { statusListIndex }),
errorOnNotFound: false,
})

const type = details.type === StatusListType.StatusList2021 ? 'StatusList2021Entry' : details.type
const resultStatusIndex = entry?.statusListIndex ?? statusListIndex ?? 0
const status = await checkStatusIndexFromStatusListCredential({
statusListCredential: details.statusListCredential,
...(details.type === StatusListType.StatusList2021 ? { statusPurpose: details.statusList2021?.statusPurpose } : {}),
type,
id: details.id,
statusListIndex: resultStatusIndex,
})

if (!entry) {
entry = {
statusList: details.id,
value: '0',
statusListIndex: resultStatusIndex,
}
}

response.statusCode = 200
return response.send({ ...entry, status })
} catch (e) {
return sendErrorResponse(response, 500, e.message as string, e)
}
})
}

export function getStatusListCredentialIndexStatusEndpointLegacy(router: Router, context: IRequiredContext, opts: ICredentialStatusListEndpointOpts) {
if (opts?.enabled === false) {
console.log(`Get statusList credential index status endpoint is disabled`)
return
}
const path = opts?.path ?? '/status-lists/:index/status/index/:statusListIndex'
router.get(path, checkAuth(opts?.endpoint), async (request: Request, response: Response) => {
try {
Expand Down Expand Up @@ -164,7 +244,7 @@ export function updateStatusEndpoint(router: Router, context: IRequiredContext,
try {
debug(JSON.stringify(request.body, null, 2))
const updateRequest = request.body as UpdateW3cCredentialStatusRequest | UpdateIndexedCredentialStatusRequest
const statusListId = updateRequest.statusListId ?? request.query.statusListId?.toString() ?? opts.statusListId
const statusListId = updateRequest.statusListId ?? request.query.statusListId?.toString() ?? opts.statusListId // TODO why query params when we have a JSON body ??
const statusListCorrelationId = updateRequest.statusListCorrelationId ?? request.query.statusListorrelationId?.toString() ?? opts.correlationId
const entryCorrelationId = updateRequest.entryCorrelationId ?? request.query.entryCorrelationId?.toString()

Expand All @@ -178,6 +258,7 @@ export function updateStatusEndpoint(router: Router, context: IRequiredContext,
...(statusListCorrelationId ? { correlationId: statusListCorrelationId } : { id: buildStatusListId(request) }),
dbName: opts.dbName,
})
let details: StatusListResult = await driver.getStatusList()

// Get status list entry based on request type
let statusListEntry: IStatusListEntryEntity | undefined
Expand All @@ -194,15 +275,6 @@ export function updateStatusEndpoint(router: Router, context: IRequiredContext,
errorOnNotFound: true,
})
} else {
if (!updateRequest.statusListIndex || updateRequest.statusListIndex < 0) {
return sendErrorResponse(response, 400, 'Invalid statusListIndex supplied')
}
const driver = await getDriver({
...(statusListCorrelationId ? { statusListCorrelationId } : { id: buildStatusListId(request) }),
dbName: opts.dbName,
})
const details = await driver.getStatusList()

statusListEntry = await driver.getStatusListEntryByIndex({
statusListId: details.id,
...(entryCorrelationId ? { correlationId: entryCorrelationId } : { statusListIndex: updateRequest.statusListIndex }),
Expand All @@ -215,9 +287,7 @@ export function updateStatusEndpoint(router: Router, context: IRequiredContext,
return sendErrorResponse(response, 404, `Status list entry for ${identifier} not found for ${statusListId}`)
}

let details = await driver.getStatusList()
let statusListCredential = details.statusListCredential

for (const updateItem of updateRequest.credentialStatus) {
if (!updateItem.status) {
return sendErrorResponse(response, 400, `Required 'status' value was missing in the credentialStatus array`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
createNewStatusListEndpoint,
getStatusListCredentialEndpoint,
getStatusListCredentialIndexStatusEndpoint,
getStatusListCredentialIndexStatusEndpointLegacy,
updateStatusEndpoint,
} from './api-functions'
import { IStatusListOpts } from './types'
Expand Down Expand Up @@ -48,6 +49,7 @@ export class StatuslistManagementApiServer {
if (features.includes('status-list-hosting')) {
getStatusListCredentialEndpoint(this.router, context, opts.endpointOpts.getStatusList)
getStatusListCredentialIndexStatusEndpoint(this.router, context, opts.endpointOpts.getStatusList)
getStatusListCredentialIndexStatusEndpointLegacy(this.router, context, opts.endpointOpts.getStatusList)
}
if (features.includes('w3c-vc-api-credential-status')) {
updateStatusEndpoint(this.router, context, opts.endpointOpts.vcApiCredentialStatus)
Expand Down
12 changes: 11 additions & 1 deletion packages/vc-status-list-issuer-rest-api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export interface UpdateW3cCredentialStatusRequest extends UpdateCredentialStatus
}

export interface UpdateIndexedCredentialStatusRequest extends UpdateCredentialStatusRequest {
statusListIndex: number
statusListIndex?: number
}

interface UpdateCredentialStatusRequest {
Expand All @@ -50,3 +50,13 @@ export interface UpdateCredentialStatusItem {
type?: StatusListType // makes very little sense, but listed in the spec. Would expect a purpose
status: string
}

export enum StatusListIdType {
StatusListId = 'StatusListId',
StatusListCorrelationId = 'StatusListCorrelationId',
}

export enum EntryIdType {
StatusListIndex = 'StatusListIndex',
EntryCorrelationId = 'StatusListCorrelationId',
}

0 comments on commit f6539aa

Please sign in to comment.