From a4304dd7f9b0e59e6766bd888d625b7e25202161 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 21 May 2018 19:31:28 -0300 Subject: [PATCH 1/2] Add missing pagination fields in the response of REST /directory endpoint --- packages/rocketchat-api/server/v1/misc.js | 7 ++- .../client/views/app/directory.js | 4 +- server/methods/browseChannels.js | 52 +++++++++++-------- tests/end-to-end/api/00-miscellaneous.js | 6 +++ 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/packages/rocketchat-api/server/v1/misc.js b/packages/rocketchat-api/server/v1/misc.js index e6e08db89271f..2e5987e0edc9a 100644 --- a/packages/rocketchat-api/server/v1/misc.js +++ b/packages/rocketchat-api/server/v1/misc.js @@ -158,6 +158,11 @@ RocketChat.API.v1.addRoute('directory', { authRequired: true }, { if (!result) { return RocketChat.API.v1.failure('Please verify the parameters'); } - return RocketChat.API.v1.success({ result }); + return RocketChat.API.v1.success({ + result: result.results, + count: result.results.length, + offset, + total: result.total + }); } }); diff --git a/packages/rocketchat-ui/client/views/app/directory.js b/packages/rocketchat-ui/client/views/app/directory.js index d6ac6d9d47a25..e73f5083069f3 100644 --- a/packages/rocketchat-ui/client/views/app/directory.js +++ b/packages/rocketchat-ui/client/views/app/directory.js @@ -12,8 +12,8 @@ function timeAgo(time) { } function directorySearch(config, cb) { - return Meteor.call('browseChannels', config, (err, results) => { - cb(results && results.length && results.map(result => { + return Meteor.call('browseChannels', config, (err, result) => { + cb(result.results && result.results.length && result.results.map(result => { if (config.type === 'channels') { return { name: result.name, diff --git a/server/methods/browseChannels.js b/server/methods/browseChannels.js index a2dc672884b69..1d918f63595e8 100644 --- a/server/methods/browseChannels.js +++ b/server/methods/browseChannels.js @@ -24,7 +24,7 @@ const sortUsers = function(field, direction) { Meteor.methods({ - browseChannels({text='', type = 'channels', sortBy = 'name', sortDirection = 'asc', page = 0, limit = 10}) { + browseChannels({text = '', type = 'channels', sortBy = 'name', sortDirection = 'asc', page = 0, limit = 10}) { const regex = new RegExp(s.trim(s.escapeRegExp(text)), 'i'); if (!['channels', 'users'].includes(type)) { @@ -35,7 +35,7 @@ Meteor.methods({ return; } - if (!['name', 'createdAt', ...type === 'channels'? ['usernames'] : [], ...type === 'users' ? ['username'] : []].includes(sortBy)) { + if (!['name', 'createdAt', ...type === 'channels' ? ['usernames'] : [], ...type === 'users' ? ['username'] : []].includes(sortBy)) { return; } @@ -55,17 +55,20 @@ Meteor.methods({ if (!RocketChat.authz.hasPermission(user._id, 'view-c-room')) { return; } - return RocketChat.models.Rooms.findByNameAndType(regex, 'c', { - ...options, - sort, - fields: { - description: 1, - name: 1, - ts: 1, - archived: 1, - usernames: 1 - } - }).fetch(); + return { + results: RocketChat.models.Rooms.findByNameAndType(regex, 'c', { + ...options, + sort, + fields: { + description: 1, + name: 1, + ts: 1, + archived: 1, + usernames: 1 + } + }).fetch(), + total: RocketChat.models.Rooms.findByNameAndType(regex, 'c').count() + }; } // type === users @@ -73,16 +76,19 @@ Meteor.methods({ return; } const sort = sortUsers(sortBy, sortDirection); - return RocketChat.models.Users.findByActiveUsersExcept(text, [user.username], { - ...options, - sort, - fields: { - username: 1, - name: 1, - createdAt: 1, - emails: 1 - } - }).fetch(); + return { + results: RocketChat.models.Users.findByActiveUsersExcept(text, [user.username], { + ...options, + sort, + fields: { + username: 1, + name: 1, + createdAt: 1, + emails: 1 + } + }).fetch(), + total: RocketChat.models.Users.findByActiveUsersExcept(text, [user.username]).count() + }; } }); diff --git a/tests/end-to-end/api/00-miscellaneous.js b/tests/end-to-end/api/00-miscellaneous.js index 935bd9c3138ef..34677f824fb1e 100644 --- a/tests/end-to-end/api/00-miscellaneous.js +++ b/tests/end-to-end/api/00-miscellaneous.js @@ -139,6 +139,9 @@ describe('miscellaneous', function() { .expect((res) => { expect(res.body).to.have.property('success', true); expect(res.body).to.have.property('result').and.to.be.an('array'); + expect(res.body).to.have.property('offset'); + expect(res.body).to.have.property('total'); + expect(res.body).to.have.property('count'); expect(res.body.result[0]).to.have.property('_id'); expect(res.body.result[0]).to.have.property('createdAt'); expect(res.body.result[0]).to.have.property('username'); @@ -160,6 +163,9 @@ describe('miscellaneous', function() { .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('offset'); + expect(res.body).to.have.property('total'); + expect(res.body).to.have.property('count'); expect(res.body).to.have.property('result').and.to.be.an('array'); expect(res.body.result[0]).to.have.property('_id'); expect(res.body.result[0]).to.have.property('name'); From d617047b6f9207257c8a6622875e0227d2272901 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 22 May 2018 17:21:43 -0300 Subject: [PATCH 2/2] Add support to choose sort field in REST directory --- packages/rocketchat-api/server/v1/misc.js | 9 ++++- tests/end-to-end/api/00-miscellaneous.js | 48 ++++++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/packages/rocketchat-api/server/v1/misc.js b/packages/rocketchat-api/server/v1/misc.js index 2e5987e0edc9a..1dc196e6bc2a6 100644 --- a/packages/rocketchat-api/server/v1/misc.js +++ b/packages/rocketchat-api/server/v1/misc.js @@ -145,12 +145,17 @@ RocketChat.API.v1.addRoute('directory', { authRequired: true }, { const { sort, query } = this.parseJsonQuery(); const { text, type } = query; - const sortDirection = sort && sort === 1 ? 'asc' : 'desc'; + if (sort && Object.keys(sort).length > 1) { + return RocketChat.API.v1.failure('This method support only one "sort" parameter'); + } + const sortBy = sort ? Object.keys(sort)[0] : undefined; + const sortDirection = sort && Object.values(sort)[0] === 1 ? 'asc' : 'desc'; const result = Meteor.runAsUser(this.userId, () => Meteor.call('browseChannels', { text, type, - sort: sortDirection, + sortBy, + sortDirection, page: offset, limit: count })); diff --git a/tests/end-to-end/api/00-miscellaneous.js b/tests/end-to-end/api/00-miscellaneous.js index 34677f824fb1e..a788c2b8878da 100644 --- a/tests/end-to-end/api/00-miscellaneous.js +++ b/tests/end-to-end/api/00-miscellaneous.js @@ -174,7 +174,33 @@ describe('miscellaneous', function() { }) .end(done); }); - + it('should return an array(result) when search by channel with sort params correctly and execute succesfully', (done) => { + request.get(api('directory')) + .set(credentials) + .query({ + query: JSON.stringify({ + text: testChannel.name, + type: 'channels' + }), + sort: JSON.stringify(({ + name: 1 + })) + }) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('offset'); + expect(res.body).to.have.property('total'); + expect(res.body).to.have.property('count'); + expect(res.body).to.have.property('result').and.to.be.an('array'); + expect(res.body.result[0]).to.have.property('_id'); + expect(res.body.result[0]).to.have.property('name'); + expect(res.body.result[0]).to.have.property('usernames').and.to.be.an('array'); + expect(res.body.result[0]).to.have.property('ts'); + }) + .end(done); + }); it('should return an error when send invalid query', (done) => { request.get(api('directory')) .set(credentials) @@ -191,6 +217,26 @@ describe('miscellaneous', function() { }) .end(done); }); + it('should return an error when have more than one sort parameter', (done) => { + request.get(api('directory')) + .set(credentials) + .query({ + query: JSON.stringify({ + text: testChannel.name, + type: 'channels' + }), + sort: JSON.stringify(({ + name: 1, + test: 1 + })) + }) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + }) + .end(done); + }); }); describe('[/spotlight]', () => { let user;