diff --git a/.changeset/fifty-tools-walk.md b/.changeset/fifty-tools-walk.md new file mode 100644 index 0000000000000..a3339bc48c78d --- /dev/null +++ b/.changeset/fifty-tools-walk.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/rest-typings": patch +--- + +Add OpenAPI support for the Rocket.Chat e2e.setRoomKeyID 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/e2e.ts b/apps/meteor/app/api/server/v1/e2e.ts index a8a5e9175d876..3686f2a7b9007 100644 --- a/apps/meteor/app/api/server/v1/e2e.ts +++ b/apps/meteor/app/api/server/v1/e2e.ts @@ -1,7 +1,9 @@ import { Subscriptions, Users } from '@rocket.chat/models'; import { + ajv, + validateUnauthorizedErrorResponse, + validateBadRequestErrorResponse, ise2eGetUsersOfRoomWithoutKeyParamsGET, - ise2eSetRoomKeyIDParamsPOST, ise2eSetUserPublicAndPrivateKeysParamsPOST, ise2eUpdateGroupKeyParamsPOST, isE2EProvideUsersGroupKeyProps, @@ -20,12 +22,61 @@ import { setRoomKeyIDMethod } from '../../../e2e/server/methods/setRoomKeyID'; import { setUserPublicAndPrivateKeysMethod } from '../../../e2e/server/methods/setUserPublicAndPrivateKeys'; import { updateGroupKey } from '../../../e2e/server/methods/updateGroupKey'; import { settings } from '../../../settings/server'; +import type { ExtractRoutesFromAPI } from '../ApiClass'; import { API } from '../api'; // After 10s the room lock will expire, meaning that if for some reason the process never completed // The next reset will be available 10s after const LockMap = new ExpiryMap(10000); +type E2eSetRoomKeyIdProps = { + rid: string; + keyID: string; +}; + +const E2eSetRoomKeyIdSchema = { + type: 'object', + properties: { + rid: { + type: 'string', + }, + keyID: { + type: 'string', + }, + }, + required: ['rid', 'keyID'], + additionalProperties: false, +}; + +const isE2eSetRoomKeyIdProps = ajv.compile(E2eSetRoomKeyIdSchema); + +const e2eEndpoints = API.v1.post( + 'e2e.setRoomKeyID', + { + authRequired: true, + body: isE2eSetRoomKeyIdProps, + response: { + 400: validateBadRequestErrorResponse, + 401: validateUnauthorizedErrorResponse, + 200: ajv.compile({ + type: 'object', + properties: { + success: { type: 'boolean', enum: [true] }, + }, + required: ['success'], + }), + }, + }, + + async function action() { + const { rid, keyID } = this.bodyParams; + + await setRoomKeyIDMethod(this.userId, rid, keyID); + + return API.v1.success(); + }, +); + API.v1.addRoute( 'e2e.fetchMyKeys', { @@ -57,55 +108,6 @@ API.v1.addRoute( }, ); -/** - * @openapi - * /api/v1/e2e.setRoomKeyID: - * post: - * description: Sets the end-to-end encryption key ID for a room - * security: - * - autenticated: {} - * requestBody: - * description: A tuple containing the room ID and the key ID - * content: - * application/json: - * schema: - * type: object - * properties: - * rid: - * type: string - * keyID: - * type: string - * responses: - * 200: - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/ApiSuccessV1' - * default: - * description: Unexpected error - * content: - * application/json: - * schema: - * $ref: '#/components/schemas/ApiFailureV1' - */ - -API.v1.addRoute( - 'e2e.setRoomKeyID', - { - authRequired: true, - validateParams: ise2eSetRoomKeyIDParamsPOST, - }, - { - async post() { - const { rid, keyID } = this.bodyParams; - - await setRoomKeyIDMethod(this.userId, rid, keyID); - - return API.v1.success(); - }, - }, -); - /** * @openapi * /api/v1/e2e.setUserPublicAndPrivateKeys: @@ -323,3 +325,10 @@ API.v1.addRoute( }, }, ); + +export type E2eEndpoints = ExtractRoutesFromAPI; + +declare module '@rocket.chat/rest-typings' { + // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface + interface Endpoints extends E2eEndpoints {} +} diff --git a/packages/rest-typings/src/index.ts b/packages/rest-typings/src/index.ts index 6b669d9b9b189..4f11ad9baf02e 100644 --- a/packages/rest-typings/src/index.ts +++ b/packages/rest-typings/src/index.ts @@ -249,7 +249,6 @@ export * from './v1/autotranslate/AutotranslateGetSupportedLanguagesParamsGET'; export * from './v1/autotranslate/AutotranslateSaveSettingsParamsPOST'; export * from './v1/autotranslate/AutotranslateTranslateMessageParamsPOST'; export * from './v1/e2e/e2eGetUsersOfRoomWithoutKeyParamsGET'; -export * from './v1/e2e/e2eSetRoomKeyIDParamsPOST'; export * from './v1/e2e/e2eSetUserPublicAndPrivateKeysParamsPOST'; export * from './v1/e2e/e2eUpdateGroupKeyParamsPOST'; export * from './v1/e2e'; diff --git a/packages/rest-typings/src/v1/e2e.ts b/packages/rest-typings/src/v1/e2e.ts index b065ac10386eb..7c7bd8a1d1a66 100644 --- a/packages/rest-typings/src/v1/e2e.ts +++ b/packages/rest-typings/src/v1/e2e.ts @@ -67,27 +67,6 @@ const E2eUpdateGroupKeySchema = { export const isE2eUpdateGroupKeyProps = ajv.compile(E2eUpdateGroupKeySchema); -type E2eSetRoomKeyIdProps = { - rid: string; - keyID: string; -}; - -const E2eSetRoomKeyIdSchema = { - type: 'object', - properties: { - rid: { - type: 'string', - }, - keyID: { - type: 'string', - }, - }, - required: ['rid', 'keyID'], - additionalProperties: false, -}; - -export const isE2eSetRoomKeyIdProps = ajv.compile(E2eSetRoomKeyIdSchema); - type E2EProvideUsersGroupKeyProps = { usersSuggestedGroupKeys: Record; }; @@ -187,9 +166,6 @@ export type E2eEndpoints = { '/v1/e2e.rejectSuggestedGroupKey': { POST: (params: E2eGetUsersOfRoomWithoutKeyProps) => void; }; - '/v1/e2e.setRoomKeyID': { - POST: (params: E2eSetRoomKeyIdProps) => void; - }; '/v1/e2e.fetchMyKeys': { GET: () => { public_key: string; private_key: string }; }; diff --git a/packages/rest-typings/src/v1/e2e/e2eSetRoomKeyIDParamsPOST.ts b/packages/rest-typings/src/v1/e2e/e2eSetRoomKeyIDParamsPOST.ts deleted file mode 100644 index 8977d8c96b6dc..0000000000000 --- a/packages/rest-typings/src/v1/e2e/e2eSetRoomKeyIDParamsPOST.ts +++ /dev/null @@ -1,26 +0,0 @@ -import Ajv from 'ajv'; - -const ajv = new Ajv({ - coerceTypes: true, -}); - -export type e2eSetRoomKeyIDParamsPOST = { - rid: string; - keyID: string; -}; - -const e2eSetRoomKeyIDParamsPOSTSchema = { - type: 'object', - properties: { - rid: { - type: 'string', - }, - keyID: { - type: 'string', - }, - }, - additionalProperties: false, - required: ['rid', 'keyID'], -}; - -export const ise2eSetRoomKeyIDParamsPOST = ajv.compile(e2eSetRoomKeyIDParamsPOSTSchema);