Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slimy-apples-complain.md
Original file line number Diff line number Diff line change
@@ -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
18 changes: 16 additions & 2 deletions apps/meteor/app/api/server/v1/rooms.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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();
},
Expand Down
7 changes: 4 additions & 3 deletions apps/meteor/server/lib/eraseRoom.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
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';

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', {
Expand Down Expand Up @@ -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();
Expand Down
37 changes: 33 additions & 4 deletions apps/meteor/tests/end-to-end/api/rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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', () => {
Expand Down
Loading