Skip to content

Commit eba8e36

Browse files
feat: rooms.hide endpoint (#34208)
1 parent 1854c9b commit eba8e36

File tree

7 files changed

+153
-0
lines changed

7 files changed

+153
-0
lines changed

.changeset/chilly-sheep-cover.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@rocket.chat/rest-typings': minor
3+
'@rocket.chat/models': minor
4+
'@rocket.chat/i18n': minor
5+
'@rocket.chat/meteor': minor
6+
---
7+
8+
Adds a new endpoint `rooms.hide` to hide rooms of any type when provided with the room's ID

apps/meteor/app/api/server/v1/rooms.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
isRoomsCleanHistoryProps,
1313
isRoomsOpenProps,
1414
isRoomsMembersOrderedByRoleProps,
15+
isRoomsHideProps,
1516
} from '@rocket.chat/rest-typings';
1617
import { Meteor } from 'meteor/meteor';
1718

@@ -21,6 +22,7 @@ import * as dataExport from '../../../../server/lib/dataExport';
2122
import { eraseRoom } from '../../../../server/lib/eraseRoom';
2223
import { findUsersOfRoomOrderedByRole } from '../../../../server/lib/findUsersOfRoomOrderedByRole';
2324
import { openRoom } from '../../../../server/lib/openRoom';
25+
import { hideRoomMethod } from '../../../../server/methods/hideRoom';
2426
import { muteUserInRoom } from '../../../../server/methods/muteUserInRoom';
2527
import { unmuteUserInRoom } from '../../../../server/methods/unmuteUserInRoom';
2628
import { canAccessRoomAsync, canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
@@ -962,3 +964,31 @@ API.v1.addRoute(
962964
},
963965
},
964966
);
967+
968+
API.v1.addRoute(
969+
'rooms.hide',
970+
{ authRequired: true, validateParams: isRoomsHideProps },
971+
{
972+
async post() {
973+
const { roomId } = this.bodyParams;
974+
975+
if (!(await canAccessRoomIdAsync(roomId, this.userId))) {
976+
return API.v1.unauthorized();
977+
}
978+
979+
const user = await Users.findOneById(this.userId, { projections: { _id: 1 } });
980+
981+
if (!user) {
982+
return API.v1.failure('error-invalid-user');
983+
}
984+
985+
const modCount = await hideRoomMethod(this.userId, roomId);
986+
987+
if (!modCount) {
988+
return API.v1.failure('error-room-already-hidden');
989+
}
990+
991+
return API.v1.success();
992+
},
993+
},
994+
);

apps/meteor/tests/end-to-end/api/rooms.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4204,4 +4204,94 @@ describe('[Rooms]', () => {
42044204
});
42054205
});
42064206
});
4207+
4208+
describe('/rooms.hide', () => {
4209+
let roomA: IRoom;
4210+
let roomB: IRoom;
4211+
const roomName = `rooms.hide.test.${Date.now()}`;
4212+
let memberA: TestUser<IUser>;
4213+
let memberB: TestUser<IUser>;
4214+
let nonMember: TestUser<IUser>;
4215+
let nonMemberCredentials: Credentials;
4216+
4217+
before(async () => {
4218+
memberA = await createUser();
4219+
memberB = await createUser();
4220+
nonMember = await createUser();
4221+
nonMemberCredentials = await login(nonMember.username, password);
4222+
});
4223+
4224+
before(async () => {
4225+
roomA = (await createRoom({ type: 'c', name: roomName, members: [memberA.username, memberB.username] })).body.channel;
4226+
roomB = (await createRoom({ type: 'd', username: memberB.username })).body.room;
4227+
});
4228+
4229+
after(async () => {
4230+
await deleteRoom({ type: 'c', roomId: roomA._id });
4231+
await deleteRoom({ type: 'd', roomId: roomB._id });
4232+
await deleteUser(memberA);
4233+
await deleteUser(memberB);
4234+
await deleteUser(nonMember);
4235+
});
4236+
4237+
it('should hide the room', async () => {
4238+
await request
4239+
.post(api('rooms.hide'))
4240+
.set(credentials)
4241+
.send({ roomId: roomA._id })
4242+
.expect('Content-Type', 'application/json')
4243+
.expect(200)
4244+
.expect((res) => {
4245+
expect(res.body).to.have.property('success', true);
4246+
});
4247+
});
4248+
4249+
it('should be already hidden', async () => {
4250+
await request
4251+
.post(api('rooms.hide'))
4252+
.set(credentials)
4253+
.send({ roomId: roomA._id })
4254+
.expect('Content-Type', 'application/json')
4255+
.expect(400)
4256+
.expect((res) => {
4257+
expect(res.body).to.have.property('success', false);
4258+
expect(res.body).to.have.property('error', `error-room-already-hidden`);
4259+
});
4260+
});
4261+
4262+
it('should fail if roomId is not provided', async () => {
4263+
await request
4264+
.post(api('rooms.hide'))
4265+
.set(credentials)
4266+
.send()
4267+
.expect('Content-Type', 'application/json')
4268+
.expect(400)
4269+
.expect((res: Response) => {
4270+
expect(res.body).to.have.property('success', false);
4271+
});
4272+
});
4273+
4274+
it('should return 401 if user is not logged in', async () => {
4275+
await request
4276+
.post(api('rooms.hide'))
4277+
.expect('Content-Type', 'application/json')
4278+
.expect(401)
4279+
.expect((res) => {
4280+
expect(res.body).to.have.property('status', 'error');
4281+
expect(res.body).to.have.property('message');
4282+
});
4283+
});
4284+
4285+
it('should return forbidden if user does not have access to the room', async () => {
4286+
await request
4287+
.post(api('rooms.hide'))
4288+
.set(nonMemberCredentials)
4289+
.send({ roomId: roomB._id })
4290+
.expect('Content-Type', 'application/json')
4291+
.expect(401)
4292+
.expect((res) => {
4293+
expect(res.body).to.have.property('success', false);
4294+
});
4295+
});
4296+
});
42074297
});

packages/i18n/src/locales/en.i18n.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,6 +2245,7 @@
22452245
"error-room-does-not-exist": "This room does not exist",
22462246
"error-role-already-present": "A role with this name already exists",
22472247
"error-room-already-closed": "Room is already closed",
2248+
"error-room-already-hidden": "Room is already hidden",
22482249
"error-room-is-not-closed": "Room is not closed",
22492250
"error-room-onHold": "Error! Room is On Hold",
22502251
"error-room-is-already-on-hold": "Error! Room is already On Hold",

packages/i18n/src/locales/pt-BR.i18n.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,6 +1817,7 @@
18171817
"error-role-name-required": "Nome do papel é obrigatório",
18181818
"error-room-does-not-exist": "Essa sala não existe",
18191819
"error-role-already-present": "Já existe uma função com este nome",
1820+
"error-room-already-hidden": "A sala já está oculta",
18201821
"error-room-is-not-closed": "Sala não está fechada",
18211822
"error-room-onHold": "Erro! Sala está em espera",
18221823
"error-selected-agent-room-agent-are-same": "O agente selecionado e o agente da sala são iguais",

packages/models/src/models/Subscriptions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,7 @@ export class SubscriptionsRaw extends BaseRaw<ISubscription> implements ISubscri
13191319
const query = {
13201320
'rid': roomId,
13211321
'u._id': userId,
1322+
'open': true,
13221323
};
13231324

13241325
const update: UpdateFilter<ISubscription> = {

packages/rest-typings/src/v1/rooms.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,24 @@ const membersOrderedByRoleRolePropsSchema = {
670670

671671
export const isRoomsMembersOrderedByRoleProps = ajv.compile<RoomsMembersOrderedByRoleProps>(membersOrderedByRoleRolePropsSchema);
672672

673+
type RoomsHideProps = {
674+
roomId: string;
675+
};
676+
677+
const roomsHideSchema = {
678+
type: 'object',
679+
properties: {
680+
roomId: {
681+
type: 'string',
682+
minLength: 1,
683+
},
684+
},
685+
required: ['roomId'],
686+
additionalProperties: false,
687+
};
688+
689+
export const isRoomsHideProps = ajv.compile<RoomsHideProps>(roomsHideSchema);
690+
673691
export type RoomsEndpoints = {
674692
'/v1/rooms.autocomplete.channelAndPrivate': {
675693
GET: (params: RoomsAutoCompleteChannelAndPrivateProps) => {
@@ -846,4 +864,8 @@ export type RoomsEndpoints = {
846864
members: (IUser & { roles?: IRole['_id'][] })[];
847865
}>;
848866
};
867+
868+
'/v1/rooms.hide': {
869+
POST: (params: RoomsHideProps) => void;
870+
};
849871
};

0 commit comments

Comments
 (0)