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
4 changes: 2 additions & 2 deletions app/api/server/lib/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ export async function findRoomsAvailableForTeams({ uid, name }) {
},
};

const userRooms = Subscriptions.findByUserIdAndType(uid, 'p', { fields: { rid: 1 } })
const userRooms = Subscriptions.findByUserIdAndRoles(uid, ['owner'], { fields: { rid: 1 } })
.fetch()
.map((item) => item.rid);

const rooms = await Rooms.findChannelAndGroupListWithoutTeamsByNameStarting(name, userRooms, options).toArray();
const rooms = await Rooms.findChannelAndGroupListWithoutTeamsByNameStartingByOwner(uid, name, userRooms, options).toArray();

return {
items: rooms,
Expand Down
2 changes: 1 addition & 1 deletion app/api/server/v1/teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ API.v1.addRoute('teams.addRooms', { authRequired: true }, {
}

if (!hasPermission(this.userId, 'add-team-channel', team.roomId)) {
return API.v1.unauthorized();
return API.v1.unauthorized('error-no-permission-team-channel');
}

const validRooms = Promise.await(Team.addRooms(this.userId, rooms, team._id));
Expand Down
9 changes: 9 additions & 0 deletions app/models/server/models/Subscriptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,15 @@ export class Subscriptions extends Base {
return this.find(query, options);
}

findByUserIdAndRoles(userId, roles, options) {
const query = {
'u._id': userId,
roles: { $in: roles },
};

return this.find(query, options);
}

findByUserIdUpdatedAfter(userId, updatedAt, options) {
const query = {
'u._id': userId,
Expand Down
17 changes: 4 additions & 13 deletions app/models/server/raw/Rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export class RoomsRaw extends BaseRaw {
return this.find(query, options);
}

findChannelAndGroupListWithoutTeamsByNameStarting(name, groupsToAccept, options) {
findChannelAndGroupListWithoutTeamsByNameStartingByOwner(uid, name, groupsToAccept, options) {
const nameRegex = new RegExp(`^${ escapeRegExp(name).trim() }`, 'i');

const query = {
Expand All @@ -192,20 +192,11 @@ export class RoomsRaw extends BaseRaw {
prid: {
$exists: false,
},
$or: [
{
t: 'c',
},
{
t: 'p',
_id: {
$in: groupsToAccept,
},
},
],
_id: {
$in: groupsToAccept,
},
name: nameRegex,
};

return this.find(query, options);
}

Expand Down
2 changes: 2 additions & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,8 @@
"error-user-registration-disabled": "User registration is disabled",
"error-user-registration-secret": "User registration is only allowed via Secret URL",
"error-validating-department-chat-closing-tags": "At least one closing tag is required when the department requires tag(s) on closing conversations.",
"error-no-permission-team-channel": "You don't have permission to add this channel to the team",
"error-no-owner-channel": "Only owners can add this channel to the team",
"error-you-are-last-owner": "You are the last owner. Please set new owner before leaving the room.",
"Errors_and_Warnings": "Errors and Warnings",
"Esc_to": "Esc to",
Expand Down
10 changes: 5 additions & 5 deletions server/services/team/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,20 +312,20 @@ export class TeamService extends ServiceClass implements ITeamService {
}

// validate access for every room first
validRooms.forEach(async (room) => {
for await (const room of validRooms) {
const canSeeRoom = await canAccessRoom(room, user);
if (!canSeeRoom) {
throw new Error('invalid-room');
}
});
}

for (const room of validRooms) {
for await (const room of validRooms) {
if (room.teamId) {
throw new Error('room-already-on-team');
}

if (room.u?._id !== uid) {
throw new Error('invalid-user');
if (!await this.SubscriptionsModel.isUserInRole(uid, 'owner', room._id)) {
throw new Error('error-no-owner-channel');
}

room.teamId = teamId;
Expand Down
102 changes: 97 additions & 5 deletions tests/end-to-end/api/25-teams.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect } from 'chai';

import { getCredentials, api, request, credentials } from '../../data/api-data';
import { getCredentials, api, request, credentials, methodCall } from '../../data/api-data';
import { updatePermission } from '../../data/permissions.helper.js';

describe('[Teams]', () => {
describe.only('[Teams]', () => {
before((done) => getCredentials(done));

const community = `community${ Date.now() }`;
Expand All @@ -15,13 +15,14 @@ describe('[Teams]', () => {
let privateRoom2 = null;
let testUser;
let testUser2;
const testUserCredentials = {};

before('Create test users', (done) => {
let username = `user.test.${ Date.now() }`;
let email = `${ username }@rocket.chat`;
request.post(api('users.create'))
.set(credentials)
.send({ email, name: username, username, password: username })
.send({ email, name: username, username, password: username, roles: ['user'] })
.then((res) => {
testUser = res.body.user;

Expand All @@ -37,6 +38,21 @@ describe('[Teams]', () => {
});
});

before('login testUser', (done) => {
request.post(api('login'))
.send({
user: testUser.username,
password: testUser.username,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
testUserCredentials['X-Auth-Token'] = res.body.data.authToken;
testUserCredentials['X-User-Id'] = res.body.data.userId;
})
.end(done);
});

describe('/teams.create', () => {
it('should create a public team', (done) => {
request.post(api('teams.create'))
Expand Down Expand Up @@ -654,7 +670,8 @@ describe('[Teams]', () => {
expect(res.body.rooms[0]).to.have.property('teamId', teamId);
expect(res.body.rooms[0]).to.not.have.property('teamDefault');
})
.then(() => done());
.then(() => done())
.catch(done);
});

before('create channel 2', (done) => {
Expand Down Expand Up @@ -742,6 +759,8 @@ describe('[Teams]', () => {
});

describe('/teams.addRooms', () => {
let privateRoom3;

before('create private channel', (done) => {
const channelName = `community-channel-private${ Date.now() }`;
request.post(api('groups.create'))
Expand Down Expand Up @@ -780,6 +799,25 @@ describe('[Teams]', () => {
})
.end(done);
});
before('create yet another private channel', (done) => {
const channelName = `community-channel-private${ Date.now() }`;
request.post(api('groups.create'))
.set(credentials)
.send({
name: channelName,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.nested.property('group._id');
expect(res.body).to.have.nested.property('group.name', channelName);
expect(res.body).to.have.nested.property('group.t', 'p');
expect(res.body).to.have.nested.property('group.msgs', 0);
privateRoom3 = res.body.group;
})
.end(done);
});
before('create public channel', (done) => {
const channelName = `community-channel-public${ Date.now() }`;
request.post(api('channels.create'))
Expand Down Expand Up @@ -832,7 +870,7 @@ describe('[Teams]', () => {
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error');
expect(res.body.error).to.be.equal('unauthorized');
expect(res.body.error).to.be.equal('error-no-permission-team-channel');
})
.end(done);
});
Expand Down Expand Up @@ -905,6 +943,60 @@ describe('[Teams]', () => {
.end(done);
});
});

it('should fail if the user cannot access the channel', (done) => {
updatePermission('add-team-channel', ['admin', 'user'])
.then(() => {
request.post(api('teams.addRooms'))
.set(testUserCredentials)
.send({
rooms: [privateRoom3._id],
teamId: privateTeam._id,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error');
expect(res.body.error).to.be.equal('invalid-room');
})
.end(done);
})
.catch(done);
});

it('should fail if the user is not the owner of the channel', (done) => {
request.post(methodCall('addUsersToRoom'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'addUsersToRoom',
params: [{ rid: privateRoom3._id, users: [testUser.username] }],
}),
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
.then(() => {
request.post(api('teams.addRooms'))
.set(testUserCredentials)
.send({
rooms: [privateRoom3._id],
teamId: privateTeam._id,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error');
expect(res.body.error).to.be.equal('error-no-owner-channel');
})
.end(done);
})
.catch(done);
});
});

describe('/teams.listRooms', () => {
Expand Down