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/giant-dancers-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed an `UnhandledPromiseRejection` error on `PUT livechat/departments/:_id` endpoint when `agents` array failed validation
12 changes: 2 additions & 10 deletions apps/meteor/app/livechat/imports/server/rest/departments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,6 @@ API.v1.addRoute(
const permissionToSave = await hasPermissionAsync(this.userId, 'manage-livechat-departments');
const permissionToAddAgents = await hasPermissionAsync(this.userId, 'add-livechat-department-agents');

check(this.urlParams, {
_id: String,
});

check(this.bodyParams, {
department: Object,
agents: Match.Maybe(Array),
Expand All @@ -128,13 +124,13 @@ API.v1.addRoute(
}

if (success && agents && permissionToAddAgents) {
success = Livechat.saveDepartmentAgents(_id, { upsert: agents });
success = await Livechat.saveDepartmentAgents(_id, { upsert: agents });
}

if (success) {
return API.v1.success({
department: await LivechatDepartment.findOneById(_id),
agents: await LivechatDepartmentAgents.find({ departmentId: _id }).toArray(),
agents: await LivechatDepartmentAgents.findByDepartmentId(_id).toArray(),
});
}

Expand Down Expand Up @@ -266,10 +262,6 @@ API.v1.addRoute(
return API.v1.success(agents);
},
async post() {
check(this.urlParams, {
_id: String,
});

check(
this.bodyParams,
Match.ObjectIncluding({
Expand Down
3 changes: 1 addition & 2 deletions apps/meteor/app/livechat/server/lib/Livechat.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ export const Livechat = {
},

async saveDepartmentAgents(_id, departmentAgents) {
check(_id, String);
check(departmentAgents, {
upsert: Match.Maybe([
Match.ObjectIncluding({
Expand All @@ -212,7 +211,7 @@ export const Livechat = {
]),
});

const department = await LivechatDepartmentRaw.findOneById(_id);
const department = await LivechatDepartmentRaw.findOneById(_id, { projection: { enabled: 1 } });
if (!department) {
throw new Meteor.Error('error-department-not-found', 'Department not found', {
method: 'livechat:saveDepartmentAgents',
Expand Down
62 changes: 60 additions & 2 deletions apps/meteor/tests/end-to-end/api/livechat/10-departments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,15 @@ import { IS_EE } from '../../../e2e/config/constants';
});

describe('PUT livechat/departments/:_id', () => {
let department: ILivechatDepartment;
before(async () => {
department = await createDepartment();
});
after(async () => {
await deleteDepartment(department._id);
});

it('should return an error if fallbackForwardDepartment points to same department', async () => {
const department = await createDepartment();
await request
.put(api(`livechat/department/${department._id}`))
.set(credentials)
Expand All @@ -361,7 +368,58 @@ import { IS_EE } from '../../../e2e/config/constants';
})
.expect('Content-Type', 'application/json')
.expect(400);
await deleteDepartment(department._id);
});
it('should fail if `agents` param is not an array', async () => {
await request
.put(api(`livechat/department/${department._id}`))
.set(credentials)
.send({
department: {
name: faker.hacker.adjective(),
enabled: true,
showOnOfflineForm: true,
showOnRegistration: true,
email: faker.internet.email(),
},
agents: 'not an array',
})
.expect('Content-Type', 'application/json')
.expect(400);
});
it('should throw an error if user has permission to add agents and agents array has invalid format', async () => {
await updatePermission('add-livechat-department-agents', ['admin']);
await request
.put(api(`livechat/department/${department._id}`))
.set(credentials)
.send({
department: {
name: faker.hacker.adjective(),
enabled: true,
showOnOfflineForm: true,
showOnRegistration: true,
email: faker.internet.email(),
},
agents: [{ notAValidKey: 'string' }],
})
.expect('Content-Type', 'application/json')
.expect(400);
});
it('should throw an error if user has permission to add agents and agents array has invalid internal format', async () => {
await request
.put(api(`livechat/department/${department._id}`))
.set(credentials)
.send({
department: {
name: faker.hacker.adjective(),
enabled: true,
showOnOfflineForm: true,
showOnRegistration: true,
email: faker.internet.email(),
},
agents: [{ upsert: [{ notAValidKey: 'string' }] }],
})
.expect('Content-Type', 'application/json')
.expect(400);
});
});

Expand Down