The Rocket.Chat desktops apps for Windows, macOS and Linux are available to download here.
The Rocket.Chat desktops apps for Windows, macOS and Linux are available to download here.
@@ -148,13 +156,15 @@
{{description}}
{{/if}}
{{/unless}}
-
+
{{#if actions}}
-
- {{#each actions}}
- {{> messageAction}}
- {{/each}}
-
+ {{#unless collapsed}}
+
+ {{#each actions}}
+ {{> messageAction}}
+ {{/each}}
+
+ {{/unless}}
{{/if}}
{{#each attachments}}
diff --git a/packages/rocketchat-message-attachments/client/messageAttachment.js b/packages/rocketchat-message-attachments/client/messageAttachment.js
index 73438fdd78e2..49081a449acf 100644
--- a/packages/rocketchat-message-attachments/client/messageAttachment.js
+++ b/packages/rocketchat-message-attachments/client/messageAttachment.js
@@ -50,8 +50,7 @@ Template.messageAttachment.helpers({
if (this.collapsed != null) {
return this.collapsed;
} else {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'collapseMediaByDefault') === true;
+ return RocketChat.getUserPreference(Meteor.userId(), 'collapseMediaByDefault') === true;
}
},
time() {
@@ -69,4 +68,11 @@ Template.messageAttachment.helpers({
isFile() {
return this.type === 'file';
},
+ isPDF() {
+ if (this.type === 'file' && this.title_link.endsWith('.pdf') && Template.parentData().file) {
+ this.fileId = Template.parentData().file._id;
+ return true;
+ }
+ return false;
+ },
});
diff --git a/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.css b/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.css
index 6377e7c943df..e4e39ed64cfc 100644
--- a/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.css
+++ b/packages/rocketchat-message-attachments/client/stylesheets/messageAttachments.css
@@ -145,6 +145,16 @@ html.rtl .attachment {
border-radius: 5px;
}
+ & .attachment-canvas {
+ display: none;
+ }
+
+ & .attachment-pdf-loading {
+ display: none;
+
+ font-size: 1.5rem;
+ }
+
& .actions-container {
margin-top: 6px;
}
diff --git a/packages/rocketchat-message-pin/package.js b/packages/rocketchat-message-pin/package.js
index 5fa6da757927..a31b1efc4851 100644
--- a/packages/rocketchat-message-pin/package.js
+++ b/packages/rocketchat-message-pin/package.js
@@ -25,6 +25,7 @@ Package.onUse(function(api) {
], 'client');
api.addFiles([
+ 'server/models/Rooms.js',
'server/settings.js',
'server/pinMessage.js',
'server/publications/pinnedMessages.js',
diff --git a/packages/rocketchat-message-pin/server/models/Rooms.js b/packages/rocketchat-message-pin/server/models/Rooms.js
new file mode 100644
index 000000000000..6cdf5e14c8be
--- /dev/null
+++ b/packages/rocketchat-message-pin/server/models/Rooms.js
@@ -0,0 +1,13 @@
+RocketChat.models.Rooms.setLastMessagePinned = function(roomId, pinnedBy, pinned, pinnedAt) {
+ const query = { _id: roomId };
+
+ const update = {
+ $set: {
+ 'lastMessage.pinned': pinned,
+ 'lastMessage.pinnedAt': pinnedAt || new Date,
+ 'lastMessage.pinnedBy': pinnedBy,
+ },
+ };
+
+ return this.update(query, update);
+};
diff --git a/packages/rocketchat-message-pin/server/pinMessage.js b/packages/rocketchat-message-pin/server/pinMessage.js
index 497662b5f0cf..2abd64bda757 100644
--- a/packages/rocketchat-message-pin/server/pinMessage.js
+++ b/packages/rocketchat-message-pin/server/pinMessage.js
@@ -50,7 +50,7 @@ Meteor.methods({
if (RocketChat.settings.get('Message_KeepHistory')) {
RocketChat.models.Messages.cloneAndSaveAsHistoryById(message._id);
}
-
+ const room = Meteor.call('canAccessRoom', message.rid, Meteor.userId());
const me = RocketChat.models.Users.findOneById(userId);
originalMessage.pinned = true;
@@ -63,6 +63,9 @@ Meteor.methods({
originalMessage = RocketChat.callbacks.run('beforeSaveMessage', originalMessage);
RocketChat.models.Messages.setPinnedByIdAndUserId(originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned);
+ if (RocketChat.isTheLastMessage(room, message)) {
+ RocketChat.models.Rooms.setLastMessagePinned(room._id, originalMessage.pinnedBy, originalMessage.pinned);
+ }
const attachments = [];
@@ -134,6 +137,10 @@ Meteor.methods({
username: me.username,
};
originalMessage = RocketChat.callbacks.run('beforeSaveMessage', originalMessage);
+ const room = Meteor.call('canAccessRoom', message.rid, Meteor.userId());
+ if (RocketChat.isTheLastMessage(room, message)) {
+ RocketChat.models.Rooms.setLastMessagePinned(room._id, originalMessage.pinnedBy, originalMessage.pinned);
+ }
return RocketChat.models.Messages.setPinnedByIdAndUserId(originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned);
},
diff --git a/packages/rocketchat-message-snippet/package.js b/packages/rocketchat-message-snippet/package.js
index e342ecca1c3a..5292dba032cb 100644
--- a/packages/rocketchat-message-snippet/package.js
+++ b/packages/rocketchat-message-snippet/package.js
@@ -28,6 +28,7 @@ Package.onUse(function(api) {
// Server
api.addFiles([
'server/startup/settings.js',
+ 'server/models/Rooms.js',
'server/methods/snippetMessage.js',
'server/requests.js',
'server/publications/snippetedMessagesByRoom.js',
diff --git a/packages/rocketchat-message-snippet/server/methods/snippetMessage.js b/packages/rocketchat-message-snippet/server/methods/snippetMessage.js
index bf4cf3156f43..ff7a6e0b476f 100644
--- a/packages/rocketchat-message-snippet/server/methods/snippetMessage.js
+++ b/packages/rocketchat-message-snippet/server/methods/snippetMessage.js
@@ -36,6 +36,10 @@ Meteor.methods({
// Create the SnippetMessage
RocketChat.models.Messages.setSnippetedByIdAndUserId(message, filename, message.snippetedBy,
message.snippeted, Date.now, filename);
+ if (RocketChat.isTheLastMessage(room, message)) {
+ RocketChat.models.Rooms.setLastMessageSnippeted(room._id, message, filename, message.snippetedBy,
+ message.snippeted, Date.now, filename);
+ }
RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser(
'message_snippeted', message.rid, '', me, { snippetId: message._id, snippetName: filename });
diff --git a/packages/rocketchat-message-snippet/server/models/Rooms.js b/packages/rocketchat-message-snippet/server/models/Rooms.js
new file mode 100644
index 000000000000..907c911531df
--- /dev/null
+++ b/packages/rocketchat-message-snippet/server/models/Rooms.js
@@ -0,0 +1,17 @@
+RocketChat.models.Rooms.setLastMessageSnippeted = function(roomId, message, snippetName, snippetedBy, snippeted, snippetedAt) {
+ const query = { _id: roomId };
+
+ const msg = `\`\`\`${ message.msg }\`\`\``;
+
+ const update = {
+ $set: {
+ 'lastMessage.msg': msg,
+ 'lastMessage.snippeted': snippeted,
+ 'lastMessage.snippetedAt': snippetedAt || new Date,
+ 'lastMessage.snippetedBy': snippetedBy,
+ 'lastMessage.snippetName': snippetName,
+ },
+ };
+
+ return this.update(query, update);
+};
diff --git a/packages/rocketchat-message-star/client/actionButton.js b/packages/rocketchat-message-star/client/actionButton.js
index 5ed9dcb4ab34..52b2fd201492 100644
--- a/packages/rocketchat-message-star/client/actionButton.js
+++ b/packages/rocketchat-message-star/client/actionButton.js
@@ -1,4 +1,3 @@
-import _ from 'underscore';
import toastr from 'toastr';
Meteor.startup(function() {
@@ -21,7 +20,7 @@ Meteor.startup(function() {
return false;
}
- return !_.findWhere(message.starred, { _id: Meteor.userId() });
+ return !message.starred || !message.starred.find((star) => star._id === Meteor.userId());
},
order: 10,
group: 'menu',
@@ -46,7 +45,7 @@ Meteor.startup(function() {
return false;
}
- return Boolean(_.findWhere(message.starred, { _id: Meteor.userId() }));
+ return message.starred && message.starred.find((star) => star._id === Meteor.userId());
},
order: 10,
group: 'menu',
diff --git a/packages/rocketchat-message-star/package.js b/packages/rocketchat-message-star/package.js
index edcc39d9d13f..1a8f1bbe5b78 100644
--- a/packages/rocketchat-message-star/package.js
+++ b/packages/rocketchat-message-star/package.js
@@ -25,6 +25,7 @@ Package.onUse(function(api) {
], 'client');
api.addFiles([
+ 'server/models/Rooms.js',
'server/settings.js',
'server/starMessage.js',
'server/publications/starredMessages.js',
diff --git a/packages/rocketchat-message-star/server/models/Rooms.js b/packages/rocketchat-message-star/server/models/Rooms.js
new file mode 100644
index 000000000000..bd457526d6f7
--- /dev/null
+++ b/packages/rocketchat-message-star/server/models/Rooms.js
@@ -0,0 +1,21 @@
+RocketChat.models.Rooms.updateLastMessageStar = function(roomId, userId, starred) {
+ let update;
+ const query = { _id: roomId };
+
+ if (starred) {
+ update = {
+ $addToSet: {
+ 'lastMessage.starred': { _id: userId },
+ },
+ };
+ } else {
+ update = {
+ $pull: {
+ 'lastMessage.starred': { _id: userId },
+ },
+ };
+ }
+
+ return this.update(query, update);
+};
+
diff --git a/packages/rocketchat-message-star/server/starMessage.js b/packages/rocketchat-message-star/server/starMessage.js
index 1bacf3673cb9..1b64fadb9b5c 100644
--- a/packages/rocketchat-message-star/server/starMessage.js
+++ b/packages/rocketchat-message-star/server/starMessage.js
@@ -17,6 +17,10 @@ Meteor.methods({
if (!subscription) {
return false;
}
+ const room = Meteor.call('canAccessRoom', message.rid, Meteor.userId());
+ if (RocketChat.isTheLastMessage(room, message)) {
+ RocketChat.models.Rooms.updateLastMessageStar(room._id, Meteor.userId(), message.starred);
+ }
return RocketChat.models.Messages.updateUserStarById(message._id, Meteor.userId(), message.starred);
},
diff --git a/packages/rocketchat-oembed/client/oembedAudioWidget.js b/packages/rocketchat-oembed/client/oembedAudioWidget.js
index 9ac57ba09fa6..9b4b997cba09 100644
--- a/packages/rocketchat-oembed/client/oembedAudioWidget.js
+++ b/packages/rocketchat-oembed/client/oembedAudioWidget.js
@@ -3,8 +3,7 @@ Template.oembedAudioWidget.helpers({
if (this.collapsed) {
return this.collapsed;
} else {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'collapseMediaByDefault') === true;
+ return RocketChat.getUserPreference(Meteor.userId(), 'collapseMediaByDefault') === true;
}
},
});
diff --git a/packages/rocketchat-oembed/client/oembedFrameWidget.js b/packages/rocketchat-oembed/client/oembedFrameWidget.js
index a1c1b5535bfb..59eabfe5d26e 100644
--- a/packages/rocketchat-oembed/client/oembedFrameWidget.js
+++ b/packages/rocketchat-oembed/client/oembedFrameWidget.js
@@ -3,8 +3,7 @@ Template.oembedFrameWidget.helpers({
if (this.collapsed) {
return this.collapsed;
} else {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'collapseMediaByDefault') === true;
+ return RocketChat.getUserPreference(Meteor.userId(), 'collapseMediaByDefault') === true;
}
},
});
diff --git a/packages/rocketchat-oembed/client/oembedImageWidget.js b/packages/rocketchat-oembed/client/oembedImageWidget.js
index 7b2046b51529..a9e6f994c6a1 100644
--- a/packages/rocketchat-oembed/client/oembedImageWidget.js
+++ b/packages/rocketchat-oembed/client/oembedImageWidget.js
@@ -1,11 +1,9 @@
Template.oembedImageWidget.helpers({
loadImage() {
- const user = Meteor.user();
-
- if (RocketChat.getUserPreference(user, 'autoImageLoad') === false && this.downloadImages == null) {
+ if (RocketChat.getUserPreference(Meteor.userId(), 'autoImageLoad') === false && this.downloadImages == null) {
return false;
}
- if (Meteor.Device.isPhone() && RocketChat.getUserPreference(user, 'saveMobileBandwidth') && this.downloadImages == null) {
+ if (Meteor.Device.isPhone() && RocketChat.getUserPreference(Meteor.userId(), 'saveMobileBandwidth') && this.downloadImages == null) {
return false;
}
return true;
@@ -14,8 +12,7 @@ Template.oembedImageWidget.helpers({
if (this.collapsed != null) {
return this.collapsed;
} else {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'collapseMediaByDefault') === true;
+ return RocketChat.getUserPreference(Meteor.userId(), 'collapseMediaByDefault') === true;
}
},
});
diff --git a/packages/rocketchat-oembed/client/oembedUrlWidget.js b/packages/rocketchat-oembed/client/oembedUrlWidget.js
index a8d2180c8042..c8abef9ef4c3 100644
--- a/packages/rocketchat-oembed/client/oembedUrlWidget.js
+++ b/packages/rocketchat-oembed/client/oembedUrlWidget.js
@@ -62,8 +62,7 @@ Template.oembedUrlWidget.helpers({
if (this.collapsed != null) {
return this.collapsed;
} else {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'collapseMediaByDefault') === true;
+ return RocketChat.getUserPreference(Meteor.userId(), 'collapseMediaByDefault') === true;
}
},
});
diff --git a/packages/rocketchat-oembed/client/oembedVideoWidget.js b/packages/rocketchat-oembed/client/oembedVideoWidget.js
index c54b6a6671c2..456b99b0dd05 100644
--- a/packages/rocketchat-oembed/client/oembedVideoWidget.js
+++ b/packages/rocketchat-oembed/client/oembedVideoWidget.js
@@ -27,8 +27,7 @@ Template.oembedVideoWidget.helpers({
if (this.collapsed) {
return this.collapsed;
} else {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'collapseMediaByDefault') === true;
+ return RocketChat.getUserPreference(Meteor.userId(), 'collapseMediaByDefault') === true;
}
},
diff --git a/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js b/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js
index d27db69d362b..a91b18f5db3b 100644
--- a/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js
+++ b/packages/rocketchat-push-notifications/client/views/pushNotificationsFlexTab.js
@@ -73,21 +73,21 @@ Template.pushNotificationsFlexTab.helpers({
}
},
defaultAudioNotification() {
- let preference = RocketChat.getUserPreference(Meteor.user(), 'audioNotifications');
+ let preference = RocketChat.getUserPreference(Meteor.userId(), 'audioNotifications');
if (preference === 'default') {
preference = RocketChat.settings.get('Accounts_Default_User_Preferences_audioNotifications');
}
return notificationLabels[preference];
},
defaultDesktopNotification() {
- let preference = RocketChat.getUserPreference(Meteor.user(), 'desktopNotifications');
+ let preference = RocketChat.getUserPreference(Meteor.userId(), 'desktopNotifications');
if (preference === 'default') {
preference = RocketChat.settings.get('Accounts_Default_User_Preferences_desktopNotifications');
}
return notificationLabels[preference];
},
defaultMobileNotification() {
- let preference = RocketChat.getUserPreference(Meteor.user(), 'mobileNotifications');
+ let preference = RocketChat.getUserPreference(Meteor.userId(), 'mobileNotifications');
if (preference === 'default') {
preference = RocketChat.settings.get('Accounts_Default_User_Preferences_mobileNotifications');
}
@@ -190,7 +190,7 @@ Template.pushNotificationsFlexTab.events({
'click [data-play]'(e) {
e.preventDefault();
- const user = Meteor.user();
+ const user = Meteor.userId();
let value = Template.instance().form.audioNotificationValue.get();
if (value === '0') {
@@ -340,7 +340,7 @@ Template.pushNotificationsPopover.helpers({
return Template.instance().data.options;
},
defaultDesktopNotification() {
- let preference = RocketChat.getUserPreference(Meteor.user(), 'desktopNotifications');
+ let preference = RocketChat.getUserPreference(Meteor.userId(), 'desktopNotifications');
if (preference === 'default') {
preference = RocketChat.settings.get('Accounts_Default_User_Preferences_desktopNotifications');
}
diff --git a/packages/rocketchat-reactions/package.js b/packages/rocketchat-reactions/package.js
index 78e23d96093b..03ae0e50d4dd 100644
--- a/packages/rocketchat-reactions/package.js
+++ b/packages/rocketchat-reactions/package.js
@@ -16,6 +16,7 @@ Package.onUse(function(api) {
api.addFiles('client/init.js', 'client');
api.addFiles('server/models/Messages.js');
+ api.addFiles('server/models/Rooms.js');
api.addFiles('client/methods/setReaction.js', 'client');
api.addFiles('setReaction.js', 'server');
diff --git a/packages/rocketchat-reactions/server/models/Rooms.js b/packages/rocketchat-reactions/server/models/Rooms.js
new file mode 100644
index 000000000000..26e16f8b7628
--- /dev/null
+++ b/packages/rocketchat-reactions/server/models/Rooms.js
@@ -0,0 +1,7 @@
+RocketChat.models.Rooms.setReactionsInLastMessage = function(roomId, lastMessage) {
+ return this.update({ _id: roomId }, { $set: { lastMessage } });
+};
+
+RocketChat.models.Rooms.unsetReactionsInLastMessage = function(roomId) {
+ return this.update({ _id: roomId }, { $unset: { lastMessage: { reactions: 1 } } });
+};
diff --git a/packages/rocketchat-reactions/setReaction.js b/packages/rocketchat-reactions/setReaction.js
index 807ecdcb336a..f51303b7d572 100644
--- a/packages/rocketchat-reactions/setReaction.js
+++ b/packages/rocketchat-reactions/setReaction.js
@@ -61,9 +61,15 @@ Meteor.methods({
if (_.isEmpty(message.reactions)) {
delete message.reactions;
+ if (RocketChat.isTheLastMessage(room, message)) {
+ RocketChat.models.Rooms.unsetReactionsInLastMessage(room._id);
+ }
RocketChat.models.Messages.unsetReactions(messageId);
RocketChat.callbacks.run('unsetReaction', messageId, reaction);
} else {
+ if (RocketChat.isTheLastMessage(room, message)) {
+ RocketChat.models.Rooms.setReactionsInLastMessage(room._id, message);
+ }
RocketChat.models.Messages.setReactions(messageId, message.reactions);
RocketChat.callbacks.run('setReaction', messageId, reaction);
}
@@ -77,7 +83,9 @@ Meteor.methods({
};
}
message.reactions[reaction].usernames.push(user.username);
-
+ if (RocketChat.isTheLastMessage(room, message)) {
+ RocketChat.models.Rooms.setReactionsInLastMessage(room._id, message);
+ }
RocketChat.models.Messages.setReactions(messageId, message.reactions);
RocketChat.callbacks.run('setReaction', messageId, reaction);
}
diff --git a/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css b/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css
index 0e0981fe07d9..9b6776363d9c 100644
--- a/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css
+++ b/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-header.css
@@ -129,3 +129,20 @@
}
}
}
+
+@media (min-width: 1372px) { /* 1440px -68px (eletron menu) */
+ .sidebar {
+ flex: 0 0 20%;
+
+ width: 20%;
+ max-width: 20%;
+
+ &__toolbar {
+ justify-content: flex-end;
+
+ &-button {
+ margin: 0 6px;
+ }
+ }
+ }
+}
diff --git a/packages/rocketchat-ui-account/client/accountPreferences.js b/packages/rocketchat-ui-account/client/accountPreferences.js
index 56f9b169cb2b..b25787debce0 100644
--- a/packages/rocketchat-ui-account/client/accountPreferences.js
+++ b/packages/rocketchat-ui-account/client/accountPreferences.js
@@ -18,7 +18,7 @@ function checkedSelected(property, value, defaultValue = undefined) {
if (defaultValue && defaultValue.hash) {
defaultValue = undefined;
}
- return RocketChat.getUserPreference(Meteor.user(), property, defaultValue) === value;
+ return RocketChat.getUserPreference(Meteor.userId(), property, defaultValue) === value;
}
Template.accountPreferences.helpers({
@@ -26,13 +26,13 @@ Template.accountPreferences.helpers({
return (RocketChat.CustomSounds && RocketChat.CustomSounds.getList && RocketChat.CustomSounds.getList()) || [];
},
newMessageNotification() {
- return RocketChat.getUserPreference(Meteor.user(), 'newMessageNotification');
+ return RocketChat.getUserPreference(Meteor.userId(), 'newMessageNotification');
},
newRoomNotification() {
- return RocketChat.getUserPreference(Meteor.user(), 'newRoomNotification');
+ return RocketChat.getUserPreference(Meteor.userId(), 'newRoomNotification');
},
muteFocusedConversations() {
- return RocketChat.getUserPreference(Meteor.user(), 'muteFocusedConversations');
+ return RocketChat.getUserPreference(Meteor.userId(), 'muteFocusedConversations');
},
languages() {
const languages = TAPi18n.getLanguages();
@@ -60,7 +60,7 @@ Template.accountPreferences.helpers({
return checkedSelected(property, value, defaultValue);
},
highlights() {
- const userHighlights = RocketChat.getUserPreference(Meteor.user(), 'highlights');
+ const userHighlights = RocketChat.getUserPreference(Meteor.userId(), 'highlights');
return userHighlights ? userHighlights.join(',\n') : undefined;
},
desktopNotificationEnabled() {
@@ -70,14 +70,14 @@ Template.accountPreferences.helpers({
return KonchatNotification.notificationStatus.get() === 'denied' || (window.Notification && Notification.permission === 'denied');
},
desktopNotificationDuration() {
- const userPref = RocketChat.getUserPreference(Meteor.user(), 'desktopNotificationDuration', 'undefined');
+ const userPref = RocketChat.getUserPreference(Meteor.userId(), 'desktopNotificationDuration', 'undefined');
return userPref !== 'undefined' ? userPref : undefined;
},
defaultDesktopNotificationDuration() {
return RocketChat.settings.get('Accounts_Default_User_Preferences_desktopNotificationDuration');
},
idleTimeLimit() {
- return RocketChat.getUserPreference(Meteor.user(), 'idleTimeLimit');
+ return RocketChat.getUserPreference(Meteor.userId(), 'idleTimeLimit');
},
defaultIdleTimeLimit() {
return RocketChat.settings.get('Accounts_Default_User_Preferences_idleTimeLimit');
@@ -98,15 +98,14 @@ Template.accountPreferences.helpers({
return RocketChat.settings.get('UserData_EnableDownload') !== false;
},
notificationsSoundVolume() {
- return RocketChat.getUserPreference(Meteor.user(), 'notificationsSoundVolume');
+ return RocketChat.getUserPreference(Meteor.userId(), 'notificationsSoundVolume');
},
dontAskAgainList() {
- return RocketChat.getUserPreference(Meteor.user(), 'dontAskAgainList');
+ return RocketChat.getUserPreference(Meteor.userId(), 'dontAskAgainList');
},
});
Template.accountPreferences.onCreated(function() {
- const user = Meteor.user();
const settingsTemplate = this.parentTemplate(3);
if (settingsTemplate.child == null) {
@@ -115,7 +114,7 @@ Template.accountPreferences.onCreated(function() {
settingsTemplate.child.push(this);
- this.useEmojis = new ReactiveVar(RocketChat.getUserPreference(user, 'useEmojis'));
+ this.useEmojis = new ReactiveVar(RocketChat.getUserPreference(Meteor.userId(), 'useEmojis'));
let instance = this;
@@ -173,7 +172,7 @@ Template.accountPreferences.onCreated(function() {
}
// if highlights changed we need page reload
- const highlights = RocketChat.getUserPreference(Meteor.user(), 'highlights');
+ const highlights = RocketChat.getUserPreference(Meteor.userId(), 'highlights');
if (highlights && highlights.join('\n') !== data.highlights.join('\n')) {
reload = true;
}
diff --git a/packages/rocketchat-ui-account/client/avatar/prompt.js b/packages/rocketchat-ui-account/client/avatar/prompt.js
index 108a56bf74f9..5722aa7d18f3 100644
--- a/packages/rocketchat-ui-account/client/avatar/prompt.js
+++ b/packages/rocketchat-ui-account/client/avatar/prompt.js
@@ -65,7 +65,7 @@ Template.avatarPrompt.events({
if (s.trim($('#avatarurl').val())) {
Meteor.call('setAvatarFromService', $('#avatarurl').val(), '', this.service, function(err) {
if (err) {
- if (err.details.timeToReset && err.details.timeToReset) {
+ if (err.details && err.details.timeToReset) {
toastr.error(t('error-too-many-requests', {
seconds: parseInt(err.details.timeToReset / 1000),
}));
diff --git a/packages/rocketchat-ui-admin/client/admin.js b/packages/rocketchat-ui-admin/client/admin.js
index e274d97375dd..7a2ceeb60d1a 100644
--- a/packages/rocketchat-ui-admin/client/admin.js
+++ b/packages/rocketchat-ui-admin/client/admin.js
@@ -479,7 +479,7 @@ Template.admin.events({
}
});
},
- 'click .rc-header__section-button .remove-custom-oauth'() {
+ 'click .remove-custom-oauth'() {
const name = this.section.replace('Custom OAuth: ', '');
const config = {
title: TAPi18n.__('Are_you_sure'),
diff --git a/packages/rocketchat-ui-message/client/message.js b/packages/rocketchat-ui-message/client/message.js
index 2c553832df29..8503d934ca0e 100644
--- a/packages/rocketchat-ui-message/client/message.js
+++ b/packages/rocketchat-ui-message/client/message.js
@@ -3,6 +3,39 @@ import _ from 'underscore';
import moment from 'moment';
import { DateFormat } from 'meteor/rocketchat:lib';
+async function renderPdfToCanvas(canvasId, pdfLink) {
+
+ if (navigator.userAgent.toLowerCase().indexOf('safari/') > -1) {
+ const [, version] = /Version\/([0-9]+)/.exec(navigator.userAgent) || [null, 0];
+ if (version <= 12) {
+ return;
+ }
+ }
+
+ if (!pdfLink || /\.pdf$/i.test(pdfLink)) { return; }
+ const canvas = document.getElementById(canvasId);
+ if (!canvas) { return; }
+ const pdfjsLib = await import('pdfjs-dist');
+ pdfjsLib.GlobalWorkerOptions.workerSrc = `${ Meteor.absoluteUrl() }node_modules/pdfjs-dist/build/pdf.worker.js`;
+ const loader = document.getElementById('js-loading-${canvasId}');
+ if (loader) { loader.style.display = 'block'; }
+ const pdf = await pdfjsLib.getDocument(pdfLink);
+ const page = await pdf.getPage(1);
+ const scale = 0.5;
+ const viewport = page.getViewport(scale);
+ const context = canvas.getContext('2d');
+ canvas.height = viewport.height;
+ canvas.width = viewport.width;
+ page.render({
+ canvasContext: context,
+ viewport,
+ });
+ if (loader) { loader.style.display = 'none'; }
+ canvas.style.maxWidth = '-webkit-fill-available';
+ canvas.style.maxWidth = '-moz-available';
+ canvas.style.display = 'block';
+}
+
Template.message.helpers({
encodeURI(text) {
return encodeURI(text);
@@ -26,8 +59,7 @@ Template.message.helpers({
}
},
roleTags() {
- const user = Meteor.user();
- if (!RocketChat.settings.get('UI_DisplayRoles') || RocketChat.getUserPreference(user, 'hideRoles')) {
+ if (!RocketChat.settings.get('UI_DisplayRoles') || RocketChat.getUserPreference(Meteor.userId(), 'hideRoles')) {
return [];
}
@@ -364,7 +396,10 @@ Template.message.onCreated(function() {
});
Template.message.onViewRendered = function(context) {
- return this._domrange.onAttached(function(domRange) {
+ return this._domrange.onAttached((domRange) => {
+ if (context.file && context.file.type === 'application/pdf') {
+ Meteor.defer(() => { renderPdfToCanvas(context.file._id, context.attachments[0].title_link); });
+ }
const currentNode = domRange.lastNode();
const currentDataset = currentNode.dataset;
const getPreviousSentMessage = (currentNode) => {
diff --git a/packages/rocketchat-ui-message/client/messageBox.js b/packages/rocketchat-ui-message/client/messageBox.js
index 92ea0e42864f..5c482873265e 100644
--- a/packages/rocketchat-ui-message/client/messageBox.js
+++ b/packages/rocketchat-ui-message/client/messageBox.js
@@ -267,7 +267,7 @@ Template.messageBox.helpers({
return RocketChat.Layout.isEmbedded();
},
isEmojiEnable() {
- return RocketChat.getUserPreference(Meteor.user(), 'useEmojis');
+ return RocketChat.getUserPreference(Meteor.userId(), 'useEmojis');
},
dataReply() {
return Template.instance().dataReply.get();
diff --git a/packages/rocketchat-ui-message/package.js b/packages/rocketchat-ui-message/package.js
index 805eda964bad..e2288d4e04e8 100644
--- a/packages/rocketchat-ui-message/package.js
+++ b/packages/rocketchat-ui-message/package.js
@@ -44,5 +44,7 @@ Package.onUse(function(api) {
api.addFiles('startup/messageBoxActions.js', 'client');
+ api.addAssets('../../node_modules/pdfjs-dist/build/pdf.worker.js', 'client');
+
api.export('renderMessageBody');
});
diff --git a/packages/rocketchat-ui-sidenav/client/roomList.js b/packages/rocketchat-ui-sidenav/client/roomList.js
index e6bcbd9c3780..5802b49d6a57 100644
--- a/packages/rocketchat-ui-sidenav/client/roomList.js
+++ b/packages/rocketchat-ui-sidenav/client/roomList.js
@@ -13,7 +13,16 @@ Template.roomList.helpers({
if (this.anonymous) {
return RocketChat.models.Rooms.find({ t: 'c' }, { sort: { name: 1 } });
}
- const user = Meteor.userId();
+
+ const user = RocketChat.models.Users.findOne(Meteor.userId(), {
+ fields: {
+ 'settings.preferences.sidebarSortby': 1,
+ 'settings.preferences.sidebarShowFavorites': 1,
+ 'settings.preferences.sidebarShowUnread': 1,
+ 'services.tokenpass': 1,
+ },
+ });
+
const sortBy = RocketChat.getUserPreference(user, 'sidebarSortby') || 'alphabetical';
const query = {
open: true,
diff --git a/packages/rocketchat-ui-sidenav/client/sideNav.js b/packages/rocketchat-ui-sidenav/client/sideNav.js
index 27b5a8c7a96a..62387ab0019f 100644
--- a/packages/rocketchat-ui-sidenav/client/sideNav.js
+++ b/packages/rocketchat-ui-sidenav/client/sideNav.js
@@ -42,7 +42,7 @@ Template.sideNav.helpers({
},
sidebarHideAvatar() {
- return RocketChat.getUserPreference(Meteor.user(), 'sidebarHideAvatar');
+ return RocketChat.getUserPreference(Meteor.userId(), 'sidebarHideAvatar');
},
});
diff --git a/packages/rocketchat-ui-sidenav/client/sortlist.js b/packages/rocketchat-ui-sidenav/client/sortlist.js
index 45aae8366058..2d0d9c7ede83 100644
--- a/packages/rocketchat-ui-sidenav/client/sortlist.js
+++ b/packages/rocketchat-ui-sidenav/client/sortlist.js
@@ -3,18 +3,18 @@
import { hideOldSubscriptions } from 'meteor/rocketchat:lib';
const checked = function(prop, field) {
- const user = Meteor.userId();
+ const userId = Meteor.userId();
if (prop === 'sidebarShowFavorites') {
- return RocketChat.getUserPreference(user, 'sidebarShowFavorites');
+ return RocketChat.getUserPreference(userId, 'sidebarShowFavorites');
}
if (prop === 'sidebarGroupByType') {
- return RocketChat.getUserPreference(user, 'sidebarGroupByType');
+ return RocketChat.getUserPreference(userId, 'sidebarGroupByType');
}
if (prop === 'sidebarShowUnread') {
- return RocketChat.getUserPreference(user, 'sidebarShowUnread');
+ return RocketChat.getUserPreference(userId, 'sidebarShowUnread');
}
if (prop === 'sidebarSortby') {
- return (RocketChat.getUserPreference(user, 'sidebarSortby') || 'alphabetical') === field;
+ return (RocketChat.getUserPreference(userId, 'sidebarSortby') || 'alphabetical') === field;
}
};
diff --git a/packages/rocketchat-ui/client/lib/fileUpload.js b/packages/rocketchat-ui/client/lib/fileUpload.js
index ce9ed295eda5..3a3177a803aa 100644
--- a/packages/rocketchat-ui/client/lib/fileUpload.js
+++ b/packages/rocketchat-ui/client/lib/fileUpload.js
@@ -30,7 +30,7 @@ const showUploadPreview = (file, callback) => {
const getAudioUploadPreview = (file, preview) => `\
-
`;
-const getUploadPreview = (file, preview) => {
+const getUploadPreview = async(file, preview) => {
if (file.type === 'audio') {
return getAudioUploadPreview(file, preview);
}
@@ -117,14 +117,21 @@ const getUploadPreview = (file, preview) => {
return getVideoUploadPreview(file, preview);
}
- if (file.type === 'image') {
+ const isImageFormatSupported = () => new Promise((resolve) => {
+ const element = document.createElement('img');
+ element.onload = () => resolve(true);
+ element.onerror = () => resolve(false);
+ element.src = preview;
+ });
+
+ if (file.type === 'image' && await isImageFormatSupported()) {
return getImageUploadPreview(file, preview);
}
return getGenericUploadPreview(file, preview);
};
-fileUpload = (files) => {
+fileUpload = async(files) => {
files = [].concat(files);
const roomId = Session.get('openedRoom');
@@ -155,9 +162,9 @@ fileUpload = (files) => {
return;
}
- showUploadPreview(file, (file, preview) => modal.open({
+ showUploadPreview(file, async(file, preview) => modal.open({
title: t('Upload_file_question'),
- text: getUploadPreview(file, preview),
+ text: await getUploadPreview(file, preview),
showCancelButton: true,
closeOnConfirm: false,
closeOnCancel: false,
diff --git a/packages/rocketchat-ui/client/lib/notification.js b/packages/rocketchat-ui/client/lib/notification.js
index 3686fd9b083a..3d92f6d5218d 100644
--- a/packages/rocketchat-ui/client/lib/notification.js
+++ b/packages/rocketchat-ui/client/lib/notification.js
@@ -30,8 +30,7 @@ const KonchatNotification = {
canReply: true,
});
- const user = Meteor.user();
- const notificationDuration = notification.duration - 0 || RocketChat.getUserPreference(user, 'desktopNotificationDuration') - 0;
+ const notificationDuration = notification.duration - 0 || RocketChat.getUserPreference(Meteor.userId(), 'desktopNotificationDuration') - 0;
if (notificationDuration > 0) {
setTimeout((() => n.close()), notificationDuration * 1000);
}
@@ -89,9 +88,9 @@ const KonchatNotification = {
newMessage(rid) {
if (!Session.equals(`user_${ Meteor.user().username }_status`, 'busy')) {
- const user = Meteor.user();
- const newMessageNotification = RocketChat.getUserPreference(user, 'newMessageNotification');
- const audioVolume = RocketChat.getUserPreference(user, 'notificationsSoundVolume');
+ const userId = Meteor.userId();
+ const newMessageNotification = RocketChat.getUserPreference(userId, 'newMessageNotification');
+ const audioVolume = RocketChat.getUserPreference(userId, 'notificationsSoundVolume');
const sub = ChatSubscription.findOne({ rid }, { fields: { audioNotificationValue: 1 } });
diff --git a/packages/rocketchat-ui/client/views/app/modal.js b/packages/rocketchat-ui/client/views/app/modal.js
index 22630fef4e3e..f2157cffb9d8 100644
--- a/packages/rocketchat-ui/client/views/app/modal.js
+++ b/packages/rocketchat-ui/client/views/app/modal.js
@@ -132,7 +132,7 @@ Template.rc_modal.events({
label: dontAskAgain.label,
};
- let dontAskAgainList = RocketChat.getUserPreference(Meteor.user(), 'dontAskAgainList');
+ let dontAskAgainList = RocketChat.getUserPreference(Meteor.userId(), 'dontAskAgainList');
if (dontAskAgainList) {
dontAskAgainList.push(dontAskAgainObject);
} else {
diff --git a/packages/rocketchat-ui/client/views/app/room.js b/packages/rocketchat-ui/client/views/app/room.js
index ac282e9f1c61..706bc14e4eb1 100644
--- a/packages/rocketchat-ui/client/views/app/room.js
+++ b/packages/rocketchat-ui/client/views/app/room.js
@@ -400,8 +400,7 @@ Template.room.helpers({
},
messageViewMode() {
- const user = Meteor.user();
- const viewMode = RocketChat.getUserPreference(user, 'messageViewMode');
+ const viewMode = RocketChat.getUserPreference(Meteor.userId(), 'messageViewMode');
const modes = ['', 'cozy', 'compact'];
return modes[viewMode] || modes[0];
},
@@ -411,13 +410,11 @@ Template.room.helpers({
},
hideUsername() {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'hideUsernames') ? 'hide-usernames' : undefined;
+ return RocketChat.getUserPreference(Meteor.userId(), 'hideUsernames') ? 'hide-usernames' : undefined;
},
hideAvatar() {
- const user = Meteor.user();
- return RocketChat.getUserPreference(user, 'hideAvatars') ? 'hide-avatars' : undefined;
+ return RocketChat.getUserPreference(Meteor.userId(), 'hideAvatars') ? 'hide-avatars' : undefined;
},
userCanDrop() {
@@ -495,9 +492,7 @@ Template.room.events({
},
'click .messages-container-main'() {
- const user = Meteor.user();
-
- if ((Template.instance().tabBar.getState() === 'opened') && RocketChat.getUserPreference(user, 'hideFlexTab')) {
+ if (Template.instance().tabBar.getState() === 'opened' && RocketChat.getUserPreference(Meteor.userId(), 'hideFlexTab')) {
Template.instance().tabBar.close();
}
},
@@ -641,7 +636,6 @@ Template.room.events({
},
'scroll .wrapper': _.throttle(function(e, t) {
-
lazyloadtick();
const $roomLeader = $('.room-leader');
@@ -654,10 +648,14 @@ Template.room.events({
}
lastScrollTop = e.target.scrollTop;
- if ((RoomHistoryManager.isLoading(this._id) === false && RoomHistoryManager.hasMore(this._id) === true) || RoomHistoryManager.hasMoreNext(this._id) === true) {
- if (RoomHistoryManager.hasMore(this._id) === true && e.target.scrollTop === 0) {
+ const isLoading = RoomHistoryManager.isLoading(this._id);
+ const hasMore = RoomHistoryManager.hasMore(this._id);
+ const hasMoreNext = RoomHistoryManager.hasMoreNext(this._id);
+
+ if ((isLoading === false && hasMore === true) || hasMoreNext === true) {
+ if (hasMore === true && e.target.scrollTop === 0) {
RoomHistoryManager.getMore(this._id);
- } else if (RoomHistoryManager.hasMoreNext(this._id) === true && e.target.scrollTop >= e.target.scrollHeight - e.target.clientHeight) {
+ } else if (hasMoreNext === true && Math.ceil(e.target.scrollTop) >= e.target.scrollHeight - e.target.clientHeight) {
RoomHistoryManager.getMoreNext(this._id);
}
}
diff --git a/packages/rocketchat-ui/getAvatarUrlFromUsername.js b/packages/rocketchat-ui/getAvatarUrlFromUsername.js
index d9e17c396539..66b6db3983ea 100644
--- a/packages/rocketchat-ui/getAvatarUrlFromUsername.js
+++ b/packages/rocketchat-ui/getAvatarUrlFromUsername.js
@@ -1,7 +1,7 @@
// TODO: remove global
this.getAvatarUrlFromUsername = function(username) {
const key = `avatar_random_${ username }`;
- const random = typeof Session !== 'undefined' ? Session.keys[key] : 0;
+ const random = typeof Session !== 'undefined' && typeof Session.keys[key] !== 'undefined' ? Session.keys[key] : 0;
if (username == null) {
return;
}
diff --git a/packages/rocketchat-user-data-download/server/cronProcessDownloads.js b/packages/rocketchat-user-data-download/server/cronProcessDownloads.js
index 59af82a29b82..c275d807f1ae 100644
--- a/packages/rocketchat-user-data-download/server/cronProcessDownloads.js
+++ b/packages/rocketchat-user-data-download/server/cronProcessDownloads.js
@@ -291,7 +291,7 @@ const sendEmail = function(userId) {
}
const userData = RocketChat.models.Users.findOneById(userId);
- if (!userData || userData.emails || userData.emails[0] || userData.emails[0].address) {
+ if (!userData || !userData.emails || !userData.emails[0] || !userData.emails[0].address) {
return;
}
const emailAddress = `${ userData.name } <${ userData.emails[0].address }>`;
diff --git a/server/methods/loadNextMessages.js b/server/methods/loadNextMessages.js
index 431a6b399be7..73ae17e105bd 100644
--- a/server/methods/loadNextMessages.js
+++ b/server/methods/loadNextMessages.js
@@ -1,5 +1,3 @@
-import _ from 'underscore';
-
Meteor.methods({
loadNextMessages(rid, end, limit = 20) {
check(rid, String);
@@ -37,15 +35,8 @@ Meteor.methods({
records = RocketChat.models.Messages.findVisibleByRoomId(rid, options).fetch();
}
- const messages = records.map((message) => {
- message.starred = _.findWhere(message.starred, {
- _id: fromId,
- });
- return message;
- });
-
return {
- messages,
+ messages: records.map((message) => RocketChat.composeMessageObjectWithUser(message, fromId)),
};
},
});
diff --git a/server/methods/loadSurroundingMessages.js b/server/methods/loadSurroundingMessages.js
index 97f6a39efd37..74df083c1937 100644
--- a/server/methods/loadSurroundingMessages.js
+++ b/server/methods/loadSurroundingMessages.js
@@ -1,5 +1,3 @@
-import _ from 'underscore';
-
Meteor.methods({
loadSurroundingMessages(message, limit = 50) {
check(message, Object);
@@ -42,14 +40,7 @@ Meteor.methods({
};
}
- const recordsBefore = RocketChat.models.Messages.findVisibleByRoomIdBeforeTimestamp(message.rid, message.ts, options).fetch();
-
- const messages = recordsBefore.map((message) => {
- message.starred = _.findWhere(message.starred, {
- _id: fromId,
- });
- return message;
- });
+ const messages = RocketChat.models.Messages.findVisibleByRoomIdBeforeTimestamp(message.rid, message.ts, options).fetch();
const moreBefore = messages.length === options.limit;
@@ -61,18 +52,13 @@ Meteor.methods({
options.limit = Math.floor(limit / 2);
- const recordsAfter = RocketChat.models.Messages.findVisibleByRoomIdAfterTimestamp(message.rid, message.ts, options).fetch();
- const afterMessages = recordsAfter.map((message) => {
- message.starred = _.findWhere(message.starred, {
- _id: fromId,
- });
- return message;
- });
+ const afterMessages = RocketChat.models.Messages.findVisibleByRoomIdAfterTimestamp(message.rid, message.ts, options).fetch();
const moreAfter = afterMessages.length === options.limit;
return {
- messages: messages.concat(afterMessages),
+ messages: messages.concat(afterMessages)
+ .map((message) => RocketChat.composeMessageObjectWithUser(message, fromId)),
moreBefore,
moreAfter,
};
diff --git a/server/publications/messages.js b/server/publications/messages.js
index 6efcea8fda2c..2e4f733d8f71 100644
--- a/server/publications/messages.js
+++ b/server/publications/messages.js
@@ -1,5 +1,3 @@
-import _ from 'underscore';
-
Meteor.publish('messages', function(rid/* , start*/) {
if (!this.userId) {
return this.ready();
@@ -24,16 +22,10 @@ Meteor.publish('messages', function(rid/* , start*/) {
const cursorHandle = cursor.observeChanges({
added(_id, record) {
- record.starred = _.findWhere(record.starred, {
- _id: publication.userId,
- });
- return publication.added('rocketchat_message', _id, record);
+ return publication.added('rocketchat_message', _id, RocketChat.composeMessageObjectWithUser(record, publication.userId));
},
changed(_id, record) {
- record.starred = _.findWhere(record.starred, {
- _id: publication.userId,
- });
- return publication.changed('rocketchat_message', _id, record);
+ return publication.changed('rocketchat_message', _id, RocketChat.composeMessageObjectWithUser(record, publication.userId));
},
});
diff --git a/server/startup/presence.js b/server/startup/presence.js
index 4a1b9cf46af3..6bc6029168cc 100644
--- a/server/startup/presence.js
+++ b/server/startup/presence.js
@@ -14,5 +14,9 @@ Meteor.startup(function() {
UserPresence.start();
- return UserPresenceMonitor.start();
+ const startMonitor = typeof process.env.DISABLE_PRESENCE_MONITOR === 'undefined' ||
+ !['true', 'yes'].includes(String(process.env.DISABLE_PRESENCE_MONITOR).toLowerCase());
+ if (startMonitor) {
+ UserPresenceMonitor.start();
+ }
});
diff --git a/tests/end-to-end/api/01-users.js b/tests/end-to-end/api/01-users.js
index 10b72f616769..56cd313a6134 100644
--- a/tests/end-to-end/api/01-users.js
+++ b/tests/end-to-end/api/01-users.js
@@ -14,15 +14,44 @@ import {
targetUser,
log,
} from '../../data/api-data.js';
-import { adminEmail, preferences, password } from '../../data/user.js';
+import { adminEmail, preferences, password, adminUsername } from '../../data/user.js';
import { imgURL } from '../../data/interactions.js';
import { customFieldText, clearCustomFields, setCustomFields } from '../../data/custom-fields.js';
+const updateSetting = (setting, value) => new Promise((resolve) => {
+ request.post(`/api/v1/settings/${ setting }`)
+ .set(credentials)
+ .send({ value })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(resolve);
+});
+
describe('[Users]', function() {
this.retries(0);
before((done) => getCredentials(done));
+ it('enabling E2E in server and generating keys to user...', (done) => {
+ updateSetting('E2E_Enable', true).then(() => {
+ request.post(api('e2e.setUserPublicAndPivateKeys'))
+ .set(credentials)
+ .send({
+ private_key: 'test',
+ public_key: 'test',
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ });
+
describe('[/users.create]', () => {
before((done) => clearCustomFields(done));
after((done) => clearCustomFields(done));
@@ -48,10 +77,12 @@ describe('[Users]', function() {
expect(res.body).to.have.nested.property('user.emails[0].address', apiEmail);
expect(res.body).to.have.nested.property('user.active', true);
expect(res.body).to.have.nested.property('user.name', apiUsername);
+ expect(res.body).to.not.have.nested.property('user.e2e');
expect(res.body).to.not.have.nested.property('user.customFields');
targetUser._id = res.body.user._id;
+ targetUser.username = res.body.user.username;
})
.end(done);
});
@@ -88,6 +119,7 @@ describe('[Users]', function() {
expect(res.body).to.have.nested.property('user.active', true);
expect(res.body).to.have.nested.property('user.name', username);
expect(res.body).to.have.nested.property('user.customFields.customFieldText', 'success');
+ expect(res.body).to.not.have.nested.property('user.e2e');
})
.end(done);
});
@@ -136,6 +168,45 @@ describe('[Users]', function() {
});
});
+ describe('[/users.register]', () => {
+ const email = `email@email${ Date.now() }.com`;
+ const username = `myusername${ Date.now() }`;
+ it('should register new user', (done) => {
+ request.post(api('users.register'))
+ .send({
+ email,
+ name: 'name',
+ username,
+ pass: 'test',
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.nested.property('user.username', username);
+ expect(res.body).to.have.nested.property('user.emails[0].address', email);
+ expect(res.body).to.have.nested.property('user.active', true);
+ expect(res.body).to.have.nested.property('user.name', 'name');
+ })
+ .end(done);
+ });
+ it('should return an error when trying register new user with an existing username', (done) => {
+ request.post(api('users.register'))
+ .send({
+ email,
+ name: 'name',
+ username,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(400)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', false);
+ expect(res.body).to.have.property('error').and.to.be.equal('Username is already in use');
+ })
+ .end(done);
+ });
+ });
+
describe('[/users.info]', () => {
it('should query information about a user by userId', (done) => {
request.get(api('users.info'))
@@ -151,6 +222,7 @@ describe('[Users]', function() {
expect(res.body).to.have.nested.property('user.emails[0].address', apiEmail);
expect(res.body).to.have.nested.property('user.active', true);
expect(res.body).to.have.nested.property('user.name', apiUsername);
+ expect(res.body).to.not.have.nested.property('user.e2e');
})
.end(done);
});
@@ -183,6 +255,8 @@ describe('[Users]', function() {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('count');
expect(res.body).to.have.property('total');
+ const myself = res.body.users.find((user) => user.username === adminUsername);
+ expect(myself).to.not.have.property('e2e');
})
.end(done);
});
@@ -209,10 +283,70 @@ describe('[Users]', function() {
});
describe('[/users.setAvatar]', () => {
- it.skip('should set the avatar of the auth user', (done) => {
+ let user;
+ before((done) => {
+ const username = `user.test.${ Date.now() }`;
+ const email = `${ username }@rocket.chat`;
+ request.post(api('users.create'))
+ .set(credentials)
+ .send({ email, name: username, username, password })
+ .end((err, res) => {
+ user = res.body.user;
+ done();
+ });
+ });
+
+ let userCredentials;
+ before((done) => {
+ request.post(api('login'))
+ .send({
+ user: user.username,
+ password,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ userCredentials = {};
+ userCredentials['X-Auth-Token'] = res.body.data.authToken;
+ userCredentials['X-User-Id'] = res.body.data.userId;
+ })
+ .end(done);
+ });
+ after((done) => {
+ request.post(api('users.delete')).set(credentials).send({
+ userId: user._id,
+ }).end(done);
+ user = undefined;
+ });
+
+ it('should set the avatar of the auth user by a local image', (done) => {
+ request.post(api('users.setAvatar'))
+ .set(userCredentials)
+ .attach('image', imgURL)
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('should prevent from updating someone else\'s avatar', (done) => {
+ request.post(api('users.setAvatar'))
+ .set(userCredentials)
+ .attach('image', imgURL)
+ .field({ userId: targetUser._id })
+ .expect('Content-Type', 'application/json')
+ .expect(400)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', false);
+ })
+ .end(done);
+ });
+ it('should set the avatar of another user by username and local image', (done) => {
request.post(api('users.setAvatar'))
.set(credentials)
- .attach('avatarUrl', imgURL)
+ .attach('image', imgURL)
+ .field({ username: targetUser.username })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
@@ -220,20 +354,21 @@ describe('[Users]', function() {
})
.end(done);
});
- });
-
- describe('[/users.update]', () => {
- const updateSetting = (setting, value) => new Promise((resolve) => {
- request.post(`/api/v1/settings/${ setting }`)
+ it('should set the avatar of another user by userId and local image', (done) => {
+ request.post(api('users.setAvatar'))
.set(credentials)
- .send({ value })
+ .attach('image', imgURL)
+ .field({ userId: targetUser._id })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
- .end(resolve);
+ .end(done);
});
+ });
+
+ describe('[/users.update]', () => {
const updatePermission = (permission, roles) => new Promise((resolve) => {
request.post(api('permissions.update'))
.set(credentials)
@@ -284,6 +419,7 @@ describe('[Users]', function() {
expect(res.body).to.have.nested.property('user.emails[0].address', apiEmail);
expect(res.body).to.have.nested.property('user.active', true);
expect(res.body).to.have.nested.property('user.name', `edited${ apiUsername }`);
+ expect(res.body).to.not.have.nested.property('user.e2e');
})
.end(done);
});
@@ -303,6 +439,7 @@ describe('[Users]', function() {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.nested.property('user.emails[0].address', `edited${ apiEmail }`);
expect(res.body).to.have.nested.property('user.emails[0].verified', false);
+ expect(res.body).to.not.have.nested.property('user.e2e');
})
.end(done);
});
@@ -321,6 +458,7 @@ describe('[Users]', function() {
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.nested.property('user.emails[0].verified', true);
+ expect(res.body).to.not.have.nested.property('user.e2e');
})
.end(done);
});
@@ -588,6 +726,23 @@ describe('[Users]', function() {
const editedName = `basic-info-test-name${ +new Date() }`;
const editedEmail = `test${ +new Date() }@mail.com`;
+ it('enabling E2E in server and generating keys to user...', (done) => {
+ updateSetting('E2E_Enable', true).then(() => {
+ request.post(api('e2e.setUserPublicAndPivateKeys'))
+ .set(userCredentials)
+ .send({
+ private_key: 'test',
+ public_key: 'test',
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ });
+
it('should update the user own basic information', (done) => {
request.post(api('users.updateOwnBasicInfo'))
.set(userCredentials)
@@ -606,6 +761,7 @@ describe('[Users]', function() {
expect(res.body).to.have.property('success', true);
expect(user.username).to.be.equal(editedUsername);
expect(user.name).to.be.equal(editedName);
+ expect(user).to.not.have.property('e2e');
})
.end(done);
});
@@ -624,6 +780,7 @@ describe('[Users]', function() {
const { user } = res.body;
expect(res.body).to.have.property('success', true);
expect(user.username).to.be.equal(editedUsername);
+ expect(user).to.not.have.property('e2e');
})
.end(done);
});
@@ -686,6 +843,7 @@ describe('[Users]', function() {
expect(res.body).to.have.property('success', true);
expect(user.emails[0].address).to.be.equal(editedEmail);
expect(user.emails[0].verified).to.be.false;
+ expect(user).to.not.have.property('e2e');
})
.end(done);
});
@@ -998,7 +1156,7 @@ describe('[Users]', function() {
})
.end(resolve);
});
- const testUsername = `testuser${ +new Date() }`;
+ const testUsername = `testuserdelete${ +new Date() }`;
let targetUser;
it('register a new user...', (done) => {
request.post(api('users.register'))
diff --git a/tests/end-to-end/api/02-channels.js b/tests/end-to-end/api/02-channels.js
index 4cbd2cddb5f9..30fe33e61ff2 100644
--- a/tests/end-to-end/api/02-channels.js
+++ b/tests/end-to-end/api/02-channels.js
@@ -15,7 +15,7 @@ import {
apiPublicChannelName,
channel,
} from '../../data/api-data.js';
-import { adminEmail, password } from '../../data/user.js';
+import { adminEmail, password, adminUsername } from '../../data/user.js';
import supertest from 'supertest';
function getRoomInfo(roomId) {
@@ -55,22 +55,135 @@ describe('[Channels]', function() {
.end(done);
});
- it('/channels.info', (done) => {
- request.get(api('channels.info'))
- .set(credentials)
- .query({
- roomId: channel._id,
- })
- .expect('Content-Type', 'application/json')
- .expect(200)
- .expect((res) => {
- expect(res.body).to.have.property('success', true);
- expect(res.body).to.have.nested.property('channel._id');
- expect(res.body).to.have.nested.property('channel.name', apiPublicChannelName);
- expect(res.body).to.have.nested.property('channel.t', 'c');
- expect(res.body).to.have.nested.property('channel.msgs', 0);
- })
- .end(done);
+ describe('[/channels.info]', () => {
+ let testChannel = {};
+ let channelMessage = {};
+ it('creating new channel...', (done) => {
+ request.post(api('channels.create'))
+ .set(credentials)
+ .send({
+ name: apiPublicChannelName,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ testChannel = res.body.channel;
+ })
+ .end(done);
+ });
+ it('should return channel basic structure', (done) => {
+ request.get(api('channels.info'))
+ .set(credentials)
+ .query({
+ roomId: testChannel._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.nested.property('channel._id');
+ expect(res.body).to.have.nested.property('channel.name', apiPublicChannelName);
+ expect(res.body).to.have.nested.property('channel.t', 'c');
+ expect(res.body).to.have.nested.property('channel.msgs', 0);
+ })
+ .end(done);
+ });
+ it('sending a message...', (done) => {
+ request.post(api('chat.sendMessage'))
+ .set(credentials)
+ .send({
+ message: {
+ text: 'Sample message',
+ rid: testChannel._id,
+ },
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ channelMessage = res.body.message;
+ })
+ .end(done);
+ });
+ it('REACTing with last message', (done) => {
+ request.post(api('chat.react'))
+ .set(credentials)
+ .send({
+ emoji: ':squid:',
+ messageId: channelMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('STARring last message', (done) => {
+ request.post(api('chat.starMessage'))
+ .set(credentials)
+ .send({
+ messageId: channelMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('PINning last message', (done) => {
+ request.post(api('chat.pinMessage'))
+ .set(credentials)
+ .send({
+ messageId: channelMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('should return channel structure with "lastMessage" object including pin, reaction and star(should be an array) infos', (done) => {
+ request.get(api('channels.info'))
+ .set(credentials)
+ .query({
+ roomId: testChannel._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.property('channel').and.to.be.an('object');
+ const { channel } = res.body;
+ expect(channel).to.have.property('lastMessage').and.to.be.an('object');
+ expect(channel.lastMessage).to.have.property('reactions').and.to.be.an('object');
+ expect(channel.lastMessage).to.have.property('pinned').and.to.be.a('boolean');
+ expect(channel.lastMessage).to.have.property('pinnedAt').and.to.be.a('string');
+ expect(channel.lastMessage).to.have.property('pinnedBy').and.to.be.an('object');
+ expect(channel.lastMessage).to.have.property('starred').and.to.be.an('array');
+ })
+ .end(done);
+ });
+ it('should return all channels messages where the last message of array should have the "star" array with USERS star ONLY', (done) => {
+ request.get(api('channels.messages'))
+ .set(credentials)
+ .query({
+ roomId: testChannel._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.property('messages').and.to.be.an('array');
+ const { messages } = res.body;
+ const lastMessage = messages.filter((message) => message._id === channelMessage._id)[0];
+ expect(lastMessage).to.have.property('starred').and.to.be.an('array');
+ expect(lastMessage.starred[0]._id).to.be.equal(adminUsername);
+ })
+ .end(done);
+ });
});
it('/channels.invite', async(done) => {
diff --git a/tests/end-to-end/api/03-groups.js b/tests/end-to-end/api/03-groups.js
index 9594ca5390c6..b03ab6a638e1 100644
--- a/tests/end-to-end/api/03-groups.js
+++ b/tests/end-to-end/api/03-groups.js
@@ -5,6 +5,7 @@
import { getCredentials, api, login, request, credentials, group, log, apiPrivateChannelName } from '../../data/api-data.js';
import { adminEmail, password } from '../../data/user.js';
import supertest from 'supertest';
+import { adminUsername } from '../../data/user';
function getRoomInfo(roomId) {
return new Promise((resolve/* , reject*/) => {
@@ -43,22 +44,135 @@ describe('[Groups]', function() {
.end(done);
});
- it('/groups.info', (done) => {
- request.get(api('groups.info'))
- .set(credentials)
- .query({
- roomId: group._id,
- })
- .expect('Content-Type', 'application/json')
- .expect(200)
- .expect((res) => {
- expect(res.body).to.have.property('success', true);
- expect(res.body).to.have.nested.property('group._id');
- expect(res.body).to.have.nested.property('group.name', apiPrivateChannelName);
- expect(res.body).to.have.nested.property('group.t', 'p');
- expect(res.body).to.have.nested.property('group.msgs', 0);
- })
- .end(done);
+ describe('[/groups.info]', () => {
+ let testGroup = {};
+ let groupMessage = {};
+ it('creating new group...', (done) => {
+ request.post(api('groups.create'))
+ .set(credentials)
+ .send({
+ name: apiPrivateChannelName,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ testGroup = res.body.group;
+ })
+ .end(done);
+ });
+ it('should return group basic structure', (done) => {
+ request.get(api('groups.info'))
+ .set(credentials)
+ .query({
+ roomId: testGroup._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.nested.property('group._id');
+ expect(res.body).to.have.nested.property('group.name', apiPrivateChannelName);
+ expect(res.body).to.have.nested.property('group.t', 'p');
+ expect(res.body).to.have.nested.property('group.msgs', 0);
+ })
+ .end(done);
+ });
+ it('sending a message...', (done) => {
+ request.post(api('chat.sendMessage'))
+ .set(credentials)
+ .send({
+ message: {
+ text: 'Sample message',
+ rid: testGroup._id,
+ },
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ groupMessage = res.body.message;
+ })
+ .end(done);
+ });
+ it('REACTing with last message', (done) => {
+ request.post(api('chat.react'))
+ .set(credentials)
+ .send({
+ emoji: ':squid:',
+ messageId: groupMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('STARring last message', (done) => {
+ request.post(api('chat.starMessage'))
+ .set(credentials)
+ .send({
+ messageId: groupMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('PINning last message', (done) => {
+ request.post(api('chat.pinMessage'))
+ .set(credentials)
+ .send({
+ messageId: groupMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('should return group structure with "lastMessage" object including pin, reaction and star(should be an array) infos', (done) => {
+ request.get(api('groups.info'))
+ .set(credentials)
+ .query({
+ roomId: testGroup._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.property('group').and.to.be.an('object');
+ const { group } = res.body;
+ expect(group).to.have.property('lastMessage').and.to.be.an('object');
+ expect(group.lastMessage).to.have.property('reactions').and.to.be.an('object');
+ expect(group.lastMessage).to.have.property('pinned').and.to.be.a('boolean');
+ expect(group.lastMessage).to.have.property('pinnedAt').and.to.be.a('string');
+ expect(group.lastMessage).to.have.property('pinnedBy').and.to.be.an('object');
+ expect(group.lastMessage).to.have.property('starred').and.to.be.an('array');
+ })
+ .end(done);
+ });
+ it('should return all groups messages where the last message of array should have the "star" array with USERS star ONLY', (done) => {
+ request.get(api('groups.messages'))
+ .set(credentials)
+ .query({
+ roomId: testGroup._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.property('messages').and.to.be.an('array');
+ const { messages } = res.body;
+ const lastMessage = messages.filter((message) => message._id === groupMessage._id)[0];
+ expect(lastMessage).to.have.property('starred').and.to.be.an('array');
+ expect(lastMessage.starred[0]._id).to.be.equal(adminUsername);
+ })
+ .end(done);
+ });
});
it('/groups.invite', async(done) => {
diff --git a/tests/end-to-end/api/04-direct-message.js b/tests/end-to-end/api/04-direct-message.js
index 4b4a0ea8d215..f22b7f290215 100644
--- a/tests/end-to-end/api/04-direct-message.js
+++ b/tests/end-to-end/api/04-direct-message.js
@@ -2,9 +2,20 @@
/* globals expect */
/* eslint no-unused-vars: 0 */
-import { getCredentials, api, login, request, credentials, directMessage, log, apiUsername, apiEmail } from '../../data/api-data.js';
+import {
+ getCredentials,
+ api,
+ login,
+ request,
+ credentials,
+ directMessage,
+ log,
+ apiUsername,
+ apiEmail,
+} from '../../data/api-data.js';
import { adminEmail, password } from '../../data/user.js';
import supertest from 'supertest';
+import { adminUsername } from '../../data/user';
describe('[Direct Messages]', function() {
this.retries(0);
@@ -44,6 +55,99 @@ describe('[Direct Messages]', function() {
.end(done);
});
+ describe('Testing DM info', () => {
+ let testDM = {};
+ let dmMessage = {};
+ it('creating new DM...', (done) => {
+ request.post(api('im.create'))
+ .set(credentials)
+ .send({
+ username: 'rocket.cat',
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ testDM = res.body.room;
+ })
+ .end(done);
+ });
+ it('sending a message...', (done) => {
+ request.post(api('chat.sendMessage'))
+ .set(credentials)
+ .send({
+ message: {
+ text: 'Sample message',
+ rid: testDM._id,
+ },
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ dmMessage = res.body.message;
+ })
+ .end(done);
+ });
+ it('REACTing with last message', (done) => {
+ request.post(api('chat.react'))
+ .set(credentials)
+ .send({
+ emoji: ':squid:',
+ messageId: dmMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('STARring last message', (done) => {
+ request.post(api('chat.starMessage'))
+ .set(credentials)
+ .send({
+ messageId: dmMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('PINning last message', (done) => {
+ request.post(api('chat.pinMessage'))
+ .set(credentials)
+ .send({
+ messageId: dmMessage._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ })
+ .end(done);
+ });
+ it('should return all DM messages where the last message of array should have the "star" array with USERS star ONLY', (done) => {
+ request.get(api('im.messages'))
+ .set(credentials)
+ .query({
+ roomId: testDM._id,
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.property('messages').and.to.be.an('array');
+ const { messages } = res.body;
+ const lastMessage = messages.filter((message) => message._id === dmMessage._id)[0];
+ expect(lastMessage).to.have.property('starred').and.to.be.an('array');
+ expect(lastMessage.starred[0]._id).to.be.equal(adminUsername);
+ })
+ .end(done);
+ });
+ });
+
it('/im.history', (done) => {
request.get(api('im.history'))
.set(credentials)