diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index 835c6cc5fd65b..01c18260549fb 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -9,7 +9,6 @@ import { isRoomsImagesProps, isRoomsMuteUnmuteUserProps, isRoomsExportProps, - isRoomsIsMemberProps, isRoomsCleanHistoryProps, isRoomsOpenProps, isRoomsMembersOrderedByRoleProps, @@ -18,6 +17,7 @@ import { isRoomsInviteProps, validateBadRequestErrorResponse, validateUnauthorizedErrorResponse, + validateForbiddenErrorResponse, } from '@rocket.chat/rest-typings'; import { isTruthy } from '@rocket.chat/tools'; import { Meteor } from 'meteor/meteor'; @@ -792,34 +792,60 @@ API.v1.addRoute( }, }, ); - -API.v1.addRoute( +const isMemeberEndpoint = API.v1.get( 'rooms.isMember', { authRequired: true, - validateParams: isRoomsIsMemberProps, + query: ajv.compile<{ roomId: string; userId?: string; username?: string }>({ + type: 'object', + properties: { + roomId: { type: 'string' }, + userId: { type: 'string' }, + username: { type: 'string' }, + }, + oneOf: [{ required: ['roomId', 'userId'] }, { required: ['roomId', 'username'] }], + additionalProperties: false, + }), + response: { + 200: ajv.compile<{ isMember: boolean }>({ + type: 'object', + properties: { + success: { + type: 'boolean', + enum: [true], + description: 'Indicates if the request was successful.', + }, + isMember: { + type: 'boolean', + }, + }, + required: ['success', 'isMember'], + additionalProperties: false, + }), + 400: validateBadRequestErrorResponse, + 401: validateUnauthorizedErrorResponse, + 403: validateForbiddenErrorResponse, + }, }, - { - async get() { - const { roomId, userId, username } = this.queryParams; - const [room, user] = await Promise.all([ - findRoomByIdOrName({ - params: { roomId }, - }) as Promise, - Users.findOneByIdOrUsername(userId || username), - ]); - - if (!user?._id) { - return API.v1.failure('error-user-not-found'); - } + async function action() { + const { roomId, userId, username } = this.queryParams; + const room = await findRoomByIdOrName({ + params: { roomId }, + }); - if (await canAccessRoomAsync(room, { _id: this.user._id })) { - return API.v1.success({ - isMember: (await Subscriptions.countByRoomIdAndUserId(room._id, user._id)) > 0, - }); - } - return API.v1.forbidden(); - }, + if (!(await canAccessRoomAsync(room, { _id: this.userId }))) { + return API.v1.forbidden('unauthorized'); + } + + const user = await Users.findOneByIdOrUsername((userId || username)!); + + if (!user?._id) { + return API.v1.failure('error-user-not-found'); + } + + return API.v1.success({ + isMember: (await Subscriptions.countByRoomIdAndUserId(room._id, user._id)) > 0, + }); }, ); @@ -1236,9 +1262,9 @@ export const roomEndpoints = API.v1 ); type RoomEndpoints = ExtractRoutesFromAPI & - ExtractRoutesFromAPI & ExtractRoutesFromAPI & - ExtractRoutesFromAPI; + ExtractRoutesFromAPI & + ExtractRoutesFromAPI; declare module '@rocket.chat/rest-typings' { // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface diff --git a/packages/rest-typings/src/v1/rooms.ts b/packages/rest-typings/src/v1/rooms.ts index 97b8d483f2212..c94c0d8e6b565 100644 --- a/packages/rest-typings/src/v1/rooms.ts +++ b/packages/rest-typings/src/v1/rooms.ts @@ -458,21 +458,6 @@ const GETRoomsNameExistsSchema = { export const isGETRoomsNameExists = ajv.compile(GETRoomsNameExistsSchema); -type RoomsIsMemberProps = { roomId: string } & ({ username: string } | { userId: string }); - -const RoomsIsMemberPropsSchema = { - type: 'object', - properties: { - roomId: { type: 'string', minLength: 1 }, - userId: { type: 'string', minLength: 1 }, - username: { type: 'string', minLength: 1 }, - }, - oneOf: [{ required: ['roomId', 'userId'] }, { required: ['roomId', 'username'] }], - additionalProperties: false, -}; - -export const isRoomsIsMemberProps = ajv.compile(RoomsIsMemberPropsSchema); - export type Notifications = { disableNotifications?: string; muteGroupMentions?: string; @@ -819,10 +804,6 @@ export type RoomsEndpoints = { }>; }; - '/v1/rooms.isMember': { - GET: (params: RoomsIsMemberProps) => { isMember: boolean }; - }; - '/v1/rooms.muteUser': { POST: (params: RoomsMuteUnmuteUser) => void; };