@sphereon/ssi-sdk.data-store 0.34.1-feature.SSISDK.78.306 → 0.34.1-feature.SSISDK.82.linkedVP.326
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 +261 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +261 -96
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/__tests__/digitalCredential.store.test.ts +116 -1
- package/src/digitalCredential/DigitalCredentialStore.ts +38 -0
- package/src/entities/digitalCredential/DigitalCredentialEntity.ts +6 -0
- package/src/migrations/generic/14-AddLinkedVpFields.ts +66 -0
- package/src/migrations/generic/index.ts +2 -1
- package/src/migrations/postgres/1763387280001-AddLinkedVpFields.ts +29 -0
- package/src/migrations/sqlite/1763387280002-AddLinkedVpFields.ts +32 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/ssi-sdk.data-store",
|
|
3
|
-
"version": "0.34.1-feature.SSISDK.
|
|
3
|
+
"version": "0.34.1-feature.SSISDK.82.linkedVP.326+2b4ebda9",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@sphereon/kmp-mdoc-core": "0.2.0-SNAPSHOT.26",
|
|
30
30
|
"@sphereon/pex": "5.0.0-unstable.28",
|
|
31
|
-
"@sphereon/ssi-sdk-ext.did-utils": "0.34.1-feature.SSISDK.
|
|
32
|
-
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-feature.SSISDK.
|
|
33
|
-
"@sphereon/ssi-sdk.agent-config": "0.34.1-feature.SSISDK.
|
|
34
|
-
"@sphereon/ssi-sdk.core": "0.34.1-feature.SSISDK.
|
|
35
|
-
"@sphereon/ssi-sdk.data-store-types": "0.34.1-feature.SSISDK.
|
|
36
|
-
"@sphereon/ssi-types": "0.34.1-feature.SSISDK.
|
|
31
|
+
"@sphereon/ssi-sdk-ext.did-utils": "0.34.1-feature.SSISDK.82.linkedVP.326+2b4ebda9",
|
|
32
|
+
"@sphereon/ssi-sdk-ext.identifier-resolution": "0.34.1-feature.SSISDK.82.linkedVP.326+2b4ebda9",
|
|
33
|
+
"@sphereon/ssi-sdk.agent-config": "0.34.1-feature.SSISDK.82.linkedVP.326+2b4ebda9",
|
|
34
|
+
"@sphereon/ssi-sdk.core": "0.34.1-feature.SSISDK.82.linkedVP.326+2b4ebda9",
|
|
35
|
+
"@sphereon/ssi-sdk.data-store-types": "0.34.1-feature.SSISDK.82.linkedVP.326+2b4ebda9",
|
|
36
|
+
"@sphereon/ssi-types": "0.34.1-feature.SSISDK.82.linkedVP.326+2b4ebda9",
|
|
37
37
|
"@veramo/core": "4.2.0",
|
|
38
38
|
"@veramo/utils": "4.2.0",
|
|
39
39
|
"blakejs": "^1.2.1",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"PostgreSQL",
|
|
67
67
|
"Contact Store"
|
|
68
68
|
],
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "2b4ebda97cd73ad5b73555cb8bb9d087f0d98395"
|
|
70
70
|
}
|
|
@@ -334,7 +334,7 @@ describe('Database entities tests', (): void => {
|
|
|
334
334
|
expect(result).toEqual(false)
|
|
335
335
|
})
|
|
336
336
|
|
|
337
|
-
it('should update stored digital credential', async (): Promise<void> => {
|
|
337
|
+
it('should update stored digital credential state', async (): Promise<void> => {
|
|
338
338
|
const rawCredential: string =
|
|
339
339
|
'eyJraWQiOiJkaWQ6a2V5Ono2TWtyaGt5M3B1c20yNk1laUZhWFUzbjJuZWtyYW13RlVtZ0dyZUdHa0RWNnpRaiN6Nk1rcmhreTNwdXNtMjZNZWlGYVhVM24ybmVrcmFtd0ZVbWdHcmVHR2tEVjZ6UWoiLCJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vc3BoZXJlb24tb3BlbnNvdXJjZS5naXRodWIuaW8vc3NpLW1vYmlsZS13YWxsZXQvY29udGV4dC9zcGhlcmVvbi13YWxsZXQtaWRlbnRpdHktdjEuanNvbmxkIl0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJTcGhlcmVvbldhbGxldElkZW50aXR5Q3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJmaXJzdE5hbWUiOiJTIiwibGFzdE5hbWUiOiJLIiwiZW1haWxBZGRyZXNzIjoic0BrIn19LCJzdWIiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJqdGkiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJuYmYiOjE3MDg0NDA4MDgsImlzcyI6ImRpZDprZXk6ejZNa3Joa3kzcHVzbTI2TWVpRmFYVTNuMm5la3JhbXdGVW1nR3JlR0drRFY2elFqIn0.G0M84XVAxSmzGY-NQuB9NBofNrINSn6lvxW6761Vlq6ypvYgtc2xNdpiRmw8ryVNfnpzrr4Z5cB1RlrC05rJAw'
|
|
340
340
|
const digitalCredential: AddCredentialArgs = {
|
|
@@ -359,6 +359,121 @@ describe('Database entities tests', (): void => {
|
|
|
359
359
|
expect(result.verifiedState).toEqual(CredentialStateType.VERIFIED)
|
|
360
360
|
})
|
|
361
361
|
|
|
362
|
+
// Add these test cases to digitalCredential.store.test.ts after the existing update tests
|
|
363
|
+
|
|
364
|
+
it('should update digital credential fields', async (): Promise<void> => {
|
|
365
|
+
const rawCredential: string =
|
|
366
|
+
'eyJraWQiOiJkaWQ6a2V5Ono2TWtyaGt5M3B1c20yNk1laUZhWFUzbjJuZWtyYW13RlVtZ0dyZUdHa0RWNnpRaiN6Nk1rcmhreTNwdXNtMjZNZWlGYVhVM24ybmVrcmFtd0ZVbWdHcmVHR2tEVjZ6UWoiLCJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vc3BoZXJlb24tb3BlbnNvdXJjZS5naXRodWIuaW8vc3NpLW1vYmlsZS13YWxsZXQvY29udGV4dC9zcGhlcmVvbi13YWxsZXQtaWRlbnRpdHktdjEuanNvbmxkIl0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJTcGhlcmVvbldhbGxldElkZW50aXR5Q3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJmaXJzdE5hbWUiOiJTIiwibGFzdE5hbWUiOiJLIiwiZW1haWxBZGRyZXNzIjoic0BrIn19LCJzdWIiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJqdGkiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJuYmYiOjE3MDg0NDA4MDgsImlzcyI6ImRpZDprZXk6ejZNa3Joa3kzcHVzbTI2TWVpRmFYVTNuMm5la3JhbXdGVW1nR3JlR0drRFY2elFqIn0.G0M84XVAxSmzGY-NQuB9NBofNrINSn6lvxW6761Vlq6ypvYgtc2xNdpiRmw8ryVNfnpzrr4Z5cB1RlrC05rJAw'
|
|
367
|
+
const digitalCredential: AddCredentialArgs = {
|
|
368
|
+
rawDocument: rawCredential,
|
|
369
|
+
kmsKeyRef: 'testRef',
|
|
370
|
+
identifierMethod: 'did',
|
|
371
|
+
issuerCorrelationType: CredentialCorrelationType.DID,
|
|
372
|
+
subjectCorrelationType: CredentialCorrelationType.DID,
|
|
373
|
+
issuerCorrelationId: 'did:key:z6Mkrhky3pusm26MeiFaXU3n2nekramwFUmgGreGGkDV6zQj',
|
|
374
|
+
subjectCorrelationId: 'did:key:z6Mkrhky3pusm26MeiFaXU3n2nekramwFUmgGreGGkDV6zQj',
|
|
375
|
+
credentialRole: CredentialRole.VERIFIER,
|
|
376
|
+
tenantId: 'urn:uuid:nnag4b43-1e7a-98f8-a32c-a48dbc5b10mj',
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const savedDigitalCredential: DigitalCredential = await digitalCredentialStore.addCredential(digitalCredential)
|
|
380
|
+
|
|
381
|
+
const result = await digitalCredentialStore.updateCredential({
|
|
382
|
+
id: savedDigitalCredential.id,
|
|
383
|
+
kmsKeyRef: 'newTestRef',
|
|
384
|
+
tenantId: 'urn:uuid:new-tenant-id',
|
|
385
|
+
linkedVpId: 'vp-123',
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
expect(result.kmsKeyRef).toEqual('newTestRef')
|
|
389
|
+
expect(result.tenantId).toEqual('urn:uuid:new-tenant-id')
|
|
390
|
+
expect(result.linkedVpId).toEqual('vp-123')
|
|
391
|
+
expect(result.id).toEqual(savedDigitalCredential.id)
|
|
392
|
+
expect(result.hash).toEqual(savedDigitalCredential.hash)
|
|
393
|
+
expect(result.createdAt).toEqual(savedDigitalCredential.createdAt)
|
|
394
|
+
expect(result.lastUpdatedAt.getTime()).toBeGreaterThan(savedDigitalCredential.lastUpdatedAt.getTime())
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
it('should update digital credential by hash', async (): Promise<void> => {
|
|
398
|
+
const rawCredential: string =
|
|
399
|
+
'eyJraWQiOiJkaWQ6a2V5Ono2TWtyaGt5M3B1c20yNk1laUZhWFUzbjJuZWtyYW13RlVtZ0dyZUdHa0RWNnpRaiN6Nk1rcmhreTNwdXNtMjZNZWlGYVhVM24ybmVrcmFtd0ZVbWdHcmVHR2tEVjZ6UWoiLCJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vc3BoZXJlb24tb3BlbnNvdXJjZS5naXRodWIuaW8vc3NpLW1vYmlsZS13YWxsZXQvY29udGV4dC9zcGhlcmVvbi13YWxsZXQtaWRlbnRpdHktdjEuanNvbmxkIl0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJTcGhlcmVvbldhbGxldElkZW50aXR5Q3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJmaXJzdE5hbWUiOiJTIiwibGFzdE5hbWUiOiJLIiwiZW1haWxBZGRyZXNzIjoic0BrIn19LCJzdWIiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJqdGkiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJuYmYiOjE3MDg0NDA4MDgsImlzcyI6ImRpZDprZXk6ejZNa3Joa3kzcHVzbTI2TWVpRmFYVTNuMm5la3JhbXdGVW1nR3JlR0drRFY2elFqIn0.G0M84XVAxSmzGY-NQuB9NBofNrINSn6lvxW6761Vlq6ypvYgtc2xNdpiRmw8ryVNfnpzrr4Z5cB1RlrC05rJAw'
|
|
400
|
+
const digitalCredential: AddCredentialArgs = {
|
|
401
|
+
rawDocument: rawCredential,
|
|
402
|
+
kmsKeyRef: 'testRef',
|
|
403
|
+
identifierMethod: 'did',
|
|
404
|
+
issuerCorrelationType: CredentialCorrelationType.DID,
|
|
405
|
+
subjectCorrelationType: CredentialCorrelationType.DID,
|
|
406
|
+
issuerCorrelationId: 'did:key:z6Mkrhky3pusm26MeiFaXU3n2nekramwFUmgGreGGkDV6zQj',
|
|
407
|
+
subjectCorrelationId: 'did:key:z6Mkrhky3pusm26MeiFaXU3n2nekramwFUmgGreGGkDV6zQj',
|
|
408
|
+
credentialRole: CredentialRole.VERIFIER,
|
|
409
|
+
tenantId: 'urn:uuid:nnag4b43-1e7a-98f8-a32c-a48dbc5b10mj',
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const savedDigitalCredential: DigitalCredential = await digitalCredentialStore.addCredential(digitalCredential)
|
|
413
|
+
|
|
414
|
+
const result = await digitalCredentialStore.updateCredential({
|
|
415
|
+
hash: savedDigitalCredential.hash,
|
|
416
|
+
rpCorrelationId: 'did:example:rp',
|
|
417
|
+
rpCorrelationType: CredentialCorrelationType.DID,
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
expect(result.rpCorrelationId).toEqual('did:example:rp')
|
|
421
|
+
expect(result.rpCorrelationType).toEqual(CredentialCorrelationType.DID)
|
|
422
|
+
expect(result.hash).toEqual(savedDigitalCredential.hash)
|
|
423
|
+
})
|
|
424
|
+
|
|
425
|
+
it('should throw error when updating credential without id or hash', async (): Promise<void> => {
|
|
426
|
+
await expect(
|
|
427
|
+
digitalCredentialStore.updateCredential({
|
|
428
|
+
kmsKeyRef: 'newRef',
|
|
429
|
+
} as any),
|
|
430
|
+
).rejects.toThrowError('No id or hash param is provided.')
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
it('should throw error when updating non-existent credential', async (): Promise<void> => {
|
|
434
|
+
await expect(
|
|
435
|
+
digitalCredentialStore.updateCredential({
|
|
436
|
+
id: 'non-existent-id',
|
|
437
|
+
kmsKeyRef: 'newRef',
|
|
438
|
+
}),
|
|
439
|
+
).rejects.toThrowError('No credential found for args: {"id":"non-existent-id"}')
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
it('should preserve immutable fields when updating credential', async (): Promise<void> => {
|
|
443
|
+
const rawCredential: string =
|
|
444
|
+
'eyJraWQiOiJkaWQ6a2V5Ono2TWtyaGt5M3B1c20yNk1laUZhWFUzbjJuZWtyYW13RlVtZ0dyZUdHa0RWNnpRaiN6Nk1rcmhreTNwdXNtMjZNZWlGYVhVM24ybmVrcmFtd0ZVbWdHcmVHR2tEVjZ6UWoiLCJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vc3BoZXJlb24tb3BlbnNvdXJjZS5naXRodWIuaW8vc3NpLW1vYmlsZS13YWxsZXQvY29udGV4dC9zcGhlcmVvbi13YWxsZXQtaWRlbnRpdHktdjEuanNvbmxkIl0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJTcGhlcmVvbldhbGxldElkZW50aXR5Q3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJmaXJzdE5hbWUiOiJTIiwibGFzdE5hbWUiOiJLIiwiZW1haWxBZGRyZXNzIjoic0BrIn19LCJzdWIiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJqdGkiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJuYmYiOjE3MDg0NDA4MDgsImlzcyI6ImRpZDprZXk6ejZNa3Joa3kzcHVzbTI2TWVpRmFYVTNuMm5la3JhbXdGVW1nR3JlR0drRFY2elFqIn0.G0M84XVAxSmzGY-NQuB9NBofNrINSn6lvxW6761Vlq6ypvYgtc2xNdpiRmw8ryVNfnpzrr4Z5cB1RlrC05rJAw'
|
|
445
|
+
const digitalCredential: AddCredentialArgs = {
|
|
446
|
+
rawDocument: rawCredential,
|
|
447
|
+
kmsKeyRef: 'testRef',
|
|
448
|
+
identifierMethod: 'did',
|
|
449
|
+
issuerCorrelationType: CredentialCorrelationType.DID,
|
|
450
|
+
subjectCorrelationType: CredentialCorrelationType.DID,
|
|
451
|
+
issuerCorrelationId: 'did:key:z6Mkrhky3pusm26MeiFaXU3n2nekramwFUmgGreGGkDV6zQj',
|
|
452
|
+
subjectCorrelationId: 'did:key:z6Mkrhky3pusm26MeiFaXU3n2nekramwFUmgGreGGkDV6zQj',
|
|
453
|
+
credentialRole: CredentialRole.VERIFIER,
|
|
454
|
+
tenantId: 'urn:uuid:nnag4b43-1e7a-98f8-a32c-a48dbc5b10mj',
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const savedDigitalCredential: DigitalCredential = await digitalCredentialStore.addCredential(digitalCredential)
|
|
458
|
+
const originalId = savedDigitalCredential.id
|
|
459
|
+
const originalHash = savedDigitalCredential.hash
|
|
460
|
+
const originalCreatedAt = savedDigitalCredential.createdAt
|
|
461
|
+
|
|
462
|
+
// Try to update with different id, hash, and createdAt - these should be ignored
|
|
463
|
+
const result = await digitalCredentialStore.updateCredential({
|
|
464
|
+
id: savedDigitalCredential.id,
|
|
465
|
+
kmsKeyRef: 'updatedRef',
|
|
466
|
+
hash: 'should-be-ignored' as any,
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
// Verify immutable fields remain unchanged
|
|
470
|
+
expect(result.id).toEqual(originalId)
|
|
471
|
+
expect(result.hash).toEqual(originalHash)
|
|
472
|
+
expect(result.createdAt).toEqual(originalCreatedAt)
|
|
473
|
+
// Verify mutable field was updated
|
|
474
|
+
expect(result.kmsKeyRef).toEqual('updatedRef')
|
|
475
|
+
})
|
|
476
|
+
|
|
362
477
|
it('should throw exception on updating stored digital credential to revoked', async (): Promise<void> => {
|
|
363
478
|
const rawCredential: string =
|
|
364
479
|
'eyJraWQiOiJkaWQ6a2V5Ono2TWtyaGt5M3B1c20yNk1laUZhWFUzbjJuZWtyYW13RlVtZ0dyZUdHa0RWNnpRaiN6Nk1rcmhreTNwdXNtMjZNZWlGYVhVM24ybmVrcmFtd0ZVbWdHcmVHR2tEVjZ6UWoiLCJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vc3BoZXJlb24tb3BlbnNvdXJjZS5naXRodWIuaW8vc3NpLW1vYmlsZS13YWxsZXQvY29udGV4dC9zcGhlcmVvbi13YWxsZXQtaWRlbnRpdHktdjEuanNvbmxkIl0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJTcGhlcmVvbldhbGxldElkZW50aXR5Q3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJmaXJzdE5hbWUiOiJTIiwibGFzdE5hbWUiOiJLIiwiZW1haWxBZGRyZXNzIjoic0BrIn19LCJzdWIiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJqdGkiOiJ1cm46dXVpZDpkZGE3YmYyNC04ZTdhLTQxZjgtYjY2Yy1hNDhkYmM1YjEwZmEiLCJuYmYiOjE3MDg0NDA4MDgsImlzcyI6ImRpZDprZXk6ejZNa3Joa3kzcHVzbTI2TWVpRmFYVTNuMm5la3JhbXdGVW1nR3JlR0drRFY2elFqIn0.G0M84XVAxSmzGY-NQuB9NBofNrINSn6lvxW6761Vlq6ypvYgtc2xNdpiRmw8ryVNfnpzrr4Z5cB1RlrC05rJAw'
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
GetCredentialsResponse,
|
|
9
9
|
NonPersistedDigitalCredential,
|
|
10
10
|
RemoveCredentialArgs,
|
|
11
|
+
UpdateCredentialArgs,
|
|
11
12
|
UpdateCredentialStateArgs,
|
|
12
13
|
} from '@sphereon/ssi-sdk.data-store-types'
|
|
13
14
|
import { CredentialRole, OrPromise } from '@sphereon/ssi-types'
|
|
@@ -72,6 +73,43 @@ export class DigitalCredentialStore extends AbstractDigitalCredentialStore {
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
updateCredential = async (args: UpdateCredentialArgs): Promise<DigitalCredential> => {
|
|
77
|
+
const dcRepo = await this.getRepository()
|
|
78
|
+
const whereClause: Record<string, any> = {}
|
|
79
|
+
|
|
80
|
+
if ('id' in args) {
|
|
81
|
+
whereClause.id = args.id
|
|
82
|
+
} else if ('hash' in args) {
|
|
83
|
+
whereClause.hash = args.hash
|
|
84
|
+
} else {
|
|
85
|
+
return Promise.reject(Error('No id or hash param is provided.'))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const credential: DigitalCredentialEntity | null = await dcRepo.findOne({
|
|
89
|
+
where: whereClause,
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
if (!credential) {
|
|
93
|
+
return Promise.reject(Error(`No credential found for args: ${JSON.stringify(whereClause)}`))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Separate identifier from updates
|
|
97
|
+
const { id, hash, ...updates } = args as any
|
|
98
|
+
|
|
99
|
+
const updatedCredential: DigitalCredential = {
|
|
100
|
+
...credential,
|
|
101
|
+
...updates,
|
|
102
|
+
id: credential.id,
|
|
103
|
+
hash: credential.hash,
|
|
104
|
+
createdAt: credential.createdAt,
|
|
105
|
+
lastUpdatedAt: new Date(),
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
debug('Updating credential', updatedCredential)
|
|
109
|
+
const updatedResult: DigitalCredentialEntity = await dcRepo.save(updatedCredential, { transaction: true })
|
|
110
|
+
return digitalCredentialFrom(updatedResult)
|
|
111
|
+
}
|
|
112
|
+
|
|
75
113
|
removeCredential = async (args: RemoveCredentialArgs): Promise<boolean> => {
|
|
76
114
|
if (!args) {
|
|
77
115
|
return false
|
|
@@ -76,6 +76,12 @@ export class DigitalCredentialEntity extends BaseEntity implements DigitalCreden
|
|
|
76
76
|
@Column('text', { name: 'tenant_id', nullable: true })
|
|
77
77
|
tenantId?: string
|
|
78
78
|
|
|
79
|
+
@Column('text', { name: 'linked_vp_id', nullable: true })
|
|
80
|
+
linkedVpId?: string
|
|
81
|
+
|
|
82
|
+
@CreateDateColumn({ name: 'linked_vp_from', nullable: true, type: typeOrmDateTime() })
|
|
83
|
+
linkedVpFrom?: Date
|
|
84
|
+
|
|
79
85
|
@CreateDateColumn({ name: 'created_at', nullable: false, type: typeOrmDateTime() })
|
|
80
86
|
createdAt!: Date
|
|
81
87
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import Debug, { Debugger } from 'debug'
|
|
2
|
+
import { DatabaseType, MigrationInterface, QueryRunner } from 'typeorm'
|
|
3
|
+
import { AddLinkedVpFields1763387280001 } from '../postgres/1763387280001-AddLinkedVpFields'
|
|
4
|
+
import { AddLinkedVpFields1763387280002 } from '../sqlite/1763387280002-AddLinkedVpFields'
|
|
5
|
+
|
|
6
|
+
const debug: Debugger = Debug('sphereon:ssi-sdk:migrations')
|
|
7
|
+
|
|
8
|
+
export class AddLinkedVpFields1763387280000 implements MigrationInterface {
|
|
9
|
+
name: string = 'AddLinkedVpFields1763387280000'
|
|
10
|
+
|
|
11
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
12
|
+
debug('migration: adding linked VP fields to DigitalCredential table')
|
|
13
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
14
|
+
|
|
15
|
+
switch (dbType) {
|
|
16
|
+
case 'postgres': {
|
|
17
|
+
debug('using postgres migration file for AddLinkedVpFields')
|
|
18
|
+
const mig: AddLinkedVpFields1763387280001 = new AddLinkedVpFields1763387280001()
|
|
19
|
+
await mig.up(queryRunner)
|
|
20
|
+
debug('Postgres migration statements for AddLinkedVpFields executed')
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
case 'sqlite':
|
|
24
|
+
case 'expo':
|
|
25
|
+
case 'react-native': {
|
|
26
|
+
debug('using sqlite/react-native migration file for AddLinkedVpFields')
|
|
27
|
+
const mig: AddLinkedVpFields1763387280002 = new AddLinkedVpFields1763387280002()
|
|
28
|
+
await mig.up(queryRunner)
|
|
29
|
+
debug('SQLite migration statements for AddLinkedVpFields executed')
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
default:
|
|
33
|
+
return Promise.reject(
|
|
34
|
+
`Migrations are currently only supported for sqlite, react-native, expo, and postgres for AddLinkedVpFields. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`,
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
40
|
+
debug('migration: reverting linked VP fields from DigitalCredential table')
|
|
41
|
+
const dbType: DatabaseType = queryRunner.connection.driver.options.type
|
|
42
|
+
|
|
43
|
+
switch (dbType) {
|
|
44
|
+
case 'postgres': {
|
|
45
|
+
debug('using postgres migration file for AddLinkedVpFields')
|
|
46
|
+
const mig: AddLinkedVpFields1763387280001 = new AddLinkedVpFields1763387280001()
|
|
47
|
+
await mig.down(queryRunner)
|
|
48
|
+
debug('Postgres migration statements for AddLinkedVpFields reverted')
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
case 'sqlite':
|
|
52
|
+
case 'expo':
|
|
53
|
+
case 'react-native': {
|
|
54
|
+
debug('using sqlite/react-native migration file for AddLinkedVpFields')
|
|
55
|
+
const mig: AddLinkedVpFields1763387280002 = new AddLinkedVpFields1763387280002()
|
|
56
|
+
await mig.down(queryRunner)
|
|
57
|
+
debug('SQLite migration statements for AddLinkedVpFields reverted')
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
default:
|
|
61
|
+
return Promise.reject(
|
|
62
|
+
`Migrations are currently only supported for sqlite, react-native, expo, and postgres for AddLinkedVpFields. Was ${dbType}. Please run your database without migrations and with 'migrationsRun: false' and 'synchronize: true' for now`,
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -3,6 +3,7 @@ import { CreatePresentationDefinitions1716533767523 } from './10-CreatePresentat
|
|
|
3
3
|
import { FixCredentialClaimsReferencesUuid1741895822987 } from './11-FixCredentialClaimsReferenceUuid'
|
|
4
4
|
import { AddBitstringStatusListEnum1741895823000, CreateBitstringStatusList1741895823000 } from './12-CreateBitstringStatusList'
|
|
5
5
|
import { CreateDcqlQueryItem1726617600000 } from './13-CreateDcqlQueryItem'
|
|
6
|
+
import { AddLinkedVpFields1763387280000 } from './14-AddLinkedVpFields'
|
|
6
7
|
import { CreateIssuanceBranding1659463079429 } from './2-CreateIssuanceBranding'
|
|
7
8
|
import { CreateContacts1690925872318 } from './3-CreateContacts'
|
|
8
9
|
import { CreateStatusList1693866470000 } from './4-CreateStatusList'
|
|
@@ -34,7 +35,7 @@ export const DataStoreStatusListMigrations = [
|
|
|
34
35
|
CreateBitstringStatusList1741895823000,
|
|
35
36
|
]
|
|
36
37
|
export const DataStoreEventLoggerMigrations = [CreateAuditEvents1701635835330]
|
|
37
|
-
export const DataStoreDigitalCredentialMigrations = [CreateDigitalCredential1708525189000]
|
|
38
|
+
export const DataStoreDigitalCredentialMigrations = [CreateDigitalCredential1708525189000, AddLinkedVpFields1763387280000]
|
|
38
39
|
export const DataStoreMachineStateMigrations = [CreateMachineStateStore1708098041262]
|
|
39
40
|
export const DataStorePresentationDefinitionMigrations = [CreatePresentationDefinitions1716533767523, CreateDcqlQueryItem1726617600000]
|
|
40
41
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export class AddLinkedVpFields1763387280001 implements MigrationInterface {
|
|
4
|
+
name = 'AddLinkedVpFields1763387280001'
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`
|
|
8
|
+
ALTER TABLE "DigitalCredential"
|
|
9
|
+
ADD COLUMN "linked_vp_id" text
|
|
10
|
+
`)
|
|
11
|
+
|
|
12
|
+
await queryRunner.query(`
|
|
13
|
+
ALTER TABLE "DigitalCredential"
|
|
14
|
+
ADD COLUMN "linked_vp_from" TIMESTAMP
|
|
15
|
+
`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
19
|
+
await queryRunner.query(`
|
|
20
|
+
ALTER TABLE "DigitalCredential"
|
|
21
|
+
DROP COLUMN "linked_vp_from"
|
|
22
|
+
`)
|
|
23
|
+
|
|
24
|
+
await queryRunner.query(`
|
|
25
|
+
ALTER TABLE "DigitalCredential"
|
|
26
|
+
DROP COLUMN "linked_vp_id"
|
|
27
|
+
`)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
export class AddLinkedVpFields1763387280002 implements MigrationInterface {
|
|
4
|
+
name = 'AddLinkedVpFields1763387280002'
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`
|
|
8
|
+
ALTER TABLE "DigitalCredential"
|
|
9
|
+
ADD COLUMN "linked_vp_id" text
|
|
10
|
+
`)
|
|
11
|
+
|
|
12
|
+
await queryRunner.query(`
|
|
13
|
+
ALTER TABLE "DigitalCredential"
|
|
14
|
+
ADD COLUMN "linked_vp_from" datetime
|
|
15
|
+
`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
19
|
+
// SQLite doesn't support DROP COLUMN in older versions
|
|
20
|
+
// For production, you may need to recreate the table
|
|
21
|
+
// For now, we'll try the direct approach which works in SQLite 3.35.0+
|
|
22
|
+
await queryRunner.query(`
|
|
23
|
+
ALTER TABLE "DigitalCredential"
|
|
24
|
+
DROP COLUMN "linked_vp_from"
|
|
25
|
+
`)
|
|
26
|
+
|
|
27
|
+
await queryRunner.query(`
|
|
28
|
+
ALTER TABLE "DigitalCredential"
|
|
29
|
+
DROP COLUMN "linked_vp_id"
|
|
30
|
+
`)
|
|
31
|
+
}
|
|
32
|
+
}
|