diff --git a/.changeset/migrate-chat-ignoreUser-to-openapi.md b/.changeset/migrate-chat-ignoreUser-to-openapi.md new file mode 100644 index 0000000000000..8170437ecf97a --- /dev/null +++ b/.changeset/migrate-chat-ignoreUser-to-openapi.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/meteor': minor +'@rocket.chat/rest-typings': minor +--- + +Migrated chat.ignoreUser endpoint to new OpenAPI pattern with AJV validation diff --git a/apps/meteor/app/api/server/v1/chat.ts b/apps/meteor/app/api/server/v1/chat.ts index a00d57e46ae72..1e4d4bfa3cc52 100644 --- a/apps/meteor/app/api/server/v1/chat.ts +++ b/apps/meteor/app/api/server/v1/chat.ts @@ -4,7 +4,6 @@ import { MessageTypes } from '@rocket.chat/message-types'; import { Messages, Users, Rooms, Subscriptions } from '@rocket.chat/models'; import { ajv, - isChatReportMessageProps, isChatGetURLPreviewProps, isChatUpdateProps, isChatGetThreadsListProps, @@ -14,7 +13,6 @@ import { isChatPostMessageProps, isChatSearchProps, isChatSendMessageProps, - isChatIgnoreUserProps, isChatGetPinnedMessagesProps, isChatGetMentionedMessagesProps, isChatReactProps, @@ -275,6 +273,51 @@ const isChatPinMessageProps = ajv.compile(ChatPinMessageSchema); const isChatUnpinMessageProps = ajv.compile(ChatUnpinMessageSchema); +type ChatReportMessage = { + messageId: IMessage['_id']; + description: string; +}; + +const ChatReportMessageSchema = { + type: 'object', + properties: { + messageId: { type: 'string', minLength: 1 }, + description: { type: 'string', minLength: 1 }, + }, + required: ['messageId', 'description'], + additionalProperties: false, +}; + +const isChatReportMessageLocalProps = ajv.compile(ChatReportMessageSchema); + +type ChatIgnoreUser = { + rid: string; + userId: string; + ignore?: 'true' | 'false' | '1' | '0'; +}; + +const ChatIgnoreUserSchema = { + type: 'object', + properties: { + rid: { + type: 'string', + minLength: 1, + }, + userId: { + type: 'string', + minLength: 1, + }, + ignore: { + type: 'string', + enum: ['true', 'false', '1', '0'], + }, + }, + required: ['rid', 'userId'], + additionalProperties: false, +}; + +export const isChatIgnoreUserLocalProps = ajv.compile(ChatIgnoreUserSchema); + const chatEndpoints = API.v1 .post( 'chat.pinMessage', @@ -419,6 +462,30 @@ const chatEndpoints = API.v1 }); }, ) + .post( + 'chat.reportMessage', + { + authRequired: true, + body: isChatReportMessageLocalProps, + response: { + 200: ajv.compile({ + type: 'object', + properties: { + success: { type: 'boolean', enum: [true] }, + }, + required: ['success'], + additionalProperties: false, + }), + 400: validateBadRequestErrorResponse, + 401: validateUnauthorizedErrorResponse, + }, + }, + async function action() { + const { messageId, description } = this.bodyParams; + await reportMessage(messageId, description, this.userId); + return API.v1.success(); + }, + ) .post( 'chat.starMessage', { @@ -555,6 +622,32 @@ const chatEndpoints = API.v1 } await unfollowMessage(this.user, { mid }); + return API.v1.success(); + }, + ) + .get( + 'chat.ignoreUser', + { + authRequired: true, + query: isChatIgnoreUserLocalProps, + response: { + 200: ajv.compile({ + type: 'object', + properties: { success: { type: 'boolean', enum: [true] } }, + required: ['success'], + additionalProperties: false, + }), + 400: validateBadRequestErrorResponse, + 401: validateUnauthorizedErrorResponse, + }, + }, + async function action() { + const { rid, userId } = this.queryParams; + const { ignore = 'true' } = this.queryParams; + + const ignoreBool = ignore === 'true' || ignore === '1'; + + await ignoreUser(this.userId, { rid, userId, ignore: ignoreBool }); return API.v1.success(); }, @@ -677,52 +770,6 @@ API.v1.addRoute( }, ); -API.v1.addRoute( - 'chat.reportMessage', - { authRequired: true, validateParams: isChatReportMessageProps }, - { - async post() { - const { messageId, description } = this.bodyParams; - if (!messageId) { - return API.v1.failure('The required "messageId" param is missing.'); - } - - if (!description) { - return API.v1.failure('The required "description" param is missing.'); - } - - await reportMessage(messageId, description, this.userId); - - return API.v1.success(); - }, - }, -); - -API.v1.addRoute( - 'chat.ignoreUser', - { authRequired: true, validateParams: isChatIgnoreUserProps }, - { - async get() { - const { rid, userId } = this.queryParams; - let { ignore = true } = this.queryParams; - - ignore = typeof ignore === 'string' ? /true|1/.test(ignore) : ignore; - - if (!rid?.trim()) { - throw new Meteor.Error('error-room-id-param-not-provided', 'The required "rid" param is missing.'); - } - - if (!userId?.trim()) { - throw new Meteor.Error('error-user-id-param-not-provided', 'The required "userId" param is missing.'); - } - - await ignoreUser(this.userId, { rid, userId, ignore }); - - return API.v1.success(); - }, - }, -); - API.v1.addRoute( 'chat.getDeletedMessages', { authRequired: true, validateParams: isChatGetDeletedMessagesProps }, diff --git a/packages/rest-typings/src/v1/chat.ts b/packages/rest-typings/src/v1/chat.ts index b52bba2d61ed5..570a3fd27cd05 100644 --- a/packages/rest-typings/src/v1/chat.ts +++ b/packages/rest-typings/src/v1/chat.ts @@ -291,38 +291,6 @@ const ChatReactSchema = { export const isChatReactProps = ajv.compile(ChatReactSchema); -/** - * The param `ignore` cannot be boolean, since this is a GET method. Use strings 'true' or 'false' instead. - * @param {string} ignore - */ -type ChatIgnoreUser = { - rid: string; - userId: string; - ignore: string; -}; - -const ChatIgnoreUserSchema = { - type: 'object', - properties: { - rid: { - type: 'string', - minLength: 1, - }, - userId: { - type: 'string', - minLength: 1, - }, - ignore: { - type: 'string', - minLength: 1, - }, - }, - required: ['rid', 'userId', 'ignore'], - additionalProperties: false, -}; - -export const isChatIgnoreUserProps = ajv.compile(ChatIgnoreUserSchema); - type ChatSearch = PaginatedRequest<{ roomId: IRoom['_id']; searchText: string; @@ -930,9 +898,6 @@ export type ChatEndpoints = { '/v1/chat.react': { POST: (params: ChatReact) => void; }; - '/v1/chat.ignoreUser': { - GET: (params: ChatIgnoreUser) => void; - }; '/v1/chat.search': { GET: (params: ChatSearch) => { messages: IMessage[];