@axinom/mosaic-id-guard 0.18.0-rc.9 → 0.18.0

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 (49) hide show
  1. package/dist/common/helpers/guard-authorization.d.ts +22 -0
  2. package/dist/common/helpers/guard-authorization.d.ts.map +1 -0
  3. package/dist/common/helpers/guard-authorization.js +49 -0
  4. package/dist/common/helpers/guard-authorization.js.map +1 -0
  5. package/dist/common/id-guard-error.d.ts +1 -0
  6. package/dist/common/id-guard-error.d.ts.map +1 -1
  7. package/dist/common/id-guard-error.js +7 -1
  8. package/dist/common/id-guard-error.js.map +1 -1
  9. package/dist/common/id-guard-errors.d.ts +8 -0
  10. package/dist/common/id-guard-errors.d.ts.map +1 -1
  11. package/dist/common/id-guard-errors.js +8 -0
  12. package/dist/common/id-guard-errors.js.map +1 -1
  13. package/dist/graphql/ax-guard-plugin.d.ts +23 -0
  14. package/dist/graphql/ax-guard-plugin.d.ts.map +1 -0
  15. package/dist/graphql/ax-guard-plugin.js +29 -0
  16. package/dist/graphql/ax-guard-plugin.js.map +1 -0
  17. package/dist/graphql/enforce-strict-permissions.plugin.d.ts +1 -1
  18. package/dist/graphql/enforce-strict-permissions.plugin.d.ts.map +1 -1
  19. package/dist/graphql/index.d.ts +3 -2
  20. package/dist/graphql/index.d.ts.map +1 -1
  21. package/dist/graphql/index.js +3 -2
  22. package/dist/graphql/index.js.map +1 -1
  23. package/dist/graphql/{guard-plugin.d.ts → query-mutation-guard-plugin.d.ts} +2 -2
  24. package/dist/graphql/query-mutation-guard-plugin.d.ts.map +1 -0
  25. package/dist/graphql/{guard-plugin.js → query-mutation-guard-plugin.js} +5 -26
  26. package/dist/graphql/query-mutation-guard-plugin.js.map +1 -0
  27. package/dist/graphql/subscription-guard-plugin.d.ts +20 -0
  28. package/dist/graphql/subscription-guard-plugin.d.ts.map +1 -0
  29. package/dist/graphql/subscription-guard-plugin.js +81 -0
  30. package/dist/graphql/subscription-guard-plugin.js.map +1 -0
  31. package/package.json +9 -10
  32. package/src/common/helpers/guard-authorization.ts +76 -0
  33. package/src/common/id-guard-error.ts +13 -0
  34. package/src/common/id-guard-errors.ts +10 -0
  35. package/src/graphql/ax-guard-plugin.ts +29 -0
  36. package/src/graphql/enforce-strict-permissions.plugin.ts +1 -1
  37. package/src/graphql/index.ts +3 -2
  38. package/src/graphql/{guard-plugin.spec.ts → query-mutation-guard-plugin.spec.ts} +3 -3
  39. package/src/graphql/{guard-plugin.ts → query-mutation-guard-plugin.ts} +12 -36
  40. package/src/graphql/subscription-guard-plugin.spec.ts +257 -0
  41. package/src/graphql/subscription-guard-plugin.ts +112 -0
  42. package/dist/graphql/guard-plugin.d.ts.map +0 -1
  43. package/dist/graphql/guard-plugin.js.map +0 -1
  44. package/dist/graphql/subscription-authorization-hook-factory.d.ts +0 -13
  45. package/dist/graphql/subscription-authorization-hook-factory.d.ts.map +0 -1
  46. package/dist/graphql/subscription-authorization-hook-factory.js +0 -182
  47. package/dist/graphql/subscription-authorization-hook-factory.js.map +0 -1
  48. package/src/graphql/subscription-authorization-hook-factory.spec.ts +0 -749
  49. package/src/graphql/subscription-authorization-hook-factory.ts +0 -286
@@ -1,749 +0,0 @@
1
- import { Request, Response } from 'express';
2
- import { ExecutionArgs, GraphQLSchema } from 'graphql';
3
- import gql from 'graphql-tag';
4
- import { CloseCode } from 'graphql-ws';
5
- import { makePluginHook, PostGraphileOptions } from 'postgraphile';
6
- import { ExecutionParams } from 'subscriptions-transport-ws';
7
- import { IdGuardErrors, SubjectType } from '../common';
8
- import { subscriptionAuthorizationHookFactory } from './subscription-authorization-hook-factory';
9
-
10
- describe('subscriptionAuthorizationHookFactory', () => {
11
- describe('When calling the subscription through postgraphile:ws:onOperation', () => {
12
- it('Management User without required permissions -> UserNotAuthorized error', async () => {
13
- // Arrange
14
- const hookGenerator = subscriptionAuthorizationHookFactory;
15
- const buildOptions: PostGraphileOptions<Request, Response> = {
16
- graphileBuildOptions: {
17
- // permission definition without permissions for the required subscription 'echoSubscription'
18
- permissionDefinition: {
19
- gqlOptions: {
20
- anonymousGqlOperations: [],
21
- ignoredGqlOperations: [],
22
- },
23
- permissions: [
24
- {
25
- key: 'Editor',
26
- title: 'Editor',
27
- gqlOperations: ['otherEndpoint'],
28
- },
29
- ],
30
- },
31
- },
32
- };
33
- const hookPlugin = hookGenerator(buildOptions);
34
- const context = {
35
- subject: {
36
- sub: 'test-user',
37
- permissions: { 'test-service': ['Editor'] },
38
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime + 20 seconds
39
- subjectType: SubjectType.UserAccount,
40
- },
41
- config: { serviceId: 'test-service' },
42
- };
43
-
44
- const params: ExecutionParams = {
45
- query: `subscription EchoSubscription {
46
- echoSubscription
47
- }`,
48
- operationName: 'EchoSubscription',
49
- context: context,
50
- variables: [],
51
- };
52
- const hookFunction = makePluginHook([hookPlugin]);
53
-
54
- // Act & Assert
55
- expect(() =>
56
- hookFunction('postgraphile:ws:onOperation', params, context),
57
- ).toThrow('User is not authorized to access the operation.');
58
- });
59
-
60
- it('EndUserApplication token without required permissions -> UserNotAuthorized error', async () => {
61
- // Arrange
62
- const hookGenerator = subscriptionAuthorizationHookFactory;
63
- const buildOptions: PostGraphileOptions<Request, Response> = {
64
- graphileBuildOptions: {
65
- endUserAuthorizationConfig: {
66
- anonymousGqlOperations: [],
67
- applicationTokenAllowedGqlOperations: [
68
- 'subscriptionPlans',
69
- 'subscriptionLifecycleStatusMutated',
70
- ],
71
- },
72
- },
73
- };
74
- const hookPlugin = hookGenerator(buildOptions);
75
- const context = {
76
- subject: {
77
- sub: 'test-user',
78
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime + 20 seconds
79
- subjectType: SubjectType.EndUserApplication,
80
- },
81
- config: { serviceId: 'test-service' },
82
- };
83
-
84
- const params: ExecutionParams = {
85
- query: `subscription EchoSubscription {
86
- echoSubscription
87
- }`,
88
- operationName: 'EchoSubscription',
89
- context: context,
90
- variables: [],
91
- };
92
- const hookFunction = makePluginHook([hookPlugin]);
93
-
94
- // Act & Assert
95
- expect(() =>
96
- hookFunction('postgraphile:ws:onOperation', params, context),
97
- ).toThrow('Application Token is not authorized to access the operation.');
98
- });
99
-
100
- it.each([
101
- SubjectType.UserAccount,
102
- SubjectType.ManagedServiceAccount,
103
- SubjectType.ServiceAccount,
104
- SubjectType.ImpersonatedUserAccount,
105
- SubjectType.EndUserApplication,
106
- SubjectType.EndUserAccount,
107
- ])(
108
- 'Authorized %s with expired token for subscription -> UserNotAuthorized error',
109
- async (subjectType) => {
110
- // Arrange
111
- const hookGenerator = subscriptionAuthorizationHookFactory;
112
- let buildOptions: PostGraphileOptions<Request, Response>;
113
- if (
114
- subjectType !== SubjectType.EndUserAccount &&
115
- subjectType !== SubjectType.EndUserApplication
116
- ) {
117
- buildOptions = {
118
- graphileBuildOptions: {
119
- permissionDefinition: {
120
- gqlOptions: {
121
- anonymousGqlOperations: [],
122
- ignoredGqlOperations: [],
123
- },
124
- permissions: [
125
- {
126
- key: 'Editor',
127
- title: 'Editor',
128
- gqlOperations: ['otherEndpoint', 'echoSubscription'],
129
- },
130
- ],
131
- },
132
- },
133
- };
134
- } else {
135
- buildOptions = {
136
- graphileBuildOptions: {
137
- endUserAuthorizationConfig: {
138
- anonymousGqlOperations: [],
139
- applicationTokenAllowedGqlOperations: ['echoSubscription'],
140
- },
141
- },
142
- };
143
- }
144
-
145
- const hookPlugin = hookGenerator(buildOptions);
146
- const context = {
147
- subject: {
148
- sub: 'test-user',
149
- permissions: { 'test-service': ['Editor'] },
150
- exp: new Date().getTime() / 1000 - 20, // set expiry time of the token to currentTime - 20 seconds
151
- subjectType: subjectType,
152
- },
153
- config: { serviceId: 'test-service' },
154
- };
155
-
156
- const params: ExecutionParams = {
157
- query: `subscription EchoSubscription {
158
- echoSubscription
159
- }`,
160
- operationName: 'EchoSubscription',
161
- context: context,
162
- variables: [],
163
- };
164
- const hookFunction = makePluginHook([hookPlugin]);
165
-
166
- // Act & Assert
167
- expect(() =>
168
- hookFunction('postgraphile:ws:onOperation', params, context),
169
- ).toThrow('Access Token has expired.');
170
- },
171
- );
172
-
173
- it.each([
174
- SubjectType.UserAccount,
175
- SubjectType.ManagedServiceAccount,
176
- SubjectType.ServiceAccount,
177
- SubjectType.ImpersonatedUserAccount,
178
- SubjectType.EndUserApplication,
179
- SubjectType.EndUserAccount,
180
- ])(
181
- 'Authorized %s with non-expired token for subscription -> no error',
182
- async (subjectType) => {
183
- // Arrange
184
- const hookGenerator = subscriptionAuthorizationHookFactory;
185
- let buildOptions: PostGraphileOptions<Request, Response>;
186
- if (
187
- subjectType !== SubjectType.EndUserAccount &&
188
- subjectType !== SubjectType.EndUserApplication
189
- ) {
190
- buildOptions = {
191
- graphileBuildOptions: {
192
- permissionDefinition: {
193
- gqlOptions: {
194
- anonymousGqlOperations: [],
195
- ignoredGqlOperations: [],
196
- },
197
- permissions: [
198
- {
199
- key: 'Editor',
200
- title: 'Editor',
201
- gqlOperations: ['otherEndpoint', 'echoSubscription'],
202
- },
203
- ],
204
- },
205
- },
206
- };
207
- } else {
208
- buildOptions = {
209
- graphileBuildOptions: {
210
- endUserAuthorizationConfig: {
211
- anonymousGqlOperations: [],
212
- applicationTokenAllowedGqlOperations: ['echoSubscription'],
213
- },
214
- },
215
- };
216
- }
217
- const hookPlugin = hookGenerator(buildOptions);
218
-
219
- const context = {
220
- subject: {
221
- sub: 'test-user',
222
- permissions: { 'test-service': ['Editor'] },
223
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime + 20 seconds
224
- subjectType: subjectType,
225
- },
226
- config: { serviceId: 'test-service' },
227
- };
228
-
229
- const params: ExecutionParams = {
230
- query: `subscription EchoSubscription {
231
- echoSubscription
232
- }`,
233
- operationName: 'EchoSubscription',
234
- context: context,
235
- variables: [],
236
- };
237
- const hookFunction = makePluginHook([hookPlugin]);
238
-
239
- // Act & Assert
240
- expect(() =>
241
- hookFunction('postgraphile:ws:onOperation', params, context),
242
- ).not.toThrow();
243
- },
244
- );
245
-
246
- it.each([
247
- SubjectType.UserAccount,
248
- SubjectType.ManagedServiceAccount,
249
- SubjectType.ServiceAccount,
250
- SubjectType.ImpersonatedUserAccount,
251
- SubjectType.EndUserApplication,
252
- SubjectType.EndUserAccount,
253
- ])(
254
- 'When ensureOnlyAuthentication is set to true and %s with non-expired token without any specific permission for subscription -> no error',
255
- async (subjectType) => {
256
- // Arrange
257
- const hookGenerator = subscriptionAuthorizationHookFactory;
258
- let buildOptions: PostGraphileOptions<Request, Response>;
259
- if (
260
- subjectType !== SubjectType.EndUserAccount &&
261
- subjectType !== SubjectType.EndUserApplication
262
- ) {
263
- buildOptions = {
264
- graphileBuildOptions: {
265
- ensureOnlyAuthentication: true,
266
- permissionDefinition: {
267
- gqlOptions: {
268
- anonymousGqlOperations: [],
269
- ignoredGqlOperations: [],
270
- },
271
- permissions: [
272
- {
273
- key: 'Editor',
274
- title: 'Editor',
275
- gqlOperations: ['otherEndpoint'],
276
- },
277
- ],
278
- },
279
- },
280
- };
281
- } else {
282
- buildOptions = {
283
- graphileBuildOptions: {
284
- ensureOnlyAuthentication: true,
285
- endUserAuthorizationConfig: {
286
- anonymousGqlOperations: [],
287
- applicationTokenAllowedGqlOperations: ['otherEndpoint'],
288
- },
289
- },
290
- };
291
- }
292
- const hookPlugin = hookGenerator(buildOptions);
293
-
294
- const context = {
295
- subject: {
296
- sub: 'test-user',
297
- permissions: { 'test-service': ['Editor'] },
298
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime + 20 seconds
299
- subjectType: subjectType,
300
- },
301
- config: { serviceId: 'test-service' },
302
- };
303
-
304
- const params: ExecutionParams = {
305
- query: `subscription EchoSubscription {
306
- echoSubscription
307
- }`,
308
- operationName: 'EchoSubscription',
309
- context: context,
310
- variables: [],
311
- };
312
- const hookFunction = makePluginHook([hookPlugin]);
313
-
314
- // Act & Assert
315
- expect(() =>
316
- hookFunction('postgraphile:ws:onOperation', params, context),
317
- ).not.toThrow();
318
- },
319
- );
320
- });
321
-
322
- describe('When calling the subscription through postgraphile:ws:onSubscribe', () => {
323
- const schema: GraphQLSchema = {
324
- astNode: {
325
- kind: 'SchemaDefinition',
326
- operationTypes: [
327
- {
328
- kind: 'OperationTypeDefinition',
329
- operation: 'subscription',
330
- type: {
331
- kind: 'NamedType',
332
- name: {
333
- kind: 'Name',
334
- value: 'EchoSubscription',
335
- },
336
- },
337
- },
338
- ],
339
- },
340
- description: 'EchoSubscription',
341
- extensionASTNodes: [],
342
- extensions: [],
343
- getDirective: jest.fn(),
344
- getDirectives: jest.fn(),
345
- getImplementations: jest.fn(),
346
- getMutationType: jest.fn(),
347
- getPossibleTypes: jest.fn(),
348
- getQueryType: jest.fn(),
349
- getSubscriptionType: jest.fn(),
350
- getType: jest.fn(),
351
- getTypeMap: jest.fn(),
352
- isPossibleType: jest.fn(),
353
- isSubType: jest.fn(),
354
- toConfig: jest.fn(),
355
- };
356
- it('Management User without required permissions -> UserNotAuthorized error', async () => {
357
- // Arrange
358
- const hookGenerator = subscriptionAuthorizationHookFactory;
359
- const buildOptions: PostGraphileOptions<Request, Response> = {
360
- graphileBuildOptions: {
361
- // permission definition without permissions for the required subscription 'echoSubscription'
362
- permissionDefinition: {
363
- gqlOptions: {
364
- anonymousGqlOperations: [],
365
- ignoredGqlOperations: [],
366
- },
367
- permissions: [
368
- {
369
- key: 'Editor',
370
- title: 'Editor',
371
- gqlOperations: ['otherEndpoint'],
372
- },
373
- ],
374
- },
375
- },
376
- };
377
- const hookPlugin = hookGenerator(buildOptions);
378
- const socket = {
379
- close: jest.fn(),
380
- };
381
- const socketSpy = jest.spyOn(socket, 'close');
382
- const context = {
383
- extra: {
384
- request: {
385
- authContext: {
386
- subject: {
387
- sub: 'test-user',
388
- permissions: { 'test-service': ['Editor'] },
389
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime - 20 seconds
390
- subjectType: SubjectType.UserAccount,
391
- },
392
- },
393
- },
394
- socket,
395
- },
396
- config: { serviceId: 'test-service' },
397
- };
398
-
399
- const args: ExecutionArgs = {
400
- schema,
401
- document: gql(`subscription EchoSubscription {
402
- echoSubscription
403
- }`),
404
- operationName: 'EchoSubscription',
405
- contextValue: {
406
- subject: context.extra.request.authContext.subject,
407
- config: { serviceId: 'test-service' },
408
- },
409
- };
410
- const hookFunction = makePluginHook([hookPlugin]);
411
-
412
- // Act & Assert
413
- expect(() =>
414
- hookFunction('postgraphile:ws:onSubscribe', args, {
415
- context: context,
416
- }),
417
- ).toThrow('User is not authorized to access the operation.');
418
- });
419
-
420
- it('ApplicationToken user without required permissions -> UserNotAuthorized error', async () => {
421
- // Arrange
422
- const hookGenerator = subscriptionAuthorizationHookFactory;
423
- const buildOptions: PostGraphileOptions<Request, Response> = {
424
- graphileBuildOptions: {
425
- // endUserAuthorizationConfig without permissions for the required subscription 'echoSubscription'
426
- endUserAuthorizationConfig: {
427
- anonymousGqlOperations: [],
428
- applicationTokenAllowedGqlOperations: [
429
- 'subscriptionPlans',
430
- 'subscriptionLifecycleStatusMutated',
431
- ],
432
- },
433
- },
434
- };
435
- const hookPlugin = hookGenerator(buildOptions);
436
- const socket = {
437
- close: jest.fn(),
438
- };
439
- const socketSpy = jest.spyOn(socket, 'close');
440
- const context = {
441
- extra: {
442
- request: {
443
- authContext: {
444
- subject: {
445
- sub: 'test-user',
446
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime - 20 seconds
447
- subjectType: SubjectType.EndUserApplication,
448
- },
449
- },
450
- },
451
- socket,
452
- },
453
- config: { serviceId: 'test-service' },
454
- };
455
-
456
- const args: ExecutionArgs = {
457
- schema,
458
- document: gql(`subscription EchoSubscription {
459
- echoSubscription
460
- }`),
461
- operationName: 'EchoSubscription',
462
- contextValue: {
463
- subject: context.extra.request.authContext.subject,
464
- config: { serviceId: 'test-service' },
465
- },
466
- };
467
- const hookFunction = makePluginHook([hookPlugin]);
468
-
469
- // Act & Assert
470
- expect(() =>
471
- hookFunction('postgraphile:ws:onSubscribe', args, {
472
- context: context,
473
- }),
474
- ).toThrow('Application Token is not authorized to access the operation.');
475
- });
476
-
477
- it.each([
478
- SubjectType.UserAccount,
479
- SubjectType.ManagedServiceAccount,
480
- SubjectType.ServiceAccount,
481
- SubjectType.ImpersonatedUserAccount,
482
- SubjectType.EndUserApplication,
483
- SubjectType.EndUserAccount,
484
- ])(
485
- 'Authorized %s with expired token for subscription -> Closes the websocket with CloseCode.Forbidden',
486
- async (subjectType) => {
487
- // Arrange
488
- const hookGenerator = subscriptionAuthorizationHookFactory;
489
-
490
- let buildOptions: PostGraphileOptions<Request, Response>;
491
- if (
492
- subjectType !== SubjectType.EndUserAccount &&
493
- subjectType !== SubjectType.EndUserApplication
494
- ) {
495
- buildOptions = {
496
- graphileBuildOptions: {
497
- permissionDefinition: {
498
- gqlOptions: {
499
- anonymousGqlOperations: [],
500
- ignoredGqlOperations: [],
501
- },
502
- permissions: [
503
- {
504
- key: 'Editor',
505
- title: 'Editor',
506
- gqlOperations: ['otherEndpoint', 'echoSubscription'],
507
- },
508
- ],
509
- },
510
- },
511
- };
512
- } else {
513
- buildOptions = {
514
- graphileBuildOptions: {
515
- endUserAuthorizationConfig: {
516
- anonymousGqlOperations: [],
517
- applicationTokenAllowedGqlOperations: [],
518
- },
519
- },
520
- };
521
- }
522
-
523
- const hookPlugin = hookGenerator(buildOptions);
524
- const socket = {
525
- close: jest.fn(),
526
- };
527
- const socketSpy = jest.spyOn(socket, 'close');
528
-
529
- const context = {
530
- extra: {
531
- request: {
532
- authContext: {
533
- subject: {
534
- sub: 'test-user',
535
- permissions: { 'test-service': ['Editor'] },
536
- exp: new Date().getTime() / 1000 - 20, // set expiry time of the token to currentTime - 20 seconds
537
- subjectType,
538
- },
539
- },
540
- },
541
- socket,
542
- },
543
- config: { serviceId: 'test-service' },
544
- };
545
-
546
- const args: ExecutionArgs = {
547
- schema,
548
- document: gql(`subscription EchoSubscription {
549
- echoSubscription
550
- }`),
551
- operationName: 'EchoSubscription',
552
- contextValue: {
553
- subject: context.extra.request.authContext.subject,
554
- config: { serviceId: 'test-service' },
555
- },
556
- };
557
- const hookFunction = makePluginHook([hookPlugin]);
558
-
559
- // Act
560
- hookFunction('postgraphile:ws:onSubscribe', args, { context: context });
561
- // Assert
562
- expect(socketSpy).toHaveBeenCalledWith(
563
- CloseCode.Forbidden,
564
- IdGuardErrors.AccessTokenExpired.code,
565
- );
566
- },
567
- );
568
-
569
- it.each([
570
- SubjectType.UserAccount,
571
- SubjectType.ManagedServiceAccount,
572
- SubjectType.ServiceAccount,
573
- SubjectType.ImpersonatedUserAccount,
574
- SubjectType.EndUserApplication,
575
- SubjectType.EndUserAccount,
576
- ])(
577
- 'Authorized %s with non-expired token for subscription -> no error',
578
- async (subjectType) => {
579
- // Arrange
580
- const hookGenerator = subscriptionAuthorizationHookFactory;
581
- let buildOptions: PostGraphileOptions<Request, Response>;
582
- if (
583
- subjectType !== SubjectType.EndUserAccount &&
584
- subjectType !== SubjectType.EndUserApplication
585
- ) {
586
- buildOptions = {
587
- graphileBuildOptions: {
588
- permissionDefinition: {
589
- gqlOptions: {
590
- anonymousGqlOperations: [],
591
- ignoredGqlOperations: [],
592
- },
593
- permissions: [
594
- {
595
- key: 'Editor',
596
- title: 'Editor',
597
- gqlOperations: ['otherEndpoint', 'echoSubscription'],
598
- },
599
- ],
600
- },
601
- },
602
- };
603
- } else {
604
- buildOptions = {
605
- graphileBuildOptions: {
606
- endUserAuthorizationConfig: {
607
- anonymousGqlOperations: [],
608
- applicationTokenAllowedGqlOperations: ['echoSubscription'],
609
- },
610
- },
611
- };
612
- }
613
- const hookPlugin = hookGenerator(buildOptions);
614
- const socket = {
615
- close: jest.fn(),
616
- };
617
- const socketSpy = jest.spyOn(socket, 'close');
618
- const context = {
619
- extra: {
620
- request: {
621
- authContext: {
622
- subject: {
623
- sub: 'test-user',
624
- permissions: { 'test-service': ['Editor'] },
625
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime - 20 seconds
626
- subjectType,
627
- },
628
- },
629
- },
630
- socket,
631
- },
632
- config: { serviceId: 'test-service' },
633
- };
634
-
635
- const args: ExecutionArgs = {
636
- schema,
637
- document: gql(`subscription EchoSubscription {
638
- echoSubscription
639
- }`),
640
- operationName: 'EchoSubscription',
641
- contextValue: {
642
- subject: context.extra.request.authContext.subject,
643
- config: { serviceId: 'test-service' },
644
- },
645
- };
646
- const hookFunction = makePluginHook([hookPlugin]);
647
-
648
- // Act & Assert
649
- expect(() =>
650
- hookFunction('postgraphile:ws:onSubscribe', args, {
651
- context: context,
652
- }),
653
- ).not.toThrow();
654
- expect(socketSpy).not.toHaveBeenCalled();
655
- },
656
- );
657
-
658
- it.each([
659
- SubjectType.UserAccount,
660
- SubjectType.ManagedServiceAccount,
661
- SubjectType.ServiceAccount,
662
- SubjectType.ImpersonatedUserAccount,
663
- SubjectType.EndUserApplication,
664
- SubjectType.EndUserAccount,
665
- ])(
666
- 'When ensureOnlyAuthentication is set to true, %s with non-expired token and no specific permission for subscription -> no error',
667
- async (subjectType) => {
668
- // Arrange
669
- const hookGenerator = subscriptionAuthorizationHookFactory;
670
- let buildOptions: PostGraphileOptions<Request, Response>;
671
- if (
672
- subjectType !== SubjectType.EndUserAccount &&
673
- subjectType !== SubjectType.EndUserApplication
674
- ) {
675
- buildOptions = {
676
- graphileBuildOptions: {
677
- ensureOnlyAuthentication: true,
678
- permissionDefinition: {
679
- gqlOptions: {
680
- anonymousGqlOperations: [],
681
- ignoredGqlOperations: [],
682
- },
683
- permissions: [
684
- {
685
- key: 'Editor',
686
- title: 'Editor',
687
- gqlOperations: ['otherEndpoint'],
688
- },
689
- ],
690
- },
691
- },
692
- };
693
- } else {
694
- buildOptions = {
695
- graphileBuildOptions: {
696
- ensureOnlyAuthentication: true,
697
- endUserAuthorizationConfig: {
698
- anonymousGqlOperations: [],
699
- applicationTokenAllowedGqlOperations: ['otherEndpoint'],
700
- },
701
- },
702
- };
703
- }
704
- const hookPlugin = hookGenerator(buildOptions);
705
- const socket = {
706
- close: jest.fn(),
707
- };
708
- const socketSpy = jest.spyOn(socket, 'close');
709
- const context = {
710
- extra: {
711
- request: {
712
- authContext: {
713
- subject: {
714
- sub: 'test-user',
715
- permissions: { 'test-service': ['Editor'] },
716
- exp: new Date().getTime() / 1000 + 20, // set expiry time of the token to currentTime - 20 seconds
717
- subjectType,
718
- },
719
- },
720
- },
721
- socket,
722
- },
723
- config: { serviceId: 'test-service' },
724
- };
725
-
726
- const args: ExecutionArgs = {
727
- schema,
728
- document: gql(`subscription EchoSubscription {
729
- echoSubscription
730
- }`),
731
- operationName: 'EchoSubscription',
732
- contextValue: {
733
- subject: context.extra.request.authContext.subject,
734
- config: { serviceId: 'test-service' },
735
- },
736
- };
737
- const hookFunction = makePluginHook([hookPlugin]);
738
-
739
- // Act & Assert
740
- expect(() =>
741
- hookFunction('postgraphile:ws:onSubscribe', args, {
742
- context: context,
743
- }),
744
- ).not.toThrow();
745
- expect(socketSpy).not.toHaveBeenCalled();
746
- },
747
- );
748
- });
749
- });