@sphereon/ssi-sdk.data-store 0.11.1-unstable.64

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.
Files changed (100) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +67 -0
  3. package/dist/contact/AbstractContactStore.d.ts +15 -0
  4. package/dist/contact/AbstractContactStore.d.ts.map +1 -0
  5. package/dist/contact/AbstractContactStore.js +7 -0
  6. package/dist/contact/AbstractContactStore.js.map +1 -0
  7. package/dist/contact/ContactStore.d.ts +30 -0
  8. package/dist/contact/ContactStore.d.ts.map +1 -0
  9. package/dist/contact/ContactStore.js +281 -0
  10. package/dist/contact/ContactStore.js.map +1 -0
  11. package/dist/entities/contact/BaseConfigEntity.d.ts +5 -0
  12. package/dist/entities/contact/BaseConfigEntity.d.ts.map +1 -0
  13. package/dist/entities/contact/BaseConfigEntity.js +26 -0
  14. package/dist/entities/contact/BaseConfigEntity.js.map +1 -0
  15. package/dist/entities/contact/ConnectionEntity.d.ts +12 -0
  16. package/dist/entities/contact/ConnectionEntity.d.ts.map +1 -0
  17. package/dist/entities/contact/ConnectionEntity.js +66 -0
  18. package/dist/entities/contact/ConnectionEntity.js.map +1 -0
  19. package/dist/entities/contact/ContactEntity.d.ts +16 -0
  20. package/dist/entities/contact/ContactEntity.d.ts.map +1 -0
  21. package/dist/entities/contact/ContactEntity.js +108 -0
  22. package/dist/entities/contact/ContactEntity.js.map +1 -0
  23. package/dist/entities/contact/CorrelationIdentifierEntity.d.ts +12 -0
  24. package/dist/entities/contact/CorrelationIdentifierEntity.d.ts.map +1 -0
  25. package/dist/entities/contact/CorrelationIdentifierEntity.js +76 -0
  26. package/dist/entities/contact/CorrelationIdentifierEntity.js.map +1 -0
  27. package/dist/entities/contact/DidAuthConfigEntity.d.ts +11 -0
  28. package/dist/entities/contact/DidAuthConfigEntity.d.ts.map +1 -0
  29. package/dist/entities/contact/DidAuthConfigEntity.js +49 -0
  30. package/dist/entities/contact/DidAuthConfigEntity.js.map +1 -0
  31. package/dist/entities/contact/IdentityEntity.d.ts +22 -0
  32. package/dist/entities/contact/IdentityEntity.d.ts.map +1 -0
  33. package/dist/entities/contact/IdentityEntity.js +137 -0
  34. package/dist/entities/contact/IdentityEntity.js.map +1 -0
  35. package/dist/entities/contact/IdentityMetadataItemEntity.d.ts +12 -0
  36. package/dist/entities/contact/IdentityMetadataItemEntity.d.ts.map +1 -0
  37. package/dist/entities/contact/IdentityMetadataItemEntity.js +73 -0
  38. package/dist/entities/contact/IdentityMetadataItemEntity.js.map +1 -0
  39. package/dist/entities/contact/OpenIdConfigEntity.d.ts +15 -0
  40. package/dist/entities/contact/OpenIdConfigEntity.d.ts.map +1 -0
  41. package/dist/entities/contact/OpenIdConfigEntity.js +70 -0
  42. package/dist/entities/contact/OpenIdConfigEntity.js.map +1 -0
  43. package/dist/index.d.ts +16 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +59 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/migrations/generic/1-CreateContacts.d.ts +7 -0
  48. package/dist/migrations/generic/1-CreateContacts.d.ts.map +1 -0
  49. package/dist/migrations/generic/1-CreateContacts.js +72 -0
  50. package/dist/migrations/generic/1-CreateContacts.js.map +1 -0
  51. package/dist/migrations/generic/index.d.ts +10 -0
  52. package/dist/migrations/generic/index.d.ts.map +1 -0
  53. package/dist/migrations/generic/index.js +13 -0
  54. package/dist/migrations/generic/index.js.map +1 -0
  55. package/dist/migrations/index.d.ts +2 -0
  56. package/dist/migrations/index.d.ts.map +1 -0
  57. package/dist/migrations/index.js +6 -0
  58. package/dist/migrations/index.js.map +1 -0
  59. package/dist/migrations/internal-migrations-ormconfig.d.ts +6 -0
  60. package/dist/migrations/internal-migrations-ormconfig.d.ts.map +1 -0
  61. package/dist/migrations/internal-migrations-ormconfig.js +29 -0
  62. package/dist/migrations/internal-migrations-ormconfig.js.map +1 -0
  63. package/dist/migrations/postgres/1659463079428-CreateContacts.d.ts +7 -0
  64. package/dist/migrations/postgres/1659463079428-CreateContacts.d.ts.map +1 -0
  65. package/dist/migrations/postgres/1659463079428-CreateContacts.js +55 -0
  66. package/dist/migrations/postgres/1659463079428-CreateContacts.js.map +1 -0
  67. package/dist/migrations/sqlite/1659463069549-CreateContacts.d.ts +7 -0
  68. package/dist/migrations/sqlite/1659463069549-CreateContacts.d.ts.map +1 -0
  69. package/dist/migrations/sqlite/1659463069549-CreateContacts.js +79 -0
  70. package/dist/migrations/sqlite/1659463069549-CreateContacts.js.map +1 -0
  71. package/dist/types/IAbstractContactStore.d.ts +41 -0
  72. package/dist/types/IAbstractContactStore.d.ts.map +1 -0
  73. package/dist/types/IAbstractContactStore.js +3 -0
  74. package/dist/types/IAbstractContactStore.js.map +1 -0
  75. package/dist/types/contact.d.ts +91 -0
  76. package/dist/types/contact.d.ts.map +1 -0
  77. package/dist/types/contact.js +21 -0
  78. package/dist/types/contact.js.map +1 -0
  79. package/package.json +45 -0
  80. package/src/__tests__/contact.entities.test.ts +911 -0
  81. package/src/__tests__/contact.store.test.ts +743 -0
  82. package/src/contact/AbstractContactStore.ts +26 -0
  83. package/src/contact/ContactStore.ts +373 -0
  84. package/src/entities/contact/BaseConfigEntity.ts +8 -0
  85. package/src/entities/contact/ConnectionEntity.ts +48 -0
  86. package/src/entities/contact/ContactEntity.ts +76 -0
  87. package/src/entities/contact/CorrelationIdentifierEntity.ts +41 -0
  88. package/src/entities/contact/DidAuthConfigEntity.ts +31 -0
  89. package/src/entities/contact/IdentityEntity.ts +106 -0
  90. package/src/entities/contact/IdentityMetadataItemEntity.ts +39 -0
  91. package/src/entities/contact/OpenIdConfigEntity.ts +48 -0
  92. package/src/index.ts +45 -0
  93. package/src/migrations/generic/1-CreateContacts.ts +54 -0
  94. package/src/migrations/generic/index.ts +10 -0
  95. package/src/migrations/index.ts +1 -0
  96. package/src/migrations/internal-migrations-ormconfig.ts +28 -0
  97. package/src/migrations/postgres/1659463079428-CreateContacts.ts +61 -0
  98. package/src/migrations/sqlite/1659463069549-CreateContacts.ts +111 -0
  99. package/src/types/IAbstractContactStore.ts +51 -0
  100. package/src/types/contact.ts +101 -0
@@ -0,0 +1,911 @@
1
+ import { DataSource } from 'typeorm'
2
+
3
+ import {
4
+ CorrelationIdentifierEnum,
5
+ DataStoreContactEntities,
6
+ DataStoreMigrations,
7
+ contactEntityFrom,
8
+ connectionEntityFrom,
9
+ identityEntityFrom,
10
+ didAuthConfigEntityFrom,
11
+ openIdConfigEntityFrom,
12
+ ContactEntity,
13
+ IdentityEntity,
14
+ ConnectionTypeEnum,
15
+ OpenIdConfigEntity,
16
+ DidAuthConfigEntity,
17
+ ConnectionEntity,
18
+ CorrelationIdentifierEntity,
19
+ IdentityMetadataItemEntity,
20
+ IdentityRoleEnum,
21
+ } from '../index'
22
+
23
+ describe('Database entities test', () => {
24
+ let dbConnection: DataSource
25
+
26
+ beforeEach(async () => {
27
+ dbConnection = await new DataSource({
28
+ type: 'sqlite',
29
+ database: ':memory:',
30
+ //logging: 'all',
31
+ migrationsRun: false,
32
+ migrations: DataStoreMigrations,
33
+ synchronize: false,
34
+ entities: DataStoreContactEntities,
35
+ }).initialize()
36
+ await dbConnection.runMigrations()
37
+ expect(await dbConnection.showMigrations()).toBeFalsy()
38
+ })
39
+
40
+ afterEach(async () => {
41
+ await (await dbConnection).destroy()
42
+ })
43
+
44
+ it('Should save contact to database', async () => {
45
+ const contact = {
46
+ name: 'test_name',
47
+ alias: 'test_alias',
48
+ uri: 'example.com',
49
+ }
50
+
51
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
52
+ await dbConnection.getRepository(ContactEntity).save(contactEntity)
53
+
54
+ const fromDb = await dbConnection.getRepository(ContactEntity).findOne({
55
+ where: { name: contact.name },
56
+ })
57
+
58
+ expect(fromDb).toBeDefined()
59
+ expect(fromDb?.identities?.length).toEqual(0)
60
+ expect(fromDb?.name).toEqual(contact.name)
61
+ expect(fromDb?.alias).toEqual(contact.alias)
62
+ expect(fromDb?.uri).toEqual(contact.uri)
63
+ })
64
+
65
+ it('should throw error when saving contact with blank name', async () => {
66
+ const contact = {
67
+ name: '',
68
+ alias: 'test_alias',
69
+ uri: 'example.com',
70
+ }
71
+
72
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
73
+
74
+ await expect(dbConnection.getRepository(ContactEntity).save(contactEntity)).rejects.toThrow('Blank names are not allowed')
75
+ })
76
+
77
+ it('should throw error when saving contact with blank alias', async () => {
78
+ const contact = {
79
+ name: 'test_name',
80
+ alias: '',
81
+ uri: 'example.com',
82
+ }
83
+
84
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
85
+
86
+ await expect(dbConnection.getRepository(ContactEntity).save(contactEntity)).rejects.toThrow('Blank aliases are not allowed')
87
+ })
88
+
89
+ it('Should enforce unique name for a contact', async () => {
90
+ const contactName = 'non_unique_name'
91
+ const contact1 = {
92
+ name: contactName,
93
+ alias: 'unique_alias1',
94
+ uri: 'example.com',
95
+ }
96
+ const contact1Entity: ContactEntity = contactEntityFrom(contact1)
97
+ await dbConnection.getRepository(ContactEntity).save(contact1Entity)
98
+
99
+ const contact2 = {
100
+ name: contactName,
101
+ alias: 'unique_alias2',
102
+ uri: 'example.com',
103
+ }
104
+ const contact2Entity: ContactEntity = contactEntityFrom(contact2)
105
+
106
+ await expect(dbConnection.getRepository(ContactEntity).save(contact2Entity)).rejects.toThrowError(
107
+ 'SQLITE_CONSTRAINT: UNIQUE constraint failed: Contact.name'
108
+ )
109
+ })
110
+
111
+ it('Should enforce unique alias for a contact', async () => {
112
+ const alias = 'non_unique_alias'
113
+ const contact1 = {
114
+ name: 'unique_name1',
115
+ alias,
116
+ uri: 'example.com',
117
+ }
118
+ const contact1Entity: ContactEntity = contactEntityFrom(contact1)
119
+ await dbConnection.getRepository(ContactEntity).save(contact1Entity)
120
+
121
+ const contact2 = {
122
+ name: 'unique_name2',
123
+ alias,
124
+ uri: 'example.com',
125
+ }
126
+ const contact2Entity: ContactEntity = contactEntityFrom(contact2)
127
+
128
+ await expect(dbConnection.getRepository(ContactEntity).save(contact2Entity)).rejects.toThrowError(
129
+ 'SQLITE_CONSTRAINT: UNIQUE constraint failed: Contact.alias'
130
+ )
131
+ })
132
+
133
+ it('Should enforce unique alias for an identity', async () => {
134
+ const alias = 'non_unique_alias'
135
+ const identity1 = {
136
+ alias,
137
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
138
+ identifier: {
139
+ type: CorrelationIdentifierEnum.DID,
140
+ correlationId: 'unique_correlationId1',
141
+ },
142
+ }
143
+ const identity1Entity: IdentityEntity = identityEntityFrom(identity1)
144
+ await dbConnection.getRepository(IdentityEntity).save(identity1Entity)
145
+
146
+ const identity2 = {
147
+ alias: alias,
148
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
149
+ identifier: {
150
+ type: CorrelationIdentifierEnum.DID,
151
+ correlationId: 'unique_correlationId2',
152
+ },
153
+ }
154
+ const identity2Entity: IdentityEntity = identityEntityFrom(identity2)
155
+ await expect(dbConnection.getRepository(IdentityEntity).save(identity2Entity)).rejects.toThrowError(
156
+ 'SQLITE_CONSTRAINT: UNIQUE constraint failed: Identity.alias'
157
+ )
158
+ })
159
+
160
+ it('Should enforce unique correlationId for a identity', async () => {
161
+ const correlationId = 'non_unique_correlationId'
162
+ const identity1 = {
163
+ alias: 'unique_alias1',
164
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
165
+ identifier: {
166
+ type: CorrelationIdentifierEnum.DID,
167
+ correlationId,
168
+ },
169
+ }
170
+ const identity1Entity: IdentityEntity = identityEntityFrom(identity1)
171
+ await dbConnection.getRepository(IdentityEntity).save(identity1Entity)
172
+
173
+ const identity2 = {
174
+ alias: 'unique_alias2',
175
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
176
+ identifier: {
177
+ type: CorrelationIdentifierEnum.DID,
178
+ correlationId,
179
+ },
180
+ }
181
+ const identity2Entity: IdentityEntity = identityEntityFrom(identity2)
182
+ await expect(dbConnection.getRepository(IdentityEntity).save(identity2Entity)).rejects.toThrowError(
183
+ 'SQLITE_CONSTRAINT: UNIQUE constraint failed: CorrelationIdentifier.correlation_id'
184
+ )
185
+ })
186
+
187
+ it('Should save identity to database', async () => {
188
+ const correlationId = 'example_did'
189
+ const identity = {
190
+ alias: correlationId,
191
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
192
+ identifier: {
193
+ type: CorrelationIdentifierEnum.DID,
194
+ correlationId,
195
+ },
196
+ }
197
+
198
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
199
+
200
+ await dbConnection.getRepository(IdentityEntity).save(identityEntity)
201
+
202
+ const fromDb = await dbConnection.getRepository(IdentityEntity).findOne({
203
+ where: {
204
+ identifier: {
205
+ correlationId,
206
+ },
207
+ },
208
+ })
209
+
210
+ expect(fromDb).toBeDefined()
211
+ expect(fromDb?.connection).toBeNull()
212
+ expect(fromDb?.identifier).toBeDefined()
213
+ expect(fromDb?.identifier.correlationId).toEqual(identity.identifier.correlationId)
214
+ expect(fromDb?.identifier.type).toEqual(identity.identifier.type)
215
+ })
216
+
217
+ it('should throw error when saving identity with blank alias', async () => {
218
+ const identity = {
219
+ alias: '',
220
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
221
+ identifier: {
222
+ type: CorrelationIdentifierEnum.DID,
223
+ correlationId: 'example_did',
224
+ },
225
+ }
226
+
227
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
228
+
229
+ await expect(dbConnection.getRepository(IdentityEntity).save(identityEntity)).rejects.toThrow('Blank aliases are not allowed')
230
+ })
231
+
232
+ it('should throw error when saving identity with blank correlation id', async () => {
233
+ const identity = {
234
+ alias: 'example_did',
235
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
236
+ identifier: {
237
+ type: CorrelationIdentifierEnum.DID,
238
+ correlationId: '',
239
+ },
240
+ }
241
+
242
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
243
+
244
+ await expect(dbConnection.getRepository(IdentityEntity).save(identityEntity)).rejects.toThrow('Blank correlation ids are not allowed')
245
+ })
246
+
247
+ it('should throw error when saving identity with blank metadata label', async () => {
248
+ const correlationId = 'example_did'
249
+ const identity = {
250
+ alias: correlationId,
251
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
252
+ identifier: {
253
+ type: CorrelationIdentifierEnum.DID,
254
+ correlationId,
255
+ },
256
+ metadata: [
257
+ {
258
+ label: '',
259
+ value: 'example_value',
260
+ },
261
+ ],
262
+ }
263
+
264
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
265
+
266
+ await expect(dbConnection.getRepository(IdentityEntity).save(identityEntity)).rejects.toThrow('Blank metadata labels are not allowed')
267
+ })
268
+
269
+ it('should throw error when saving identity with blank metadata value', async () => {
270
+ const correlationId = 'example_did'
271
+ const identity = {
272
+ alias: correlationId,
273
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
274
+ identifier: {
275
+ type: CorrelationIdentifierEnum.DID,
276
+ correlationId,
277
+ },
278
+ metadata: [
279
+ {
280
+ label: 'example_label',
281
+ value: '',
282
+ },
283
+ ],
284
+ }
285
+
286
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
287
+
288
+ await expect(dbConnection.getRepository(IdentityEntity).save(identityEntity)).rejects.toThrow('Blank metadata values are not allowed')
289
+ })
290
+
291
+ it('Should save identity with openid connection to database', async () => {
292
+ const correlationId = 'example.com'
293
+ const identity = {
294
+ alias: correlationId,
295
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
296
+ identifier: {
297
+ type: CorrelationIdentifierEnum.URL,
298
+ correlationId,
299
+ },
300
+ connection: {
301
+ type: ConnectionTypeEnum.OPENID_CONNECT,
302
+ config: {
303
+ clientId: '138d7bf8-c930-4c6e-b928-97d3a4928b01',
304
+ clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0',
305
+ scopes: ['auth'],
306
+ issuer: 'https://example.com/app-test',
307
+ redirectUrl: 'app:/callback',
308
+ dangerouslyAllowInsecureHttpRequests: true,
309
+ clientAuthMethod: 'post' as const,
310
+ },
311
+ },
312
+ }
313
+
314
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
315
+
316
+ await dbConnection.getRepository(IdentityEntity).save(identityEntity)
317
+
318
+ const fromDb = await dbConnection.getRepository(IdentityEntity).findOne({
319
+ where: {
320
+ identifier: {
321
+ correlationId,
322
+ },
323
+ },
324
+ })
325
+
326
+ expect(fromDb).toBeDefined()
327
+ expect(fromDb?.connection).toBeDefined()
328
+ expect(fromDb?.identifier).toBeDefined()
329
+ expect(fromDb?.identifier.correlationId).toEqual(identity.identifier.correlationId)
330
+ expect(fromDb?.identifier.type).toEqual(identity.identifier.type)
331
+ expect(fromDb?.connection?.type).toEqual(identity.connection.type)
332
+ expect(fromDb?.connection?.config).toBeDefined()
333
+ expect((fromDb?.connection?.config as OpenIdConfigEntity).clientId).toEqual(identity.connection.config.clientId)
334
+ })
335
+
336
+ it('Should save identity with didauth connection to database', async () => {
337
+ const correlationId = 'example.com'
338
+ const identity = {
339
+ alias: correlationId,
340
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
341
+ identifier: {
342
+ type: CorrelationIdentifierEnum.URL,
343
+ correlationId,
344
+ },
345
+ connection: {
346
+ type: ConnectionTypeEnum.SIOPv2,
347
+ config: {
348
+ identifier: {
349
+ did: 'did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
350
+ provider: 'test_provider',
351
+ keys: [],
352
+ services: [],
353
+ },
354
+ redirectUrl: 'https://example.com',
355
+ stateId: 'e91f3510-5ce9-42ee-83b7-fa68ff323d27',
356
+ sessionId: 'https://example.com/did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
357
+ },
358
+ },
359
+ }
360
+
361
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
362
+
363
+ await dbConnection.getRepository(IdentityEntity).save(identityEntity)
364
+
365
+ const fromDb = await dbConnection.getRepository(IdentityEntity).findOne({
366
+ where: {
367
+ identifier: {
368
+ correlationId,
369
+ },
370
+ },
371
+ })
372
+
373
+ expect(fromDb).toBeDefined()
374
+ expect(fromDb?.connection).toBeDefined()
375
+ expect(fromDb?.identifier).toBeDefined()
376
+ expect(fromDb?.identifier.correlationId).toEqual(identity.identifier.correlationId)
377
+ expect(fromDb?.identifier.type).toEqual(identity.identifier.type)
378
+ expect(fromDb?.connection?.type).toEqual(identity.connection.type)
379
+ expect(fromDb?.connection?.config).toBeDefined()
380
+ expect((fromDb?.connection?.config as DidAuthConfigEntity).identifier).toEqual(identity.connection.config.identifier.did)
381
+ })
382
+
383
+ it('Should save connection with openid config to database', async () => {
384
+ const connection = {
385
+ type: ConnectionTypeEnum.OPENID_CONNECT,
386
+ config: {
387
+ clientId: '138d7bf8-c930-4c6e-b928-97d3a4928b01',
388
+ clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0',
389
+ scopes: ['auth'],
390
+ issuer: 'https://example.com/app-test',
391
+ redirectUrl: 'app:/callback',
392
+ dangerouslyAllowInsecureHttpRequests: true,
393
+ clientAuthMethod: 'post' as const,
394
+ },
395
+ }
396
+ const connectionEntity = connectionEntityFrom(connection)
397
+ await dbConnection.getRepository(ConnectionEntity).save(connectionEntity, {
398
+ transaction: true,
399
+ })
400
+
401
+ const fromDb = await dbConnection.getRepository(ConnectionEntity).findOne({
402
+ where: { type: connection.type },
403
+ })
404
+
405
+ expect(fromDb).toBeDefined()
406
+
407
+ const fromDbConfig = await dbConnection.getRepository(OpenIdConfigEntity).findOne({
408
+ where: { id: fromDb?.id },
409
+ })
410
+
411
+ expect(fromDbConfig).toBeDefined()
412
+ expect(fromDb?.type).toEqual(connection.type)
413
+ expect(fromDb?.config).toBeDefined()
414
+ expect((fromDb?.config as OpenIdConfigEntity).clientId).toEqual(connection.config.clientId)
415
+ })
416
+
417
+ it('Should save connection with didauth config to database', async () => {
418
+ const connection = {
419
+ type: ConnectionTypeEnum.SIOPv2,
420
+ config: {
421
+ identifier: {
422
+ did: 'did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
423
+ provider: 'test_provider',
424
+ keys: [],
425
+ services: [],
426
+ },
427
+ redirectUrl: 'https://example.com',
428
+ stateId: 'e91f3510-5ce9-42ee-83b7-fa68ff323d27',
429
+ sessionId: 'https://example.com/did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
430
+ },
431
+ }
432
+ const connectionEntity = connectionEntityFrom(connection)
433
+ await dbConnection.getRepository(ConnectionEntity).save(connectionEntity, {
434
+ transaction: true,
435
+ })
436
+
437
+ const fromDb = await dbConnection.getRepository(ConnectionEntity).findOne({
438
+ where: { type: connection.type },
439
+ })
440
+
441
+ expect(fromDb).toBeDefined()
442
+
443
+ const fromDbConfig = await dbConnection.getRepository(DidAuthConfigEntity).findOne({
444
+ where: { id: fromDb?.id },
445
+ })
446
+
447
+ expect(fromDbConfig).toBeDefined()
448
+ expect(fromDb?.type).toEqual(connection.type)
449
+ expect(fromDb?.config).toBeDefined()
450
+ expect((fromDb?.config as DidAuthConfigEntity).identifier).toEqual(connection.config.identifier.did)
451
+ })
452
+
453
+ it('Should save openid config to database', async () => {
454
+ const clientId = '138d7bf8-c930-4c6e-b928-97d3a4928b01'
455
+ const config = {
456
+ clientId,
457
+ clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0',
458
+ scopes: ['auth'],
459
+ issuer: 'https://example.com/app-test',
460
+ redirectUrl: 'app:/callback',
461
+ dangerouslyAllowInsecureHttpRequests: true,
462
+ clientAuthMethod: 'post' as const,
463
+ }
464
+
465
+ const configEntity = openIdConfigEntityFrom(config)
466
+ await dbConnection.getRepository(OpenIdConfigEntity).save(configEntity, {
467
+ transaction: true,
468
+ })
469
+
470
+ const fromDb = await dbConnection.getRepository(OpenIdConfigEntity).findOne({
471
+ where: { clientId: config.clientId },
472
+ })
473
+
474
+ expect(fromDb).toBeDefined()
475
+ expect((fromDb as OpenIdConfigEntity).clientId).toEqual(config.clientId)
476
+ })
477
+
478
+ it('Should save didauth config to database', async () => {
479
+ const sessionId = 'https://example.com/did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01'
480
+ const config = {
481
+ identifier: {
482
+ did: 'did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
483
+ provider: 'test_provider',
484
+ keys: [],
485
+ services: [],
486
+ },
487
+ redirectUrl: 'https://example.com',
488
+ stateId: 'e91f3510-5ce9-42ee-83b7-fa68ff323d27',
489
+ sessionId,
490
+ }
491
+
492
+ const configEntity = didAuthConfigEntityFrom(config)
493
+ await dbConnection.getRepository(DidAuthConfigEntity).save(configEntity, {
494
+ transaction: true,
495
+ })
496
+
497
+ const fromDb = await dbConnection.getRepository(DidAuthConfigEntity).findOne({
498
+ where: { sessionId: config.sessionId },
499
+ })
500
+
501
+ expect(fromDb).toBeDefined()
502
+ expect((fromDb as DidAuthConfigEntity).identifier).toEqual(config.identifier.did)
503
+ })
504
+
505
+ it('Should delete contact and all child relations', async () => {
506
+ const contact = {
507
+ name: 'relation_test_name',
508
+ alias: 'relation_test_alias',
509
+ uri: 'example.com',
510
+ }
511
+
512
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
513
+ const savedContact = await dbConnection.getRepository(ContactEntity).save(contactEntity)
514
+
515
+ const correlationId = 'relation_example.com'
516
+ const identity = {
517
+ alias: correlationId,
518
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
519
+ identifier: {
520
+ type: CorrelationIdentifierEnum.URL,
521
+ correlationId,
522
+ },
523
+ connection: {
524
+ type: ConnectionTypeEnum.OPENID_CONNECT,
525
+ config: {
526
+ clientId: '138d7bf8-c930-4c6e-b928-97d3a4928b01',
527
+ clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0',
528
+ scopes: ['auth'],
529
+ issuer: 'https://example.com/app-test',
530
+ redirectUrl: 'app:/callback',
531
+ dangerouslyAllowInsecureHttpRequests: true,
532
+ clientAuthMethod: 'post' as const,
533
+ },
534
+ },
535
+ metadata: [
536
+ {
537
+ label: 'example_label',
538
+ value: 'example_value',
539
+ },
540
+ ],
541
+ }
542
+
543
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
544
+ identityEntity.contact = savedContact
545
+
546
+ const savedIdentity = await dbConnection.getRepository(IdentityEntity).save(identityEntity)
547
+
548
+ expect(
549
+ await dbConnection.getRepository(ContactEntity).findOne({
550
+ where: { name: contact.name },
551
+ })
552
+ ).toBeDefined()
553
+
554
+ await dbConnection.getRepository(ContactEntity).delete({ id: savedContact.id })
555
+
556
+ // check contact
557
+ await expect(
558
+ await dbConnection.getRepository(ContactEntity).findOne({
559
+ where: { name: contact.name },
560
+ })
561
+ ).toBeNull()
562
+
563
+ // check identity
564
+ expect(
565
+ await dbConnection.getRepository(IdentityEntity).findOne({
566
+ where: { alias: correlationId },
567
+ })
568
+ ).toBeNull()
569
+
570
+ // check identity identifier
571
+ expect(
572
+ await dbConnection.getRepository(CorrelationIdentifierEntity).findOne({
573
+ where: { id: savedIdentity.identifier.id },
574
+ })
575
+ ).toBeNull()
576
+
577
+ // check identity connection
578
+ expect(
579
+ await dbConnection.getRepository(ConnectionEntity).findOne({
580
+ where: { id: savedIdentity.connection!.id },
581
+ })
582
+ ).toBeNull()
583
+
584
+ // check connection config
585
+ expect(
586
+ await dbConnection.getRepository(OpenIdConfigEntity).findOne({
587
+ where: { id: savedIdentity.connection!.config.id },
588
+ })
589
+ ).toBeNull()
590
+
591
+ // check identity metadata
592
+ expect(
593
+ await dbConnection.getRepository(IdentityMetadataItemEntity).findOne({
594
+ where: { id: savedIdentity.metadata![0].id },
595
+ })
596
+ ).toBeNull()
597
+ })
598
+
599
+ it('Should delete identity and all child relations', async () => {
600
+ const contact = {
601
+ name: 'relation_test_name',
602
+ alias: 'relation_test_alias',
603
+ uri: 'example.com',
604
+ }
605
+
606
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
607
+ const savedContact = await dbConnection.getRepository(ContactEntity).save(contactEntity)
608
+
609
+ const correlationId = 'relation_example.com'
610
+ const identity = {
611
+ alias: correlationId,
612
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
613
+ identifier: {
614
+ type: CorrelationIdentifierEnum.URL,
615
+ correlationId,
616
+ },
617
+ connection: {
618
+ type: ConnectionTypeEnum.SIOPv2,
619
+ config: {
620
+ identifier: {
621
+ did: 'did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
622
+ provider: 'test_provider',
623
+ keys: [],
624
+ services: [],
625
+ },
626
+ redirectUrl: 'https://example.com',
627
+ stateId: 'e91f3510-5ce9-42ee-83b7-fa68ff323d27',
628
+ sessionId: 'https://example.com/did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
629
+ },
630
+ },
631
+ metadata: [
632
+ {
633
+ label: 'example_label',
634
+ value: 'example_value',
635
+ },
636
+ ],
637
+ }
638
+
639
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
640
+ identityEntity.contact = savedContact
641
+
642
+ const savedIdentity = await dbConnection.getRepository(IdentityEntity).save(identityEntity)
643
+
644
+ expect(
645
+ await dbConnection.getRepository(ContactEntity).findOne({
646
+ where: { name: contact.name },
647
+ })
648
+ ).toBeDefined()
649
+
650
+ await dbConnection.getRepository(IdentityEntity).delete({ id: savedIdentity.id })
651
+
652
+ // check identity
653
+ expect(
654
+ await dbConnection.getRepository(IdentityEntity).findOne({
655
+ where: { alias: correlationId },
656
+ })
657
+ ).toBeNull()
658
+
659
+ // check identity identifier
660
+ expect(
661
+ await dbConnection.getRepository(CorrelationIdentifierEntity).findOne({
662
+ where: { id: savedIdentity.identifier.id },
663
+ })
664
+ ).toBeNull()
665
+
666
+ // check identity connection
667
+ expect(
668
+ await dbConnection.getRepository(ConnectionEntity).findOne({
669
+ where: { id: savedIdentity.connection!.id },
670
+ })
671
+ ).toBeNull()
672
+
673
+ // check connection config
674
+ expect(
675
+ await dbConnection.getRepository(OpenIdConfigEntity).findOne({
676
+ where: { id: savedIdentity.connection!.config.id },
677
+ })
678
+ ).toBeNull()
679
+
680
+ // check identity metadata
681
+ expect(
682
+ await dbConnection.getRepository(IdentityMetadataItemEntity).findOne({
683
+ where: { id: savedIdentity.metadata![0].id },
684
+ })
685
+ ).toBeNull()
686
+ })
687
+
688
+ it('Should not delete contact when deleting identity', async () => {
689
+ const contact = {
690
+ name: 'relation_test_name',
691
+ alias: 'relation_test_alias',
692
+ uri: 'example.com',
693
+ }
694
+
695
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
696
+ const savedContact = await dbConnection.getRepository(ContactEntity).save(contactEntity)
697
+
698
+ const correlationId = 'relation_example.com'
699
+ const identity = {
700
+ alias: correlationId,
701
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
702
+ identifier: {
703
+ type: CorrelationIdentifierEnum.URL,
704
+ correlationId,
705
+ },
706
+ connection: {
707
+ type: ConnectionTypeEnum.SIOPv2,
708
+ config: {
709
+ identifier: {
710
+ did: 'did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
711
+ provider: 'test_provider',
712
+ keys: [],
713
+ services: [],
714
+ },
715
+ redirectUrl: 'https://example.com',
716
+ stateId: 'e91f3510-5ce9-42ee-83b7-fa68ff323d27',
717
+ sessionId: 'https://example.com/did:test:138d7bf8-c930-4c6e-b928-97d3a4928b01',
718
+ },
719
+ },
720
+ metadata: [
721
+ {
722
+ label: 'example_label',
723
+ value: 'example_value',
724
+ },
725
+ ],
726
+ }
727
+
728
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
729
+ identityEntity.contact = savedContact
730
+
731
+ const savedIdentity = await dbConnection.getRepository(IdentityEntity).save(identityEntity)
732
+
733
+ await dbConnection.getRepository(IdentityEntity).delete({ id: savedIdentity.id })
734
+
735
+ // check identity
736
+ expect(
737
+ await dbConnection.getRepository(IdentityEntity).findOne({
738
+ where: { id: savedIdentity.id },
739
+ })
740
+ ).toBeNull()
741
+
742
+ // check contact
743
+ expect(
744
+ await dbConnection.getRepository(ContactEntity).findOne({
745
+ where: { name: contact.name },
746
+ })
747
+ ).toBeDefined()
748
+ })
749
+
750
+ it('Should set creation date when saving contact', async () => {
751
+ const contact = {
752
+ name: 'test_name',
753
+ alias: 'test_alias',
754
+ uri: 'example.com',
755
+ }
756
+
757
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
758
+ await dbConnection.getRepository(ContactEntity).save(contactEntity)
759
+
760
+ const fromDb = await dbConnection.getRepository(ContactEntity).findOne({
761
+ where: { name: contact.name },
762
+ })
763
+
764
+ expect(fromDb).toBeDefined()
765
+ expect(fromDb?.createdAt).toBeDefined()
766
+ })
767
+
768
+ it('Should not update creation date when updating contact', async () => {
769
+ const contact = {
770
+ name: 'test_name',
771
+ alias: 'test_alias',
772
+ uri: 'example.com',
773
+ }
774
+
775
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
776
+ const savedContact = await dbConnection.getRepository(ContactEntity).save(contactEntity)
777
+ const newContactName = 'new_name'
778
+ await dbConnection.getRepository(ContactEntity).save({ ...savedContact, name: newContactName })
779
+
780
+ const fromDb = await dbConnection.getRepository(ContactEntity).findOne({
781
+ where: { id: savedContact.id },
782
+ })
783
+
784
+ expect(fromDb).toBeDefined()
785
+ expect(fromDb?.createdAt).toEqual(savedContact?.createdAt)
786
+ })
787
+
788
+ it('Should set creation date when saving identity', async () => {
789
+ const correlationId = 'example_did'
790
+ const identity = {
791
+ alias: correlationId,
792
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
793
+ identifier: {
794
+ type: CorrelationIdentifierEnum.DID,
795
+ correlationId,
796
+ },
797
+ }
798
+
799
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
800
+ await dbConnection.getRepository(IdentityEntity).save(identityEntity)
801
+
802
+ const fromDb = await dbConnection.getRepository(IdentityEntity).findOne({
803
+ where: {
804
+ identifier: {
805
+ correlationId,
806
+ },
807
+ },
808
+ })
809
+
810
+ expect(fromDb).toBeDefined()
811
+ expect(fromDb?.createdAt).toBeDefined()
812
+ })
813
+
814
+ it('Should not update creation date when saving identity', async () => {
815
+ const correlationId = 'example_did'
816
+ const identity = {
817
+ alias: correlationId,
818
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
819
+ identifier: {
820
+ type: CorrelationIdentifierEnum.DID,
821
+ correlationId,
822
+ },
823
+ }
824
+
825
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
826
+ const savedIdentity = await dbConnection.getRepository(IdentityEntity).save(identityEntity)
827
+ const newCorrelationId = 'new_example_did'
828
+ await dbConnection
829
+ .getRepository(IdentityEntity)
830
+ .save({ ...savedIdentity, identifier: { ...savedIdentity.identifier, correlationId: newCorrelationId } })
831
+
832
+ const fromDb = await dbConnection.getRepository(IdentityEntity).findOne({
833
+ where: {
834
+ identifier: {
835
+ correlationId: newCorrelationId,
836
+ },
837
+ },
838
+ })
839
+
840
+ expect(fromDb).toBeDefined()
841
+ expect(fromDb?.createdAt).toEqual(savedIdentity?.createdAt)
842
+ })
843
+
844
+ it('Should set last updated date when saving contact', async () => {
845
+ const contact = {
846
+ name: 'test_name',
847
+ alias: 'test_alias',
848
+ uri: 'example.com',
849
+ }
850
+
851
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
852
+ await dbConnection.getRepository(ContactEntity).save(contactEntity)
853
+
854
+ const fromDb = await dbConnection.getRepository(ContactEntity).findOne({
855
+ where: { name: contact.name },
856
+ })
857
+
858
+ expect(fromDb).toBeDefined()
859
+ expect(fromDb?.lastUpdatedAt).toBeDefined()
860
+ })
861
+
862
+ it('Should update last updated date when updating contact', async () => {
863
+ const contact = {
864
+ name: 'test_name',
865
+ alias: 'test_alias',
866
+ uri: 'example.com',
867
+ }
868
+
869
+ const contactEntity: ContactEntity = contactEntityFrom(contact)
870
+ const savedContact = await dbConnection.getRepository(ContactEntity).save(contactEntity)
871
+
872
+ // waiting here to get a different timestamp
873
+ await new Promise((resolve) => setTimeout(resolve, 2000))
874
+
875
+ const newContactName = 'new_name'
876
+ await dbConnection.getRepository(ContactEntity).save({ ...savedContact, name: newContactName })
877
+
878
+ const fromDb = await dbConnection.getRepository(ContactEntity).findOne({
879
+ where: { id: savedContact.id },
880
+ })
881
+
882
+ expect(fromDb).toBeDefined()
883
+ expect(fromDb?.lastUpdatedAt).not.toEqual(savedContact?.lastUpdatedAt)
884
+ })
885
+
886
+ it('Should set last updated date when saving identity', async () => {
887
+ const correlationId = 'example_did'
888
+ const identity = {
889
+ alias: correlationId,
890
+ roles: [IdentityRoleEnum.ISSUER, IdentityRoleEnum.VERIFIER],
891
+ identifier: {
892
+ type: CorrelationIdentifierEnum.DID,
893
+ correlationId,
894
+ },
895
+ }
896
+
897
+ const identityEntity: IdentityEntity = identityEntityFrom(identity)
898
+ await dbConnection.getRepository(IdentityEntity).save(identityEntity)
899
+
900
+ const fromDb = await dbConnection.getRepository(IdentityEntity).findOne({
901
+ where: {
902
+ identifier: {
903
+ correlationId,
904
+ },
905
+ },
906
+ })
907
+
908
+ expect(fromDb).toBeDefined()
909
+ expect(fromDb?.lastUpdatedAt).toBeDefined()
910
+ })
911
+ })