Skip to content

Commit

Permalink
fix: New users are not automatically inserted in auto-join rooms insi…
Browse files Browse the repository at this point in the history
…de default teams (#31720)

Co-authored-by: Matheus Barbosa Silva <[email protected]>
  • Loading branch information
Gustrb and matheusbsilva137 authored Mar 5, 2024
1 parent b0aace7 commit 0f0d631
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/calm-penguins-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Now we are considering channels with auto-join inside teams on user creation
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Message } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
import { Subscriptions, Rooms } from '@rocket.chat/models';
import { Subscriptions } from '@rocket.chat/models';

import { callbacks } from '../../../../lib/callbacks';
import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig';
import { getDefaultChannels } from './getDefaultChannels';

export const addUserToDefaultChannels = async function (user: IUser, silenced?: boolean): Promise<void> {
await callbacks.run('beforeJoinDefaultChannels', user);
const defaultRooms = await Rooms.findByDefaultAndTypes(true, ['c', 'p'], {
projection: { usernames: 0 },
}).toArray();
const defaultRooms = await getDefaultChannels();

for await (const room of defaultRooms) {
if (!(await Subscriptions.findOneByRoomIdAndUserId(room._id, user._id, { projection: { _id: 1 } }))) {
const autoTranslateConfig = getSubscriptionAutotranslateDefaultConfig(user);
Expand Down
25 changes: 25 additions & 0 deletions apps/meteor/app/lib/server/functions/getDefaultChannels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { IRoom } from '@rocket.chat/core-typings';
import { Rooms } from '@rocket.chat/models';

export async function getDefaultChannels(): Promise<IRoom[]> {
const defaultRooms = await Rooms.findByDefaultAndTypes(true, ['c', 'p'], {
projection: { usernames: 0 },
}).toArray();
const roomsThatAreGoingToBeJoined = new Set(defaultRooms.map((room) => room._id));

// If any of those are teams, we need to get all the channels that have the auto-join flag as well
const teamRooms = defaultRooms.filter((room) => room.teamMain && room.teamId);
if (teamRooms.length > 0) {
for await (const teamRoom of teamRooms) {
const defaultTeamRooms = await Rooms.findDefaultRoomsForTeam(teamRoom.teamId).toArray();

const defaultTeamRoomsThatWereNotAlreadyAdded = defaultTeamRooms.filter((channel) => !roomsThatAreGoingToBeJoined.has(channel._id));

defaultTeamRoomsThatWereNotAlreadyAdded.forEach((channel) => roomsThatAreGoingToBeJoined.add(channel._id));
// Add the channels to the defaultRooms list
defaultRooms.push(...defaultTeamRoomsThatWereNotAlreadyAdded);
}
}

return defaultRooms;
}
17 changes: 16 additions & 1 deletion apps/meteor/tests/data/rooms.helper.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { api, credentials, request } from './api-data';

export const createRoom = ({ name, type, username, token, agentId, members, credentials: customCredentials, voipCallDirection = 'inbound' }) => {
export const createRoom = ({ name, type, username, token, agentId, members, credentials: customCredentials, extraData, voipCallDirection = 'inbound' }) => {
if (!type) {
throw new Error('"type" is required in "createRoom.ts" test helper');
}
Expand Down Expand Up @@ -31,6 +31,7 @@ export const createRoom = ({ name, type, username, token, agentId, members, cred
.send({
...params,
...(members && { members }),
...(extraData && { extraData }),
});
};

Expand Down Expand Up @@ -65,3 +66,17 @@ function actionRoom({ action, type, roomId }) {
export const deleteRoom = ({ type, roomId }) => actionRoom({ action: 'delete', type, roomId });

export const closeRoom = ({ type, roomId }) => actionRoom({ action: 'close', type, roomId });

export const setRoomConfig = ({ roomId, favorite, isDefault }) => {
return request
.post(api('rooms.saveRoomSettings'))
.set(credentials)
.send({
rid: roomId,
default: isDefault,
favorite: favorite ? {
defaultValue: true,
favorite: false
} : undefined
});
};
1 change: 1 addition & 0 deletions apps/meteor/tests/data/uploads.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export async function testFileUploads(filesEndpoint: 'channels.files' | 'groups.
name: null,
username: null,
members: null,
extraData: null,
});

return roomResponse.body.room;
Expand Down
159 changes: 158 additions & 1 deletion apps/meteor/tests/end-to-end/api/01-users.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { imgURL } from '../../data/interactions';
import { createAgent, makeAgentAvailable } from '../../data/livechat/rooms';
import { removeAgent, getAgent } from '../../data/livechat/users';
import { updatePermission, updateSetting } from '../../data/permissions.helper';
import { createRoom, deleteRoom } from '../../data/rooms.helper';
import { createRoom, deleteRoom, setRoomConfig } from '../../data/rooms.helper';
import { createTeam, deleteTeam } from '../../data/teams.helper';
import { adminEmail, preferences, password, adminUsername } from '../../data/user';
import { createUser, login, deleteUser, getUserStatus, getUserByUsername } from '../../data/users.helper.js';

Expand Down Expand Up @@ -279,6 +280,162 @@ describe('[Users]', function () {
.end(done);
});
});

describe('auto join default channels', () => {
let defaultTeamRoomId;
let defaultTeamId;
let group;
let user;
let userCredentials;
let user2;
let user3;
let userNoDefault;
const teamName = `defaultTeam_${Date.now()}`;

before(async () => {
const defaultTeam = await createTeam(credentials, teamName, 0);
defaultTeamRoomId = defaultTeam.roomId;
defaultTeamId = defaultTeam._id;
});

before(async () => {
const { body } = await createRoom({
name: `defaultGroup_${Date.now()}`,
type: 'p',
credentials,
extraData: {
broadcast: false,
encrypted: false,
teamId: defaultTeamId,
topic: '',
},
});
group = body.group;
});

after(() =>
Promise.all([
deleteRoom({ roomId: group._id, type: 'p' }),
deleteTeam(credentials, teamName),
deleteUser(user),
deleteUser(user2),
deleteUser(user3),
deleteUser(userNoDefault),
]),
);

it('should not create subscriptions to non default teams or rooms even if joinDefaultChannels is true', async () => {
userNoDefault = await createUser({ joinDefaultChannels: true });
const noDefaultUserCredentials = await login(userNoDefault.username, password);
await request
.get(api('subscriptions.getOne'))
.set(noDefaultUserCredentials)
.query({ roomId: defaultTeamRoomId })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription').that.is.null;
});

await request
.get(api('subscriptions.getOne'))
.set(noDefaultUserCredentials)
.query({ roomId: group._id })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription').that.is.null;
});
});

it('should create a subscription for a default team room if joinDefaultChannels is true', async () => {
await setRoomConfig({ roomId: defaultTeamRoomId, favorite: true, isDefault: true });

user = await createUser({ joinDefaultChannels: true });
userCredentials = await login(user.username, password);
await request
.get(api('subscriptions.getOne'))
.set(userCredentials)
.query({ roomId: defaultTeamRoomId })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription');
expect(res.body.subscription).to.have.property('rid', defaultTeamRoomId);
});
});

it('should NOT create a subscription for non auto-join rooms inside a default team', async () => {
await request
.get(api('subscriptions.getOne'))
.set(userCredentials)
.query({ roomId: group._id })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription').that.is.null;
});
});

it('should create a subscription for the user in all the auto join rooms of the team', async () => {
await request.post(api('teams.updateRoom')).set(credentials).send({
roomId: group._id,
isDefault: true,
});

user2 = await createUser({ joinDefaultChannels: true });
const user2Credentials = await login(user2.username, password);

await request
.get(api('subscriptions.getOne'))
.set(user2Credentials)
.query({ roomId: group._id })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription');
expect(res.body.subscription).to.have.property('rid', group._id);
});
});

it('should create a subscription for a default room inside a non default team', async () => {
await setRoomConfig({ roomId: defaultTeamRoomId, isDefault: false });
await setRoomConfig({ roomId: group._id, favorite: true, isDefault: true });

user3 = await createUser({ joinDefaultChannels: true });
const user3Credentials = await login(user3.username, password);

// New user should be subscribed to the default room inside a team
await request
.get(api('subscriptions.getOne'))
.set(user3Credentials)
.query({ roomId: group._id })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription');
expect(res.body.subscription).to.have.property('rid', group._id);
});

// New user should not be subscribed to the parent team
await request
.get(api('subscriptions.getOne'))
.set(user3Credentials)
.query({ roomId: defaultTeamRoomId })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription').that.is.null;
});
});
});
});

describe('[/users.register]', () => {
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/tests/end-to-end/apps/05-video-conferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('Apps - Video Conferences', function () {
agentId: undefined,
members: undefined,
credentials: undefined,
extraData: undefined,
});

roomId = res.body.group._id;
Expand Down

0 comments on commit 0f0d631

Please sign in to comment.