@sphereon/ssi-sdk.oid4vci-issuer 0.32.1-next.54 → 0.33.1-feature.vcdm2.4
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/IssuerInstance.d.ts +4 -5
- package/dist/IssuerInstance.d.ts.map +1 -1
- package/dist/IssuerInstance.js +21 -28
- package/dist/IssuerInstance.js.map +1 -1
- package/dist/agent/OID4VCIIssuer.d.ts +3 -2
- package/dist/agent/OID4VCIIssuer.d.ts.map +1 -1
- package/dist/agent/OID4VCIIssuer.js +155 -168
- package/dist/agent/OID4VCIIssuer.js.map +1 -1
- package/dist/functions.d.ts +4 -5
- package/dist/functions.d.ts.map +1 -1
- package/dist/functions.js +243 -235
- package/dist/functions.js.map +1 -1
- package/dist/index.js +5 -23
- package/dist/index.js.map +1 -1
- package/dist/state-manager/TypeOrmStateManager.d.ts +1 -0
- package/dist/state-manager/TypeOrmStateManager.d.ts.map +1 -0
- package/dist/state-manager/TypeOrmStateManager.js +2 -0
- package/dist/state-manager/TypeOrmStateManager.js.map +1 -0
- package/dist/state-manager/oid4vcState/IAbstractMachineStateStore.d.ts +39 -0
- package/dist/state-manager/oid4vcState/IAbstractMachineStateStore.d.ts.map +1 -0
- package/dist/state-manager/oid4vcState/IAbstractMachineStateStore.js +2 -0
- package/dist/state-manager/oid4vcState/IAbstractMachineStateStore.js.map +1 -0
- package/dist/state-manager/oid4vcState/MachineStateStore.d.ts +1 -0
- package/dist/state-manager/oid4vcState/MachineStateStore.d.ts.map +1 -0
- package/dist/state-manager/oid4vcState/MachineStateStore.js +137 -0
- package/dist/state-manager/oid4vcState/MachineStateStore.js.map +1 -0
- package/dist/types/IOID4VCIIssuer.d.ts +10 -2
- package/dist/types/IOID4VCIIssuer.d.ts.map +1 -1
- package/dist/types/IOID4VCIIssuer.js +1 -2
- package/package.json +19 -16
- package/src/IssuerInstance.ts +8 -7
- package/src/agent/OID4VCIIssuer.ts +49 -13
- package/src/functions.ts +79 -29
- package/src/state-manager/TypeOrmStateManager.ts +0 -0
- package/src/state-manager/oid4vcState/IAbstractMachineStateStore.ts +51 -0
- package/src/state-manager/oid4vcState/MachineStateStore.ts +135 -0
- package/src/types/IOID4VCIIssuer.ts +16 -1
package/src/functions.ts
CHANGED
|
@@ -3,10 +3,12 @@ import {
|
|
|
3
3
|
CredentialRequest,
|
|
4
4
|
IssuerMetadata,
|
|
5
5
|
Jwt,
|
|
6
|
+
JWTHeader,
|
|
7
|
+
JWTPayload,
|
|
6
8
|
JwtVerifyResult,
|
|
7
9
|
OID4VCICredentialFormat,
|
|
10
|
+
StatusListOpts,
|
|
8
11
|
} from '@sphereon/oid4vci-common'
|
|
9
|
-
import { JWTHeader, JWTPayload } from '@sphereon/oid4vci-common/lib/types'
|
|
10
12
|
import { CredentialDataSupplier, CredentialIssuanceInput, CredentialSignerCallback, VcIssuer, VcIssuerBuilder } from '@sphereon/oid4vci-issuer'
|
|
11
13
|
import { getAgentResolver, IDIDOptions } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
12
14
|
import { legacyKeyRefsToIdentifierOpts, ManagedIdentifierOptsOrResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
@@ -14,7 +16,7 @@ import { contextHasPlugin } from '@sphereon/ssi-sdk.agent-config'
|
|
|
14
16
|
import { SdJwtVcPayload } from '@sphereon/ssi-sdk.sd-jwt/dist'
|
|
15
17
|
import { IStatusListPlugin } from '@sphereon/ssi-sdk.vc-status-list'
|
|
16
18
|
import { CompactSdJwtVc, CredentialMapper, ICredential, W3CVerifiableCredential } from '@sphereon/ssi-types'
|
|
17
|
-
import { CredentialPayload,
|
|
19
|
+
import { CredentialPayload, ProofFormat } from '@veramo/core'
|
|
18
20
|
import { bytesToBase64 } from '@veramo/utils'
|
|
19
21
|
import { createJWT, decodeJWT, JWTVerifyOptions, verifyJWT } from 'did-jwt'
|
|
20
22
|
import { Resolvable } from 'did-resolver'
|
|
@@ -24,7 +26,7 @@ import fetch from 'cross-fetch'
|
|
|
24
26
|
import { AuthorizationResponseStateStatus } from '@sphereon/did-auth-siop'
|
|
25
27
|
|
|
26
28
|
export function getJwtVerifyCallback({ verifyOpts }: { verifyOpts?: JWTVerifyOptions }, _context: IRequiredContext) {
|
|
27
|
-
return async (args: { jwt: string; kid?: string }): Promise<JwtVerifyResult
|
|
29
|
+
return async (args: { jwt: string; kid?: string }): Promise<JwtVerifyResult> => {
|
|
28
30
|
const resolver = getAgentResolver(_context, {
|
|
29
31
|
resolverResolution: true,
|
|
30
32
|
uniresolverResolution: true,
|
|
@@ -45,17 +47,18 @@ export function getJwtVerifyCallback({ verifyOpts }: { verifyOpts?: JWTVerifyOpt
|
|
|
45
47
|
return Promise.reject(Error(`the identifier of type ${identifier.method} is missing jwks (ExternalJwkInfo)`))
|
|
46
48
|
}
|
|
47
49
|
const { alg } = jwkInfo.jwk
|
|
48
|
-
if (!alg) {
|
|
49
|
-
return Promise.reject(Error(`the ExternalJwkInfo of identifier of type ${identifier.method} is missing alg in its jwk`))
|
|
50
|
-
}
|
|
51
|
-
|
|
52
50
|
const header = jwtDecode<JWTHeader>(args.jwt, { header: true })
|
|
53
51
|
const payload = jwtDecode<JWTPayload>(args.jwt, { header: false })
|
|
52
|
+
const kid = args.kid ?? header.kid
|
|
53
|
+
//const jwk = !kid ? jwkInfo.jwk : undefined // TODO double-check if this is correct
|
|
54
|
+
const jwk = jwkInfo.jwk // FIXME workaround IATAB2B-57
|
|
54
55
|
return {
|
|
55
56
|
alg,
|
|
56
57
|
...identifier,
|
|
57
58
|
jwt: { header, payload },
|
|
58
|
-
|
|
59
|
+
...(kid && { kid }),
|
|
60
|
+
...(jwk && { jwk }),
|
|
61
|
+
} as JwtVerifyResult
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
const decodedJwt = (await decodeJWT(args.jwt)) as Jwt
|
|
@@ -66,7 +69,7 @@ export function getJwtVerifyCallback({ verifyOpts }: { verifyOpts?: JWTVerifyOpt
|
|
|
66
69
|
return {
|
|
67
70
|
alg: decodedJwt.header.alg,
|
|
68
71
|
jwt: decodedJwt,
|
|
69
|
-
} as JwtVerifyResult
|
|
72
|
+
} as JwtVerifyResult
|
|
70
73
|
}
|
|
71
74
|
const did = kid.split('#')[0]
|
|
72
75
|
|
|
@@ -157,11 +160,25 @@ export async function getAccessTokenSignerCallback(
|
|
|
157
160
|
}
|
|
158
161
|
|
|
159
162
|
async function accessTokenSignerCallback(jwt: Jwt, kid?: string): Promise<string> {
|
|
160
|
-
const issuer =
|
|
163
|
+
const issuer =
|
|
164
|
+
opts.idOpts?.issuer ??
|
|
165
|
+
(typeof opts.idOpts?.identifier === 'string' ? opts.idOpts.identifier : (opts.didOpts?.idOpts?.identifier?.toString() ?? opts?.iss))
|
|
161
166
|
if (!issuer) {
|
|
162
167
|
throw Error('No issuer configured for access tokens')
|
|
163
168
|
}
|
|
164
|
-
|
|
169
|
+
|
|
170
|
+
let kidHeader: string | undefined = jwt?.header?.kid ?? kid
|
|
171
|
+
if (!kidHeader) {
|
|
172
|
+
if (
|
|
173
|
+
opts.idOpts?.method === 'did' ||
|
|
174
|
+
opts.idOpts?.method === 'kid' ||
|
|
175
|
+
(typeof opts.didOpts?.idOpts.identifier === 'string' && opts.didOpts?.idOpts?.identifier?.startsWith('did:'))
|
|
176
|
+
) {
|
|
177
|
+
// @ts-ignore
|
|
178
|
+
kidHeader = opts.idOpts?.kid ?? opts.didOpts?.idOpts?.kid ?? opts?.didOpts?.identifierOpts?.kid
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return await createJWT(jwt.payload, { signer, issuer }, { ...jwt.header, ...(kidHeader && { kid: kidHeader }), typ: 'JWT' })
|
|
165
182
|
}
|
|
166
183
|
|
|
167
184
|
return accessTokenSignerCallback
|
|
@@ -172,14 +189,15 @@ export async function getCredentialSignerCallback(
|
|
|
172
189
|
crypto?: Crypto
|
|
173
190
|
},
|
|
174
191
|
context: IRequiredContext,
|
|
175
|
-
): Promise<CredentialSignerCallback
|
|
192
|
+
): Promise<CredentialSignerCallback> {
|
|
176
193
|
async function issueVCCallback(args: {
|
|
177
194
|
credentialRequest: CredentialRequest
|
|
178
195
|
credential: CredentialIssuanceInput
|
|
179
|
-
jwtVerifyResult: JwtVerifyResult
|
|
196
|
+
jwtVerifyResult: JwtVerifyResult
|
|
180
197
|
format?: OID4VCICredentialFormat
|
|
198
|
+
statusLists?: Array<StatusListOpts>
|
|
181
199
|
}): Promise<W3CVerifiableCredential | CompactSdJwtVc> {
|
|
182
|
-
const { jwtVerifyResult, format } = args
|
|
200
|
+
const { jwtVerifyResult, format, statusLists } = args
|
|
183
201
|
const credential = args.credential as ICredential // TODO: SDJWT
|
|
184
202
|
let proofFormat: ProofFormat
|
|
185
203
|
|
|
@@ -206,9 +224,10 @@ export async function getCredentialSignerCallback(
|
|
|
206
224
|
// TODO: We should extend the plugin capabilities of issuance so we do not have to tuck this into the sign callback
|
|
207
225
|
if (contextHasPlugin<IStatusListPlugin>(context, 'slAddStatusToCredential')) {
|
|
208
226
|
// Add status list if enabled (and when the input has a credentialStatus object (can be empty))
|
|
209
|
-
const credentialStatusVC = await context.agent.slAddStatusToCredential({ credential })
|
|
227
|
+
const credentialStatusVC = await context.agent.slAddStatusToCredential({ credential, statusLists })
|
|
210
228
|
if (credential.credentialStatus && !credential.credentialStatus.statusListCredential) {
|
|
211
229
|
credential.credentialStatus = credentialStatusVC.credentialStatus
|
|
230
|
+
// TODO update statusLists somehow?
|
|
212
231
|
}
|
|
213
232
|
}
|
|
214
233
|
|
|
@@ -239,6 +258,28 @@ export async function getCredentialSignerCallback(
|
|
|
239
258
|
_sd: credential['_sd'],
|
|
240
259
|
}
|
|
241
260
|
}
|
|
261
|
+
|
|
262
|
+
if (contextHasPlugin<IStatusListPlugin>(context, 'slAddStatusToSdJwtCredential')) {
|
|
263
|
+
if ((sdJwtPayload.status && sdJwtPayload.status.status_list) || (statusLists && statusLists.length > 0)) {
|
|
264
|
+
// Add status list if enabled (and when the input has a credentialStatus object (can be empty))
|
|
265
|
+
const sdJwtPayloadWithStatus = await context.agent.slAddStatusToSdJwtCredential({ credential: sdJwtPayload, statusLists })
|
|
266
|
+
if (sdJwtPayload.status?.status_list?.idx) {
|
|
267
|
+
if (!sdJwtPayloadWithStatus.status || !sdJwtPayloadWithStatus.status.status_list) {
|
|
268
|
+
// sdJwtPayload and sdJwtPayloadWithStatus is the same for now, but we should use the result anyway as this could be subject to change
|
|
269
|
+
return Promise.reject(Error('slAddStatusToSdJwtCredential did not return a status_list'))
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Update statusListId & statusListIndex back to the credential session TODO SSISDK-4 This is not a clean way to do this.
|
|
273
|
+
if (statusLists && statusLists.length > 0) {
|
|
274
|
+
const statusList = statusLists[0]
|
|
275
|
+
statusList.statusListId = sdJwtPayloadWithStatus.status.status_list.uri
|
|
276
|
+
statusList.statusListIndex = sdJwtPayloadWithStatus.status.status_list.idx
|
|
277
|
+
}
|
|
278
|
+
sdJwtPayload.status.status_list.idx = sdJwtPayloadWithStatus.status.status_list.idx
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
242
283
|
const result = await context.agent.createSdJwtVc({
|
|
243
284
|
credentialPayload: sdJwtPayload,
|
|
244
285
|
disclosureFrame: disclosureFrame,
|
|
@@ -263,10 +304,10 @@ export async function createVciIssuerBuilder(
|
|
|
263
304
|
credentialDataSupplier?: CredentialDataSupplier
|
|
264
305
|
},
|
|
265
306
|
context: IRequiredContext,
|
|
266
|
-
): Promise<VcIssuerBuilder
|
|
307
|
+
): Promise<VcIssuerBuilder> {
|
|
267
308
|
const { issuerOpts, issuerMetadata, authorizationServerMetadata } = args
|
|
268
309
|
|
|
269
|
-
const builder = new VcIssuerBuilder
|
|
310
|
+
const builder = new VcIssuerBuilder()
|
|
270
311
|
// @ts-ignore
|
|
271
312
|
const resolver =
|
|
272
313
|
args.resolver ??
|
|
@@ -287,14 +328,23 @@ export async function createVciIssuerBuilder(
|
|
|
287
328
|
builder.withAuthorizationMetadata(authorizationServerMetadata)
|
|
288
329
|
// builder.withUserPinRequired(issuerOpts.userPinRequired ?? false) was removed from implementers draft v1
|
|
289
330
|
builder.withCredentialSignerCallback(await getCredentialSignerCallback(idOpts, context))
|
|
331
|
+
|
|
332
|
+
if (issuerOpts.asClientOpts) {
|
|
333
|
+
builder.withASClientMetadata(issuerOpts.asClientOpts)
|
|
334
|
+
// @ts-ignore
|
|
335
|
+
// const authorizationServer = issuerMetadata.authorization_servers[0] as string
|
|
336
|
+
// Set the OIDC verifier
|
|
337
|
+
// builder.withJWTVerifyCallback(oidcAccessTokenVerifyCallback({clientMetadata: issuerOpts.asClientOpts, credentialIssuer: issuerMetadata.credential_issuer as string, authorizationServer}))
|
|
338
|
+
}
|
|
339
|
+
// Do not use it when asClient is used
|
|
290
340
|
builder.withJWTVerifyCallback(getJwtVerifyCallback({ verifyOpts: jwtVerifyOpts }, context))
|
|
341
|
+
|
|
291
342
|
if (args.credentialDataSupplier) {
|
|
292
343
|
builder.withCredentialDataSupplier(args.credentialDataSupplier)
|
|
293
344
|
}
|
|
294
345
|
builder.withInMemoryCNonceState()
|
|
295
346
|
builder.withInMemoryCredentialOfferState()
|
|
296
347
|
builder.withInMemoryCredentialOfferURIState()
|
|
297
|
-
builder.build()
|
|
298
348
|
|
|
299
349
|
return builder
|
|
300
350
|
}
|
|
@@ -312,7 +362,7 @@ export async function createVciIssuer(
|
|
|
312
362
|
credentialDataSupplier?: CredentialDataSupplier
|
|
313
363
|
},
|
|
314
364
|
context: IRequiredContext,
|
|
315
|
-
): Promise<VcIssuer
|
|
365
|
+
): Promise<VcIssuer> {
|
|
316
366
|
return (
|
|
317
367
|
await createVciIssuerBuilder(
|
|
318
368
|
{
|
|
@@ -326,20 +376,19 @@ export async function createVciIssuer(
|
|
|
326
376
|
).build()
|
|
327
377
|
}
|
|
328
378
|
|
|
329
|
-
export async function createAuthRequestUriCallback(opts: { path: string
|
|
379
|
+
export async function createAuthRequestUriCallback(opts: { path: string; presentationDefinitionId: string }): Promise<() => Promise<string>> {
|
|
330
380
|
async function authRequestUriCallback(): Promise<string> {
|
|
331
381
|
const path = opts.path.replace(':definitionId', opts.presentationDefinitionId)
|
|
332
382
|
return fetch(path, {
|
|
333
383
|
method: 'POST',
|
|
334
384
|
headers: {
|
|
335
385
|
'Content-Type': 'application/json',
|
|
336
|
-
}
|
|
337
|
-
})
|
|
338
|
-
.then(async (response): Promise<string> => {
|
|
386
|
+
},
|
|
387
|
+
}).then(async (response): Promise<string> => {
|
|
339
388
|
if (response.status >= 400) {
|
|
340
389
|
return Promise.reject(Error(await response.text()))
|
|
341
390
|
} else {
|
|
342
|
-
const responseData = await response.json()
|
|
391
|
+
const responseData = await response.json()
|
|
343
392
|
|
|
344
393
|
if (!responseData.authRequestURI) {
|
|
345
394
|
return Promise.reject(Error('Missing auth request uri in response body'))
|
|
@@ -348,13 +397,15 @@ export async function createAuthRequestUriCallback(opts: { path: string, present
|
|
|
348
397
|
return responseData.authRequestURI
|
|
349
398
|
}
|
|
350
399
|
})
|
|
351
|
-
|
|
352
400
|
}
|
|
353
401
|
|
|
354
402
|
return authRequestUriCallback
|
|
355
403
|
}
|
|
356
404
|
|
|
357
|
-
export async function createVerifyAuthResponseCallback(opts: {
|
|
405
|
+
export async function createVerifyAuthResponseCallback(opts: {
|
|
406
|
+
path: string
|
|
407
|
+
presentationDefinitionId: string
|
|
408
|
+
}): Promise<(correlationId: string) => Promise<boolean>> {
|
|
358
409
|
async function verifyAuthResponseCallback(correlationId: string): Promise<boolean> {
|
|
359
410
|
return fetch(opts.path, {
|
|
360
411
|
method: 'POST',
|
|
@@ -362,12 +413,11 @@ export async function createVerifyAuthResponseCallback(opts: { path: string, pre
|
|
|
362
413
|
'Content-Type': 'application/json',
|
|
363
414
|
},
|
|
364
415
|
body: JSON.stringify({ definitionId: opts.presentationDefinitionId, correlationId }),
|
|
365
|
-
})
|
|
366
|
-
.then(async (response): Promise<boolean> => {
|
|
416
|
+
}).then(async (response): Promise<boolean> => {
|
|
367
417
|
if (response.status >= 400) {
|
|
368
418
|
return Promise.reject(Error(await response.text()))
|
|
369
419
|
} else {
|
|
370
|
-
const responseData = await response.json()
|
|
420
|
+
const responseData = await response.json()
|
|
371
421
|
|
|
372
422
|
if (!responseData.status) {
|
|
373
423
|
return Promise.reject(Error('Missing status in response body'))
|
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { StateType } from '@sphereon/oid4vci-common'
|
|
2
|
+
import { Oid4vcStateEntity } from '@sphereon/ssi-sdk.data-store'
|
|
3
|
+
|
|
4
|
+
export interface IOid4vcStateStore<StateType> {
|
|
5
|
+
persistOid4vcState(args: Oid4vcStateStoreParams<StateType>): Promise<Oid4vcStatePersisted<StateType>>
|
|
6
|
+
|
|
7
|
+
findOid4vcStates(args: StoreOid4vcFindActiveArgs): Promise<Array<Oid4vcStatePersisted<StateType>>>
|
|
8
|
+
|
|
9
|
+
getOid4vcState(args: StoreOid4vcGetArgs): Promise<Oid4vcStatePersisted<StateType>>
|
|
10
|
+
|
|
11
|
+
deleteOid4vcState(args: StoreOid4vcDeleteArgs): Promise<boolean>
|
|
12
|
+
|
|
13
|
+
deleteExpiredOid4vcStates(args: StoreOid4vcDeleteExpiredArgs): Promise<number>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type StoreMachineStatePersistArgs<StateType> = Omit<Oid4vcStateStoreParams<StateType>, 'createdAt' | 'updatedAt'>
|
|
17
|
+
|
|
18
|
+
export type StoreOid4vcFindActiveArgs = Partial<Pick<Oid4vcStateStoreParams<StateType>, 'expiresAt' | 'tenantId' | 'stateId'>>
|
|
19
|
+
|
|
20
|
+
export type FindMachineStatesFilterArgs = Array<Partial<Omit<Oid4vcStateStoreParams<StateType>, 'state'>>>
|
|
21
|
+
|
|
22
|
+
export type StoreFindMachineStatesArgs = {
|
|
23
|
+
filter: FindMachineStatesFilterArgs
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type StoreOid4vcGetArgs = Pick<Oid4vcStateEntity<StateType>, 'id' | 'stateId' | 'correlationId' | 'lookups' | 'tenantId'>
|
|
27
|
+
export type Oid4vcStateStore<StateType> = Pick<Oid4vcStateEntity<StateType>, 'id' | 'stateId' | 'correlationId' | 'lookups'>
|
|
28
|
+
|
|
29
|
+
export type StoreOid4vcDeleteArgs = StoreOid4vcGetArgs
|
|
30
|
+
export type StoreOid4vcDeleteExpiredArgs = {
|
|
31
|
+
id?: string
|
|
32
|
+
correlationId?: string
|
|
33
|
+
sessionId?: string
|
|
34
|
+
lookups?: Array<string>
|
|
35
|
+
tenantId?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type Oid4vcStatePersisted<StateType> = {
|
|
39
|
+
id: string
|
|
40
|
+
stateId?: string
|
|
41
|
+
correlationId?: string
|
|
42
|
+
type: string
|
|
43
|
+
state: StateType
|
|
44
|
+
lookups?: Array<string>
|
|
45
|
+
createdAt: Date
|
|
46
|
+
lastUpdatedAt: Date
|
|
47
|
+
expiresAt?: Date
|
|
48
|
+
tenantId?: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type Oid4vcStateStoreParams<StateType> = Omit<Oid4vcStatePersisted<StateType>, 'id'>
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// import Debug from 'debug'
|
|
2
|
+
//
|
|
3
|
+
//
|
|
4
|
+
// const debug = Debug('sphereon:ssi-sdk:machine-state:store')
|
|
5
|
+
//
|
|
6
|
+
// /**
|
|
7
|
+
// * Represents a data store for managing machine states.
|
|
8
|
+
// */
|
|
9
|
+
// export class MachineStateStore extends IAbstractMachineStateStore {
|
|
10
|
+
// private readonly _dbConnection: OrPromise<DataSource>
|
|
11
|
+
//
|
|
12
|
+
// constructor(dbConnection: OrPromise<DataSource>) {
|
|
13
|
+
// super()
|
|
14
|
+
// this._dbConnection = dbConnection
|
|
15
|
+
// }
|
|
16
|
+
// async persistMachineState(state: StoreMachineStatePersistArgs): Promise<StoreMachineStateInfo> {
|
|
17
|
+
// const connection: DataSource = await this._dbConnection
|
|
18
|
+
// const { machineName, instanceId, tenantId } = state
|
|
19
|
+
// debug(`Executing persistMachineState for machine ${machineName}, instance ${instanceId}, tenantId: ${tenantId}...`)
|
|
20
|
+
// const entity = MachineStateStore.machineStateInfoEntityFrom(state)
|
|
21
|
+
// const existing = await connection.getRepository(MachineStateInfoEntity).findOne({
|
|
22
|
+
// where: {
|
|
23
|
+
// instanceId: state.instanceId,
|
|
24
|
+
// },
|
|
25
|
+
// })
|
|
26
|
+
// if (existing && existing.updatedCount > state.updatedCount) {
|
|
27
|
+
// const error = `Updating machine state with an older version is not allowed. Machine ${existing.machineName}, last count: ${
|
|
28
|
+
// existing.updatedCount
|
|
29
|
+
// }, new count: ${existing.updatedCount}, last updated: ${existing.updatedAt}, current: ${new Date()}, instance: ${existing.instanceId}`
|
|
30
|
+
// console.log(error)
|
|
31
|
+
// return Promise.reject(new Error(error))
|
|
32
|
+
// }
|
|
33
|
+
// // No need for a transaction. This is a single entity. We don't want to be surprised by an isolation level hiding the state from others
|
|
34
|
+
// const result = await connection.getRepository(MachineStateInfoEntity).save(entity, { transaction: false })
|
|
35
|
+
// debug(`Done persistMachineState machine ${machineName}, instance ${instanceId}, tenantId: ${tenantId}`)
|
|
36
|
+
// return MachineStateStore.machineInfoFrom(result)
|
|
37
|
+
// }
|
|
38
|
+
//
|
|
39
|
+
// async findActiveMachineStates(args: StoreMachineStatesFindActiveArgs): Promise<Array<StoreMachineStateInfo>> {
|
|
40
|
+
// const { tenantId, machineName, instanceId } = args
|
|
41
|
+
// const connection: DataSource = await this._dbConnection
|
|
42
|
+
// debug(`Executing findActiveMachineStates query with machineName: ${machineName}, tenantId: ${tenantId}`)
|
|
43
|
+
// const queryBuilder = connection
|
|
44
|
+
// .getRepository(MachineStateInfoEntity)
|
|
45
|
+
// .createQueryBuilder('state')
|
|
46
|
+
// .where('state.completedAt IS NULL')
|
|
47
|
+
// .andWhere(
|
|
48
|
+
// new Brackets((qb) => {
|
|
49
|
+
// qb.where('state.expiresAt IS NULL').orWhere('state.expiresAt > :now', { now: new Date() })
|
|
50
|
+
// }),
|
|
51
|
+
// )
|
|
52
|
+
//
|
|
53
|
+
// if (instanceId) {
|
|
54
|
+
// queryBuilder.andWhere('state.instanceId = :instanceId', { instanceId })
|
|
55
|
+
// }
|
|
56
|
+
// if (tenantId) {
|
|
57
|
+
// queryBuilder.andWhere('state.tenantId = :tenantId', { tenantId })
|
|
58
|
+
// }
|
|
59
|
+
// if (machineName) {
|
|
60
|
+
// queryBuilder.andWhere('state.machineName = :machineName', { machineName })
|
|
61
|
+
// }
|
|
62
|
+
//
|
|
63
|
+
// return (
|
|
64
|
+
// (await queryBuilder
|
|
65
|
+
// .orderBy('state.updatedAt', 'DESC')
|
|
66
|
+
// .getMany()
|
|
67
|
+
// .then((entities) => entities.map(MachineStateStore.machineInfoFrom))) ?? []
|
|
68
|
+
// )
|
|
69
|
+
// }
|
|
70
|
+
//
|
|
71
|
+
// async findMachineStates(args?: StoreFindMachineStatesArgs): Promise<Array<StoreMachineStateInfo>> {
|
|
72
|
+
// const connection: DataSource = await this._dbConnection
|
|
73
|
+
// debug('findMachineStates', args)
|
|
74
|
+
// const result: Array<MachineStateInfoEntity> = await connection.getRepository(MachineStateInfoEntity).find({
|
|
75
|
+
// ...(args?.filter && { where: args?.filter }),
|
|
76
|
+
// transaction: false,
|
|
77
|
+
// })
|
|
78
|
+
//
|
|
79
|
+
// return result.map((event: MachineStateInfoEntity) => MachineStateStore.machineInfoFrom(event))
|
|
80
|
+
// }
|
|
81
|
+
//
|
|
82
|
+
// async getMachineState(args: StoreMachineStateGetArgs): Promise<StoreMachineStateInfo> {
|
|
83
|
+
// const connection: DataSource = await this._dbConnection
|
|
84
|
+
// debug('getMachineState', args)
|
|
85
|
+
// return connection.getRepository(MachineStateInfoEntity).findOneOrFail({ where: { instanceId: args.instanceId } })
|
|
86
|
+
// }
|
|
87
|
+
//
|
|
88
|
+
// async deleteMachineState(args: StoreMachineStateDeleteArgs): Promise<boolean> {
|
|
89
|
+
// debug(`Executing deleteMachineState query with id: ${args.instanceId}`)
|
|
90
|
+
// if (!args.instanceId) {
|
|
91
|
+
// throw new Error('No instanceId parameter is provided.')
|
|
92
|
+
// }
|
|
93
|
+
// try {
|
|
94
|
+
// const connection: DataSource = await this._dbConnection
|
|
95
|
+
//
|
|
96
|
+
// const result = await connection.getRepository(MachineStateInfoEntity).delete(args.instanceId)
|
|
97
|
+
// return result.affected != null && result.affected > 0
|
|
98
|
+
// } catch (error) {
|
|
99
|
+
// debug(`Error deleting state: ${error}`)
|
|
100
|
+
// return false
|
|
101
|
+
// }
|
|
102
|
+
// }
|
|
103
|
+
//
|
|
104
|
+
// async deleteExpiredMachineStates(args: StoreMachineStateDeleteExpiredArgs): Promise<number> {
|
|
105
|
+
// const { machineName, tenantId, deleteDoneStates } = args
|
|
106
|
+
// debug(`Executing deleteExpiredMachineStates query with params: ${JSON.stringify(args)}`)
|
|
107
|
+
// try {
|
|
108
|
+
// const connection: DataSource = await this._dbConnection
|
|
109
|
+
//
|
|
110
|
+
// const deleteCriteria: FindOptionsWhere<MachineStateInfoEntity> = {
|
|
111
|
+
// ...(machineName && { machineName }),
|
|
112
|
+
// ...(tenantId && { tenantId }),
|
|
113
|
+
// // When deleteOnDone state is set we only look at completedAt, in other cases we compare current time with expiresAt
|
|
114
|
+
// ...(!deleteDoneStates && { expiresAt: LessThan(new Date()) }),
|
|
115
|
+
// ...(deleteDoneStates && { completedAt: Not(IsNull()) }),
|
|
116
|
+
// }
|
|
117
|
+
// const result = await connection.getRepository(MachineStateInfoEntity).delete(deleteCriteria)
|
|
118
|
+
// return result.affected ?? 0
|
|
119
|
+
// } catch (error) {
|
|
120
|
+
// debug(`Error deleting machine info: ${error}`)
|
|
121
|
+
// return Promise.reject(new Error(`Error deleting expired machine states for machine type ${machineName}`))
|
|
122
|
+
// }
|
|
123
|
+
// }
|
|
124
|
+
//
|
|
125
|
+
// protected static machineInfoFrom = (machineStateInfoEntity: MachineStateInfoEntity): StoreMachineStateInfo => {
|
|
126
|
+
// // We are making sure no entity function get copied
|
|
127
|
+
// return JSON.parse(JSON.stringify(machineStateInfoEntity))
|
|
128
|
+
// }
|
|
129
|
+
//
|
|
130
|
+
// static machineStateInfoEntityFrom = (machineStateInfo: StoreMachineStateInfo | StoreMachineStatePersistArgs): MachineStateInfoEntity => {
|
|
131
|
+
// const entity = new MachineStateInfoEntity()
|
|
132
|
+
// Object.assign(entity, machineStateInfo)
|
|
133
|
+
// return entity
|
|
134
|
+
// }
|
|
135
|
+
// }
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AccessTokenRequest,
|
|
3
3
|
AccessTokenResponse,
|
|
4
|
+
ClientMetadata,
|
|
4
5
|
CredentialConfigurationSupported,
|
|
5
6
|
CredentialDataSupplierInput,
|
|
6
7
|
CredentialIssuerMetadataOpts,
|
|
8
|
+
CredentialOfferMode,
|
|
7
9
|
CredentialOfferSession,
|
|
8
10
|
CredentialRequest,
|
|
9
11
|
CredentialResponse,
|
|
10
12
|
Grant,
|
|
11
13
|
JsonLdIssuerCredentialDefinition,
|
|
14
|
+
QRCodeOpts,
|
|
15
|
+
StatusListOpts,
|
|
12
16
|
} from '@sphereon/oid4vci-common'
|
|
13
17
|
import { CredentialDataSupplier } from '@sphereon/oid4vci-issuer'
|
|
14
18
|
import { IDIDOptions, ResolveOpts } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
@@ -17,7 +21,7 @@ import { IOID4VCIStore } from '@sphereon/ssi-sdk.oid4vci-issuer-store'
|
|
|
17
21
|
import { ICredential } from '@sphereon/ssi-types/dist'
|
|
18
22
|
import { IAgentContext, ICredentialIssuer, IDIDManager, IKeyManager, IPluginMethodMap, IResolver } from '@veramo/core'
|
|
19
23
|
import { IssuerInstance } from '../IssuerInstance'
|
|
20
|
-
import { IJwtService } from '@sphereon/ssi-sdk-ext.
|
|
24
|
+
import { IJwtService } from '@sphereon/ssi-sdk-ext.jwt-service'
|
|
21
25
|
|
|
22
26
|
export type IssuerCredentialDefinition = JsonLdIssuerCredentialDefinition
|
|
23
27
|
|
|
@@ -41,6 +45,16 @@ export interface ICreateOfferArgs extends IIssuerInstanceArgs {
|
|
|
41
45
|
credentialDefinition?: IssuerCredentialDefinition
|
|
42
46
|
credentialOfferUri?: string
|
|
43
47
|
credentialDataSupplierInput?: CredentialDataSupplierInput // Optional storage that can help the credential Data Supplier. For instance to store credential input data during offer creation, if no additional data can be supplied later on
|
|
48
|
+
|
|
49
|
+
redirectUri?: string
|
|
50
|
+
// auth_session?: string; Would be a nice extension to support, to allow external systems to determine what the auth_session value should be
|
|
51
|
+
// @Deprecated use tx_code in the grant object
|
|
52
|
+
correlationId?: string
|
|
53
|
+
sessionLifeTimeInSec?: number
|
|
54
|
+
qrCodeOpts?: QRCodeOpts
|
|
55
|
+
client_id?: string
|
|
56
|
+
statusListOpts?: Array<StatusListOpts>
|
|
57
|
+
offerMode?: CredentialOfferMode
|
|
44
58
|
baseUri?: string
|
|
45
59
|
scheme?: string
|
|
46
60
|
pinLength?: number
|
|
@@ -74,6 +88,7 @@ export interface IIssuerInstanceOptions extends IMetadataOptions {
|
|
|
74
88
|
}
|
|
75
89
|
|
|
76
90
|
export interface IIssuerOptions {
|
|
91
|
+
asClientOpts?: ClientMetadata
|
|
77
92
|
idOpts?: ManagedIdentifierOptsOrResult
|
|
78
93
|
resolveOpts?: ResolveOpts
|
|
79
94
|
/**
|