fix: API method `rooms.delete` deleting main team room (#36790)

Co-authored-by: Abhinav Kumar <15830206+abhinavkrin@users.noreply.github.com>
Co-authored-by: Douglas Fabris <27704687+dougfabris@users.noreply.github.com>
pull/37197/head^2
Tiago Evangelista Pinto 3 months ago committed by GitHub
parent 6f13304f52
commit c635c9f17c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      .changeset/slimy-apples-complain.md
  2. 18
      apps/meteor/app/api/server/v1/rooms.ts
  3. 7
      apps/meteor/server/lib/eraseRoom.ts
  4. 37
      apps/meteor/tests/end-to-end/api/rooms.ts

@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes an issue where the API method `rooms.delete` inadvertently deletes the main room of a team

@ -1,4 +1,4 @@
import { Media, Team } from '@rocket.chat/core-services';
import { Media, MeteorError, Team } from '@rocket.chat/core-services';
import type { IRoom, IUpload } from '@rocket.chat/core-typings';
import { isPrivateRoom, isPublicRoom } from '@rocket.chat/core-typings';
import { Messages, Rooms, Users, Uploads, Subscriptions } from '@rocket.chat/models';
@ -130,7 +130,21 @@ API.v1.addRoute(
return API.v1.failure("The 'roomId' param is required");
}
await eraseRoom(roomId, this.userId);
const room = await Rooms.findOneById(roomId);
if (!room) {
throw new MeteorError('error-invalid-room', 'Invalid room', {
method: 'eraseRoom',
});
}
if (room.teamMain) {
throw new Meteor.Error('error-cannot-delete-team-channel', 'Cannot delete a team channel', {
method: 'eraseRoom',
});
}
await eraseRoom(room, this.userId);
return API.v1.success();
},

@ -1,5 +1,6 @@
import { AppEvents, Apps } from '@rocket.chat/apps';
import { Message, Team } from '@rocket.chat/core-services';
import type { IRoom } from '@rocket.chat/core-typings';
import { Rooms } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
@ -7,8 +8,8 @@ import { roomCoordinator } from './rooms/roomCoordinator';
import { hasPermissionAsync } from '../../app/authorization/server/functions/hasPermission';
import { deleteRoom } from '../../app/lib/server/functions/deleteRoom';
export async function eraseRoom(rid: string, uid: string): Promise<void> {
const room = await Rooms.findOneById(rid);
export async function eraseRoom(roomOrId: string | IRoom, uid: string): Promise<void> {
const room = typeof roomOrId === 'string' ? await Rooms.findOneById(roomOrId) : roomOrId;
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
@ -46,7 +47,7 @@ export async function eraseRoom(rid: string, uid: string): Promise<void> {
}
}
await deleteRoom(rid);
await deleteRoom(room._id);
if (team) {
const user = await Meteor.userAsync();

@ -2598,13 +2598,30 @@ describe('[Rooms]', () => {
describe('/rooms.delete', () => {
let testChannel: IRoom;
let testTeam: ITeam;
let testUser: IUser;
let testUser2: IUser;
let userCredentials: Credentials;
before('create an channel', async () => {
const result = await createRoom({ type: 'c', name: `channel.test.${Date.now()}-${Math.random()}` });
testChannel = result.body.channel;
before('create channel and team', async () => {
testUser = await createUser();
testUser2 = await createUser();
userCredentials = await login(testUser.username, password);
const {
body: { channel },
} = await createRoom({ type: 'c', name: `channel.test.${Date.now()}-${Math.random()}` });
testChannel = channel;
testTeam = await createTeam(userCredentials, `team.test.${Date.now()}-${Math.random()}`, TEAM_TYPE.PUBLIC, [
testUser.username as string,
testUser2.username as string,
]);
});
after(() => deleteRoom({ type: 'c', roomId: testChannel._id }));
after('delete channel and team', async () => {
await deleteTeam(userCredentials, testTeam.name);
await deleteRoom({ type: 'c', roomId: testChannel._id });
});
it('should throw an error when roomId is not provided', (done) => {
void request
@ -2643,6 +2660,18 @@ describe('[Rooms]', () => {
})
.end(done);
});
it('should throw an error when room is a main team room', (done) => {
void request
.post(api('rooms.delete'))
.set(credentials)
.send({ roomId: testTeam.roomId })
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
})
.end(done);
});
});
describe('rooms.saveRoomSettings', () => {

Loading…
Cancel
Save