diff --git a/packages/rocketchat-api/server/v1/rooms.js b/packages/rocketchat-api/server/v1/rooms.js index 3dd8eebc4d9c..b4bda08164b6 100644 --- a/packages/rocketchat-api/server/v1/rooms.js +++ b/packages/rocketchat-api/server/v1/rooms.js @@ -1,5 +1,28 @@ import Busboy from 'busboy'; +function findRoomByIdOrName({ params, checkedArchived = true}) { + if ((!params.roomId || !params.roomId.trim()) && (!params.roomName || !params.roomName.trim())) { + throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" or "roomName" is required'); + } + + const fields = { ...RocketChat.API.v1.defaultFieldsToExclude }; + + let room; + if (params.roomId) { + room = RocketChat.models.Rooms.findOneById(params.roomId, { fields }); + } else if (params.roomName) { + room = RocketChat.models.Rooms.findOneByName(params.roomName, { fields }); + } + if (!room) { + throw new Meteor.Error('error-room-not-found', 'The required "roomId" or "roomName" param provided does not match any channel'); + } + if (checkedArchived && room.archived) { + throw new Meteor.Error('error-room-archived', `The channel, ${ room.name }, is archived`); + } + + return room; +} + RocketChat.API.v1.addRoute('rooms.get', { authRequired: true }, { get() { const { updatedSince } = this.queryParams; @@ -115,3 +138,20 @@ RocketChat.API.v1.addRoute('rooms.saveNotification', { authRequired: true }, { return RocketChat.API.v1.success(); } }); + +RocketChat.API.v1.addRoute('rooms.favorite', { authRequired: true }, { + post() { + const { favorite } = this.bodyParams; + + if (!this.bodyParams.hasOwnProperty('favorite')) { + return RocketChat.API.v1.failure('The \'favorite\' param is required'); + } + + const room = findRoomByIdOrName({ params: this.bodyParams }); + + Meteor.runAsUser(this.userId, () => Meteor.call('toggleFavorite', room._id, favorite)); + + return RocketChat.API.v1.success(); + } +}); + diff --git a/server/methods/toogleFavorite.js b/server/methods/toogleFavorite.js index 402e2701f527..1fddcca302c7 100644 --- a/server/methods/toogleFavorite.js +++ b/server/methods/toogleFavorite.js @@ -9,6 +9,14 @@ Meteor.methods({ }); } + const userSubscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, Meteor.userId()); + if (!userSubscription) { + throw new Meteor.Error('error-invalid-subscription', + 'You must be part of a room to favorite it', + { method: 'toggleFavorite' } + ); + } + return RocketChat.models.Subscriptions.setFavoriteByRoomIdAndUserId(rid, Meteor.userId(), f); } }); diff --git a/tests/end-to-end/api/09-rooms.js b/tests/end-to-end/api/09-rooms.js index 4a619f77cff1..7eb2434bc83a 100644 --- a/tests/end-to-end/api/09-rooms.js +++ b/tests/end-to-end/api/09-rooms.js @@ -71,4 +71,88 @@ describe('[Rooms]', function() { .end(done); }); }); + + describe('/rooms.favorite', () => { + let testChannel; + const testChannelName = `channel.test.${ Date.now() }`; + it('create an channel', (done) => { + request.post(api('channels.create')) + .set(credentials) + .send({ + name: testChannelName + }) + .end((err, res) => { + testChannel = res.body.channel; + done(); + }); + }); + it('should favorite the room when send favorite: true by roomName', (done) => { + request.post(api('rooms.favorite')) + .set(credentials) + .send({ + roomName: testChannelName, + favorite: true + }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + }) + .end(done); + }); + it('should unfavorite the room when send favorite: false by roomName', (done) => { + request.post(api('rooms.favorite')) + .set(credentials) + .send({ + roomName: testChannelName, + favorite: false + }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + }) + .end(done); + }); + it('should favorite the room when send favorite: true by roomId', (done) => { + request.post(api('rooms.favorite')) + .set(credentials) + .send({ + roomId: testChannel._id, + favorite: true + }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + }) + .end(done); + }); + + it('should unfavorite room when send favorite: false by roomId', (done) => { + request.post(api('rooms.favorite')) + .set(credentials) + .send({ + roomId: testChannel._id, + favorite: false + }) + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + }) + .end(done); + }); + + it('should return an error when send an invalid room', (done) => { + request.post(api('rooms.favorite')) + .set(credentials) + .send({ + roomId: 'foo', + favorite: false + }) + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error'); + }) + .end(done); + }); + }); });