Do not use users collection for visitors

pull/9135/head
Diego Sampaio 8 years ago
parent 214a7e2386
commit 9caf0cddbf
No known key found for this signature in database
GPG Key ID: E060152B30502562
  1. 1
      packages/rocketchat-lib/package.js
  2. 86
      packages/rocketchat-lib/server/functions/loadMessageHistory.js
  3. 5
      packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
  4. 4
      packages/rocketchat-livechat/app/client/lib/CustomFields.js
  5. 1
      packages/rocketchat-livechat/app/client/lib/LivechatVideoCall.js
  6. 6
      packages/rocketchat-livechat/app/client/lib/_livechat.js
  7. 15
      packages/rocketchat-livechat/app/client/lib/chatMessages.js
  8. 3
      packages/rocketchat-livechat/app/client/lib/commands.js
  9. 12
      packages/rocketchat-livechat/app/client/lib/fromApp/Notifications.js
  10. 5
      packages/rocketchat-livechat/app/client/lib/fromApp/RoomHistoryManager.js
  11. 2
      packages/rocketchat-livechat/app/client/lib/hooks.js
  12. 4
      packages/rocketchat-livechat/app/client/lib/msgTyping.js
  13. 4
      packages/rocketchat-livechat/app/client/lib/triggers.js
  14. 4
      packages/rocketchat-livechat/app/client/methods/sendMessageExternal.js
  15. 2
      packages/rocketchat-livechat/app/client/routes/router.js
  16. 13
      packages/rocketchat-livechat/app/client/startup/visitor.js
  17. 1
      packages/rocketchat-livechat/app/client/views/avatar.js
  18. 3
      packages/rocketchat-livechat/app/client/views/livechatWindow.js
  19. 4
      packages/rocketchat-livechat/app/client/views/message.js
  20. 12
      packages/rocketchat-livechat/app/client/views/messages.js
  21. 1
      packages/rocketchat-livechat/app/client/views/options.js
  22. 9
      packages/rocketchat-livechat/app/client/views/register.js
  23. 2
      packages/rocketchat-livechat/app/client/views/survey.js
  24. 1
      packages/rocketchat-livechat/app/client/views/switchDepartment.js
  25. 33
      packages/rocketchat-livechat/app/imports/client/visitor.js
  26. 8
      packages/rocketchat-livechat/imports/server/rest/sms.js
  27. 1
      packages/rocketchat-livechat/package.js
  28. 85
      packages/rocketchat-livechat/server/lib/Livechat.js
  29. 9
      packages/rocketchat-livechat/server/methods/getAgentData.js
  30. 13
      packages/rocketchat-livechat/server/methods/loadHistory.js
  31. 38
      packages/rocketchat-livechat/server/methods/loginByToken.js
  32. 10
      packages/rocketchat-livechat/server/methods/registerGuest.js
  33. 5
      packages/rocketchat-livechat/server/methods/saveSurveyFeedback.js
  34. 31
      packages/rocketchat-livechat/server/methods/sendMessageLivechat.js
  35. 2
      packages/rocketchat-livechat/server/methods/sendTranscript.js
  36. 4
      packages/rocketchat-livechat/server/methods/setCustomField.js
  37. 148
      packages/rocketchat-livechat/server/models/LivechatVisitors.js
  38. 139
      packages/rocketchat-livechat/server/models/Users.js
  39. 8
      packages/rocketchat-livechat/server/rest/sms.js
  40. 4
      packages/rocketchat-livechat/server/sendMessageBySMS.js
  41. 85
      server/methods/loadHistory.js
  42. 32
      server/stream/messages.js

@ -78,6 +78,7 @@ Package.onUse(function(api) {
api.addFiles('server/functions/deleteUser.js', 'server');
api.addFiles('server/functions/getFullUserData.js', 'server');
api.addFiles('server/functions/getRoomByNameOrIdWithOptionToJoin.js', 'server');
api.addFiles('server/functions/loadMessageHistory.js', 'server');
api.addFiles('server/functions/removeUserFromRoom.js', 'server');
api.addFiles('server/functions/saveUser.js', 'server');
api.addFiles('server/functions/saveCustomFields.js', 'server');

@ -0,0 +1,86 @@
const hideMessagesOfType = [];
RocketChat.settings.get(/Message_HideType_.+/, function(key, value) {
const type = key.replace('Message_HideType_', '');
const types = type === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [type];
return types.forEach((type) => {
const index = hideMessagesOfType.indexOf(type);
if (value === true && index === -1) {
return hideMessagesOfType.push(type);
}
if (index > -1) {
return hideMessagesOfType.splice(index, 1);
}
});
});
RocketChat.loadMessageHistory = function loadMessageHistory({ userId, rid, end, limit = 20, ls }) {
const options = {
sort: {
ts: -1
},
limit
};
if (!RocketChat.settings.get('Message_ShowEditedStatus')) {
options.fields = {
editedAt: 0
};
}
let records;
if (end != null) {
records = RocketChat.models.Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(rid, end, hideMessagesOfType, options).fetch();
} else {
records = RocketChat.models.Messages.findVisibleByRoomIdNotContainingTypes(rid, hideMessagesOfType, options).fetch();
}
const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true;
const messages = records.map((message) => {
message.starred = _.findWhere(message.starred, {
_id: userId
});
if (message.u && message.u._id && UI_Use_Real_Name) {
const user = RocketChat.models.Users.findOneById(message.u._id);
message.u.name = user && user.name;
}
if (message.mentions && message.mentions.length && UI_Use_Real_Name) {
message.mentions.forEach((mention) => {
const user = RocketChat.models.Users.findOneById(mention._id);
mention.name = user && user.name;
});
}
return message;
});
let unreadNotLoaded = 0;
let firstUnread;
if (ls != null) {
const firstMessage = messages[messages.length - 1];
if ((firstMessage != null ? firstMessage.ts : undefined) > ls) {
delete options.limit;
const unreadMessages = RocketChat.models.Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(rid, ls, firstMessage.ts, hideMessagesOfType, {
limit: 1,
sort: {
ts: 1
}
});
firstUnread = unreadMessages.fetch()[0];
unreadNotLoaded = unreadMessages.count();
}
}
return {
messages,
firstUnread,
unreadNotLoaded
};
};

@ -96,6 +96,11 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
const user = RocketChat.models.Users.findOneById(message.u._id);
// @TODO maybe a livechat visitor
if (!user) {
return message;
}
/*
Increment unread couter if direct messages
*/

@ -1,3 +1,5 @@
import visitor from '../../imports/client/visitor';
this.CustomFields = (function() {
let queue = {};
let initiated = false;
@ -13,7 +15,7 @@ this.CustomFields = (function() {
const init = function() {
Tracker.autorun(function() {
if (Meteor.userId()) {
if (visitor.getId()) {
initiated = true;
Object.keys(queue).forEach((key) => {
setCustomField.call(this, queue[key].token, key, queue[key].value, queue[key].overwrite);

@ -1,4 +1,5 @@
/* globals LivechatVideoCall, cordova, JitsiMeetExternalAPI */
import visitor from '../../imports/client/visitor';
LivechatVideoCall = new (class LivechatVideoCall {
constructor() {

@ -1,3 +1,5 @@
import visitor from '../../imports/client/visitor';
this.Livechat = new (class Livechat {
constructor() {
this._online = new ReactiveVar(null);
@ -30,12 +32,12 @@ this.Livechat = new (class Livechat {
this.stream = new Meteor.Streamer('livechat-room');
Tracker.autorun(() => {
if (this._room.get() && Meteor.userId()) {
if (this._room.get() && visitor.getId()) {
RoomHistoryManager.getMoreIfIsEmpty(this._room.get());
visitor.subscribeToRoom(this._room.get());
visitor.setRoom(this._room.get());
Meteor.call('livechat:getAgentData', this._room.get(), (error, result) => {
Meteor.call('livechat:getAgentData', { roomId: this._room.get(), token: visitor.getToken() }, (error, result) => {
if (!error) {
this._agent.set(result);
}

@ -1,5 +1,6 @@
/* globals MsgTyping, showError, Livechat */
import toastr from 'toastr';
import visitor from '../../imports/client/visitor';
this.ChatMessages = class ChatMessages {
init(node) {
@ -61,7 +62,7 @@ this.ChatMessages = class ChatMessages {
}
this.clearEditing();
const id = element.getAttribute('id');
const message = ChatMessage.findOne({ _id: id, 'u._id': Meteor.userId() });
const message = ChatMessage.findOne({ _id: id, 'u._id': visitor.getId() });
this.input.value = message.msg;
this.editing.element = element;
this.editing.index = index || this.getEditingIndex(element);
@ -125,7 +126,7 @@ this.ChatMessages = class ChatMessages {
});
};
if (!Meteor.userId()) {
if (!visitor.getId()) {
const guest = {
token: visitor.getToken()
};
@ -139,13 +140,8 @@ this.ChatMessages = class ChatMessages {
return showError(error.reason);
}
Meteor.loginWithToken(result.token, (error) => {
if (error) {
return showError(error.reason);
}
sendMessage();
});
visitor.setId(result._id);
sendMessage();
});
} else {
sendMessage();
@ -194,6 +190,7 @@ this.ChatMessages = class ChatMessages {
const re = new RegExp(value, 'i');
// @TODO verify if used
const user = Meteor.users.findOne({ username: re }, { fields: { username: 1 } });
if (user) {
input.value = input.value.replace(value, `@${ user.username } `);

@ -1,4 +1,6 @@
/* globals LivechatVideoCall, Livechat */
import visitor from '../../imports/client/visitor';
// Functions to call on messages of type 'command'
this.Commands = {
survey() {
@ -13,6 +15,7 @@ this.Commands = {
promptTranscript() {
if (Livechat.transcript) {
// @TODO get visitor email
const user = Meteor.user();
const email = user.visitorEmails && user.visitorEmails.length > 0 ? user.visitorEmails[0].address : '';

@ -1,12 +1,14 @@
import visitor from '../../../imports/client/visitor';
this.Notifications = new class {
constructor() {
this.logged = Meteor.userId() !== null;
this.logged = visitor.getId() !== null;
this.loginCb = [];
Tracker.autorun(() => {
if (Meteor.userId() !== null && this.logged === false) {
if (visitor.getId() !== null && this.logged === false) {
this.loginCb.forEach(cb => cb());
}
return this.logged = Meteor.userId() !== null;
return this.logged = visitor.getId() !== null;
});
this.debug = false;
this.streamAll = new Meteor.Streamer('notify-all');
@ -61,7 +63,7 @@ this.Notifications = new class {
return this.streamRoom.on(`${ room }/${ eventName }`, callback);
}
onUser(eventName, callback) {
return this.streamUser.on(`${ Meteor.userId() }/${ eventName }`, callback);
return this.streamUser.on(`${ visitor.getId() }/${ eventName }`, callback);
}
unAll(callback) {
return this.streamAll.removeListener('notify', callback);
@ -73,7 +75,7 @@ this.Notifications = new class {
return this.streamRoom.removeListener(`${ room }/${ eventName }`, callback);
}
unUser(callback) {
return this.streamUser.removeListener(Meteor.userId(), callback);
return this.streamUser.removeListener(visitor.getId(), callback);
}
};

@ -1,4 +1,7 @@
/* globals readMessage UserRoles RoomRoles*/
import visitor from '../../../imports/client/visitor';
export const RoomHistoryManager = new class {
constructor() {
this.defaultLimit = 50;
@ -40,7 +43,7 @@ export const RoomHistoryManager = new class {
ts = new Date();
}
Meteor.call('loadHistory', rid, ts, limit, undefined, (err, result) => {
Meteor.call('livechat:loadHistory', { token: visitor.getToken(), rid, ts, limit }, (err, result) => {
if (err) {
return;
}

@ -1,4 +1,6 @@
/* globals CustomFields, Livechat */
import visitor from '../../imports/client/visitor';
const api = {
pageVisited(info) {
if (info.change === 'url') {

@ -1,4 +1,6 @@
/* globals Notifications */
import visitor from '../../imports/client/visitor';
export const MsgTyping = (function() {
const timeout = 15000;
const timeouts = {};
@ -34,7 +36,7 @@ export const MsgTyping = (function() {
};
Tracker.autorun(() => {
if (visitor.getRoom() && Meteor.userId()) {
if (visitor.getRoom() && visitor.getId()) {
addStream(visitor.getRoom());
}
});

@ -1,3 +1,5 @@
import visitor from '../../imports/client/visitor';
this.Triggers = (function() {
let triggers = [];
let initiated = false;
@ -5,7 +7,7 @@ this.Triggers = (function() {
let enabled = true;
const fire = function(trigger) {
if (!enabled || Meteor.userId()) {
if (!enabled || visitor.getId()) {
return;
}
trigger.actions.forEach(function(action) {

@ -1,3 +1,5 @@
import visitor from '../../imports/client/visitor';
Meteor.methods({
sendMessageLivechat(message) {
if (s.trim(message.msg) !== '') {
@ -10,7 +12,7 @@ Meteor.methods({
const user = Meteor.user();
message.u = {
_id: Meteor.userId(),
_id: visitor.getId(),
username: user && user.username || 'visitor'
};

@ -1,3 +1,5 @@
import visitor from '../../imports/client/visitor';
BlazeLayout.setRoot('body');
FlowRouter.route('/livechat', {

@ -1,21 +1,18 @@
this.visitorId = new ReactiveVar(null);
import visitor from '../../imports/client/visitor';
Meteor.startup(() => {
if (!localStorage.getItem('rocketChatLivechat')) {
localStorage.setItem('rocketChatLivechat', Random.id());
} else {
Tracker.autorun(c => {
if (!Meteor.userId() && visitor.getToken()) {
if (!visitor.getId() && visitor.getToken()) {
Meteor.call('livechat:loginByToken', visitor.getToken(), (err, result) => {
if (result && result.token) {
Meteor.loginWithToken(result.token, () => {
c.stop();
});
if (result && result._id) {
visitor.setId(result._id);
c.stop();
}
});
}
});
}
this.visitorId.set(localStorage.getItem('rocketChatLivechat'));
});

@ -6,6 +6,7 @@ Template.avatar.helpers({
username = user && user.username;
}
// @TODO get visitor username
const currentUser = Meteor.users.findOne(Meteor.userId(), { fields: { username: 1 }});
if (!username || (currentUser && currentUser.username === username)) {
return;

@ -1,4 +1,5 @@
/* globals Department, Livechat, LivechatVideoCall */
import visitor from '../../imports/client/visitor';
Template.livechatWindow.helpers({
title() {
@ -17,7 +18,7 @@ Template.livechatWindow.helpers({
return Session.get('sound');
},
showRegisterForm() {
if (Session.get('triggered') || Meteor.userId()) {
if (Session.get('triggered') || visitor.getId()) {
return false;
}
return Livechat.registrationForm;

@ -1,9 +1,11 @@
/* globals Livechat, t, tr, livechatAutolinker */
import moment from 'moment';
import visitor from '../../imports/client/visitor';
Template.message.helpers({
own() {
if (this.u && this.u._id === Meteor.userId()) {
console.log(this.u._id, visitor.getId());
if (this.u && this.u._id === visitor.getId()) {
return 'own';
}
},

@ -1,4 +1,5 @@
/* globals Livechat, LivechatVideoCall, MsgTyping */
import visitor from '../../imports/client/visitor';
Template.messages.helpers({
messages() {
@ -114,19 +115,14 @@ Template.messages.events({
'click .video-button'(event) {
event.preventDefault();
if (!Meteor.userId()) {
if (!visitor.getId()) {
Meteor.call('livechat:registerGuest', { token: visitor.getToken() }, (error, result) => {
if (error) {
return console.log(error.reason);
}
Meteor.loginWithToken(result.token, (error) => {
if (error) {
return console.log(error.reason);
}
LivechatVideoCall.request();
});
visitor.setId(result._id);
LivechatVideoCall.request();
});
} else {
LivechatVideoCall.request();

@ -1,4 +1,5 @@
/* globals Department, Livechat */
import visitor from '../../imports/client/visitor';
Template.options.helpers({
showDepartments() {

@ -1,4 +1,5 @@
/* globals Department, Livechat, LivechatVideoCall */
import visitor from '../../imports/client/visitor';
Template.register.helpers({
error() {
@ -56,12 +57,8 @@ Template.register.events({
return instance.showError(error.reason);
}
parentCall('callback', ['pre-chat-form-submit', _.omit(guest, 'token')]);
Meteor.loginWithToken(result.token, function(error) {
if (error) {
return instance.showError(error.reason);
}
start();
});
visitor.setId(result._id);
start();
});
}
},

@ -1,3 +1,5 @@
import visitor from '../../imports/client/visitor';
Template.survey.events({
'click button.skip'(e, instance) {
instance.$('#survey').remove();

@ -1,4 +1,5 @@
/* globals Department, Livechat */
import visitor from '../../imports/client/visitor';
Template.switchDepartment.helpers({
departments() {

@ -1,13 +1,12 @@
/* globals Commands */
const msgStream = new Meteor.Streamer('room-messages');
this.visitor = new class {
constructor() {
this.token = new ReactiveVar(null);
this.room = new ReactiveVar(null);
this.roomToSubscribe = new ReactiveVar(null);
this.roomSubscribed = null;
}
export default {
id: new ReactiveVar(null),
token: new ReactiveVar(null),
room: new ReactiveVar(null),
roomToSubscribe: new ReactiveVar(null),
roomSubscribed: null,
register() {
if (!localStorage.getItem('visitorToken')) {
@ -15,15 +14,23 @@ this.visitor = new class {
}
this.token.set(localStorage.getItem('visitorToken'));
}
},
getId() {
return this.id.get();
},
setId(id) {
return this.id.set(id);
},
getToken() {
return this.token.get();
}
},
setRoom(rid) {
this.room.set(rid);
}
},
getRoom(createOnEmpty = false) {
let roomId = this.room.get();
@ -33,11 +40,11 @@ this.visitor = new class {
}
return roomId;
}
},
isSubscribed(roomId) {
return this.roomSubscribed === roomId;
}
},
subscribeToRoom(roomId) {
if (this.roomSubscribed && this.roomSubscribed === roomId) {
@ -57,7 +64,7 @@ this.visitor = new class {
}
// notification sound
if (Session.equals('sound', true) && msg.u._id !== Meteor.userId()) {
if (Session.equals('sound', true) && msg.u._id !== this.getId()) {
$('#chatAudioNotification')[0].play();
}
}

@ -1,10 +1,12 @@
import LivechatVisitors from '../../../server/models/LivechatVisitors';
RocketChat.API.v1.addRoute('livechat/sms-incoming/:service', {
post() {
const SMSService = RocketChat.SMS.getService(this.urlParams.service);
const sms = SMSService.parse(this.bodyParams);
let visitor = RocketChat.models.Users.findOneVisitorByPhone(sms.from);
let visitor = LivechatVisitors.findOneVisitorByPhone(sms.from);
const sendMessage = {
message: {
@ -18,14 +20,14 @@ RocketChat.API.v1.addRoute('livechat/sms-incoming/:service', {
};
if (visitor) {
const rooms = RocketChat.models.Rooms.findOpenByVisitorToken(visitor.profile.token).fetch();
const rooms = RocketChat.models.Rooms.findOpenByVisitorToken(visitor.token).fetch();
if (rooms && rooms.length > 0) {
sendMessage.message.rid = rooms[0]._id;
} else {
sendMessage.message.rid = Random.id();
}
sendMessage.message.token = visitor.profile.token;
sendMessage.message.token = visitor.token;
} else {
sendMessage.message.rid = Random.id();
sendMessage.message.token = Random.id();

@ -138,6 +138,7 @@ Package.onUse(function(api) {
api.addFiles('server/methods/getCustomFields.js', 'server');
api.addFiles('server/methods/getAgentData.js', 'server');
api.addFiles('server/methods/getInitialData.js', 'server');
api.addFiles('server/methods/loadHistory.js', 'server');
api.addFiles('server/methods/loginByToken.js', 'server');
api.addFiles('server/methods/pageVisited.js', 'server');
api.addFiles('server/methods/registerGuest.js', 'server');

@ -1,5 +1,6 @@
/* globals HTTP */
import UAParser from 'ua-parser-js';
import LivechatVisitors from '../models/LivechatVisitors';
RocketChat.Livechat = {
historyMonitorType: 'url',
@ -58,11 +59,12 @@ RocketChat.Livechat = {
room = RocketChat.QueueMethods[routingMethod](guest, message, roomInfo);
newRoom = true;
} else {
room = Meteor.call('canAccessRoom', message.rid, guest._id);
}
if (!room) {
throw new Meteor.Error('cannot-acess-room');
console.log('getRoom.room ->', room);
console.log('getRoom.guest ->', guest);
if (room.v.token !== guest.token) {
throw new Meteor.Error('cannot-access-room');
}
return { room, newRoom };
@ -76,53 +78,49 @@ RocketChat.Livechat = {
// return messages;
return _.extend(RocketChat.sendMessage(guest, message, room), { newRoom, showConnecting: this.showConnecting() });
},
registerGuest({ token, name, email, department, phone, loginToken, username } = {}) {
registerGuest({ token, name, email, department, phone, username } = {}) {
check(token, String);
let userId;
const updateUser = {
$set: {
profile: {
guest: true,
token
}
token
}
};
const user = RocketChat.models.Users.getVisitorByToken(token, { fields: { _id: 1 } });
const user = LivechatVisitors.getVisitorByToken(token, { fields: { _id: 1 } });
if (user) {
userId = user._id;
if (loginToken) {
if (!updateUser.$addToSet) {
updateUser.$addToSet = {};
}
updateUser.$addToSet['services.resume.loginTokens'] = loginToken;
}
// if (loginToken) {
// if (!updateUser.$addToSet) {
// updateUser.$addToSet = {};
// }
// updateUser.$addToSet['services.resume.loginTokens'] = loginToken;
// }
} else {
if (!username) {
username = RocketChat.models.Users.getNextVisitorUsername();
username = LivechatVisitors.getNextVisitorUsername();
}
let existingUser = null;
if (s.trim(email) !== '' && (existingUser = RocketChat.models.Users.findOneGuestByEmailAddress(email))) {
if (loginToken) {
if (!updateUser.$addToSet) {
updateUser.$addToSet = {};
}
updateUser.$addToSet['services.resume.loginTokens'] = loginToken;
}
if (s.trim(email) !== '' && (existingUser = LivechatVisitors.findOneGuestByEmailAddress(email))) {
// if (loginToken) {
// if (!updateUser.$addToSet) {
// updateUser.$addToSet = {};
// }
// updateUser.$addToSet['services.resume.loginTokens'] = loginToken;
// }
userId = existingUser._id;
} else {
const userData = {
username,
globalRoles: ['livechat-guest'],
department,
type: 'visitor',
joinDefaultChannels: false
// globalRoles: ['livechat-guest'],
department
// type: 'visitor',
// joinDefaultChannels: false
};
if (this.connection) {
@ -131,15 +129,16 @@ RocketChat.Livechat = {
userData.host = this.connection.httpHeaders.host;
}
userId = Accounts.insertUserDoc({}, userData);
// userId = Accounts.insertUserDoc({}, userData);
if (loginToken) {
updateUser.$set.services = {
resume: {
loginTokens: [ loginToken ]
}
};
}
// if (loginToken) {
// updateUser.$set.services = {
// resume: {
// loginTokens: [ loginToken ]
// }
// };
// }
userId = LivechatVisitors.insert(userData);
}
}
@ -156,10 +155,10 @@ RocketChat.Livechat = {
}
if (name) {
RocketChat._setRealName(userId, name);
updateUser.$set.name = name;
}
Meteor.users.update(userId, updateUser);
LivechatVisitors.updateById(userId, updateUser);
return userId;
},
@ -172,7 +171,7 @@ RocketChat.Livechat = {
}
};
const user = RocketChat.models.Users.getVisitorByToken(token, { fields: { _id: 1 } });
const user = LivechatVisitors.getVisitorByToken(token, { fields: { _id: 1 } });
if (user) {
return Meteor.users.update(user._id, updateUser);
}
@ -190,7 +189,7 @@ RocketChat.Livechat = {
if (phone) {
updateData.phone = phone;
}
const ret = RocketChat.models.Users.saveGuestById(_id, updateData);
const ret = LivechatVisitors.saveGuestById(_id, updateData);
Meteor.defer(() => {
RocketChat.callbacks.run('livechat.saveGuest', updateData);
@ -534,7 +533,9 @@ RocketChat.Livechat = {
};
RocketChat.Livechat.stream = new Meteor.Streamer('livechat-room');
RocketChat.Livechat.stream.allowRead('logged');
// @TODO create a allow function
RocketChat.Livechat.stream.allowRead('all');
RocketChat.settings.get('Livechat_history_monitor_type', (key, value) => {
RocketChat.Livechat.historyMonitorType = value;

@ -1,12 +1,15 @@
import LivechatVisitors from '../models/LivechatVisitors';
Meteor.methods({
'livechat:getAgentData'(roomId) {
'livechat:getAgentData'({ roomId, token }) {
check(roomId, String);
check(token, String);
const room = RocketChat.models.Rooms.findOneById(roomId);
const user = Meteor.user();
const visitor = LivechatVisitors.getVisitorByToken(token);
// allow to only user to send transcripts from their own chats
if (!room || room.t !== 'l' || !room.v || !user.profile || room.v.token !== user.profile.token) {
if (!room || room.t !== 'l' || !room.v || room.v.token !== visitor.token) {
throw new Meteor.Error('error-invalid-room', 'Invalid room');
}

@ -0,0 +1,13 @@
import LivechatVisitors from '../models/LivechatVisitors';
Meteor.methods({
'livechat:loadHistory'({ token, rid, end, limit = 20, ls}) {
const visitor = LivechatVisitors.getVisitorByToken(token, { fields: { _id: 1 } });
if (!visitor) {
return;
}
return RocketChat.loadMessageHistory({ userId: visitor._id, rid, end, limit, ls });
}
});

@ -1,28 +1,34 @@
import LivechatVisitors from '../models/LivechatVisitors';
Meteor.methods({
'livechat:loginByToken'(token) {
const user = RocketChat.models.Users.getVisitorByToken(token, { fields: { _id: 1 } });
const user = LivechatVisitors.getVisitorByToken(token, { fields: { _id: 1 } });
if (!user) {
return;
}
const stampedToken = Accounts._generateStampedLoginToken();
const hashStampedToken = Accounts._hashStampedToken(stampedToken);
const updateUser = {
$set: {
services: {
resume: {
loginTokens: [ hashStampedToken ]
}
}
}
return {
_id: user._id
};
Meteor.users.update(user._id, updateUser);
// const stampedToken = Accounts._generateStampedLoginToken();
// const hashStampedToken = Accounts._hashStampedToken(stampedToken);
return {
token: stampedToken.token
};
// const updateUser = {
// $set: {
// services: {
// resume: {
// loginTokens: [ hashStampedToken ]
// }
// }
// }
// };
// Meteor.users.update(user._id, updateUser);
// return {
// token: stampedToken.token
// };
}
});

@ -1,22 +1,20 @@
Meteor.methods({
'livechat:registerGuest'({ token, name, email, department } = {}) {
const stampedToken = Accounts._generateStampedLoginToken();
const hashStampedToken = Accounts._hashStampedToken(stampedToken);
// const stampedToken = Accounts._generateStampedLoginToken();
// const hashStampedToken = Accounts._hashStampedToken(stampedToken);
const userId = RocketChat.Livechat.registerGuest.call(this, {
token,
name,
email,
department,
loginToken: hashStampedToken
department
});
// update visited page history to not expire
RocketChat.models.LivechatPageVisited.keepHistoryForToken(token);
return {
userId,
token: stampedToken.token
userId
};
}
});

@ -1,4 +1,5 @@
/* eslint new-cap: [2, {"capIsNewExceptions": ["Match.ObjectIncluding"]}] */
import LivechatVisitors from '../models/LivechatVisitors';
Meteor.methods({
'livechat:saveSurveyFeedback'(visitorToken, visitorRoom, formData) {
@ -6,10 +7,10 @@ Meteor.methods({
check(visitorRoom, String);
check(formData, [Match.ObjectIncluding({ name: String, value: String })]);
const visitor = RocketChat.models.Users.getVisitorByToken(visitorToken);
const visitor = LivechatVisitors.getVisitorByToken(visitorToken);
const room = RocketChat.models.Rooms.findOneById(visitorRoom);
if (visitor !== undefined && room !== undefined && room.v !== undefined && visitor.profile !== undefined && room.v.token === visitor.profile.token) {
if (visitor !== undefined && room !== undefined && room.v !== undefined && room.v.token === visitor.token) {
const updateData = {};
for (const item of formData) {
if (_.contains(['satisfaction', 'agentKnowledge', 'agentResposiveness', 'agentFriendliness'], item.name) && _.contains(['1', '2', '3', '4', '5'], item.value)) {

@ -1,16 +1,35 @@
import LivechatVisitors from '../models/LivechatVisitors';
Meteor.methods({
sendMessageLivechat(message) {
check(message.rid, String);
check(message.token, String);
sendMessageLivechat({ token, _id, rid, msg }) {
check(token, String);
check(_id, String);
check(rid, String);
check(msg, String);
const guest = Meteor.users.findOne(Meteor.userId(), {
const guest = LivechatVisitors.getVisitorByToken(token, {
fields: {
name: 1,
username: 1,
department: 1
department: 1,
token: 1
}
});
return RocketChat.Livechat.sendMessage({ guest, message });
console.log('guest ->', guest);
if (!guest) {
throw new Meteor.Error('invalid-token');
}
return RocketChat.Livechat.sendMessage({
guest,
message: {
_id,
rid,
msg,
token
}
});
}
});

@ -12,7 +12,7 @@ Meteor.methods({
const userLanguage = user.language || RocketChat.settings.get('language') || 'en';
// allow to only user to send transcripts from their own chats
if (!room || room.t !== 'l' || !room.v || !user.profile || room.v.token !== user.profile.token) {
if (!room || room.t !== 'l' || !room.v || room.v.token !== user.token) {
throw new Meteor.Error('error-invalid-room', 'Invalid room');
}

@ -1,3 +1,5 @@
import LivechatVisitors from '../models/LivechatVisitors';
Meteor.methods({
'livechat:setCustomField'(token, key, value, overwrite = true) {
const customField = RocketChat.models.LivechatCustomField.findOneById(key);
@ -6,7 +8,7 @@ Meteor.methods({
return RocketChat.models.Rooms.updateLivechatDataByToken(token, key, value, overwrite);
} else {
// Save in user
return RocketChat.models.Users.updateLivechatDataByToken(token, key, value, overwrite);
return LivechatVisitors.updateLivechatDataByToken(token, key, value, overwrite);
}
}

@ -0,0 +1,148 @@
class LivechatVisitors extends RocketChat.models._Base {
constructor() {
super('livechat_visitor');
}
/**
* Gets visitor by token
* @param {string} token - Visitor token
*/
getVisitorByToken(token, options) {
const query = {
token
};
return this.findOne(query, options);
}
/**
* Gets visitor by token
* @param {string} token - Visitor token
*/
findVisitorByToken(token) {
const query = {
token
};
return this.find(query);
}
updateLivechatDataByToken(token, key, value, overwrite = true) {
const query = {
token
};
if (!overwrite) {
const user = this.findOne(query, { fields: { livechatData: 1 } });
if (user.livechatData && typeof user.livechatData[key] !== 'undefined') {
return true;
}
}
const update = {
$set: {
[`livechatData.${ key }`]: value
}
};
return this.update(query, update);
}
/**
* Find a visitor by their phone number
* @return {object} User from db
*/
findOneVisitorByPhone(phone) {
const query = {
'phone.phoneNumber': phone
};
return this.findOne(query);
}
/**
* Get the next visitor name
* @return {string} The next visitor name
*/
getNextVisitorUsername() {
const settingsRaw = RocketChat.models.Settings.model.rawCollection();
const findAndModify = Meteor.wrapAsync(settingsRaw.findAndModify, settingsRaw);
const query = {
_id: 'Livechat_guest_count'
};
const update = {
$inc: {
value: 1
}
};
const livechatCount = findAndModify(query, null, update);
return `guest-${ livechatCount.value.value + 1 }`;
}
updateById(_id, update) {
return this.update({ _id }, update);
}
saveGuestById(_id, data) {
const setData = {};
const unsetData = {};
if (data.name) {
if (!_.isEmpty(s.trim(data.name))) {
setData.name = s.trim(data.name);
} else {
unsetData.name = 1;
}
}
if (data.email) {
if (!_.isEmpty(s.trim(data.email))) {
setData.visitorEmails = [
{ address: s.trim(data.email) }
];
} else {
unsetData.visitorEmails = 1;
}
}
if (data.phone) {
if (!_.isEmpty(s.trim(data.phone))) {
setData.phone = [
{ phoneNumber: s.trim(data.phone) }
];
} else {
unsetData.phone = 1;
}
}
const update = {};
if (!_.isEmpty(setData)) {
update.$set = setData;
}
if (!_.isEmpty(unsetData)) {
update.$unset = unsetData;
}
if (_.isEmpty(update)) {
return true;
}
return this.update({ _id }, update);
}
findOneGuestByEmailAddress(emailAddress) {
const query = {
'visitorEmails.address': new RegExp(`^${ s.escapeRegExp(emailAddress) }$`, 'i')
};
return this.findOne(query);
}
}
export default new LivechatVisitors();

@ -102,32 +102,6 @@ RocketChat.models.Users.getNextAgent = function() {
}
};
/**
* Gets visitor by token
* @param {string} token - Visitor token
*/
RocketChat.models.Users.getVisitorByToken = function(token, options) {
const query = {
'profile.guest': true,
'profile.token': token
};
return this.findOne(query, options);
};
/**
* Gets visitor by token
* @param {string} token - Visitor token
*/
RocketChat.models.Users.findVisitorByToken = function(token) {
const query = {
'profile.guest': true,
'profile.token': token
};
return this.find(query);
};
/**
* Change user's livechat status
* @param {string} token - Visitor token
@ -166,119 +140,6 @@ RocketChat.models.Users.openOffice = function() {
});
};
RocketChat.models.Users.updateLivechatDataByToken = function(token, key, value, overwrite = true) {
const query = {
'profile.token': token
};
if (!overwrite) {
const user = this.findOne(query, { fields: { livechatData: 1 } });
if (user.livechatData && typeof user.livechatData[key] !== 'undefined') {
return true;
}
}
const update = {
$set: {
[`livechatData.${ key }`]: value
}
};
return this.update(query, update);
};
/**
* Find a visitor by their phone number
* @return {object} User from db
*/
RocketChat.models.Users.findOneVisitorByPhone = function(phone) {
const query = {
'phone.phoneNumber': phone
};
return this.findOne(query);
};
/**
* Get the next visitor name
* @return {string} The next visitor name
*/
RocketChat.models.Users.getNextVisitorUsername = function() {
const settingsRaw = RocketChat.models.Settings.model.rawCollection();
const findAndModify = Meteor.wrapAsync(settingsRaw.findAndModify, settingsRaw);
const query = {
_id: 'Livechat_guest_count'
};
const update = {
$inc: {
value: 1
}
};
const livechatCount = findAndModify(query, null, update);
return `guest-${ livechatCount.value.value + 1 }`;
};
RocketChat.models.Users.saveGuestById = function(_id, data) {
const setData = {};
const unsetData = {};
if (data.name) {
if (!_.isEmpty(s.trim(data.name))) {
setData.name = s.trim(data.name);
} else {
unsetData.name = 1;
}
}
if (data.email) {
if (!_.isEmpty(s.trim(data.email))) {
setData.visitorEmails = [
{ address: s.trim(data.email) }
];
} else {
unsetData.visitorEmails = 1;
}
}
if (data.phone) {
if (!_.isEmpty(s.trim(data.phone))) {
setData.phone = [
{ phoneNumber: s.trim(data.phone) }
];
} else {
unsetData.phone = 1;
}
}
const update = {};
if (!_.isEmpty(setData)) {
update.$set = setData;
}
if (!_.isEmpty(unsetData)) {
update.$unset = unsetData;
}
if (_.isEmpty(update)) {
return true;
}
return this.update({ _id }, update);
};
RocketChat.models.Users.findOneGuestByEmailAddress = function(emailAddress) {
const query = {
'visitorEmails.address': new RegExp(`^${ s.escapeRegExp(emailAddress) }$`, 'i')
};
return this.findOne(query);
};
RocketChat.models.Users.getAgentInfo = function(agentId) {
const query = {
_id: agentId

@ -1,10 +1,12 @@
import LivechatVisitors from '../models/LivechatVisitors';
RocketChat.API.v1.addRoute('livechat/sms-incoming/:service', {
post() {
const SMSService = RocketChat.SMS.getService(this.urlParams.service);
const sms = SMSService.parse(this.bodyParams);
let visitor = RocketChat.models.Users.findOneVisitorByPhone(sms.from);
let visitor = LivechatVisitors.findOneVisitorByPhone(sms.from);
const sendMessage = {
message: {
@ -18,14 +20,14 @@ RocketChat.API.v1.addRoute('livechat/sms-incoming/:service', {
};
if (visitor) {
const rooms = RocketChat.models.Rooms.findOpenByVisitorToken(visitor.profile.token).fetch();
const rooms = RocketChat.models.Rooms.findOpenByVisitorToken(visitor.token).fetch();
if (rooms && rooms.length > 0) {
sendMessage.message.rid = rooms[0]._id;
} else {
sendMessage.message.rid = Random.id();
}
sendMessage.message.token = visitor.profile.token;
sendMessage.message.token = visitor.token;
} else {
sendMessage.message.rid = Random.id();
sendMessage.message.token = Random.id();

@ -1,3 +1,5 @@
import LivechatVisitors from './models/LivechatVisitors';
RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
// skips this callback if the message was edited
if (message.editedAt) {
@ -29,7 +31,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
return message;
}
const visitor = RocketChat.models.Users.getVisitorByToken(room.v.token);
const visitor = LivechatVisitors.getVisitorByToken(room.v.token);
if (!visitor || !visitor.profile || !visitor.phone || visitor.phone.length === 0) {
return message;

@ -1,22 +1,3 @@
const hideMessagesOfType = [];
RocketChat.settings.get(/Message_HideType_.+/, function(key, value) {
const type = key.replace('Message_HideType_', '');
const types = type === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [type];
return types.forEach((type) => {
const index = hideMessagesOfType.indexOf(type);
if (value === true && index === -1) {
return hideMessagesOfType.push(type);
}
if (index > -1) {
return hideMessagesOfType.splice(index, 1);
}
});
});
Meteor.methods({
loadHistory(rid, end, limit = 20, ls) {
check(rid, String);
@ -40,70 +21,6 @@ Meteor.methods({
return false;
}
const options = {
sort: {
ts: -1
},
limit
};
if (!RocketChat.settings.get('Message_ShowEditedStatus')) {
options.fields = {
editedAt: 0
};
}
let records;
if (end != null) {
records = RocketChat.models.Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(rid, end, hideMessagesOfType, options).fetch();
} else {
records = RocketChat.models.Messages.findVisibleByRoomIdNotContainingTypes(rid, hideMessagesOfType, options).fetch();
}
const UI_Use_Real_Name = RocketChat.settings.get('UI_Use_Real_Name') === true;
const messages = records.map((message) => {
message.starred = _.findWhere(message.starred, {
_id: fromId
});
if (message.u && message.u._id && UI_Use_Real_Name) {
const user = RocketChat.models.Users.findOneById(message.u._id);
message.u.name = user && user.name;
}
if (message.mentions && message.mentions.length && UI_Use_Real_Name) {
message.mentions.forEach((mention) => {
const user = RocketChat.models.Users.findOneById(mention._id);
mention.name = user && user.name;
});
}
return message;
});
let unreadNotLoaded = 0;
let firstUnread;
if (ls != null) {
const firstMessage = messages[messages.length - 1];
if ((firstMessage != null ? firstMessage.ts : undefined) > ls) {
delete options.limit;
const unreadMessages = RocketChat.models.Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(rid, ls, firstMessage.ts, hideMessagesOfType, {
limit: 1,
sort: {
ts: 1
}
});
firstUnread = unreadMessages.fetch()[0];
unreadNotLoaded = unreadMessages.count();
}
}
return {
messages,
firstUnread,
unreadNotLoaded
};
return RocketChat.loadMessageHistory({ userId: fromId, rid, end, limit, ls });
}
});

@ -3,24 +3,26 @@ this.msgStream = msgStream;
msgStream.allowWrite('none');
msgStream.allowRead(function(eventName) {
try {
const room = Meteor.call('canAccessRoom', eventName, this.userId);
msgStream.allowRead('all');
// @TODO fix livechat
// msgStream.allowRead(function(eventName) {
// try {
// const room = Meteor.call('canAccessRoom', eventName, this.userId);
if (!room) {
return false;
}
// if (!room) {
// return false;
// }
if (room.t === 'c' && !RocketChat.authz.hasPermission(this.userId, 'preview-c-room') && room.usernames.indexOf(room.username) === -1) {
return false;
}
// if (room.t === 'c' && !RocketChat.authz.hasPermission(this.userId, 'preview-c-room') && room.usernames.indexOf(room.username) === -1) {
// return false;
// }
return true;
} catch (error) {
/*error*/
return false;
}
});
// return true;
// } catch (error) {
// /*error*/
// return false;
// }
// });
msgStream.allowRead('__my_messages__', 'all');

Loading…
Cancel
Save