Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.

Commit a51ce1a

Browse files
authored
Fix: Security schemes protected procedures (#306)
1 parent d6de032 commit a51ce1a

File tree

4 files changed

+40
-30
lines changed

4 files changed

+40
-30
lines changed

README.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -289,31 +289,32 @@ export const openApi = createOpenApiAwsLambdaHandler({ router: appRouter });
289289

290290
Please see [full typings here](src/generator/index.ts).
291291

292-
| Property | Type | Description | Required |
293-
| ------------- | ---------- | ------------------------------------ | -------- |
294-
| `title` | `string` | The title of the API. | `true` |
295-
| `description` | `string` | A short description of the API. | `false` |
296-
| `version` | `string` | The version of the OpenAPI document. | `true` |
297-
| `baseUrl` | `string` | The base URL of the target server. | `true` |
298-
| `docsUrl` | `string` | A URL to any external documentation. | `false` |
299-
| `tags` | `string[]` | A list for ordering endpoint groups. | `false` |
292+
| Property | Type | Description | Required |
293+
| ----------------- | -------------------------------------- | ------------------------------------------------------- | -------- |
294+
| `title` | `string` | The title of the API. | `true` |
295+
| `description` | `string` | A short description of the API. | `false` |
296+
| `version` | `string` | The version of the OpenAPI document. | `true` |
297+
| `baseUrl` | `string` | The base URL of the target server. | `true` |
298+
| `docsUrl` | `string` | A URL to any external documentation. | `false` |
299+
| `tags` | `string[]` | A list for ordering endpoint groups. | `false` |
300+
| `securitySchemes` | `Record<string, SecuritySchemeObject>` | Defaults to `Authorization` header with `Bearer` scheme | `false` |
300301

301302
#### OpenApiMeta
302303

303304
Please see [full typings here](src/types.ts).
304305

305-
| Property | Type | Description | Required | Default |
306-
| -------------- | ------------------- | ------------------------------------------------------------------------------------------------------------ | -------- | ---------------------- |
307-
| `enabled` | `boolean` | Exposes this procedure to `trpc-openapi` adapters and on the OpenAPI document. | `false` | `true` |
308-
| `method` | `HttpMethod` | HTTP method this endpoint is exposed on. Value can be `GET`, `POST`, `PATCH`, `PUT` or `DELETE`. | `true` | `undefined` |
309-
| `path` | `string` | Pathname this endpoint is exposed on. Value must start with `/`, specify path parameters using `{}`. | `true` | `undefined` |
310-
| `protect` | `boolean` | Requires this endpoint to use an `Authorization` header credential with `Bearer` scheme on OpenAPI document. | `false` | `false` |
311-
| `summary` | `string` | A short summary of the endpoint included in the OpenAPI document. | `false` | `undefined` |
312-
| `description` | `string` | A verbose description of the endpoint included in the OpenAPI document. | `false` | `undefined` |
313-
| `tags` | `string[]` | A list of tags used for logical grouping of endpoints in the OpenAPI document. | `false` | `undefined` |
314-
| `headers` | `ParameterObject[]` | An array of custom headers to add for this endpoint in the OpenAPI document. | `false` | `undefined` |
315-
| `contentTypes` | `ContentType[]` | A set of content types specified as accepted in the OpenAPI document. | `false` | `['application/json']` |
316-
| `deprecated` | `boolean` | Whether or not to mark an endpoint as deprecated | `false` | `false` |
306+
| Property | Type | Description | Required | Default |
307+
| -------------- | ------------------- | ---------------------------------------------------------------------------------------------------- | -------- | ---------------------- |
308+
| `enabled` | `boolean` | Exposes this procedure to `trpc-openapi` adapters and on the OpenAPI document. | `false` | `true` |
309+
| `method` | `HttpMethod` | HTTP method this endpoint is exposed on. Value can be `GET`, `POST`, `PATCH`, `PUT` or `DELETE`. | `true` | `undefined` |
310+
| `path` | `string` | Pathname this endpoint is exposed on. Value must start with `/`, specify path parameters using `{}`. | `true` | `undefined` |
311+
| `protect` | `boolean` | Requires this endpoint to use a security scheme. | `false` | `false` |
312+
| `summary` | `string` | A short summary of the endpoint included in the OpenAPI document. | `false` | `undefined` |
313+
| `description` | `string` | A verbose description of the endpoint included in the OpenAPI document. | `false` | `undefined` |
314+
| `tags` | `string[]` | A list of tags used for logical grouping of endpoints in the OpenAPI document. | `false` | `undefined` |
315+
| `headers` | `ParameterObject[]` | An array of custom headers to add for this endpoint in the OpenAPI document. | `false` | `undefined` |
316+
| `contentTypes` | `ContentType[]` | A set of content types specified as accepted in the OpenAPI document. | `false` | `['application/json']` |
317+
| `deprecated` | `boolean` | Whether or not to mark an endpoint as deprecated | `false` | `false` |
317318

318319
#### CreateOpenApiNodeHttpHandlerOptions
319320

src/generator/index.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ export const generateOpenApiDocument = (
2020
appRouter: OpenApiRouter,
2121
opts: GenerateOpenApiDocumentOptions,
2222
): OpenAPIV3.Document => {
23+
const securitySchemes = opts.securitySchemes || {
24+
Authorization: {
25+
type: 'http',
26+
scheme: 'bearer',
27+
},
28+
};
2329
return {
2430
openapi: openApiVersion,
2531
info: {
@@ -32,14 +38,9 @@ export const generateOpenApiDocument = (
3238
url: opts.baseUrl,
3339
},
3440
],
35-
paths: getOpenApiPathsObject(appRouter, {}),
41+
paths: getOpenApiPathsObject(appRouter, Object.keys(securitySchemes)),
3642
components: {
37-
securitySchemes: opts.securitySchemes || {
38-
Authorization: {
39-
type: 'http',
40-
scheme: 'bearer',
41-
},
42-
},
43+
securitySchemes,
4344
responses: {
4445
error: errorResponseObject,
4546
},

src/generator/paths.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { getParameterObjects, getRequestBodyObject, getResponsesObject } from '.
99

1010
export const getOpenApiPathsObject = (
1111
appRouter: OpenApiRouter,
12-
pathsObject: OpenAPIV3.PathsObject,
12+
securitySchemeNames: string[],
1313
): OpenAPIV3.PathsObject => {
14+
const pathsObject: OpenAPIV3.PathsObject = {};
1415
const procedures = appRouter._def.procedures as OpenApiProcedureRecord;
1516

1617
forEachOpenApiProcedure(procedures, ({ path: procedurePath, type, procedure, openapi }) => {
@@ -62,7 +63,7 @@ export const getOpenApiPathsObject = (
6263
summary,
6364
description,
6465
tags: tags,
65-
security: protect ? [{ Authorization: [] }] : undefined,
66+
security: protect ? securitySchemeNames.map((name) => ({ [name]: [] })) : undefined,
6667
...(acceptsRequestBody(method)
6768
? {
6869
requestBody: getRequestBodyObject(inputParser, pathParameters, contentTypes),

test/generator.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2593,7 +2593,13 @@ describe('generator', () => {
25932593
});
25942594

25952595
test('with security schemes', () => {
2596-
const appRouter = t.router({});
2596+
const appRouter = t.router({
2597+
protected: t.procedure
2598+
.meta({ openapi: { method: 'POST', path: '/protected', protect: true } })
2599+
.input(z.object({ payload: z.string() }))
2600+
.output(z.object({ payload: z.string() }))
2601+
.mutation(({ input }) => ({ payload: input.payload })),
2602+
});
25972603

25982604
const openApiDocument = generateOpenApiDocument(appRouter, {
25992605
title: 'tRPC OpenAPI',
@@ -2616,5 +2622,6 @@ describe('generator', () => {
26162622
name: 'X-API-Key',
26172623
},
26182624
});
2625+
expect(openApiDocument.paths['/protected']!.post!.security).toEqual([{ ApiKey: [] }]);
26192626
});
26202627
});

0 commit comments

Comments
 (0)