-
Notifications
You must be signed in to change notification settings - Fork 13.5k
feat: add OpenAPI support #34983
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add OpenAPI support #34983
Changes from 16 commits
c7a8bc0
67f15fa
f2dede0
e7dbb5c
5ba70fd
f240d64
1064f56
54ee6ba
cebb83a
5eeaeae
0dbf8db
d432d14
b222b5e
2dda499
5f2116c
171cef9
a83e547
b933f2d
64f803b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| "@rocket.chat/meteor": minor | ||
| "@rocket.chat/rest-typings": minor | ||
| --- | ||
|
|
||
| feat: Adds OpenAPI support |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import { isOpenAPIJSONEndpoint } from '@rocket.chat/rest-typings'; | ||
| import express from 'express'; | ||
| import { WebApp } from 'meteor/webapp'; | ||
| import swaggerUi from 'swagger-ui-express'; | ||
|
|
||
| import { settings } from '../../../settings/server'; | ||
| import { Info } from '../../../utils/rocketchat.info'; | ||
| import { API } from '../api'; | ||
| import type { Route } from '../router'; | ||
|
|
||
| const app = express(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
const app = express();
app.use(helmet());
app.use(rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 500 // higher limit for API docs
}));Lack of security measures such as input validation, origin checks, and security middleware, increasing the risk of security vulnerabilities. This issue appears in multiple locations:
Please add security measures such as input validation, origin checks, and security middleware to protect against potential security threats. Talk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.
Comment on lines
+8
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const getTypedRoutes = (
typedRoutes: Record<string, Record<string, Route>>,
{ withUndocumented = false }: { withUndocumented?: boolean } = {},
): Record<string, Record<string, Route>> => {
if (!typedRoutes || typeof typedRoutes !== 'object') {
throw new Error('Invalid typedRoutes: Expected a non-null object with Route records');
}Add error handling for potential undefined or malformed Talk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction. |
||
|
|
||
| const getTypedRoutes = ( | ||
| typedRoutes: Record<string, Record<string, Route>>, | ||
| { withUndocumented = false }: { withUndocumented?: boolean } = {}, | ||
| ): Record<string, Record<string, Route>> => { | ||
| if (withUndocumented) { | ||
| return typedRoutes; | ||
| } | ||
|
|
||
| return Object.entries(typedRoutes).reduce( | ||
| (acc, [path, methods]) => { | ||
| const filteredMethods = Object.entries(methods) | ||
| .filter(([_, options]) => !options?.tags?.includes('Missing Documentation')) | ||
| .reduce( | ||
| (acc, [method, options]) => { | ||
| acc[method] = options; | ||
| return acc; | ||
| }, | ||
| {} as Record<string, Route>, | ||
| ); | ||
|
|
||
| if (Object.keys(filteredMethods).length > 0) { | ||
| acc[path] = filteredMethods; | ||
| } | ||
|
|
||
| return acc; | ||
| }, | ||
| {} as Record<string, Record<string, Route>>, | ||
| ); | ||
| }; | ||
|
|
||
| const makeOpenAPIResponse = (paths: Record<string, Record<string, Route>>) => ({ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const BASE_OPENAPI_CONFIG = {
openapi: '3.0.3',
info: {
title: 'Rocket.Chat API',
description: 'Rocket.Chat API',
version: Info.version,
},
components: {
securitySchemes: {
userId: {
type: 'apiKey',
in: 'header',
name: 'X-User-Id',
},
authToken: {
type: 'apiKey',
in: 'header',
name: 'X-Auth-Token',
},
},
schemas: {},
},
};
const makeOpenAPIResponse = (paths: Record<string, Record<string, Route>>) => ({
...BASE_OPENAPI_CONFIG,
servers: [{ url: settings.get('Site_Url') }],
paths,
});Extract the OpenAPI configuration object into a separate constant to improve maintainability and reusability Talk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction. |
||
| openapi: '3.0.3', | ||
| info: { | ||
| title: 'Rocket.Chat API', | ||
| description: 'Rocket.Chat API', | ||
| version: Info.version, | ||
| }, | ||
| servers: [ | ||
| { | ||
| url: settings.get('Site_Url'), | ||
| }, | ||
| ], | ||
| components: { | ||
| securitySchemes: { | ||
| userId: { | ||
| type: 'apiKey', | ||
| in: 'header', | ||
| name: 'X-User-Id', | ||
| }, | ||
| authToken: { | ||
| type: 'apiKey', | ||
| in: 'header', | ||
| name: 'X-Auth-Token', | ||
| }, | ||
| }, | ||
| schemas: {}, | ||
| }, | ||
| paths, | ||
| }); | ||
|
|
||
| API.default.addRoute( | ||
| 'docs/json', | ||
| { authRequired: false, validateParams: isOpenAPIJSONEndpoint }, | ||
| { | ||
| get() { | ||
| const { withUndocumented = false } = this.queryParams; | ||
|
|
||
| return API.default.success(makeOpenAPIResponse(getTypedRoutes(API.v1.typedRoutes, { withUndocumented }))); | ||
| }, | ||
| }, | ||
| ); | ||
|
|
||
| app.use( | ||
MarcosSpessatto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| '/api-docs', | ||
| swaggerUi.serve, | ||
| swaggerUi.setup(makeOpenAPIResponse(getTypedRoutes(API.v1.typedRoutes, { withUndocumented: false }))), | ||
| ); | ||
| WebApp.connectHandlers.use(app); | ||
Uh oh!
There was an error while loading. Please reload this page.