diff --git a/app/api/server/v1/chat.js b/app/api/server/v1/chat.js index f667005b988..d2c1b153cc8 100644 --- a/app/api/server/v1/chat.js +++ b/app/api/server/v1/chat.js @@ -386,16 +386,36 @@ API.v1.addRoute('chat.getThreadsList', { authRequired: true }, { get() { const { rid } = this.queryParams; const { offset, count } = this.getPaginationItems(); - + const { sort, fields, query } = this.parseJsonQuery(); if (!rid) { throw new Meteor.Error('The required "rid" query param is missing.'); } - const threads = Meteor.runAsUser(this.userId, () => Meteor.call('getThreadsList', { - rid, - limit: count, + if (!settings.get('Threads_enabled')) { + throw new Meteor.Error('error-not-allowed', 'Threads Disabled'); + } + const user = Users.findOneById(this.userId, { fields: { _id: 1 } }); + const room = Rooms.findOneById(rid, { fields: { t: 1, _id: 1 } }); + if (!canAccessRoom(room, user)) { + throw new Meteor.Error('error-not-allowed', 'Not Allowed'); + } + const threadQuery = Object.assign({}, query, { rid, tcount: { $exists: true } }); + const cursor = Messages.find(threadQuery, { + sort: sort ? sort : { ts: 1 }, skip: offset, - })); - return API.v1.success({ threads }); + limit: count, + fields, + }); + + const total = cursor.count(); + + const threads = cursor.fetch(); + + return API.v1.success({ + threads, + count: threads.length, + offset, + total, + }); }, }); @@ -437,17 +457,42 @@ API.v1.addRoute('chat.syncThreadsList', { authRequired: true }, { API.v1.addRoute('chat.getThreadMessages', { authRequired: true }, { get() { const { tmid } = this.queryParams; + const { query, fields, sort } = this.parseJsonQuery(); const { offset, count } = this.getPaginationItems(); + if (!settings.get('Threads_enabled')) { + throw new Meteor.Error('error-not-allowed', 'Threads Disabled'); + } if (!tmid) { - throw new Meteor.Error('The required "tmid" query param is missing.'); + throw new Meteor.Error('error-invalid-params', 'The required "tmid" query param is missing.'); } - const messages = Meteor.runAsUser(this.userId, () => Meteor.call('getThreadMessages', { - tmid, - limit: count, + const thread = Messages.findOneById(tmid, { fields: { rid: 1 } }); + if (!thread || !thread.rid) { + throw new Meteor.Error('error-invalid-message', 'Invalid Message'); + } + const user = Users.findOneById(this.userId, { fields: { _id: 1 } }); + const room = Rooms.findOneById(thread.rid, { fields: { t: 1, _id: 1 } }); + + if (!canAccessRoom(room, user)) { + throw new Meteor.Error('error-not-allowed', 'Not Allowed'); + } + const cursor = Messages.find({ ...query, tmid }, { + sort: sort ? sort : { ts: 1 }, skip: offset, - })); - return API.v1.success({ messages }); + limit: count, + fields, + }); + + const total = cursor.count(); + + const messages = cursor.fetch(); + + return API.v1.success({ + messages, + count: messages.length, + offset, + total, + }); }, }); @@ -472,7 +517,7 @@ API.v1.addRoute('chat.syncThreadMessages', { authRequired: true }, { updatedSinceDate = new Date(updatedSince); } const thread = Messages.findOneById(tmid, { fields: { rid: 1 } }); - if (!thread.rid) { + if (!thread || !thread.rid) { throw new Meteor.Error('error-invalid-message', 'Invalid Message'); } const user = Users.findOneById(this.userId, { fields: { _id: 1 } }); diff --git a/tests/end-to-end/api/05-chat.js b/tests/end-to-end/api/05-chat.js index d9389f20cbe..31526bc030f 100644 --- a/tests/end-to-end/api/05-chat.js +++ b/tests/end-to-end/api/05-chat.js @@ -931,25 +931,6 @@ describe('[Chat]', function() { }); }); - it('should return an error when the limit is greater than the MAX LIMIT(100) allowed', (done) => { - updateSetting('API_Upper_Count_Limit', 105).then(() => { - request.get(api('chat.getThreadsList')) - .set(credentials) - .query({ - rid: testChannel._id, - count: 101, - }) - .expect('Content-Type', 'application/json') - .expect(400) - .expect((res) => { - expect(res.body).to.have.property('success', false); - expect(res.body).to.have.property('errorType', 'error-not-allowed'); - expect(res.body).to.have.property('error', 'max limit: 100 [error-not-allowed]'); - }) - .end(() => updateSetting('API_Upper_Count_Limit', 100).then(done)); - }); - }); - it('should return an error for chat.getThreadsList when threads are not allowed in this server', (done) => { updateSetting('Threads_enabled', false).then(() => { request.get(api('chat.getThreadsList')) @@ -1004,6 +985,9 @@ describe('[Chat]', function() { .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('threads').and.to.be.an('array'); + expect(res.body).to.have.property('total'); + expect(res.body).to.have.property('offset'); + expect(res.body).to.have.property('count'); expect(res.body.threads).to.have.lengthOf(1); expect(res.body.threads[0]._id).to.be.equal(threadMessage.tmid); }) @@ -1179,25 +1163,6 @@ describe('[Chat]', function() { }); }); - it('should return an error when the limit is greater than the MAX LIMIT(100) allowed', (done) => { - updateSetting('API_Upper_Count_Limit', 105).then(() => { - request.get(api('chat.getThreadMessages')) - .set(credentials) - .query({ - tmid: threadMessage.tmid, - count: 101, - }) - .expect('Content-Type', 'application/json') - .expect(400) - .expect((res) => { - expect(res.body).to.have.property('success', false); - expect(res.body).to.have.property('errorType', 'error-not-allowed'); - expect(res.body).to.have.property('error', 'max limit: 100 [error-not-allowed]'); - }) - .end(done); - }); - }); - it('should return an error for chat.getThreadMessages when threads are not allowed in this server', (done) => { updateSetting('Threads_enabled', false).then(() => { request.get(api('chat.getThreadMessages')) @@ -1231,7 +1196,7 @@ describe('[Chat]', function() { .expect((res) => { expect(res.body).to.have.property('success', false); expect(res.body).to.have.property('errorType', 'error-not-allowed'); - expect(res.body).to.have.property('error', 'Not allowed [error-not-allowed]'); + expect(res.body).to.have.property('error', 'Not Allowed [error-not-allowed]'); }) .end(done); }); @@ -1252,9 +1217,11 @@ describe('[Chat]', function() { .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('messages').and.to.be.an('array'); - expect(res.body.messages).to.have.lengthOf(2); - expect(res.body.messages[0]._id).to.be.equal(createdThreadMessage._id); - expect(res.body.messages[1].tmid).to.be.equal(createdThreadMessage._id); + expect(res.body).to.have.property('total').and.to.be.equal(1); + expect(res.body).to.have.property('offset'); + expect(res.body).to.have.property('count'); + expect(res.body.messages).to.have.lengthOf(1); + expect(res.body.messages[0].tmid).to.be.equal(createdThreadMessage._id); }) .end(done); });