@velocitycareerlabs/server-webwallet 1.27.0-dev-build.1eaba1cba → 1.27.0-dev-build.106953732

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velocitycareerlabs/server-webwallet",
3
- "version": "1.27.0-dev-build.1eaba1cba",
3
+ "version": "1.27.0-dev-build.106953732",
4
4
  "description": "Web Wallet application",
5
5
  "repository": "https://github.com/velocitycareerlabs/packages",
6
6
  "engines": {
@@ -34,7 +34,7 @@
34
34
  "@fastify/swagger": "^9.0.0",
35
35
  "@fastify/swagger-ui": "^5.0.0",
36
36
  "@spencejs/spence-mongo-repos": "^0.10.2",
37
- "@velocitycareerlabs/migrations": "1.27.0-dev-build.1eaba1cba",
37
+ "@velocitycareerlabs/migrations": "1.27.0-dev-build.106953732",
38
38
  "@verii/auth": "1.0.1",
39
39
  "@verii/common-functions": "1.0.1",
40
40
  "@verii/common-schemas": "1.0.1",
@@ -74,5 +74,5 @@
74
74
  "nodemon": "3.1.10",
75
75
  "prettier": "2.8.8"
76
76
  },
77
- "gitHead": "5365870dbd208eefb720e0f9d154e613425e20fc"
77
+ "gitHead": "66b910eb7f77e0b6a481e96eb5b5736e01dad734"
78
78
  }
@@ -189,7 +189,9 @@ const feedsController = async (fastify) => {
189
189
  return disclosure;
190
190
  });
191
191
 
192
- const disclosures = await Promise.all(disclosurePromises);
192
+ const disclosures = (await Promise.all(disclosurePromises)).filter(
193
+ (disclosure) => disclosure !== null
194
+ );
193
195
 
194
196
  return { disclosures };
195
197
  }
@@ -1,5 +1,14 @@
1
1
  const { after, afterEach, before, describe, it, mock } = require('node:test');
2
2
  const { expect } = require('expect');
3
+ const { mongoDb } = require('@spencejs/spence-mongo-repos');
4
+ const nock = require('nock');
5
+ const presentationRequestMock = require('./disclosures-controller/mocks/presentation-request');
6
+
7
+ const submitPresentation = mock.fn();
8
+ const getAuthToken = mock.fn();
9
+ const getPresentationRequest = mock.fn(() =>
10
+ Promise.resolve(presentationRequestMock.presentationRequestMock)
11
+ );
3
12
 
4
13
  mock.module('@verii/vnf-nodejs-wallet-sdk', {
5
14
  namedExports: {
@@ -7,26 +16,30 @@ mock.module('@verii/vnf-nodejs-wallet-sdk', {
7
16
  VCLProvider: {
8
17
  getInstance: mock.fn(() => ({
9
18
  initialize: mock.fn(() => Promise.resolve(null)),
19
+ getPresentationRequest,
20
+ submitPresentation,
21
+ getAuthToken,
10
22
  })),
11
23
  },
12
24
  },
13
25
  });
14
26
 
15
- const { mongoDb } = require('@spencejs/spence-mongo-repos');
16
- const nock = require('nock');
17
27
  const buildFastify = require('./helpers/webwallet-build-fastify');
18
28
  const initFeedsFactory = require('./factories/feeds');
19
29
  const initDisclosuresFactory = require('./factories/disclosures');
30
+ const initAccountsFactory = require('./factories/accounts');
20
31
 
21
32
  const auth0Token =
22
33
  // eslint-disable-next-line max-len
23
34
  'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IktFWSJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0LyIsImF1ZCI6ImZvbyIsInNjb3BlIjoicmVhZDp1c2VycyJ9.VwIIUqx9T-AxqbfL_FyNRAeOxTwiC2JpcwtrqnEWN3DdF07ijUkF1WYy8Ahfr_p4R3KnoPbiefZnIbVANCt-lt0ej32rfil2yHhQEsvFxSOjcrx6ARmPp0YAfWlN-5Sotzkxy29jaOZMEDkmRFZg3jkdC7wosPW_S6M-olC4g3HHfylpZI8O3Jdd87Qr9wD_QtUzANwnPbl2Q-9NEyxVjAZIWg_HWK9JAAaf_2IY5VwHBvyp0oeQSEHKi4hogcM59EOc4FxdR5WH45B_PenVa6W4mHFBkH8sAXxt2Zs9s2efujkfWYfyXvgL_lN7vT-TEADlAPP2L6CpWpDISOMsQWUSgGHcN_KwRh_E7qJwahR6mv4QHY6ReEoyjkmSS3swrD1l74jNs7QLAdsMywvzCMDsHabs7DYcEMGQBdP14PJ_ucLFnkivZeBDAc6sS445ocbyrpyO40XMaMorD5khRd9ej89SxR7d_v0W6Ne2Nn4XgW3pAZzu5Rdc4JvqfzLFxkp95jxy1MTAddjWISPmNOYYyXHM9SSqSpqVECOFS0f4z2zycHRqXUcOytWrvED6VGo9x7-IVCgu8vFzj0zToIWQmsDs3UoH9RnV12z0PMwGXQzca1lT_zGwJxBF3e4zJjmcJ05OMF2JgZ2_G48O3M4Dtb0jlgWbKLd0kWlIFzQ;';
24
35
 
25
36
  const auth0UserId = '1234567890';
37
+
26
38
  describe('Feeds Controller', () => {
27
39
  let fastify;
28
40
  let persistFeeds;
29
41
  let persistDisclosures;
42
+ let persistAccounts;
30
43
 
31
44
  before(async () => {
32
45
  fastify = buildFastify();
@@ -34,14 +47,21 @@ describe('Feeds Controller', () => {
34
47
  await fastify.ready();
35
48
  await mongoDb().collection('feeds').deleteMany({});
36
49
  await mongoDb().collection('disclosures').deleteMany({});
50
+ await mongoDb().collection('accounts').deleteMany({});
37
51
  ({ persistFeeds } = initFeedsFactory(fastify));
38
52
  ({ persistDisclosures } = initDisclosuresFactory(fastify));
53
+ ({ persistAccounts } = initAccountsFactory(fastify));
39
54
  });
40
55
 
41
56
  afterEach(async () => {
42
57
  nock.cleanAll();
43
58
  await mongoDb().collection('feeds').deleteMany({});
44
59
  await mongoDb().collection('disclosures').deleteMany({});
60
+ await mongoDb().collection('accounts').deleteMany({});
61
+
62
+ getPresentationRequest.mock.resetCalls();
63
+ submitPresentation.mock.resetCalls();
64
+ getAuthToken.mock.resetCalls();
45
65
  });
46
66
 
47
67
  after(async () => {
@@ -118,6 +138,170 @@ describe('Feeds Controller', () => {
118
138
  expect(response.statusCode).toBe(204);
119
139
  });
120
140
  });
141
+
142
+ describe('shareFeed', () => {
143
+ const shareFeedHeaders = {
144
+ authorization: `Bearer ${auth0Token}`,
145
+ 'content-type': 'application/json',
146
+ };
147
+
148
+ const buildPresentationRequest = () => ({
149
+ ...presentationRequestMock.presentationRequestMock,
150
+ feed: true,
151
+ });
152
+
153
+ const defaultSubmissionResult = {
154
+ jti: 'mock-jti-123',
155
+ submissionId: 'mock-submission-456',
156
+ sessionToken: {
157
+ value: 'mock-session-token-789',
158
+ },
159
+ };
160
+
161
+ const defaultCredentials = [
162
+ {
163
+ id: 'credential-1',
164
+ inputDescriptor: 'CertificationV1.1',
165
+ jwtVc: 'mock-jwt-vc-1',
166
+ },
167
+ {
168
+ id: 'credential-2',
169
+ inputDescriptor: 'LicenseV1.1',
170
+ jwtVc: 'mock-jwt-vc-2',
171
+ },
172
+ {
173
+ id: 'credential-3',
174
+ inputDescriptor: 'NonMatchingType',
175
+ jwtVc: 'mock-jwt-vc-3',
176
+ },
177
+ ];
178
+
179
+ const defaultAccount = {
180
+ did: 'did:test:user123',
181
+ didKeyMetadatum: [
182
+ {
183
+ kty: 'EC',
184
+ crv: 'secp256k1',
185
+ x: 'test-x-value',
186
+ y: 'test-y-value',
187
+ },
188
+ ],
189
+ };
190
+
191
+ const buildSdkAuthToken = (expOffsetSeconds) => ({
192
+ accessToken: {
193
+ value: 'mock-auth-token',
194
+ jwtValue: {
195
+ payload: {
196
+ exp: Math.floor(Date.now() / 1000) + expOffsetSeconds,
197
+ },
198
+ },
199
+ },
200
+ });
201
+
202
+ const buildFeedAuthToken = (expOffsetSeconds) => ({
203
+ accessToken: {
204
+ jwtValue: {
205
+ payload: {
206
+ exp: Math.floor(Date.now() / 1000) + expOffsetSeconds,
207
+ },
208
+ },
209
+ },
210
+ });
211
+
212
+ const setupSdkMocks = ({
213
+ presentationRequest = buildPresentationRequest(),
214
+ submissionResult = defaultSubmissionResult,
215
+ authToken = buildSdkAuthToken(3600),
216
+ } = {}) => {
217
+ getPresentationRequest.mock.mockImplementation(() =>
218
+ Promise.resolve(presentationRequest)
219
+ );
220
+ submitPresentation.mock.mockImplementation(() =>
221
+ Promise.resolve(submissionResult)
222
+ );
223
+ getAuthToken.mock.mockImplementation(() => Promise.resolve(authToken));
224
+ };
225
+
226
+ const persistAccountRecord = async (overrides = {}) => {
227
+ ({ persistAccounts } = initAccountsFactory(fastify));
228
+ return persistAccounts({ auth0UserId, ...defaultAccount, ...overrides });
229
+ };
230
+
231
+ const persistFeedRecord = async (overrides = {}) => {
232
+ ({ persistFeeds } = initFeedsFactory(fastify));
233
+ const {
234
+ credentialTypes = ['CertificationV1.1', 'LicenseV1.1'],
235
+ authToken = buildFeedAuthToken(3600),
236
+ ...rest
237
+ } = overrides;
238
+
239
+ return persistFeeds({
240
+ auth0UserId,
241
+ credentialTypes,
242
+ authToken,
243
+ ...rest,
244
+ });
245
+ };
246
+
247
+ const injectShareFeed = async (credentials = defaultCredentials) =>
248
+ fastify.inject({
249
+ method: 'POST',
250
+ url: '/feeds/share-feed',
251
+ payload: { credentials },
252
+ headers: shareFeedHeaders,
253
+ });
254
+
255
+ it('should share feed and create disclosures for matching credential types', async () => {
256
+ setupSdkMocks();
257
+ await persistAccountRecord();
258
+ await persistFeedRecord();
259
+
260
+ const response = await injectShareFeed();
261
+
262
+ expect(response.statusCode).toBe(200);
263
+ const responseData = response.json();
264
+ expect(responseData).toHaveProperty('disclosures');
265
+ expect(responseData.disclosures).toHaveLength(1);
266
+ });
267
+
268
+ it('should refresh expired auth token', async () => {
269
+ setupSdkMocks({ authToken: buildSdkAuthToken(3600) });
270
+ await persistAccountRecord();
271
+ await persistFeedRecord({
272
+ authToken: buildFeedAuthToken(-3600),
273
+ refreshToken: 'mock-refresh-token',
274
+ });
275
+
276
+ const response = await injectShareFeed();
277
+
278
+ expect(response.statusCode).toBe(200);
279
+ const responseData = response.json();
280
+ expect(responseData).toHaveProperty('disclosures');
281
+ expect(responseData.disclosures).toHaveLength(1);
282
+ expect(getAuthToken.mock.calls.length).toBe(1);
283
+ });
284
+
285
+ it('should filter out null disclosures when no credentials match', async () => {
286
+ setupSdkMocks();
287
+ await persistAccountRecord();
288
+ await persistFeedRecord();
289
+
290
+ const response = await injectShareFeed([
291
+ {
292
+ id: 'credential-3',
293
+ inputDescriptor: 'NonMatchingType',
294
+ jwtVc: 'mock-jwt-vc-3',
295
+ },
296
+ ]);
297
+
298
+ expect(response.statusCode).toBe(200);
299
+ const responseData = response.json();
300
+ expect(responseData).toHaveProperty('disclosures');
301
+ expect(responseData.disclosures).toHaveLength(0);
302
+ expect(submitPresentation.mock.calls.length).toBe(0);
303
+ });
304
+ });
121
305
  });
122
306
 
123
307
  const jwks = {