From b7e617672dd00d685a9b94439f1b1b53476e570b Mon Sep 17 00:00:00 2001 From: Marcos Defendi Date: Tue, 22 Oct 2019 12:09:08 -0300 Subject: [PATCH 1/2] Replace livechat:visitorInfo publication by REST --- .../client/collections/LivechatVisitor.js | 3 - .../client/views/app/tabbar/visitorEdit.js | 9 ++- .../client/views/app/tabbar/visitorInfo.js | 11 ++-- app/livechat/imports/server/rest/visitors.js | 16 +++++ app/livechat/server/api.js | 1 + app/livechat/server/api/lib/visitors.js | 17 ++++++ .../server/publications/visitorInfo.js | 1 + app/models/server/raw/LivechatVisitors.js | 5 ++ app/models/server/raw/index.js | 3 + tests/end-to-end/api/livechat/visitors.js | 59 +++++++++++++++++++ 10 files changed, 114 insertions(+), 11 deletions(-) delete mode 100644 app/livechat/client/collections/LivechatVisitor.js create mode 100644 app/livechat/imports/server/rest/visitors.js create mode 100644 app/livechat/server/api/lib/visitors.js create mode 100644 app/models/server/raw/LivechatVisitors.js create mode 100644 tests/end-to-end/api/livechat/visitors.js diff --git a/app/livechat/client/collections/LivechatVisitor.js b/app/livechat/client/collections/LivechatVisitor.js deleted file mode 100644 index 006885bacf1a2..0000000000000 --- a/app/livechat/client/collections/LivechatVisitor.js +++ /dev/null @@ -1,3 +0,0 @@ -import { Mongo } from 'meteor/mongo'; - -export const LivechatVisitor = new Mongo.Collection('rocketchat_livechat_visitor'); diff --git a/app/livechat/client/views/app/tabbar/visitorEdit.js b/app/livechat/client/views/app/tabbar/visitorEdit.js index a10a32f58d3e3..31a3ca5d9a62c 100644 --- a/app/livechat/client/views/app/tabbar/visitorEdit.js +++ b/app/livechat/client/views/app/tabbar/visitorEdit.js @@ -5,7 +5,6 @@ import toastr from 'toastr'; import { t } from '../../../../../utils'; import { hasRole } from '../../../../../authorization'; -import { LivechatVisitor } from '../../../collections/LivechatVisitor'; import { LivechatDepartmentAgents } from '../../../collections/LivechatDepartmentAgents'; import './visitorEdit.html'; import { APIClient } from '../../../../../utils/client'; @@ -80,8 +79,12 @@ Template.visitorEdit.onCreated(function() { this.agentDepartments = new ReactiveVar([]); this.availableUserTags = new ReactiveVar([]); - this.autorun(() => { - this.visitor.set(LivechatVisitor.findOne({ _id: Template.currentData().visitorId })); + this.autorun(async () => { + const { visitorId } = Template.currentData(); + if (visitorId) { + const { visitor } = await APIClient.v1.get(`livechat/visitorInfo?visitorId=${ visitorId }`); + this.visitor.set(visitor); + } }); const rid = Template.currentData().roomId; diff --git a/app/livechat/client/views/app/tabbar/visitorInfo.js b/app/livechat/client/views/app/tabbar/visitorInfo.js index c51c8558debd8..31b33e0f28e90 100644 --- a/app/livechat/client/views/app/tabbar/visitorInfo.js +++ b/app/livechat/client/views/app/tabbar/visitorInfo.js @@ -14,7 +14,6 @@ import { Subscriptions } from '../../../../../models'; import { settings } from '../../../../../settings'; import { t, handleError, roomTypes } from '../../../../../utils'; import { hasRole, hasAllPermission, hasAtLeastOnePermission } from '../../../../../authorization'; -import { LivechatVisitor } from '../../../collections/LivechatVisitor'; import './visitorInfo.html'; import { APIClient } from '../../../../../utils/client'; @@ -313,8 +312,6 @@ Template.visitorInfo.onCreated(function() { loadRoomData(rid); } }); - - this.subscribe('livechat:visitorInfo', { rid }); } this.autorun(async () => { @@ -324,7 +321,11 @@ Template.visitorInfo.onCreated(function() { } }); - this.autorun(() => { - this.user.set(LivechatVisitor.findOne({ _id: this.visitorId.get() })); + this.autorun(async () => { + const visitorId = this.visitorId.get(); + if (visitorId) { + const { visitor } = await APIClient.v1.get(`livechat/visitorInfo?visitorId=${ visitorId }`); + this.user.set(visitor); + } }); }); diff --git a/app/livechat/imports/server/rest/visitors.js b/app/livechat/imports/server/rest/visitors.js new file mode 100644 index 0000000000000..628eae0b5e683 --- /dev/null +++ b/app/livechat/imports/server/rest/visitors.js @@ -0,0 +1,16 @@ +import { check } from 'meteor/check'; + +import { API } from '../../../../api'; +import { findVisitorInfo } from '../../../server/api/lib/visitors'; + +API.v1.addRoute('livechat/visitorInfo', { authRequired: true }, { + get() { + check(this.queryParams, { + visitorId: String, + }); + + const visitor = Promise.await(findVisitorInfo({ userId: this.userId, visitorId: this.queryParams.visitorId })); + + return API.v1.success(visitor); + }, +}); diff --git a/app/livechat/server/api.js b/app/livechat/server/api.js index 7dd933380371c..99bafa087856f 100644 --- a/app/livechat/server/api.js +++ b/app/livechat/server/api.js @@ -8,3 +8,4 @@ import '../imports/server/rest/rooms.js'; import '../imports/server/rest/appearance.js'; import '../imports/server/rest/triggers.js'; import '../imports/server/rest/integrations.js'; +import '../imports/server/rest/visitors.js'; diff --git a/app/livechat/server/api/lib/visitors.js b/app/livechat/server/api/lib/visitors.js new file mode 100644 index 0000000000000..f72351f99934c --- /dev/null +++ b/app/livechat/server/api/lib/visitors.js @@ -0,0 +1,17 @@ +import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; +import { LivechatVisitors } from '../../../../models/server/raw'; + +export async function findVisitorInfo({ userId, visitorId }) { + if (!await hasPermissionAsync(userId, 'view-l-room')) { + throw new Error('error-not-authorized'); + } + + const visitor = await LivechatVisitors.findOneById(visitorId); + if (!visitor) { + throw new Error('visitor-not-found'); + } + + return { + visitor, + }; +} diff --git a/app/livechat/server/publications/visitorInfo.js b/app/livechat/server/publications/visitorInfo.js index 6cca207b9964c..372541a382019 100644 --- a/app/livechat/server/publications/visitorInfo.js +++ b/app/livechat/server/publications/visitorInfo.js @@ -3,6 +3,7 @@ import { Meteor } from 'meteor/meteor'; import { hasPermission } from '../../../authorization'; import { LivechatRooms, LivechatVisitors } from '../../../models'; +console.warn('The publication "livechat:visitorInfo" is deprecated and will be removed after version v3.0.0'); Meteor.publish('livechat:visitorInfo', function({ rid: roomId }) { if (!this.userId) { return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:visitorInfo' })); diff --git a/app/models/server/raw/LivechatVisitors.js b/app/models/server/raw/LivechatVisitors.js new file mode 100644 index 0000000000000..2ba38dbbe782a --- /dev/null +++ b/app/models/server/raw/LivechatVisitors.js @@ -0,0 +1,5 @@ +import { BaseRaw } from './BaseRaw'; + +export class LivechatVisitorsRaw extends BaseRaw { + +} diff --git a/app/models/server/raw/index.js b/app/models/server/raw/index.js index f4f953714620d..d12ed55f0add3 100644 --- a/app/models/server/raw/index.js +++ b/app/models/server/raw/index.js @@ -20,6 +20,8 @@ import LivechatRoomsModel from '../models/LivechatRooms'; import { LivechatRoomsRaw } from './LivechatRooms'; import MessagesModel from '../models/Messages'; import { MessagesRaw } from './Messages'; +import LivechatVisitorsModel from '../models/LivechatVisitors'; +import { LivechatVisitorsRaw } from './LivechatVisitors'; export const Permissions = new PermissionsRaw(PermissionsModel.model.rawCollection()); export const Roles = new RolesRaw(RolesModel.model.rawCollection()); @@ -32,3 +34,4 @@ export const LivechatDepartment = new LivechatDepartmentRaw(LivechatDepartmentMo export const LivechatDepartmentAgents = new LivechatDepartmentAgentsRaw(LivechatDepartmentAgentsModel.model.rawCollection()); export const LivechatRooms = new LivechatRoomsRaw(LivechatRoomsModel.model.rawCollection()); export const Messages = new MessagesRaw(MessagesModel.model.rawCollection()); +export const LivechatVisitors = new LivechatVisitorsRaw(LivechatVisitorsModel.model.rawCollection()); diff --git a/tests/end-to-end/api/livechat/visitors.js b/tests/end-to-end/api/livechat/visitors.js new file mode 100644 index 0000000000000..86d2e5af1ae2e --- /dev/null +++ b/tests/end-to-end/api/livechat/visitors.js @@ -0,0 +1,59 @@ +import { getCredentials, api, request, credentials } from '../../../data/api-data.js'; +import { updatePermission, updateSetting } from '../../../data/permissions.helper'; +import { createVisitor } from '../../../data/livechat/rooms.js'; + +describe('LIVECHAT - visitors', function() { + this.retries(0); + let visitor; + + before((done) => getCredentials(done)); + + before((done) => { + updateSetting('Livechat_enabled', true) + .then(() => createVisitor()) + .then((createdVisitor) => { + visitor = createdVisitor; + done(); + }); + }); + + describe('livechat/visitorInfo', () => { + it('should return an "unauthorized error" when the user does not have the necessary permission', (done) => { + updatePermission('view-l-room', []).then(() => { + request.get(api('livechat/visitorInfo?visitorId=invalid')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body.error).to.be.equal('error-not-authorized'); + }) + .end(done); + }); + }); + it('should return an "visitor not found error" when the visitor doe snot exists', (done) => { + updatePermission('view-l-room', ['admin']).then(() => { + request.get(api('livechat/visitorInfo?visitorId=invalid')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body.error).to.be.equal('visitor-not-found'); + }) + .end(done); + }); + }); + it('should return the visitor info', (done) => { + request.get(api(`livechat/visitorInfo?visitorId=${ visitor._id }`)) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body.visitor._id).to.be.equal(visitor._id); + }) + .end(done); + }); + }); +}); From 314ae45c9a5aa483ef34f591b51b551931bfa64c Mon Sep 17 00:00:00 2001 From: Marcos Defendi Date: Tue, 22 Oct 2019 12:20:22 -0300 Subject: [PATCH 2/2] Rename endpoint --- app/livechat/client/views/app/tabbar/visitorEdit.js | 2 +- app/livechat/client/views/app/tabbar/visitorInfo.js | 2 +- app/livechat/imports/server/rest/visitors.js | 2 +- tests/end-to-end/api/livechat/visitors.js | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/livechat/client/views/app/tabbar/visitorEdit.js b/app/livechat/client/views/app/tabbar/visitorEdit.js index 31a3ca5d9a62c..a115fefe8ac0a 100644 --- a/app/livechat/client/views/app/tabbar/visitorEdit.js +++ b/app/livechat/client/views/app/tabbar/visitorEdit.js @@ -82,7 +82,7 @@ Template.visitorEdit.onCreated(function() { this.autorun(async () => { const { visitorId } = Template.currentData(); if (visitorId) { - const { visitor } = await APIClient.v1.get(`livechat/visitorInfo?visitorId=${ visitorId }`); + const { visitor } = await APIClient.v1.get(`livechat/visitors.info?visitorId=${ visitorId }`); this.visitor.set(visitor); } }); diff --git a/app/livechat/client/views/app/tabbar/visitorInfo.js b/app/livechat/client/views/app/tabbar/visitorInfo.js index 31b33e0f28e90..8c484e1da3656 100644 --- a/app/livechat/client/views/app/tabbar/visitorInfo.js +++ b/app/livechat/client/views/app/tabbar/visitorInfo.js @@ -324,7 +324,7 @@ Template.visitorInfo.onCreated(function() { this.autorun(async () => { const visitorId = this.visitorId.get(); if (visitorId) { - const { visitor } = await APIClient.v1.get(`livechat/visitorInfo?visitorId=${ visitorId }`); + const { visitor } = await APIClient.v1.get(`livechat/visitors.info?visitorId=${ visitorId }`); this.user.set(visitor); } }); diff --git a/app/livechat/imports/server/rest/visitors.js b/app/livechat/imports/server/rest/visitors.js index 628eae0b5e683..6df472bb20c5a 100644 --- a/app/livechat/imports/server/rest/visitors.js +++ b/app/livechat/imports/server/rest/visitors.js @@ -3,7 +3,7 @@ import { check } from 'meteor/check'; import { API } from '../../../../api'; import { findVisitorInfo } from '../../../server/api/lib/visitors'; -API.v1.addRoute('livechat/visitorInfo', { authRequired: true }, { +API.v1.addRoute('livechat/visitors.info', { authRequired: true }, { get() { check(this.queryParams, { visitorId: String, diff --git a/tests/end-to-end/api/livechat/visitors.js b/tests/end-to-end/api/livechat/visitors.js index 86d2e5af1ae2e..e0af003223d7b 100644 --- a/tests/end-to-end/api/livechat/visitors.js +++ b/tests/end-to-end/api/livechat/visitors.js @@ -17,10 +17,10 @@ describe('LIVECHAT - visitors', function() { }); }); - describe('livechat/visitorInfo', () => { + describe('livechat/visitors.info', () => { it('should return an "unauthorized error" when the user does not have the necessary permission', (done) => { updatePermission('view-l-room', []).then(() => { - request.get(api('livechat/visitorInfo?visitorId=invalid')) + request.get(api('livechat/visitors.info?visitorId=invalid')) .set(credentials) .expect('Content-Type', 'application/json') .expect(400) @@ -33,7 +33,7 @@ describe('LIVECHAT - visitors', function() { }); it('should return an "visitor not found error" when the visitor doe snot exists', (done) => { updatePermission('view-l-room', ['admin']).then(() => { - request.get(api('livechat/visitorInfo?visitorId=invalid')) + request.get(api('livechat/visitors.info?visitorId=invalid')) .set(credentials) .expect('Content-Type', 'application/json') .expect(400) @@ -45,7 +45,7 @@ describe('LIVECHAT - visitors', function() { }); }); it('should return the visitor info', (done) => { - request.get(api(`livechat/visitorInfo?visitorId=${ visitor._id }`)) + request.get(api(`livechat/visitors.info?visitorId=${ visitor._id }`)) .set(credentials) .expect('Content-Type', 'application/json') .expect(200)