diff --git a/.changeset/thick-nails-exist.md b/.changeset/thick-nails-exist.md index 9150fe12335e3..985c251a2044e 100644 --- a/.changeset/thick-nails-exist.md +++ b/.changeset/thick-nails-exist.md @@ -1,5 +1,5 @@ --- -"@rocket.chat/meteor": patch +'@rocket.chat/meteor': minor --- -Adds support for ban management in federated rooms, enabling authorized users to ban and unban members via UI and slash commands. +Adds support for ban management in rooms, enabling authorized users to ban and unban members via UI and slash commands. diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index bb4278bbb70fb..ae02a578ab05c 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -34,6 +34,7 @@ import { eraseRoom } from '../../../../server/lib/eraseRoom'; import { findUsersOfRoomOrderedByRole } from '../../../../server/lib/findUsersOfRoomOrderedByRole'; import { openRoom } from '../../../../server/lib/openRoom'; import type { RoomRoles } from '../../../../server/lib/roles/getRoomRoles'; +import { unbanUserFromRoom } from '../../../../server/lib/unbanUserFromRoom'; import { hideRoomMethod } from '../../../../server/methods/hideRoom'; import { muteUserInRoom } from '../../../../server/methods/muteUserInRoom'; import { toggleFavoriteMethod } from '../../../../server/methods/toggleFavorite'; @@ -45,7 +46,6 @@ import { saveRoomSettings } from '../../../channel-settings/server/methods/saveR import { createDiscussion } from '../../../discussion/server/methods/createDiscussion'; import { FileUpload } from '../../../file-upload/server'; import { sendFileMessage } from '../../../file-upload/server/methods/sendFileMessage'; -import { executeUnbanUserFromRoom } from '../../../lib/server/functions/executeUnbanUserFromRoom'; import { syncRolePrioritiesForRoomIfRequired } from '../../../lib/server/functions/syncRolePrioritiesForRoomIfRequired'; import { executeArchiveRoom } from '../../../lib/server/methods/archiveRoom'; import { cleanRoomHistoryMethod } from '../../../lib/server/methods/cleanRoomHistory'; @@ -1333,7 +1333,7 @@ export const roomEndpoints = API.v1 return API.v1.failure('Invalid user'); } - await executeUnbanUserFromRoom(this.bodyParams.roomId, user, this.user); + await unbanUserFromRoom(this.userId, { rid: this.bodyParams.roomId, username: user.username }); return API.v1.success(); }, diff --git a/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts b/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts index d158489a9d4ff..e4bbbd9a371f3 100644 --- a/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts +++ b/apps/meteor/client/hooks/roomActions/useBannedUsersRoomAction.ts @@ -1,24 +1,18 @@ -import { isRoomNativeFederated } from '@rocket.chat/core-typings'; import type { RoomToolboxActionConfig } from '@rocket.chat/ui-contexts'; -import { usePermission, useUser } from '@rocket.chat/ui-contexts'; +import { usePermission } from '@rocket.chat/ui-contexts'; import { lazy, useMemo } from 'react'; -import * as Federation from '../../lib/federation/Federation'; -import { useRoom, useRoomSubscription } from '../../views/room/contexts/RoomContext'; +import { useRoom } from '../../views/room/contexts/RoomContext'; const BannedUsers = lazy(() => import('../../views/room/contextualBar/BannedUsers')); export const useBannedUsersRoomAction = () => { const room = useRoom(); - const user = useUser(); - const subscription = useRoomSubscription(); const hasPermissionToBan = usePermission('ban-user', room._id); - const federationCanBan = isRoomNativeFederated(room) && Federation.isEditableByTheUser(user || undefined, room, subscription); - return useMemo((): RoomToolboxActionConfig | undefined => { - if (!hasPermissionToBan || !federationCanBan) { + if (!hasPermissionToBan) { return undefined; } @@ -31,5 +25,5 @@ export const useBannedUsersRoomAction = () => { order: 13, type: 'moderation', }; - }, [federationCanBan, hasPermissionToBan]); + }, [hasPermissionToBan]); }; diff --git a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx index 43dfac319a3a5..8bc56c262b73e 100644 --- a/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx +++ b/apps/meteor/client/views/room/hooks/useUserInfoActions/actions/useBanUserAction.tsx @@ -1,10 +1,8 @@ import type { IRoom, IUser } from '@rocket.chat/core-typings'; -import { isRoomNativeFederated } from '@rocket.chat/core-typings'; -import { usePermission, useUser, useUserRoom, useUserSubscription } from '@rocket.chat/ui-contexts'; +import { usePermission, useUserRoom, useUserSubscription } from '@rocket.chat/ui-contexts'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import * as Federation from '../../../../../lib/federation/Federation'; import { getRoomDirectives } from '../../../lib/getRoomDirectives'; import { useBanUser } from '../../useBanUser'; import type { UserInfoAction } from '../useUserInfoActions'; @@ -12,7 +10,6 @@ import type { UserInfoAction } from '../useUserInfoActions'; export const useBanUserAction = (user: Pick, roomId: IRoom['_id']): UserInfoAction | undefined => { const { t } = useTranslation(); - const currentUser = useUser(); const room = useUserRoom(roomId); const subscription = useUserSubscription(roomId); @@ -27,14 +24,12 @@ export const useBanUserAction = (user: Pick, roomId: const { _id: uid, username } = user; const hasPermissionToBan = usePermission('ban-user', roomId); - const federationCanBan = isRoomNativeFederated(room) && Federation.isEditableByTheUser(currentUser || undefined, room, subscription); - const { roomCanBan } = getRoomDirectives({ room, showingUserId: uid, userSubscription: subscription }); const handleBan = useBanUser({ roomId }); return useMemo(() => { - if (!hasPermissionToBan || !federationCanBan || !roomCanBan) { + if (!hasPermissionToBan || !roomCanBan) { return undefined; } @@ -45,5 +40,5 @@ export const useBanUserAction = (user: Pick, roomId: type: 'moderation' as const, variant: 'danger' as const, }; - }, [handleBan, roomCanBan, federationCanBan, hasPermissionToBan, t, username]); + }, [handleBan, roomCanBan, hasPermissionToBan, t, username]); }; diff --git a/apps/meteor/server/lib/unbanUserFromRoom.ts b/apps/meteor/server/lib/unbanUserFromRoom.ts index 488a90239cb3b..65916b399a1aa 100644 --- a/apps/meteor/server/lib/unbanUserFromRoom.ts +++ b/apps/meteor/server/lib/unbanUserFromRoom.ts @@ -1,8 +1,10 @@ import { Rooms, Users } from '@rocket.chat/models'; +import { roomCoordinator } from './rooms/roomCoordinator'; import { canAccessRoomAsync } from '../../app/authorization/server'; import { hasPermissionAsync } from '../../app/authorization/server/functions/hasPermission'; import { executeUnbanUserFromRoom } from '../../app/lib/server/functions/executeUnbanUserFromRoom'; +import { RoomMemberActions } from '../../definition/IRoomTypeConfig'; export const unbanUserFromRoom = async (fromId: string, data: { rid: string; username: string }): Promise => { if (!(await hasPermissionAsync(fromId, 'ban-user', data.rid))) { @@ -10,8 +12,8 @@ export const unbanUserFromRoom = async (fromId: string, data: { rid: string; use } const room = await Rooms.findOneById(data.rid); - if (!room) { - throw new Error('Invalid room'); + if (!room || !(await roomCoordinator.getRoomDirectives(room.t).allowMemberAction(room, RoomMemberActions.BAN, fromId))) { + throw new Error('Not allowed'); } const fromUser = await Users.findOneById(fromId);