diff --git a/.changeset/clever-trees-occur.md b/.changeset/clever-trees-occur.md new file mode 100644 index 0000000000000..7816309c20ea0 --- /dev/null +++ b/.changeset/clever-trees-occur.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/rest-typings": patch +--- + +Add OpenAPI support for the Rocket.Chat oauth-apps.update API endpoints by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation. diff --git a/apps/meteor/app/api/server/v1/oauthapps.ts b/apps/meteor/app/api/server/v1/oauthapps.ts index cb5cdd2c11e47..c12522b753a37 100644 --- a/apps/meteor/app/api/server/v1/oauthapps.ts +++ b/apps/meteor/app/api/server/v1/oauthapps.ts @@ -2,7 +2,6 @@ import type { IOAuthApps } from '@rocket.chat/core-typings'; import { OAuthApps } from '@rocket.chat/models'; import { ajv, - isUpdateOAuthAppParams, isOauthAppsGetParams, validateUnauthorizedErrorResponse, validateBadRequestErrorResponse, @@ -59,6 +58,37 @@ const OauthAppsAddParamsSchema = { const isOauthAppsAddParams = ajv.compile(OauthAppsAddParamsSchema); +type UpdateOAuthAppParams = { + appId: string; + name: string; + active: boolean; + clientId?: string | undefined; + clientSecret?: string | undefined; + redirectUri: string; +}; + +const UpdateOAuthAppParamsSchema = { + type: 'object', + properties: { + appId: { + type: 'string', + }, + name: { + type: 'string', + }, + active: { + type: 'boolean', + }, + redirectUri: { + type: 'string', + }, + }, + required: ['appId', 'name', 'active', 'redirectUri'], + additionalProperties: false, +}; + +const isUpdateOAuthAppParams = ajv.compile(UpdateOAuthAppParamsSchema); + const oauthAppsEndpoints = API.v1 .get( 'oauth-apps.list', @@ -156,6 +186,38 @@ const oauthAppsEndpoints = API.v1 return API.v1.success({ application }); }, + ) + .post( + 'oauth-apps.update', + { + authRequired: true, + body: isUpdateOAuthAppParams, + permissionsRequired: ['manage-oauth-apps'], + response: { + 400: validateBadRequestErrorResponse, + 401: validateUnauthorizedErrorResponse, + 403: validateForbiddenErrorResponse, + 200: ajv.compile({ + allOf: [ + { anyOf: [{ $ref: '#/components/schemas/IOAuthApps' }, { type: 'null' }] }, + { + type: 'object', + properties: { + success: { type: 'boolean', enum: [true] }, + }, + required: ['success'], + }, + ], + }), + }, + }, + async function action() { + const { appId } = this.bodyParams; + + const result = await updateOAuthApp(this.userId, appId, this.bodyParams); + + return API.v1.success(result); + }, ); API.v1.addRoute( @@ -185,24 +247,6 @@ API.v1.addRoute( }, ); -API.v1.addRoute( - 'oauth-apps.update', - { - authRequired: true, - validateParams: isUpdateOAuthAppParams, - permissionsRequired: ['manage-oauth-apps'], - }, - { - async post() { - const { appId } = this.bodyParams; - - const result = await updateOAuthApp(this.userId, appId, this.bodyParams); - - return API.v1.success(result); - }, - }, -); - export type OauthAppsEndpoints = ExtractRoutesFromAPI; declare module '@rocket.chat/rest-typings' { diff --git a/packages/rest-typings/src/index.ts b/packages/rest-typings/src/index.ts index 5de8562388117..5b87db07ab261 100644 --- a/packages/rest-typings/src/index.ts +++ b/packages/rest-typings/src/index.ts @@ -235,7 +235,6 @@ export * from './v1/integrations'; export * from './v1/licenses'; export * from './v1/omnichannel'; export * from './v1/oauthapps'; -export * from './v1/oauthapps/UpdateOAuthAppParamsPOST'; export * from './v1/oauthapps/OAuthAppsGetParamsGET'; export * from './helpers/PaginatedRequest'; export * from './helpers/PaginatedResult'; diff --git a/packages/rest-typings/src/v1/oauthapps.ts b/packages/rest-typings/src/v1/oauthapps.ts index 696655c76736a..0fadcf16f7804 100644 --- a/packages/rest-typings/src/v1/oauthapps.ts +++ b/packages/rest-typings/src/v1/oauthapps.ts @@ -1,7 +1,6 @@ import type { IOAuthApps } from '@rocket.chat/core-typings'; import type { OauthAppsGetParams } from './oauthapps/OAuthAppsGetParamsGET'; -import type { UpdateOAuthAppParams } from './oauthapps/UpdateOAuthAppParamsPOST'; export type OAuthAppsEndpoint = { '/v1/oauth-apps.get': { @@ -9,8 +8,4 @@ export type OAuthAppsEndpoint = { oauthApp: IOAuthApps; }; }; - - '/v1/oauth-apps.update': { - POST: (params: UpdateOAuthAppParams) => IOAuthApps | null; - }; }; diff --git a/packages/rest-typings/src/v1/oauthapps/UpdateOAuthAppParamsPOST.ts b/packages/rest-typings/src/v1/oauthapps/UpdateOAuthAppParamsPOST.ts deleted file mode 100644 index da1a2b1f326b8..0000000000000 --- a/packages/rest-typings/src/v1/oauthapps/UpdateOAuthAppParamsPOST.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ajv } from '../Ajv'; - -export type UpdateOAuthAppParams = { - appId: string; - name: string; - active: boolean; - clientId?: string | undefined; - clientSecret?: string | undefined; - redirectUri: string; -}; - -const UpdateOAuthAppParamsSchema = { - type: 'object', - properties: { - appId: { - type: 'string', - }, - name: { - type: 'string', - }, - active: { - type: 'boolean', - }, - redirectUri: { - type: 'string', - }, - }, - required: ['appId', 'name', 'active', 'redirectUri'], - additionalProperties: false, -}; - -export const isUpdateOAuthAppParams = ajv.compile(UpdateOAuthAppParamsSchema);