@velocitycareerlabs/data-loader 1.19.0-dev-build.11b7cc7b6

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 (51) hide show
  1. package/LICENSE +248 -0
  2. package/jest.config.js +7 -0
  3. package/package.json +43 -0
  4. package/src/batch-issuing/README.md +95 -0
  5. package/src/batch-issuing/constants.js +8 -0
  6. package/src/batch-issuing/fetchers.js +100 -0
  7. package/src/batch-issuing/file-readers.js +15 -0
  8. package/src/batch-issuing/file-writers.js +37 -0
  9. package/src/batch-issuing/index.js +115 -0
  10. package/src/batch-issuing/orchestrators.js +258 -0
  11. package/src/batch-issuing/prepare-data.js +208 -0
  12. package/src/batch-issuing/prompts.js +47 -0
  13. package/src/batch-issuing/validate-directory-exists.js +11 -0
  14. package/src/data-loader.js +14 -0
  15. package/src/helpers/common.js +30 -0
  16. package/src/helpers/compute-activation-date.js +12 -0
  17. package/src/helpers/index.js +6 -0
  18. package/src/helpers/load-csv.js +29 -0
  19. package/src/helpers/load-handlebars-template.js +9 -0
  20. package/src/index.js +3 -0
  21. package/src/vendor-credentials/README.md +32 -0
  22. package/src/vendor-credentials/execute-update.js +32 -0
  23. package/src/vendor-credentials/index.js +53 -0
  24. package/src/vendor-credentials/prepare-data.js +40 -0
  25. package/test/batch-issuing.test.js +916 -0
  26. package/test/data/badge-offer.template.json +22 -0
  27. package/test/data/batch-vars-offerids.csv +3 -0
  28. package/test/data/batch-vars.csv +3 -0
  29. package/test/data/batchissuing-variables.csv +3 -0
  30. package/test/data/driver-license-offer.template.json +10 -0
  31. package/test/data/driver-license-variables.csv +3 -0
  32. package/test/data/email-offer.template.json +10 -0
  33. package/test/data/email-variables.csv +3 -0
  34. package/test/data/id-document-offer.template.json +10 -0
  35. package/test/data/id-document-variables.csv +3 -0
  36. package/test/data/national-id-card-offer.template.json +10 -0
  37. package/test/data/national-id-card-variables.csv +3 -0
  38. package/test/data/offer.template.json +22 -0
  39. package/test/data/passport-offer.template.json +10 -0
  40. package/test/data/passport-variables.csv +3 -0
  41. package/test/data/person.template.json +15 -0
  42. package/test/data/phone-offer.template.json +10 -0
  43. package/test/data/phone-variables.csv +2 -0
  44. package/test/data/phones-batch-vars-offerids.csv +3 -0
  45. package/test/data/proof-of-age-offer.template.json +10 -0
  46. package/test/data/proof-of-age-variables.csv +3 -0
  47. package/test/data/resident-permit-offer.template.json +10 -0
  48. package/test/data/resident-permit-variables.csv +3 -0
  49. package/test/data/variables-no-did.csv +3 -0
  50. package/test/data/variables.csv +3 -0
  51. package/test/vendor-credentials.test.js +225 -0
@@ -0,0 +1,916 @@
1
+ const path = require('path');
2
+ const { prepareData } = require('../src/batch-issuing/prepare-data');
3
+ const { DisclosureType } = require('../src/batch-issuing/constants');
4
+
5
+ const ISO_DATETIME_TZ_FORMAT =
6
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\+\d\d:\d\d|Z)$/;
7
+
8
+ describe('batch issuing test', () => {
9
+ it("should fail if options don't have credential type or type doesn't exist", async () => {
10
+ const options = {
11
+ csvFilename: path.join(__dirname, 'data/batch-vars-offerids.csv'),
12
+ offerTemplateFilename: path.join(
13
+ __dirname,
14
+ 'data/email-offer.template.json'
15
+ ),
16
+ termsUrl: 'http://example.com/terms.html',
17
+ did: 'did:ion:sap123',
18
+ };
19
+
20
+ expect(() => prepareData(DisclosureType.NEW, options)).rejects.toThrowError(
21
+ "undefined doesn't exist. Please use one of EmailV1.0,PhoneV1.0,DriversLicenseV1.0"
22
+ );
23
+
24
+ expect(() =>
25
+ prepareData(DisclosureType.NEW, { ...options, credentialType: 'Mug2.1' })
26
+ ).rejects.toThrowError(
27
+ "Mug2.1 doesn't exist. Please use one of EmailV1.0,PhoneV1.0,DriversLicenseV1.0"
28
+ );
29
+ });
30
+
31
+ it('should load the templates and use offerIds from the csv', async () => {
32
+ const options = {
33
+ csvFilename: path.join(__dirname, 'data/batch-vars-offerids.csv'),
34
+ offerTemplateFilename: path.join(
35
+ __dirname,
36
+ 'data/email-offer.template.json'
37
+ ),
38
+ termsUrl: 'http://example.com/terms.html',
39
+ did: 'did:ion:sap123',
40
+ credentialType: 'EmailV1.0',
41
+ };
42
+
43
+ const updates = await prepareData(DisclosureType.NEW, options);
44
+ expect(
45
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
46
+ ).toBeLessThan(Date.now());
47
+
48
+ expect(updates).toEqual({
49
+ newDisclosureRequest: {
50
+ configurationType: 'issuing',
51
+ vendorEndpoint: 'integrated-issuing-identification',
52
+ types: [
53
+ {
54
+ type: 'EmailV1.0',
55
+ },
56
+ ],
57
+ identityMatchers: {
58
+ rules: [
59
+ {
60
+ valueIndex: 0,
61
+ path: ['$.emails'],
62
+ rule: 'pick',
63
+ },
64
+ ],
65
+ vendorUserIdIndex: 0,
66
+ },
67
+ vendorDisclosureId: expect.any(Number),
68
+ setIssuingDefault: true,
69
+ duration: '1h', // 1 hour by default
70
+ offerMode: 'preloaded',
71
+ purpose: 'Issuing Career Credential', // by default have a generic message
72
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
73
+ termsUrl: 'http://example.com/terms.html',
74
+ authTokenExpiresIn: 10080,
75
+ },
76
+ newExchangeOffers: [
77
+ {
78
+ newOffer: {
79
+ type: ['EmailV1.0'],
80
+ issuer: {
81
+ id: 'did:ion:sap123',
82
+ },
83
+ credentialSubject: {
84
+ vendorUserId: 'joan.lee@sap.com',
85
+ email: 'joan.lee@sap.com',
86
+ },
87
+
88
+ offerId: '100',
89
+ },
90
+ newExchange: {
91
+ type: 'ISSUING',
92
+ identityMatcherValues: ['joan.lee@sap.com'],
93
+ },
94
+ },
95
+ {
96
+ newOffer: {
97
+ type: ['EmailV1.0'],
98
+ issuer: {
99
+ id: 'did:ion:sap123',
100
+ },
101
+ credentialSubject: {
102
+ vendorUserId: 'john.smith@sap.com',
103
+ email: 'john.smith@sap.com',
104
+ },
105
+
106
+ offerId: '200',
107
+ },
108
+ newExchange: {
109
+ type: 'ISSUING',
110
+ identityMatcherValues: ['john.smith@sap.com'],
111
+ },
112
+ },
113
+ ],
114
+ });
115
+ });
116
+ it('should load the templates and use offerIds by phone from the csv', async () => {
117
+ const options = {
118
+ csvFilename: path.join(__dirname, 'data/phones-batch-vars-offerids.csv'),
119
+ offerTemplateFilename: path.join(
120
+ __dirname,
121
+ 'data/phone-offer.template.json'
122
+ ),
123
+ termsUrl: 'http://example.com/terms.html',
124
+ credentialType: 'PhoneV1.0',
125
+ did: 'did:ion:sap123',
126
+ };
127
+
128
+ const updates = await prepareData(DisclosureType.NEW, options);
129
+ expect(
130
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
131
+ ).toBeLessThan(Date.now());
132
+
133
+ expect(updates).toEqual({
134
+ newDisclosureRequest: {
135
+ configurationType: 'issuing',
136
+ vendorEndpoint: 'integrated-issuing-identification',
137
+ types: [
138
+ {
139
+ type: 'PhoneV1.0',
140
+ },
141
+ ],
142
+ identityMatchers: {
143
+ rules: [
144
+ {
145
+ valueIndex: 0,
146
+ path: ['$.phones'],
147
+ rule: 'pick',
148
+ },
149
+ ],
150
+ vendorUserIdIndex: 0,
151
+ },
152
+ vendorDisclosureId: expect.any(Number),
153
+ setIssuingDefault: true,
154
+ duration: '1h', // 1 hour by default
155
+ offerMode: 'preloaded',
156
+ purpose: 'Issuing Career Credential', // by default have a generic message
157
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
158
+ termsUrl: 'http://example.com/terms.html',
159
+ authTokenExpiresIn: 10080,
160
+ },
161
+ newExchangeOffers: [
162
+ {
163
+ newOffer: {
164
+ type: ['PhoneV1.0'],
165
+ issuer: {
166
+ id: 'did:ion:sap123',
167
+ },
168
+ credentialSubject: {
169
+ vendorUserId: '+1234567890',
170
+ phone: '+1234567890',
171
+ },
172
+
173
+ offerId: '100',
174
+ },
175
+ newExchange: {
176
+ type: 'ISSUING',
177
+ identityMatcherValues: ['+1234567890'],
178
+ },
179
+ },
180
+ {
181
+ newOffer: {
182
+ type: ['PhoneV1.0'],
183
+ issuer: {
184
+ id: 'did:ion:sap123',
185
+ },
186
+ credentialSubject: {
187
+ vendorUserId: '+2345678901',
188
+ phone: '+2345678901',
189
+ },
190
+
191
+ offerId: '200',
192
+ },
193
+ newExchange: {
194
+ type: 'ISSUING',
195
+ identityMatcherValues: ['+2345678901'],
196
+ },
197
+ },
198
+ ],
199
+ });
200
+ });
201
+ it('should load the templates and use offerIds by driver license from the csv', async () => {
202
+ const options = {
203
+ csvFilename: path.join(__dirname, 'data/driver-license-variables.csv'),
204
+ offerTemplateFilename: path.join(
205
+ __dirname,
206
+ 'data/driver-license-offer.template.json'
207
+ ),
208
+ termsUrl: 'http://example.com/terms.html',
209
+ credentialType: 'DriversLicenseV1.0',
210
+ did: 'did:ion:sap123',
211
+ };
212
+
213
+ const updates = await prepareData(DisclosureType.NEW, options);
214
+ expect(
215
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
216
+ ).toBeLessThan(Date.now());
217
+
218
+ expect(updates).toEqual({
219
+ newDisclosureRequest: {
220
+ configurationType: 'issuing',
221
+ vendorEndpoint: 'integrated-issuing-identification',
222
+ types: [
223
+ {
224
+ type: 'DriversLicenseV1.0',
225
+ },
226
+ ],
227
+ identityMatchers: {
228
+ rules: [
229
+ {
230
+ valueIndex: 0,
231
+ path: ['$.idDocumentCredentials[*].credentialSubject.identifier'],
232
+ rule: 'pick',
233
+ },
234
+ ],
235
+ vendorUserIdIndex: 0,
236
+ },
237
+ vendorDisclosureId: expect.any(Number),
238
+ setIssuingDefault: true,
239
+ duration: '1h', // 1 hour by default
240
+ offerMode: 'preloaded',
241
+ purpose: 'Issuing Career Credential', // by default have a generic message
242
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
243
+ termsUrl: 'http://example.com/terms.html',
244
+ authTokenExpiresIn: 10080,
245
+ },
246
+ newExchangeOffers: [
247
+ {
248
+ newOffer: {
249
+ type: ['DriversLicenseV1.0'],
250
+ issuer: {
251
+ id: 'did:ion:sap123',
252
+ },
253
+ credentialSubject: {
254
+ vendorUserId: 'vm123456',
255
+ identifier: 'vm123456',
256
+ },
257
+
258
+ offerId: expect.any(String),
259
+ },
260
+ newExchange: {
261
+ type: 'ISSUING',
262
+ identityMatcherValues: ['vm123456'],
263
+ },
264
+ },
265
+ {
266
+ newOffer: {
267
+ type: ['DriversLicenseV1.0'],
268
+ issuer: {
269
+ id: 'did:ion:sap123',
270
+ },
271
+ credentialSubject: {
272
+ vendorUserId: 'as4523456',
273
+ identifier: 'as4523456',
274
+ },
275
+
276
+ offerId: expect.any(String),
277
+ },
278
+ newExchange: {
279
+ type: 'ISSUING',
280
+ identityMatcherValues: ['as4523456'],
281
+ },
282
+ },
283
+ ],
284
+ });
285
+ });
286
+
287
+ it('should load the templates and use offerIds by IdDocument from the csv', async () => {
288
+ const options = {
289
+ csvFilename: path.join(__dirname, 'data/id-document-variables.csv'),
290
+ offerTemplateFilename: path.join(
291
+ __dirname,
292
+ 'data/id-document-offer.template.json'
293
+ ),
294
+ termsUrl: 'http://example.com/terms.html',
295
+ credentialType: 'IdDocumentV1.0',
296
+ did: 'did:ion:sap123',
297
+ };
298
+
299
+ const updates = await prepareData(DisclosureType.NEW, options);
300
+ expect(
301
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
302
+ ).toBeLessThan(Date.now());
303
+
304
+ expect(updates).toEqual({
305
+ newDisclosureRequest: {
306
+ configurationType: 'issuing',
307
+ vendorEndpoint: 'integrated-issuing-identification',
308
+ types: [
309
+ {
310
+ type: 'IdDocumentV1.0',
311
+ },
312
+ ],
313
+ identityMatchers: {
314
+ rules: [
315
+ {
316
+ valueIndex: 0,
317
+ path: ['$.idDocumentCredentials[*].credentialSubject.identifier'],
318
+ rule: 'pick',
319
+ },
320
+ ],
321
+ vendorUserIdIndex: 0,
322
+ },
323
+ vendorDisclosureId: expect.any(Number),
324
+ setIssuingDefault: true,
325
+ duration: '1h', // 1 hour by default
326
+ offerMode: 'preloaded',
327
+ purpose: 'Issuing Career Credential', // by default have a generic message
328
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
329
+ termsUrl: 'http://example.com/terms.html',
330
+ authTokenExpiresIn: 10080,
331
+ },
332
+ newExchangeOffers: [
333
+ {
334
+ newOffer: {
335
+ type: ['IdDocumentV1.0'],
336
+ issuer: {
337
+ id: 'did:ion:sap123',
338
+ },
339
+ credentialSubject: {
340
+ vendorUserId: 'BR514345',
341
+ identifier: 'BR514345',
342
+ },
343
+
344
+ offerId: expect.any(String),
345
+ },
346
+ newExchange: {
347
+ type: 'ISSUING',
348
+ identityMatcherValues: ['BR514345'],
349
+ },
350
+ },
351
+ {
352
+ newOffer: {
353
+ type: ['IdDocumentV1.0'],
354
+ issuer: {
355
+ id: 'did:ion:sap123',
356
+ },
357
+ credentialSubject: {
358
+ vendorUserId: 'BT678543',
359
+ identifier: 'BT678543',
360
+ },
361
+
362
+ offerId: expect.any(String),
363
+ },
364
+ newExchange: {
365
+ type: 'ISSUING',
366
+ identityMatcherValues: ['BT678543'],
367
+ },
368
+ },
369
+ ],
370
+ });
371
+ });
372
+
373
+ it('should load the templates and use offerIds by residentPermit from the csv', async () => {
374
+ const options = {
375
+ csvFilename: path.join(__dirname, 'data/resident-permit-variables.csv'),
376
+ offerTemplateFilename: path.join(
377
+ __dirname,
378
+ 'data/resident-permit-offer.template.json'
379
+ ),
380
+ termsUrl: 'http://example.com/terms.html',
381
+ credentialType: 'ResidentPermitV1.0',
382
+ did: 'did:ion:sap123',
383
+ };
384
+
385
+ const updates = await prepareData(DisclosureType.NEW, options);
386
+ expect(
387
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
388
+ ).toBeLessThan(Date.now());
389
+
390
+ expect(updates).toEqual({
391
+ newDisclosureRequest: {
392
+ configurationType: 'issuing',
393
+ vendorEndpoint: 'integrated-issuing-identification',
394
+ types: [
395
+ {
396
+ type: 'ResidentPermitV1.0',
397
+ },
398
+ ],
399
+ identityMatchers: {
400
+ rules: [
401
+ {
402
+ valueIndex: 0,
403
+ path: ['$.idDocumentCredentials[*].credentialSubject.identifier'],
404
+ rule: 'pick',
405
+ },
406
+ ],
407
+ vendorUserIdIndex: 0,
408
+ },
409
+ vendorDisclosureId: expect.any(Number),
410
+ setIssuingDefault: true,
411
+ duration: '1h', // 1 hour by default
412
+ offerMode: 'preloaded',
413
+ purpose: 'Issuing Career Credential', // by default have a generic message
414
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
415
+ termsUrl: 'http://example.com/terms.html',
416
+ authTokenExpiresIn: 10080,
417
+ },
418
+ newExchangeOffers: [
419
+ {
420
+ newOffer: {
421
+ type: ['ResidentPermitV1.0'],
422
+ issuer: {
423
+ id: 'did:ion:sap123',
424
+ },
425
+ credentialSubject: {
426
+ vendorUserId: 'ER514345',
427
+ identifier: 'ER514345',
428
+ },
429
+
430
+ offerId: expect.any(String),
431
+ },
432
+ newExchange: {
433
+ type: 'ISSUING',
434
+ identityMatcherValues: ['ER514345'],
435
+ },
436
+ },
437
+ {
438
+ newOffer: {
439
+ type: ['ResidentPermitV1.0'],
440
+ issuer: {
441
+ id: 'did:ion:sap123',
442
+ },
443
+ credentialSubject: {
444
+ vendorUserId: 'RT678543',
445
+ identifier: 'RT678543',
446
+ },
447
+
448
+ offerId: expect.any(String),
449
+ },
450
+ newExchange: {
451
+ type: 'ISSUING',
452
+ identityMatcherValues: ['RT678543'],
453
+ },
454
+ },
455
+ ],
456
+ });
457
+ });
458
+
459
+ it('should load the templates and use offerIds by passport from the csv', async () => {
460
+ const options = {
461
+ csvFilename: path.join(__dirname, 'data/passport-variables.csv'),
462
+ offerTemplateFilename: path.join(
463
+ __dirname,
464
+ 'data/passport-offer.template.json'
465
+ ),
466
+ termsUrl: 'http://example.com/terms.html',
467
+ credentialType: 'PassportV1.0',
468
+ did: 'did:ion:sap123',
469
+ };
470
+
471
+ const updates = await prepareData(DisclosureType.NEW, options);
472
+ expect(
473
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
474
+ ).toBeLessThan(Date.now());
475
+
476
+ expect(updates).toEqual({
477
+ newDisclosureRequest: {
478
+ configurationType: 'issuing',
479
+ vendorEndpoint: 'integrated-issuing-identification',
480
+ types: [
481
+ {
482
+ type: 'PassportV1.0',
483
+ },
484
+ ],
485
+ identityMatchers: {
486
+ rules: [
487
+ {
488
+ valueIndex: 0,
489
+ path: ['$.idDocumentCredentials[*].credentialSubject.identifier'],
490
+ rule: 'pick',
491
+ },
492
+ ],
493
+ vendorUserIdIndex: 0,
494
+ },
495
+ vendorDisclosureId: expect.any(Number),
496
+ setIssuingDefault: true,
497
+ duration: '1h', // 1 hour by default
498
+ offerMode: 'preloaded',
499
+ purpose: 'Issuing Career Credential', // by default have a generic message
500
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
501
+ termsUrl: 'http://example.com/terms.html',
502
+ authTokenExpiresIn: 10080,
503
+ },
504
+ newExchangeOffers: [
505
+ {
506
+ newOffer: {
507
+ type: ['PassportV1.0'],
508
+ issuer: {
509
+ id: 'did:ion:sap123',
510
+ },
511
+ credentialSubject: {
512
+ vendorUserId: 'ER514345',
513
+ identifier: 'ER514345',
514
+ },
515
+
516
+ offerId: expect.any(String),
517
+ },
518
+ newExchange: {
519
+ type: 'ISSUING',
520
+ identityMatcherValues: ['ER514345'],
521
+ },
522
+ },
523
+ {
524
+ newOffer: {
525
+ type: ['PassportV1.0'],
526
+ issuer: {
527
+ id: 'did:ion:sap123',
528
+ },
529
+ credentialSubject: {
530
+ vendorUserId: 'RT678543',
531
+ identifier: 'RT678543',
532
+ },
533
+
534
+ offerId: expect.any(String),
535
+ },
536
+ newExchange: {
537
+ type: 'ISSUING',
538
+ identityMatcherValues: ['RT678543'],
539
+ },
540
+ },
541
+ ],
542
+ });
543
+ });
544
+
545
+ it('should load the templates and use offerIds by NationalIdCard from the csv', async () => {
546
+ const options = {
547
+ csvFilename: path.join(__dirname, 'data/national-id-card-variables.csv'),
548
+ offerTemplateFilename: path.join(
549
+ __dirname,
550
+ 'data/national-id-card-offer.template.json'
551
+ ),
552
+ termsUrl: 'http://example.com/terms.html',
553
+ credentialType: 'NationalIdCardV1.0',
554
+ did: 'did:ion:sap123',
555
+ };
556
+
557
+ const updates = await prepareData(DisclosureType.NEW, options);
558
+ expect(
559
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
560
+ ).toBeLessThan(Date.now());
561
+
562
+ expect(updates).toEqual({
563
+ newDisclosureRequest: {
564
+ configurationType: 'issuing',
565
+ vendorEndpoint: 'integrated-issuing-identification',
566
+ types: [
567
+ {
568
+ type: 'NationalIdCardV1.0',
569
+ },
570
+ ],
571
+ identityMatchers: {
572
+ rules: [
573
+ {
574
+ valueIndex: 0,
575
+ path: ['$.idDocumentCredentials[*].credentialSubject.identifier'],
576
+ rule: 'pick',
577
+ },
578
+ ],
579
+ vendorUserIdIndex: 0,
580
+ },
581
+ vendorDisclosureId: expect.any(Number),
582
+ setIssuingDefault: true,
583
+ duration: '1h', // 1 hour by default
584
+ offerMode: 'preloaded',
585
+ purpose: 'Issuing Career Credential', // by default have a generic message
586
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
587
+ termsUrl: 'http://example.com/terms.html',
588
+ authTokenExpiresIn: 10080,
589
+ },
590
+ newExchangeOffers: [
591
+ {
592
+ newOffer: {
593
+ type: ['NationalIdCardV1.0'],
594
+ issuer: {
595
+ id: 'did:ion:sap123',
596
+ },
597
+ credentialSubject: {
598
+ vendorUserId: 'BR514345',
599
+ identifier: 'BR514345',
600
+ },
601
+
602
+ offerId: expect.any(String),
603
+ },
604
+ newExchange: {
605
+ type: 'ISSUING',
606
+ identityMatcherValues: ['BR514345'],
607
+ },
608
+ },
609
+ {
610
+ newOffer: {
611
+ type: ['NationalIdCardV1.0'],
612
+ issuer: {
613
+ id: 'did:ion:sap123',
614
+ },
615
+ credentialSubject: {
616
+ vendorUserId: 'BT678543',
617
+ identifier: 'BT678543',
618
+ },
619
+
620
+ offerId: expect.any(String),
621
+ },
622
+ newExchange: {
623
+ type: 'ISSUING',
624
+ identityMatcherValues: ['BT678543'],
625
+ },
626
+ },
627
+ ],
628
+ });
629
+ });
630
+
631
+ it('should load the templates and use offerIds by ProofOfAge from the csv', async () => {
632
+ const options = {
633
+ csvFilename: path.join(__dirname, 'data/proof-of-age-variables.csv'),
634
+ offerTemplateFilename: path.join(
635
+ __dirname,
636
+ 'data/proof-of-age-offer.template.json'
637
+ ),
638
+ termsUrl: 'http://example.com/terms.html',
639
+ credentialType: 'ProofOfAgeV1.0',
640
+ did: 'did:ion:sap123',
641
+ };
642
+
643
+ const updates = await prepareData(DisclosureType.NEW, options);
644
+ expect(
645
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
646
+ ).toBeLessThan(Date.now());
647
+
648
+ expect(updates).toEqual({
649
+ newDisclosureRequest: {
650
+ configurationType: 'issuing',
651
+ vendorEndpoint: 'integrated-issuing-identification',
652
+ types: [
653
+ {
654
+ type: 'ProofOfAgeV1.0',
655
+ },
656
+ ],
657
+ identityMatchers: {
658
+ rules: [
659
+ {
660
+ valueIndex: 0,
661
+ path: ['$.idDocumentCredentials[*].credentialSubject.identifier'],
662
+ rule: 'pick',
663
+ },
664
+ ],
665
+ vendorUserIdIndex: 0,
666
+ },
667
+ vendorDisclosureId: expect.any(Number),
668
+ setIssuingDefault: true,
669
+ duration: '1h', // 1 hour by default
670
+ offerMode: 'preloaded',
671
+ purpose: 'Issuing Career Credential', // by default have a generic message
672
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
673
+ termsUrl: 'http://example.com/terms.html',
674
+ authTokenExpiresIn: 10080,
675
+ },
676
+ newExchangeOffers: [
677
+ {
678
+ newOffer: {
679
+ type: ['ProofOfAgeV1.0'],
680
+ issuer: {
681
+ id: 'did:ion:sap123',
682
+ },
683
+ credentialSubject: {
684
+ vendorUserId: 'ER514345',
685
+ identifier: 'ER514345',
686
+ },
687
+
688
+ offerId: expect.any(String),
689
+ },
690
+ newExchange: {
691
+ type: 'ISSUING',
692
+ identityMatcherValues: ['ER514345'],
693
+ },
694
+ },
695
+ {
696
+ newOffer: {
697
+ type: ['ProofOfAgeV1.0'],
698
+ issuer: {
699
+ id: 'did:ion:sap123',
700
+ },
701
+ credentialSubject: {
702
+ vendorUserId: 'RT678543',
703
+ identifier: 'RT678543',
704
+ },
705
+
706
+ offerId: expect.any(String),
707
+ },
708
+ newExchange: {
709
+ type: 'ISSUING',
710
+ identityMatcherValues: ['RT678543'],
711
+ },
712
+ },
713
+ ],
714
+ });
715
+ });
716
+
717
+ it('should load the templates and csv', async () => {
718
+ const options = {
719
+ csvFilename: path.join(__dirname, 'data/variables.csv'),
720
+ offerTemplateFilename: path.join(
721
+ __dirname,
722
+ 'data/email-offer.template.json'
723
+ ),
724
+ termsUrl: 'http://example.com/terms.html',
725
+ did: 'did:ion:sap123',
726
+ credentialType: 'EmailV1.0',
727
+ };
728
+
729
+ const updates = await prepareData(DisclosureType.NEW, options);
730
+ expect(
731
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
732
+ ).toBeLessThan(Date.now());
733
+
734
+ expect(updates).toEqual({
735
+ newDisclosureRequest: {
736
+ configurationType: 'issuing',
737
+ vendorEndpoint: 'integrated-issuing-identification',
738
+ types: [
739
+ {
740
+ type: 'EmailV1.0',
741
+ },
742
+ ],
743
+ identityMatchers: {
744
+ rules: [
745
+ {
746
+ valueIndex: 0,
747
+ path: ['$.emails'],
748
+ rule: 'pick',
749
+ },
750
+ ],
751
+ vendorUserIdIndex: 0,
752
+ },
753
+ vendorDisclosureId: expect.any(Number),
754
+ setIssuingDefault: true,
755
+ duration: '1h', // 1 hour by default
756
+ offerMode: 'preloaded',
757
+ purpose: 'Issuing Career Credential', // by default have a generic message
758
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
759
+ termsUrl: 'http://example.com/terms.html',
760
+ authTokenExpiresIn: 10080,
761
+ },
762
+ newExchangeOffers: [
763
+ {
764
+ newOffer: {
765
+ type: ['EmailV1.0'],
766
+ issuer: {
767
+ id: 'did:ion:sap123',
768
+ },
769
+ credentialSubject: {
770
+ vendorUserId: 'joan.lee@sap.com',
771
+ email: 'joan.lee@sap.com',
772
+ },
773
+
774
+ offerId: expect.any(String),
775
+ },
776
+ newExchange: {
777
+ type: 'ISSUING',
778
+ identityMatcherValues: ['joan.lee@sap.com'],
779
+ },
780
+ },
781
+ {
782
+ newOffer: {
783
+ type: ['EmailV1.0'],
784
+ issuer: {
785
+ id: 'did:ion:sap123',
786
+ },
787
+ credentialSubject: {
788
+ vendorUserId: 'john.smith@sap.com',
789
+ email: 'john.smith@sap.com',
790
+ },
791
+
792
+ offerId: expect.any(String),
793
+ },
794
+ newExchange: {
795
+ type: 'ISSUING',
796
+ identityMatcherValues: ['john.smith@sap.com'],
797
+ },
798
+ },
799
+ ],
800
+ });
801
+ });
802
+
803
+ it('should load the templates and csv with vars', async () => {
804
+ const options = {
805
+ csvFilename: path.join(__dirname, 'data/variables.csv'),
806
+ offerTemplateFilename: path.join(
807
+ __dirname,
808
+ 'data/email-offer.template.json'
809
+ ),
810
+ termsUrl: 'http://example.com/terms.html',
811
+ label: 'testLabel',
812
+ offerMode: 'preloaded',
813
+ purpose: 'Some Purpose',
814
+ expiresInHours: 100,
815
+ activatesInHours: 10,
816
+ did: 'did:ion:sap456',
817
+ credentialType: 'EmailV1.0',
818
+ };
819
+
820
+ const updates = await prepareData(DisclosureType.NEW, options);
821
+
822
+ expect(updates).toEqual({
823
+ newDisclosureRequest: {
824
+ configurationType: 'issuing',
825
+ vendorEndpoint: 'integrated-issuing-identification',
826
+ types: [
827
+ {
828
+ type: 'EmailV1.0',
829
+ },
830
+ ],
831
+ identityMatchers: {
832
+ rules: [
833
+ {
834
+ valueIndex: 0,
835
+ path: ['$.emails'],
836
+ rule: 'pick',
837
+ },
838
+ ],
839
+ vendorUserIdIndex: 0,
840
+ },
841
+ vendorDisclosureId: expect.any(Number),
842
+ setIssuingDefault: true,
843
+ duration: '1h', // 1 hour by default
844
+ offerMode: 'preloaded',
845
+ purpose: options.purpose, // by default have a generic message
846
+ activationDate: expect.stringMatching(ISO_DATETIME_TZ_FORMAT),
847
+ termsUrl: 'http://example.com/terms.html',
848
+ label: options.label,
849
+ authTokenExpiresIn: 10080,
850
+ },
851
+ newExchangeOffers: [
852
+ {
853
+ newOffer: {
854
+ type: ['EmailV1.0'],
855
+ issuer: {
856
+ id: 'did:ion:sap456',
857
+ },
858
+ credentialSubject: {
859
+ vendorUserId: 'joan.lee@sap.com',
860
+ email: 'joan.lee@sap.com',
861
+ },
862
+
863
+ offerId: expect.any(String),
864
+ label: options.label,
865
+ },
866
+ newExchange: {
867
+ type: 'ISSUING',
868
+ identityMatcherValues: ['joan.lee@sap.com'],
869
+ label: options.label,
870
+ },
871
+ },
872
+ {
873
+ newOffer: {
874
+ type: ['EmailV1.0'],
875
+ issuer: {
876
+ id: 'did:ion:sap456',
877
+ },
878
+ credentialSubject: {
879
+ vendorUserId: 'john.smith@sap.com',
880
+ email: 'john.smith@sap.com',
881
+ },
882
+
883
+ offerId: expect.any(String),
884
+ label: options.label,
885
+ },
886
+ newExchange: {
887
+ type: 'ISSUING',
888
+ identityMatcherValues: ['john.smith@sap.com'],
889
+ label: options.label,
890
+ },
891
+ },
892
+ ],
893
+ });
894
+
895
+ expect(
896
+ new Date(updates.newDisclosureRequest.activationDate).getTime()
897
+ ).toBeGreaterThan(Date.now());
898
+ });
899
+
900
+ it('should have undefined newDisclosureRequest if a disclosure type is existing', async () => {
901
+ const options = {
902
+ csvFilename: path.join(__dirname, 'data/variables.csv'),
903
+ offerTemplateFilename: path.join(
904
+ __dirname,
905
+ 'data/email-offer.template.json'
906
+ ),
907
+ termsUrl: 'http://example.com/terms.html',
908
+ did: 'did:ion:sap123',
909
+ credentialType: 'EmailV1.0',
910
+ disclosure: 'foo',
911
+ };
912
+
913
+ const updates = await prepareData(DisclosureType.EXISTING, options);
914
+ expect(updates.newDisclosureRequest).toBeUndefined();
915
+ });
916
+ });