@uphold/fastify-openapi-router-plugin 0.8.0 → 1.0.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.
- package/package.json +1 -1
- package/src/parser/index.js +9 -5
- package/src/parser/params.js +1 -1
- package/src/parser/security.test.js +24 -24
- package/src/plugin.js +3 -1
package/package.json
CHANGED
package/src/parser/index.js
CHANGED
|
@@ -21,16 +21,20 @@ export const parse = async options => {
|
|
|
21
21
|
for (const method in methods) {
|
|
22
22
|
const operation = methods[method];
|
|
23
23
|
|
|
24
|
+
const securityFn = applySecurity(operation, spec, options.securityHandlers, options.securityErrorMapper);
|
|
25
|
+
const applyParamsCoercingFn = applyParamsCoercing(operation);
|
|
26
|
+
|
|
24
27
|
// Build fastify route.
|
|
25
28
|
const route = {
|
|
26
29
|
method: method.toUpperCase(),
|
|
27
30
|
onRequest: [
|
|
28
|
-
async function (request) {
|
|
31
|
+
async function openApiRouterOnRequestHook(request) {
|
|
29
32
|
request[DECORATOR_NAME].operation = operation;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
await securityFn?.(request);
|
|
35
|
+
applyParamsCoercingFn?.(request);
|
|
36
|
+
}
|
|
37
|
+
],
|
|
34
38
|
schema: {
|
|
35
39
|
headers: parseParams(operation.parameters, 'header'),
|
|
36
40
|
params: parseParams(operation.parameters, 'path'),
|
package/src/parser/params.js
CHANGED
|
@@ -103,9 +103,9 @@ describe('applySecurity()', () => {
|
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
it('should return undefined if `security` is disabled in operation', async () => {
|
|
106
|
-
const
|
|
106
|
+
const securityFn = applySecurity({ security: [] }, { security: [{ OAuth2: [] }] }, {});
|
|
107
107
|
|
|
108
|
-
expect(
|
|
108
|
+
expect(securityFn).toBeUndefined();
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
it('should stop at the first successful security block', async () => {
|
|
@@ -135,9 +135,9 @@ describe('applySecurity()', () => {
|
|
|
135
135
|
OAuth2: vi.fn(async () => ({ data: 'OAuth2 data', scopes: [] }))
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
-
const
|
|
138
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
139
139
|
|
|
140
|
-
await
|
|
140
|
+
await securityFn(request);
|
|
141
141
|
|
|
142
142
|
expect(securityHandlers.ApiKey).toHaveBeenCalledTimes(1);
|
|
143
143
|
expect(securityHandlers.ApiKey).toHaveBeenCalledWith('api key', request);
|
|
@@ -190,9 +190,9 @@ describe('applySecurity()', () => {
|
|
|
190
190
|
OAuth2: vi.fn(async () => ({ data: 'OAuth2 data', scopes: [] }))
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
-
const
|
|
193
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
194
194
|
|
|
195
|
-
await
|
|
195
|
+
await securityFn(request);
|
|
196
196
|
|
|
197
197
|
expect(securityHandlers.ApiKey).toHaveBeenCalledTimes(1);
|
|
198
198
|
expect(securityHandlers.ApiKey).toHaveBeenCalledWith('api key', request);
|
|
@@ -249,10 +249,10 @@ describe('applySecurity()', () => {
|
|
|
249
249
|
OAuth2: vi.fn(async () => ({ data: 'OAuth2 data', scopes: [] }))
|
|
250
250
|
};
|
|
251
251
|
|
|
252
|
-
const
|
|
252
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
253
253
|
|
|
254
254
|
try {
|
|
255
|
-
await
|
|
255
|
+
await securityFn(request);
|
|
256
256
|
} catch (error) {
|
|
257
257
|
expect(error).toBeInstanceOf(errors.UnauthorizedError);
|
|
258
258
|
expect(error.securityReport).toMatchInlineSnapshot(`
|
|
@@ -299,12 +299,12 @@ describe('applySecurity()', () => {
|
|
|
299
299
|
})
|
|
300
300
|
};
|
|
301
301
|
|
|
302
|
-
const
|
|
302
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
303
303
|
|
|
304
304
|
expect.assertions(2);
|
|
305
305
|
|
|
306
306
|
try {
|
|
307
|
-
await
|
|
307
|
+
await securityFn(request);
|
|
308
308
|
} catch (err) {
|
|
309
309
|
expect(err).toBeInstanceOf(errors.UnauthorizedError);
|
|
310
310
|
expect(err.securityReport).toMatchInlineSnapshot(`
|
|
@@ -354,9 +354,9 @@ describe('applySecurity()', () => {
|
|
|
354
354
|
OAuth2: vi.fn(async () => ({ data: 'OAuth2 data', scopes: ['write'] }))
|
|
355
355
|
};
|
|
356
356
|
|
|
357
|
-
const
|
|
357
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
358
358
|
|
|
359
|
-
await
|
|
359
|
+
await securityFn(request);
|
|
360
360
|
|
|
361
361
|
expect(securityHandlers.OAuth2).toHaveBeenCalledTimes(1);
|
|
362
362
|
});
|
|
@@ -385,12 +385,12 @@ describe('applySecurity()', () => {
|
|
|
385
385
|
})
|
|
386
386
|
};
|
|
387
387
|
|
|
388
|
-
const
|
|
388
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
389
389
|
|
|
390
390
|
expect.assertions(2);
|
|
391
391
|
|
|
392
392
|
try {
|
|
393
|
-
await
|
|
393
|
+
await securityFn(request);
|
|
394
394
|
} catch (err) {
|
|
395
395
|
expect(err).toBeInstanceOf(errors.UnauthorizedError);
|
|
396
396
|
expect(securityHandlers.OAuth2).toHaveBeenCalledTimes(1);
|
|
@@ -420,11 +420,11 @@ describe('applySecurity()', () => {
|
|
|
420
420
|
OAuth2: vi.fn(async () => ({ data: 'OAuth2 data', scopes: [] }))
|
|
421
421
|
};
|
|
422
422
|
|
|
423
|
-
const
|
|
423
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
424
424
|
|
|
425
425
|
expect.assertions(3);
|
|
426
426
|
|
|
427
|
-
await
|
|
427
|
+
await securityFn(request);
|
|
428
428
|
|
|
429
429
|
expect(securityHandlers.ApiKey).not.toHaveBeenCalled();
|
|
430
430
|
expect(securityHandlers.OAuth2).toHaveBeenCalledTimes(1);
|
|
@@ -468,12 +468,12 @@ describe('applySecurity()', () => {
|
|
|
468
468
|
OAuth2: vi.fn(() => ({ data: 'OAuth2 data', scopes: ['read'] }))
|
|
469
469
|
};
|
|
470
470
|
|
|
471
|
-
const
|
|
471
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
472
472
|
|
|
473
473
|
expect.assertions(2);
|
|
474
474
|
|
|
475
475
|
try {
|
|
476
|
-
await
|
|
476
|
+
await securityFn(request);
|
|
477
477
|
} catch (err) {
|
|
478
478
|
expect(err).toBeInstanceOf(errors.UnauthorizedError);
|
|
479
479
|
expect(err.securityReport).toMatchInlineSnapshot(`
|
|
@@ -513,9 +513,9 @@ describe('applySecurity()', () => {
|
|
|
513
513
|
OAuth2: vi.fn(() => {})
|
|
514
514
|
};
|
|
515
515
|
|
|
516
|
-
const
|
|
516
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
517
517
|
|
|
518
|
-
await
|
|
518
|
+
await securityFn(request);
|
|
519
519
|
|
|
520
520
|
expect(request[DECORATOR_NAME].security).toMatchObject({ OAuth2: undefined });
|
|
521
521
|
expect(request[DECORATOR_NAME].securityReport).toMatchInlineSnapshot(`
|
|
@@ -554,12 +554,12 @@ describe('applySecurity()', () => {
|
|
|
554
554
|
OAuth2: vi.fn(() => {})
|
|
555
555
|
};
|
|
556
556
|
|
|
557
|
-
const
|
|
557
|
+
const securityFn = applySecurity(operation, spec, securityHandlers);
|
|
558
558
|
|
|
559
559
|
expect.assertions(2);
|
|
560
560
|
|
|
561
561
|
try {
|
|
562
|
-
await
|
|
562
|
+
await securityFn(request);
|
|
563
563
|
} catch (err) {
|
|
564
564
|
expect(err).toBeInstanceOf(errors.UnauthorizedError);
|
|
565
565
|
expect(err.securityReport).toMatchInlineSnapshot(`
|
|
@@ -603,12 +603,12 @@ describe('applySecurity()', () => {
|
|
|
603
603
|
const customError = new Error('Mapped error');
|
|
604
604
|
const securityErrorMapper = vi.fn(() => customError);
|
|
605
605
|
|
|
606
|
-
const
|
|
606
|
+
const securityFn = applySecurity(operation, spec, securityHandlers, securityErrorMapper);
|
|
607
607
|
|
|
608
608
|
expect.assertions(3);
|
|
609
609
|
|
|
610
610
|
try {
|
|
611
|
-
await
|
|
611
|
+
await securityFn(request);
|
|
612
612
|
} catch (err) {
|
|
613
613
|
expect(err).toBe(customError);
|
|
614
614
|
expect(securityErrorMapper).toHaveBeenCalledTimes(1);
|
package/src/plugin.js
CHANGED
|
@@ -44,6 +44,8 @@ const createRoute = (fastify, routes, notImplementedErrorMapper) => {
|
|
|
44
44
|
// Check if there is a routeOptions.onRequest hook.
|
|
45
45
|
if (typeof onRequest === 'function') {
|
|
46
46
|
route.onRequest.push(onRequest);
|
|
47
|
+
} else if (Array.isArray(onRequest)) {
|
|
48
|
+
route.onRequest.push(...onRequest);
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
// Register a new route.
|
|
@@ -80,7 +82,7 @@ const plugin = async (fastify, options) => {
|
|
|
80
82
|
fastify.decorateRequest(DECORATOR_NAME, null);
|
|
81
83
|
|
|
82
84
|
// Instead, decorate each incoming request.
|
|
83
|
-
fastify.addHook('onRequest', async request
|
|
85
|
+
fastify.addHook('onRequest', async function openApiRouterGlobalOnRequestHook(request) {
|
|
84
86
|
request[DECORATOR_NAME] = {
|
|
85
87
|
operation: {},
|
|
86
88
|
security: {},
|