diff --git a/.changeset/lemon-lions-learn.md b/.changeset/lemon-lions-learn.md new file mode 100644 index 0000000000000..8ed1d10bccf0a --- /dev/null +++ b/.changeset/lemon-lions-learn.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fixes the possibility of see new messages without being subscribed to a public channel. diff --git a/apps/meteor/app/lib/server/methods/getChannelHistory.ts b/apps/meteor/app/lib/server/methods/getChannelHistory.ts index 3f3257b34fdda..e0a2a844a75eb 100644 --- a/apps/meteor/app/lib/server/methods/getChannelHistory.ts +++ b/apps/meteor/app/lib/server/methods/getChannelHistory.ts @@ -1,11 +1,10 @@ +import { Authorization } from '@rocket.chat/core-services'; import type { IMessage, MessageTypesValues } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; -import { Messages, Subscriptions, Rooms } from '@rocket.chat/models'; +import { Messages, Rooms } from '@rocket.chat/models'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -import { canAccessRoomAsync } from '../../../authorization/server'; -import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { settings } from '../../../settings/server/cached'; import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser'; import { getHiddenSystemMessages } from '../lib/getHiddenSystemMessages'; @@ -62,16 +61,8 @@ export const getChannelHistory = async ({ return false; } - if (!(await canAccessRoomAsync(room, { _id: fromUserId }))) { - return false; - } - // Make sure they can access the room - if ( - room.t === 'c' && - !(await hasPermissionAsync(fromUserId, 'preview-c-room')) && - !(await Subscriptions.findOneByRoomIdAndUserId(rid, fromUserId, { projection: { _id: 1 } })) - ) { + if (!(await Authorization.canReadRoom(room, { _id: fromUserId }))) { return false; } diff --git a/apps/meteor/server/modules/notifications/notifications.module.ts b/apps/meteor/server/modules/notifications/notifications.module.ts index a0394591aadf2..ad6bacba354b2 100644 --- a/apps/meteor/server/modules/notifications/notifications.module.ts +++ b/apps/meteor/server/modules/notifications/notifications.module.ts @@ -101,16 +101,7 @@ export class NotificationsModule { return false; } - const canAccess = await Authorization.canAccessRoom(room, { _id: this.userId || '' }, extraData); - if (!canAccess) { - // verify if can preview messages from public channels - if (room.t === 'c' && this.userId) { - return Authorization.hasPermission(this.userId, 'preview-c-room'); - } - return false; - } - - return true; + return Authorization.canReadRoom(room, { _id: this.userId || '' }, extraData); }); this.streamRoomMessage.allowRead('__my_messages__', 'all'); diff --git a/apps/meteor/server/services/authorization/canReadRoom.ts b/apps/meteor/server/services/authorization/canReadRoom.ts new file mode 100644 index 0000000000000..73e4dd86e5bd7 --- /dev/null +++ b/apps/meteor/server/services/authorization/canReadRoom.ts @@ -0,0 +1,24 @@ +import type { RoomAccessValidator } from '@rocket.chat/core-services'; +import { Authorization } from '@rocket.chat/core-services'; +import { Subscriptions } from '@rocket.chat/models'; + +import { canAccessRoom } from './canAccessRoom'; + +export const canReadRoom: RoomAccessValidator = async (...args) => { + if (!(await canAccessRoom(...args))) { + return false; + } + + const [room, user] = args; + + if ( + user?._id && + room?.t === 'c' && + !(await Authorization.hasPermission(user._id, 'preview-c-room')) && + !(await Subscriptions.findOneByRoomIdAndUserId(room?._id, user._id, { projection: { _id: 1 } })) + ) { + return false; + } + + return true; +}; diff --git a/apps/meteor/server/services/authorization/service.ts b/apps/meteor/server/services/authorization/service.ts index 5e67cf87b372c..d970068e23ba4 100644 --- a/apps/meteor/server/services/authorization/service.ts +++ b/apps/meteor/server/services/authorization/service.ts @@ -5,6 +5,7 @@ import { Subscriptions, Rooms, Users, Roles, Permissions } from '@rocket.chat/mo import mem from 'mem'; import { canAccessRoom } from './canAccessRoom'; +import { canReadRoom } from './canReadRoom'; import { AuthorizationUtils } from '../../../app/authorization/lib/AuthorizationUtils'; import './canAccessRoomLivechat'; @@ -80,6 +81,10 @@ export class Authorization extends ServiceClass implements IAuthorization { return canAccessRoom(...args); } + async canReadRoom(...args: Parameters): Promise { + return canReadRoom(...args); + } + async canAccessRoomId(rid: IRoom['_id'], uid: IUser['_id']): Promise { const room = await Rooms.findOneById>(rid, { projection: { diff --git a/packages/core-services/src/types/IAuthorization.ts b/packages/core-services/src/types/IAuthorization.ts index a6b744b17f2e2..eb58a01dc8d7e 100644 --- a/packages/core-services/src/types/IAuthorization.ts +++ b/packages/core-services/src/types/IAuthorization.ts @@ -11,6 +11,7 @@ export interface IAuthorization { hasPermission(userId: string, permissionId: string, scope?: string): Promise; hasAtLeastOnePermission(userId: string, permissions: string[], scope?: string): Promise; canAccessRoom: RoomAccessValidator; + canReadRoom: RoomAccessValidator; canAccessRoomId(rid: IRoom['_id'], uid?: IUser['_id']): Promise; getUsersFromPublicRoles(): Promise<(IRocketChatRecord & Pick)[]>; }