Date: Mon, 9 Jul 2018 17:12:17 -0300
Subject: [PATCH 23/28] [FIX] All messages notifications via email were sent as
mention alert (#11398)
---
.../server/functions/notifications/email.js | 8 ++++----
.../server/lib/sendNotificationsOnMessage.js | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/packages/rocketchat-lib/server/functions/notifications/email.js b/packages/rocketchat-lib/server/functions/notifications/email.js
index f1415b9322f0..d9e0910fe592 100644
--- a/packages/rocketchat-lib/server/functions/notifications/email.js
+++ b/packages/rocketchat-lib/server/functions/notifications/email.js
@@ -84,7 +84,7 @@ function getMessageLink(room, sub) {
return `${ message }`;
}
-export function sendEmail({ message, user, subscription, room, emailAddress, toAll }) {
+export function sendEmail({ message, user, subscription, room, emailAddress, hasMentionToUser }) {
let emailSubject;
const username = RocketChat.settings.get('UI_Use_Real_Name') ? message.u.name : message.u.username;
@@ -93,13 +93,13 @@ export function sendEmail({ message, user, subscription, room, emailAddress, toA
user: username,
room: RocketChat.roomTypes.getRoomName(room.t, room)
});
- } else if (toAll) {
- emailSubject = RocketChat.placeholders.replace(RocketChat.settings.get('Offline_Mention_All_Email'), {
+ } else if (hasMentionToUser) {
+ emailSubject = RocketChat.placeholders.replace(RocketChat.settings.get('Offline_Mention_Email'), {
user: username,
room: RocketChat.roomTypes.getRoomName(room.t, room)
});
} else {
- emailSubject = RocketChat.placeholders.replace(RocketChat.settings.get('Offline_Mention_Email'), {
+ emailSubject = RocketChat.placeholders.replace(RocketChat.settings.get('Offline_Mention_All_Email'), {
user: username,
room: RocketChat.roomTypes.getRoomName(room.t, room)
});
diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
index 58ac97fe91f3..675f0f6bf50f 100644
--- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
+++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
@@ -130,7 +130,7 @@ const sendNotification = ({
})) {
receiver.emails.some((email) => {
if (email.verified) {
- sendEmail({ message, receiver, subscription, room, emailAddress: email.address });
+ sendEmail({ message, receiver, subscription, room, emailAddress: email.address, hasMentionToUser });
return true;
}
From bf38c7fe2b136ef7e01866547c3b0718077b385d Mon Sep 17 00:00:00 2001
From: Renato Becker
Date: Mon, 9 Jul 2018 17:13:48 -0300
Subject: [PATCH 24/28] [FIX] Livechat taking inquiry leading to 404 page
(#11406)
---
packages/rocketchat-livechat/server/lib/Livechat.js | 2 +-
packages/rocketchat-livechat/server/methods/takeInquiry.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/rocketchat-livechat/server/lib/Livechat.js b/packages/rocketchat-livechat/server/lib/Livechat.js
index c8e19915cb74..60fb7d4ec52b 100644
--- a/packages/rocketchat-livechat/server/lib/Livechat.js
+++ b/packages/rocketchat-livechat/server/lib/Livechat.js
@@ -314,7 +314,7 @@ RocketChat.Livechat = {
forwardOpenChats(userId) {
RocketChat.models.Rooms.findOpenByAgent(userId).forEach((room) => {
- const guest = RocketChat.models.Users.findOneById(room.v._id);
+ const guest = LivechatVisitors.findOneById(room.v._id);
this.transfer(room, guest, { departmentId: guest.department });
});
},
diff --git a/packages/rocketchat-livechat/server/methods/takeInquiry.js b/packages/rocketchat-livechat/server/methods/takeInquiry.js
index 8f1eed7c3fc7..da199cb84740 100644
--- a/packages/rocketchat-livechat/server/methods/takeInquiry.js
+++ b/packages/rocketchat-livechat/server/methods/takeInquiry.js
@@ -61,6 +61,6 @@ Meteor.methods({
});
// return room corresponding to inquiry (for redirecting agent to the room route)
- return room;
+ return inquiry;
}
});
From 5f04a9496ae0bae88837970ed0d4e75fc32e311a Mon Sep 17 00:00:00 2001
From: Gabriel Engel
Date: Tue, 10 Jul 2018 13:41:13 -0300
Subject: [PATCH 25/28] =?UTF-8?q?replace=20=E2=80=99=20with=20'?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/rocketchat-i18n/i18n/en.i18n.json | 8 ++++----
packages/rocketchat-i18n/i18n/fr.i18n.json | 6 +++---
packages/rocketchat-i18n/i18n/uk.i18n.json | 8 ++++----
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json
index 96b4e6c56eee..e21cf7492964 100644
--- a/packages/rocketchat-i18n/i18n/en.i18n.json
+++ b/packages/rocketchat-i18n/i18n/en.i18n.json
@@ -943,13 +943,13 @@
"edit-other-user-active-status": "Edit Other User Active Status",
"edit-other-user-active-status_description": "Permission to enable or disable other accounts",
"edit-other-user-info": "Edit Other User Information",
- "edit-other-user-info_description": "Permission to change other userβs name, username or email address.",
+ "edit-other-user-info_description": "Permission to change other user's name, username or email address.",
"edit-other-user-password": "Edit Other User Password",
- "edit-other-user-password_description": "Permission to modify other userβs passwords. Requires edit-other-user-info permission.",
+ "edit-other-user-password_description": "Permission to modify other user's passwords. Requires edit-other-user-info permission.",
"edit-privileged-setting": "Edit privileged Setting",
"edit-privileged-setting_description": "Permission to edit settings",
"edit-room": "Edit Room",
- "edit-room_description": "Permission to edit a roomβs name, topic, type (private or public status) and status (active or archived)",
+ "edit-room_description": "Permission to edit a room's name, topic, type (private or public status) and status (active or archived)",
"Edit_Custom_Field": "Edit Custom Field",
"Edit_Department": "Edit Department",
"Edit_previous_message": "`%s` - Edit previous message",
@@ -2223,7 +2223,7 @@
"Settings": "Settings",
"Settings_updated": "Settings updated",
"Setup_Wizard": "Setup Wizard",
- "Setup_Wizard_Info": "Weβll guide you through setting up your first admin user, configuring your organisation and registering your server to receive free push notifications and more.",
+ "Setup_Wizard_Info": "We'll guide you through setting up your first admin user, configuring your organisation and registering your server to receive free push notifications and more.",
"Share_Location_Title": "Share Location?",
"Shared_Location": "Shared Location",
"Should_be_a_URL_of_an_image": "Should be a URL of an image.",
diff --git a/packages/rocketchat-i18n/i18n/fr.i18n.json b/packages/rocketchat-i18n/i18n/fr.i18n.json
index 58469f085c14..0f28bc445da7 100644
--- a/packages/rocketchat-i18n/i18n/fr.i18n.json
+++ b/packages/rocketchat-i18n/i18n/fr.i18n.json
@@ -336,7 +336,7 @@
"Auth_Token": "Jeton d'Auth",
"Author": "Auteur",
"Author_Information": "Informations sur l'auteur",
- "Authorization_URL": "URL dβautorisation",
+ "Authorization_URL": "URL d'autorisation",
"Authorize": "Autoriser",
"auto-translate": "Traduction automatique",
"auto-translate_description": "Permission d'utiliser l'outil de traduction automatique",
@@ -1296,7 +1296,7 @@
"Importer_importing_users": "Importation des utilisateurs.",
"Importer_not_in_progress": "L'import n'est pas en cours d'exΓ©cution.",
"Importer_not_setup": "L'importateur n'est pas configurΓ© correctement, car il n'a renvoyΓ© aucune donnΓ©e.",
- "Importer_Prepare_Restart_Import": "Recommencer lβImportation",
+ "Importer_Prepare_Restart_Import": "Recommencer l'Importation",
"Importer_Prepare_Start_Import": "Commencer l'Importation",
"Importer_Prepare_Uncheck_Archived_Channels": "DΓ©sΓ©lectionner les canaux archivΓ©s",
"Importer_Prepare_Uncheck_Deleted_Users": "DΓ©sΓ©lectionner les utilisateurs supprimΓ©s",
@@ -1810,7 +1810,7 @@
"New_visitor_navigation": "Nouvelle navigation: __history__",
"No_available_agents_to_transfer": "Aucun agent disponible pour le transfert",
"No_channel_with_name_%s_was_found": "Aucun canal nommΓ© \"%s\" n'a Γ©tΓ© trouvΓ© !",
- "No_channels_yet": "Vous ne faites partie dβaucun canal pour le moment.",
+ "No_channels_yet": "Vous ne faites partie d'aucun canal pour le moment.",
"No_direct_messages_yet": "Vous n'avez pris part Γ aucune discussion pour le moment.",
"No_Encryption": "Pas de Chiffrement",
"No_group_with_name_%s_was_found": "Aucun groupe privΓ© nommΓ© \"%s\" n'a Γ©tΓ© trouvΓ© !",
diff --git a/packages/rocketchat-i18n/i18n/uk.i18n.json b/packages/rocketchat-i18n/i18n/uk.i18n.json
index 4a69d5220f2c..78af4414f549 100644
--- a/packages/rocketchat-i18n/i18n/uk.i18n.json
+++ b/packages/rocketchat-i18n/i18n/uk.i18n.json
@@ -1372,7 +1372,7 @@
"Invalid_email": "ΠΠ΅Π²ΡΡΠ½ΠΈΠΉ email",
"Invalid_Export_File": "Π€Π°ΠΉΠ» Π·Π°Π²Π°Π½ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ Π½Π΅ Ρ ΠΊΠΎΡΠ΅ΠΊΡΠ½ΠΈΠΌ %s ΡΠ°ΠΉΠ» Π΅ΠΊΡΠΏΠΎΡΡΡ.",
"Invalid_Import_File_Type": "ΠΠ΅Π²ΡΡΠ½ΠΈΠΉ ΡΠΈΠΏ ΡΠ°ΠΉΠ»Ρ ΡΠΌΠΏΠΎΡΡΡ.",
- "Invalid_name": "ΠΠΌβΡ ΠΌΠ°Ρ Π±ΡΡΠΈ Π·Π°ΠΏΠΎΠ²Π½Π΅Π½ΠΈΠΌ",
+ "Invalid_name": "ΠΠΌ'Ρ ΠΌΠ°Ρ Π±ΡΡΠΈ Π·Π°ΠΏΠΎΠ²Π½Π΅Π½ΠΈΠΌ",
"Invalid_notification_setting_s": "ΠΠ΅ΠΏΡΠΈΠΏΡΡΡΠΈΠΌΠ° Π½Π°ΡΡΡΠΎΠΉΠΊΠ° ΡΠΏΠΎΠ²ΡΡΠ΅Π½Π½Ρ: %s",
"Invalid_pass": "ΠΠ°ΡΠΎΠ»Ρ Π½Π΅ ΠΌΠ°Ρ Π±ΡΡΠΈ ΠΏΡΡΡΠΈΠΌ",
"Invalid_reason": "ΠΡΠΈΡΠΈΠ½Π° Π΄Π»Ρ ΠΏΡΠΈΡΠ΄Π½Π°Π½Π½Ρ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π±ΡΡΠΈ ΠΏΠΎΡΠΎΠΆΠ½ΡΠΎΡ",
@@ -1784,7 +1784,7 @@
"My_location": "ΠΠΎΡ ΠΌΡΡΡΠ΅Π·Π½Π°Ρ
ΠΎΠ΄ΠΆΠ΅Π½Π½Ρ",
"n_messages": "%s ΠΏΠΎΠ²ΡΠ΄ΠΎΠΌΠ»Π΅Π½Ρ",
"N_new_messages": " %s Π½ΠΎΠ²ΠΈΡ
ΠΏΠΎΠ²ΡΠ΄ΠΎΠΌΠ»Π΅Π½Ρ",
- "Name": "ΠΠΌβΡ",
+ "Name": "ΠΠΌ'Ρ",
"Name_cant_be_empty": "ΠΠΌ'Ρ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π±ΡΡΠΈ ΠΏΠΎΡΠΎΠΆΠ½ΡΠΌ",
"Name_of_agent": "ΡΠΌ'Ρ Π°Π³Π΅Π½ΡΠ°",
"Name_optional": "ΠΠΌ'Ρ (Π½Π΅ ΠΎΠ±ΠΎΠ²'ΡΠ·ΠΊΠΎΠ²ΠΎ)",
@@ -2586,10 +2586,10 @@
"UserDataDownload_Requested": "ΠΠ°Π²Π°Π½ΡΠ°ΠΆΡΠ΅ ΠΏΠΎΡΡΡΠ±Π½ΠΈΠΉ ΡΠ°ΠΉΠ»",
"UserDataDownload_Requested_Text": "ΠΠ°Ρ ΡΠ°ΠΉΠ» Π΄Π°Π½ΠΈΡ
Π±ΡΠ΄Π΅ Π·Π³Π΅Π½Π΅ΡΠΎΠ²Π°Π½ΠΈΠΉ. ΠΠΎΡΠΈΠ»Π°Π½Π½Ρ Π½Π° ΠΉΠΎΠ³ΠΎ Π·Π°Π²Π°Π½ΡΠ°ΠΆΠ΅Π½Π½Ρ Π±ΡΠ΄Π΅ Π½Π°Π΄ΡΡΠ»Π°Π½ΠΎ Π½Π° Π²Π°ΡΡ Π΅Π»Π΅ΠΊΡΡΠΎΠ½Π½Ρ Π°Π΄ΡΠ΅ΡΡ, ΠΊΠΎΠ»ΠΈ Π²ΠΎΠ½Π° Π±ΡΠ΄Π΅ Π³ΠΎΡΠΎΠ²Π°.",
"UserDataDownload_RequestExisted_Text": "ΠΠ°Ρ ΡΠ°ΠΉΠ» Π΄Π°Π½ΠΈΡ
Π²ΠΆΠ΅ ΡΡΠ²ΠΎΡΠ΅Π½ΠΎ. ΠΠΎΡΠΈΠ»Π°Π½Π½Ρ Π½Π° ΠΉΠΎΠ³ΠΎ Π·Π°Π²Π°Π½ΡΠ°ΠΆΠ΅Π½Π½Ρ Π±ΡΠ΄Π΅ Π½Π°Π΄ΡΡΠ»Π°Π½ΠΎ Π½Π° Π²Π°ΡΡ Π΅Π»Π΅ΠΊΡΡΠΎΠ½Π½Ρ Π°Π΄ΡΠ΅ΡΡ, ΠΊΠΎΠ»ΠΈ Π²ΠΎΠ½Π° Π±ΡΠ΄Π΅ Π³ΠΎΡΠΎΠ²Π°.",
- "Username": "ΠΠΌβΡ ΠΊΠΎΡΠΈΡΡΡΠ²Π°ΡΠ°",
+ "Username": "ΠΠΌ'Ρ ΠΊΠΎΡΠΈΡΡΡΠ²Π°ΡΠ°",
"Username_already_exist": "ΠΠΌ'Ρ ΠΊΠΎΡΠΈΡΡΡΠ²Π°ΡΠ° Π²ΠΆΠ΅ ΡΡΠ½ΡΡ. ΠΡΠ΄Ρ Π»Π°ΡΠΊΠ°, ΡΠΏΡΠΎΠ±ΡΠΉΡΠ΅ ΡΠ½ΡΠ΅ ΡΠΌ'Ρ ΠΊΠΎΡΠΈΡΡΡΠ²Π°ΡΠ°.",
"Username_and_message_must_not_be_empty": "ΠΠΌ'Ρ ΠΊΠΎΡΠΈΡΡΡΠ²Π°ΡΠ° Ρ ΠΏΠΎΠ²ΡΠ΄ΠΎΠΌΠ»Π΅Π½Π½Ρ Π½Π΅ ΠΏΠΎΠ²ΠΈΠ½Π½ΠΎ Π±ΡΡΠΈ ΠΏΠΎΡΠΎΠΆΠ½ΡΠΌ.",
- "Username_cant_be_empty": "ΠΠΌβΡ ΠΌΠ°Ρ Π±ΡΡΠΈ Π·Π°ΠΏΠΎΠ²Π½Π΅Π½ΠΈΠΌ",
+ "Username_cant_be_empty": "ΠΠΌ'Ρ ΠΌΠ°Ρ Π±ΡΡΠΈ Π·Π°ΠΏΠΎΠ²Π½Π΅Π½ΠΈΠΌ",
"Username_Change_Disabled": "ΠΠ°Ρ Rocket.Chat Π°Π΄ΠΌΡΠ½ΡΡΡΡΠ°ΡΠΎΡ Π²ΡΠ΄ΠΊΠ»ΡΡΠΈΠ² Π·ΠΌΡΠ½Π° ΡΠΌΠ΅Π½ ΠΊΠΎΡΠΈΡΡΡΠ²Π°ΡΡΠ²",
"Username_denied_the_OTR_session": "__username__ Π·Π°ΠΏΠ΅ΡΠ΅ΡΡΠ²Π°Π² ΡΠ΅ΡΡΡ OTR",
"Username_description": "ΠΠΌ'Ρ ΠΊΠΎΡΠΈΡΡΡΠ²Π°ΡΠ° Π²ΠΈΠΊΠΎΡΠΈΡΡΠΎΠ²ΡΡΡΡΡΡ, ΡΠΎΠ± Π΄ΠΎΠ·Π²ΠΎΠ»ΠΈΡΠΈ ΡΠ½ΡΠΈΠΌ ΠΏΡΠΎ Π²Π°Ρ Π² ΠΏΠΎΠ²ΡΠ΄ΠΎΠΌΠ»Π΅Π½Π½ΡΡ
.",
From 9e0a8f50d70edf1e5d46d3eaa2aa2cd636a002a6 Mon Sep 17 00:00:00 2001
From: Rodrigo Nascimento
Date: Tue, 10 Jul 2018 21:19:48 -0300
Subject: [PATCH 26/28] [WIP][BREAK] Remove cache layer and internal calculated
property `room.usernames` (#10749)
[BREAK] Remove cache layer and internal calculated property `room.usernames`
---
.../both/lib/actionLinks.js | 10 +-
packages/rocketchat-api/server/api.js | 8 +-
packages/rocketchat-api/server/v1/channels.js | 142 +--
packages/rocketchat-api/server/v1/groups.js | 66 +-
packages/rocketchat-api/server/v1/im.js | 39 +-
.../rocketchat-api/server/v1/subscriptions.js | 8 +-
packages/rocketchat-api/server/v1/users.js | 29 +-
.../server/bridges/messages.js | 16 +-
.../rocketchat-apps/server/bridges/rooms.js | 2 +-
.../server/converters/rooms.js | 4 +-
.../server/functions/canAccessRoom.js | 2 +-
.../server/models/Permissions.js | 3 +-
.../server/models/Roles.js | 3 +-
.../server/publications/permissions.js | 16 +-
packages/rocketchat-cas/server/cas_server.js | 1 -
.../client/views/channelSettings.js | 3 -
.../server/models/Rooms.js | 20 +-
.../server/resolvers/channels/Channel-type.js | 11 +-
.../resolvers/channels/channelsByUser.js | 3 +-
.../server/resolvers/users/User-type.js | 2 +-
.../server/lib/triggerHandler.js | 5 +-
.../server/lib/validation.js | 2 +-
.../incoming/addIncomingIntegration.js | 2 +-
.../incoming/updateIncomingIntegration.js | 2 +-
.../server/processWebhookMessage.js | 2 +-
.../client/lib/cachedCollection.js | 3 -
.../rocketchat-lib/client/lib/openRoom.js | 1 -
packages/rocketchat-lib/package.js | 3 -
.../server/functions/Notifications.js | 8 +-
.../functions/addUserToDefaultChannels.js | 4 +-
.../server/functions/addUserToRoom.js | 5 +-
.../server/functions/createRoom.js | 6 +-
.../server/functions/deleteUser.js | 5 +-
.../server/functions/removeUserFromRoom.js | 6 +-
.../server/functions/sendMessage.js | 9 -
.../server/functions/setRealName.js | 2 +
packages/rocketchat-lib/server/lib/debug.js | 6 +-
packages/rocketchat-lib/server/lib/metrics.js | 2 +-
.../server/lib/sendNotificationsOnMessage.js | 43 +-
.../server/methods/addUsersToRoom.js | 6 +-
.../server/methods/getChannelHistory.js | 2 +-
.../server/methods/leaveRoom.js | 7 +-
.../rocketchat-lib/server/models/Rooms.js | 322 ++----
.../server/models/Subscriptions.js | 129 ++-
.../rocketchat-lib/server/models/Users.js | 78 +-
.../rocketchat-lib/server/models/_Base.js | 143 ++-
.../server/models/_BaseCache.js | 950 ------------------
.../rocketchat-lib/server/models/_BaseDb.js | 150 ++-
.../server/publications/settings.js | 38 +-
.../server/startup/cache/CacheLoad.js | 73 --
.../server/lib/Livechat.js | 3 +-
.../server/lib/QueueMethods.js | 6 +
.../server/methods/closeRoom.js | 6 +-
.../server/methods/returnAsInquiry.js | 5 -
.../server/methods/takeInquiry.js | 2 +
.../server/methods/transfer.js | 5 +-
.../server/publications/visitorHistory.js | 5 +-
.../client/actionButton.js | 8 +-
.../server/pinMessage.js | 9 +-
.../server/methods/snippetMessage.js | 5 +-
.../server/starMessage.js | 5 +-
packages/rocketchat-migrations/migrations.js | 4 +-
.../oauth/server/oauth2-server.js | 3 +-
.../rocketchat-search/server/events/events.js | 35 +-
.../server/hide.js | 2 +-
.../server/server.js | 26 +-
.../server/server.js | 17 +-
.../server/server.js | 4 +-
.../server/server.js | 13 +-
.../server/mute.js | 12 +-
.../server/unmute.js | 5 +-
.../client/views/app/directory.html | 4 +-
.../client/views/app/directory.js | 10 +-
.../server/cronProcessDownloads.js | 2 +-
server/methods/addAllUserToRoom.js | 1 -
server/methods/browseChannels.js | 32 +-
server/methods/channelsList.js | 58 +-
server/methods/createDirectMessage.js | 5 +-
server/methods/getRoomIdByNameOrId.js | 6 +-
server/methods/getRoomNameById.js | 10 +-
server/methods/getUsersOfRoom.js | 40 +-
server/methods/groupsList.js | 45 -
server/methods/loadHistory.js | 3 +-
server/methods/muteUserInRoom.js | 3 +-
server/methods/removeUserFromRoom.js | 9 +-
server/methods/unmuteUserInRoom.js | 3 +-
.../channelAndPrivateAutocomplete.js | 2 +-
server/publications/room.js | 47 +-
server/publications/spotlight.js | 7 +-
server/publications/subscription.js | 25 +-
server/startup/initialData.js | 4 +-
server/startup/migrations/v130.js | 120 +++
server/startup/roomPublishes.js | 92 --
server/stream/messages.js | 23 +-
tests/end-to-end/api/00-miscellaneous.js | 4 +-
tests/end-to-end/api/04-direct-message.js | 95 +-
tests/end-to-end/api/11-permissions.js | 15 -
97 files changed, 1141 insertions(+), 2106 deletions(-)
delete mode 100644 packages/rocketchat-lib/server/models/_BaseCache.js
delete mode 100644 packages/rocketchat-lib/server/startup/cache/CacheLoad.js
delete mode 100644 server/methods/groupsList.js
create mode 100644 server/startup/migrations/v130.js
delete mode 100644 server/startup/roomPublishes.js
diff --git a/packages/rocketchat-action-links/both/lib/actionLinks.js b/packages/rocketchat-action-links/both/lib/actionLinks.js
index edf0d0e4b257..b055555600c8 100644
--- a/packages/rocketchat-action-links/both/lib/actionLinks.js
+++ b/packages/rocketchat-action-links/both/lib/actionLinks.js
@@ -5,7 +5,8 @@ RocketChat.actionLinks = {
RocketChat.actionLinks.actions[name] = funct;
},
getMessage(name, messageId) {
- if (!Meteor.userId()) {
+ const userId = Meteor.userId();
+ if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'actionLinks.getMessage' });
}
@@ -14,8 +15,11 @@ RocketChat.actionLinks = {
throw new Meteor.Error('error-invalid-message', 'Invalid message', { function: 'actionLinks.getMessage' });
}
- const room = RocketChat.models.Rooms.findOne({ _id: message.rid });
- if (Array.isArray(room.usernames) && room.usernames.indexOf(Meteor.user().username) === -1) {
+ const subscription = RocketChat.models.Subscriptions.findOne({
+ rid: message.rid,
+ 'u._id': userId
+ });
+ if (!subscription) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { function: 'actionLinks.getMessage' });
}
diff --git a/packages/rocketchat-api/server/api.js b/packages/rocketchat-api/server/api.js
index c27b4d664226..fd0f09a1d3e2 100644
--- a/packages/rocketchat-api/server/api.js
+++ b/packages/rocketchat-api/server/api.js
@@ -9,10 +9,7 @@ class API extends Restivus {
this.fieldSeparator = '.';
this.defaultFieldsToExclude = {
joinCode: 0,
- $loki: 0,
- meta: 0,
members: 0,
- usernames: 0, // Please use the `channel/dm/group.members` endpoint. This is disabled for performance reasons
importIds: 0
};
this.limitedUserFieldsToExclude = {
@@ -85,13 +82,14 @@ class API extends Restivus {
return result;
}
- failure(result, errorType) {
+ failure(result, errorType, stack) {
if (_.isObject(result)) {
result.success = false;
} else {
result = {
success: false,
- error: result
+ error: result,
+ stack
};
if (errorType) {
diff --git a/packages/rocketchat-api/server/v1/channels.js b/packages/rocketchat-api/server/v1/channels.js
index be7de10766be..3c13e3e94a3f 100644
--- a/packages/rocketchat-api/server/v1/channels.js
+++ b/packages/rocketchat-api/server/v1/channels.js
@@ -1,15 +1,12 @@
import _ from 'underscore';
//Returns the channel IF found otherwise it will return the failure of why it didn't. Check the `statusCode` property
-function findChannelByIdOrName({ params, checkedArchived = true, returnUsernames = false }) {
+function findChannelByIdOrName({ params, checkedArchived = true }) {
if ((!params.roomId || !params.roomId.trim()) && (!params.roomName || !params.roomName.trim())) {
throw new Meteor.Error('error-roomid-param-not-provided', 'The parameter "roomId" or "roomName" is required');
}
const fields = { ...RocketChat.API.v1.defaultFieldsToExclude };
- if (returnUsernames) {
- delete fields.usernames;
- }
let room;
if (params.roomId) {
@@ -143,7 +140,7 @@ RocketChat.API.v1.addRoute('channels.close', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.counters', { authRequired: true }, {
get() {
const access = RocketChat.authz.hasPermission(this.userId, 'view-room-administration');
- const ruserId = this.requestParams().userId;
+ const userId = this.requestParams().userId;
let user = this.userId;
let unreads = null;
let userMentions = null;
@@ -152,34 +149,33 @@ RocketChat.API.v1.addRoute('channels.counters', { authRequired: true }, {
let msgs = null;
let latest = null;
let members = null;
- let lm = null;
- if (ruserId) {
+ if (userId) {
if (!access) {
return RocketChat.API.v1.unauthorized();
}
- user = ruserId;
+ user = userId;
}
const room = findChannelByIdOrName({
params: this.requestParams(),
returnUsernames: true
});
- const channel = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user);
- lm = channel._room.lm ? channel._room.lm : channel._room._updatedAt;
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user);
+ const lm = room.lm ? room.lm : room._updatedAt;
- if (typeof channel !== 'undefined' && channel.open) {
- if (channel.ls) {
- unreads = RocketChat.models.Messages.countVisibleByRoomIdBetweenTimestampsInclusive(channel.rid, channel.ls, lm);
- unreadsFrom = channel.ls;
+ if (typeof subscription !== 'undefined' && subscription.open) {
+ if (subscription.ls) {
+ unreads = RocketChat.models.Messages.countVisibleByRoomIdBetweenTimestampsInclusive(subscription.rid, subscription.ls, lm);
+ unreadsFrom = subscription.ls;
}
- userMentions = channel.userMentions;
+ userMentions = subscription.userMentions;
joined = true;
}
if (access || joined) {
msgs = room.msgs;
latest = lm;
- members = room.usernames.length;
+ members = room.usersCount;
}
return RocketChat.API.v1.success({
@@ -494,28 +490,32 @@ RocketChat.API.v1.addRoute('channels.list', { authRequired: true }, {
const { sort, fields, query } = this.parseJsonQuery();
const hasPermissionToSeeAllPublicChannels = RocketChat.authz.hasPermission(this.userId, 'view-c-room');
- const ourQuery = Object.assign({}, query, { t: 'c' });
+ const ourQuery = { ...query, t: 'c' };
- if (RocketChat.authz.hasPermission(this.userId, 'view-joined-room') && !hasPermissionToSeeAllPublicChannels) {
- ourQuery.usernames = {
- $in: [this.user.username]
- };
- } else if (!hasPermissionToSeeAllPublicChannels) {
- return RocketChat.API.v1.unauthorized();
+ if (!hasPermissionToSeeAllPublicChannels) {
+ if (!RocketChat.authz.hasPermission(this.userId, 'view-joined-room')) {
+ return RocketChat.API.v1.unauthorized();
+ }
+ const roomIds = RocketChat.models.Subscriptions.findByUserIdAndType(this.userId, 'c', { fields: { rid: 1 } }).fetch().map(s => s.rid);
+ ourQuery._id = { $in: roomIds };
}
- const rooms = RocketChat.models.Rooms.find(ourQuery, {
+ const cursor = RocketChat.models.Rooms.find(ourQuery, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields
- }).fetch();
+ });
+
+ const total = cursor.count();
+
+ const rooms = cursor.fetch();
return RocketChat.API.v1.success({
channels: rooms,
count: rooms.length,
offset,
- total: RocketChat.models.Rooms.find(ourQuery).count()
+ total
});
}
}
@@ -524,22 +524,19 @@ RocketChat.API.v1.addRoute('channels.list', { authRequired: true }, {
RocketChat.API.v1.addRoute('channels.list.joined', { authRequired: true }, {
get() {
const { offset, count } = this.getPaginationItems();
- const { sort, fields, query } = this.parseJsonQuery();
- const ourQuery = Object.assign({}, query, {
- t: 'c',
- 'u._id': this.userId
- });
-
- let rooms = _.pluck(RocketChat.models.Subscriptions.find(ourQuery).fetch(), '_room');
- const totalCount = rooms.length;
+ const { sort, fields } = this.parseJsonQuery();
- rooms = RocketChat.models.Rooms.processQueryOptionsOnResult(rooms, {
+ // TODO: CACHE: Add Breacking notice since we removed the query param
+ const cursor = RocketChat.models.Rooms.findBySubscriptionTypeAndUserId('c', this.userId, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields
});
+ const totalCount = cursor.count();
+ const rooms = cursor.fetch();
+
return RocketChat.API.v1.success({
channels: rooms,
offset,
@@ -553,8 +550,7 @@ RocketChat.API.v1.addRoute('channels.members', { authRequired: true }, {
get() {
const findResult = findChannelByIdOrName({
params: this.requestParams(),
- checkedArchived: false,
- returnUsernames: true
+ checkedArchived: false
});
if (findResult.broadcast && !RocketChat.authz.hasPermission(this.userId, 'view-broadcast-member-list')) {
@@ -562,29 +558,29 @@ RocketChat.API.v1.addRoute('channels.members', { authRequired: true }, {
}
const { offset, count } = this.getPaginationItems();
- const { sort } = this.parseJsonQuery();
-
- const shouldBeOrderedDesc = Match.test(sort, Object) && Match.test(sort.username, Number) && sort.username === -1;
+ const { sort = {} } = this.parseJsonQuery();
- let members = RocketChat.models.Rooms.processQueryOptionsOnResult(Array.from(findResult.usernames).sort(), {
+ const subscriptions = RocketChat.models.Subscriptions.findByRoomId(findResult._id, {
+ fields: { 'u._id': 1 },
+ sort: { 'u.username': sort.username != null ? sort.username : 1 },
skip: offset,
limit: count
});
- if (shouldBeOrderedDesc) {
- members = members.reverse();
- }
+ const total = subscriptions.count();
+
+ const members = subscriptions.fetch().map(s => s.u && s.u._id);
- const users = RocketChat.models.Users.find({ username: { $in: members } }, {
+ const users = RocketChat.models.Users.find({ _id: { $in: members } }, {
fields: { _id: 1, username: 1, name: 1, status: 1, utcOffset: 1 },
- sort: sort ? sort : { username: 1 }
+ sort: { username: sort.username != null ? sort.username : 1 }
}).fetch();
return RocketChat.API.v1.success({
members: users,
count: users.length,
offset,
- total: findResult.usernames.length
+ total
});
}
});
@@ -593,8 +589,7 @@ RocketChat.API.v1.addRoute('channels.messages', { authRequired: true }, {
get() {
const findResult = findChannelByIdOrName({
params: this.requestParams(),
- checkedArchived: false,
- returnUsernames: true
+ checkedArchived: false
});
const { offset, count } = this.getPaginationItems();
const { sort, fields, query } = this.parseJsonQuery();
@@ -602,27 +597,59 @@ RocketChat.API.v1.addRoute('channels.messages', { authRequired: true }, {
const ourQuery = Object.assign({}, query, { rid: findResult._id });
//Special check for the permissions
- if (RocketChat.authz.hasPermission(this.userId, 'view-joined-room') && !findResult.usernames.includes(this.user.username)) {
+ if (RocketChat.authz.hasPermission(this.userId, 'view-joined-room') && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(findResult._id, this.userId, { fields: { _id: 1 } })) {
return RocketChat.API.v1.unauthorized();
- } else if (!RocketChat.authz.hasPermission(this.userId, 'view-c-room')) {
+ }
+ if (!RocketChat.authz.hasPermission(this.userId, 'view-c-room')) {
return RocketChat.API.v1.unauthorized();
}
- const messages = RocketChat.models.Messages.find(ourQuery, {
+ const cursor = RocketChat.models.Messages.find(ourQuery, {
sort: sort ? sort : { ts: -1 },
skip: offset,
limit: count,
fields
- }).fetch();
+ });
+
+ const total = cursor.count();
+ const messages = cursor.fetch();
return RocketChat.API.v1.success({
messages,
count: messages.length,
offset,
- total: RocketChat.models.Messages.find(ourQuery).count()
+ total
});
}
});
+// TODO: CACHE: I dont like this method( functionality and how we implemented ) its very expensive
+// TODO check if this code is better or not
+// RocketChat.API.v1.addRoute('channels.online', { authRequired: true }, {
+// get() {
+// const { query } = this.parseJsonQuery();
+// const ourQuery = Object.assign({}, query, { t: 'c' });
+
+// const room = RocketChat.models.Rooms.findOne(ourQuery);
+
+// if (room == null) {
+// return RocketChat.API.v1.failure('Channel does not exists');
+// }
+
+// const ids = RocketChat.models.Subscriptions.find({ rid: room._id }, { fields: { 'u._id': 1 } }).fetch().map(sub => sub.u._id);
+
+// const online = RocketChat.models.Users.find({
+// username: { $exists: 1 },
+// _id: { $in: ids },
+// status: { $in: ['online', 'away', 'busy'] }
+// }, {
+// fields: { username: 1 }
+// }).fetch();
+
+// return RocketChat.API.v1.success({
+// online
+// });
+// }
+// });
RocketChat.API.v1.addRoute('channels.online', { authRequired: true }, {
get() {
@@ -636,14 +663,13 @@ RocketChat.API.v1.addRoute('channels.online', { authRequired: true }, {
}
const online = RocketChat.models.Users.findUsersNotOffline({
- fields: {
- username: 1
- }
+ fields: { username: 1 }
}).fetch();
const onlineInRoom = [];
online.forEach(user => {
- if (room.usernames.indexOf(user.username) !== -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(root._id, user._id, { fields: { _id: 1 } });
+ if (subscription) {
onlineInRoom.push({
_id: user._id,
username: user.username
diff --git a/packages/rocketchat-api/server/v1/groups.js b/packages/rocketchat-api/server/v1/groups.js
index ffeb3cf4434a..c5835e0f4099 100644
--- a/packages/rocketchat-api/server/v1/groups.js
+++ b/packages/rocketchat-api/server/v1/groups.js
@@ -120,7 +120,6 @@ RocketChat.API.v1.addRoute('groups.counters', { authRequired: true }, {
let msgs = null;
let latest = null;
let members = null;
- let lm = null;
if ((!params.roomId || !params.roomId.trim()) && (!params.roomName || !params.roomName.trim())) {
throw new Meteor.Error('error-room-param-not-provided', 'The parameter "roomId" or "roomName" is required');
@@ -146,22 +145,22 @@ RocketChat.API.v1.addRoute('groups.counters', { authRequired: true }, {
}
user = params.userId;
}
- const group = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user);
- lm = group._room.lm ? group._room.lm : group._room._updatedAt;
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user);
+ const lm = room.lm ? room.lm : room._updatedAt;
- if (typeof group !== 'undefined' && group.open) {
- if (group.ls) {
- unreads = RocketChat.models.Messages.countVisibleByRoomIdBetweenTimestampsInclusive(group.rid, group.ls, lm);
- unreadsFrom = group.ls;
+ if (typeof subscription !== 'undefined' && subscription.open) {
+ if (subscription.ls) {
+ unreads = RocketChat.models.Messages.countVisibleByRoomIdBetweenTimestampsInclusive(subscription.rid, subscription.ls, lm);
+ unreadsFrom = subscription.ls;
}
- userMentions = group.userMentions;
+ userMentions = subscription.userMentions;
joined = true;
}
if (access || joined) {
msgs = room.msgs;
latest = lm;
- members = room.usernames.length;
+ members = room.usersCount;
}
return RocketChat.API.v1.success({
@@ -220,7 +219,7 @@ RocketChat.API.v1.addRoute('groups.delete', { authRequired: true }, {
});
return RocketChat.API.v1.success({
- group: RocketChat.models.Rooms.processQueryOptionsOnResult([findResult._room], { fields: RocketChat.API.v1.defaultFieldsToExclude })[0]
+ group: RocketChat.models.Rooms.findOneById(findResult.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude })
});
}
});
@@ -400,22 +399,20 @@ RocketChat.API.v1.addRoute('groups.leave', { authRequired: true }, {
RocketChat.API.v1.addRoute('groups.list', { authRequired: true }, {
get() {
const { offset, count } = this.getPaginationItems();
- const { sort, fields, query } = this.parseJsonQuery();
- const ourQuery = Object.assign({}, query, {
- t: 'p',
- 'u._id': this.userId
- });
+ const { sort, fields} = this.parseJsonQuery();
- let rooms = _.pluck(RocketChat.models.Subscriptions.find(ourQuery).fetch(), '_room');
- const totalCount = rooms.length;
-
- rooms = RocketChat.models.Rooms.processQueryOptionsOnResult(rooms, {
+ // TODO: CACHE: Add Breacking notice since we removed the query param
+ const cursor = RocketChat.models.Rooms.findBySubscriptionTypeAndUserId('p', this.userId, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields
});
+ const totalCount = cursor.count();
+ const rooms = cursor.fetch();
+
+
return RocketChat.API.v1.success({
groups: rooms,
offset,
@@ -457,34 +454,36 @@ RocketChat.API.v1.addRoute('groups.listAll', { authRequired: true }, {
RocketChat.API.v1.addRoute('groups.members', { authRequired: true }, {
get() {
const findResult = findPrivateGroupByIdOrName({ params: this.requestParams(), userId: this.userId });
+ const room = RocketChat.models.Rooms.findOneById(findResult.rid, { fields: { broadcast: 1 } });
- if (findResult._room.broadcast && !RocketChat.authz.hasPermission(this.userId, 'view-broadcast-member-list')) {
+ if (room.broadcast && !RocketChat.authz.hasPermission(this.userId, 'view-broadcast-member-list')) {
return RocketChat.API.v1.unauthorized();
}
const { offset, count } = this.getPaginationItems();
- const { sort } = this.parseJsonQuery();
-
- let sortFn = (a, b) => a > b;
- if (Match.test(sort, Object) && Match.test(sort.username, Number) && sort.username === -1) {
- sortFn = (a, b) => b < a;
- }
+ const { sort = {} } = this.parseJsonQuery();
- const members = RocketChat.models.Rooms.processQueryOptionsOnResult(Array.from(findResult._room.usernames).sort(sortFn), {
+ const subscriptions = RocketChat.models.Subscriptions.findByRoomId(findResult.rid, {
+ fields: { 'u._id': 1 },
+ sort: { 'u.username': sort.username != null ? sort.username : 1 },
skip: offset,
limit: count
});
- const users = RocketChat.models.Users.find({ username: { $in: members } }, {
+ const total = subscriptions.count();
+
+ const members = subscriptions.fetch().map(s => s.u && s.u._id);
+
+ const users = RocketChat.models.Users.find({ _id: { $in: members } }, {
fields: { _id: 1, username: 1, name: 1, status: 1, utcOffset: 1 },
- sort: sort ? sort : { username: 1 }
+ sort: { username: sort.username != null ? sort.username : 1 }
}).fetch();
return RocketChat.API.v1.success({
members: users,
- count: members.length,
+ count: users.length,
offset,
- total: findResult._room.usernames.length
+ total
});
}
});
@@ -512,7 +511,7 @@ RocketChat.API.v1.addRoute('groups.messages', { authRequired: true }, {
});
}
});
-
+// TODO: CACHE: same as channels.online
RocketChat.API.v1.addRoute('groups.online', { authRequired: true }, {
get() {
const { query } = this.parseJsonQuery();
@@ -532,7 +531,8 @@ RocketChat.API.v1.addRoute('groups.online', { authRequired: true }, {
const onlineInRoom = [];
online.forEach(user => {
- if (room.usernames.indexOf(user.username) !== -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(root._id, user._id, { fields: { _id: 1 } });
+ if (subscription) {
onlineInRoom.push({
_id: user._id,
username: user.username
diff --git a/packages/rocketchat-api/server/v1/im.js b/packages/rocketchat-api/server/v1/im.js
index c2ad7d8da8e0..865b6ab3bc8a 100644
--- a/packages/rocketchat-api/server/v1/im.js
+++ b/packages/rocketchat-api/server/v1/im.js
@@ -1,5 +1,3 @@
-import _ from 'underscore';
-
function findDirectMessageRoom(params, user) {
if ((!params.roomId || !params.roomId.trim()) && (!params.username || !params.username.trim())) {
throw new Meteor.Error('error-room-param-not-provided', 'Body param "roomId" or "username" is required');
@@ -86,7 +84,7 @@ RocketChat.API.v1.addRoute(['dm.counters', 'im.counters'], { authRequired: true
if (access || joined) {
msgs = room.msgs;
latest = lm;
- members = room.usernames.length;
+ members = room.usersCount;
}
return RocketChat.API.v1.success({
@@ -187,21 +185,26 @@ RocketChat.API.v1.addRoute(['dm.members', 'im.members'], { authRequired: true },
const { offset, count } = this.getPaginationItems();
const { sort } = this.parseJsonQuery();
-
- const members = RocketChat.models.Rooms.processQueryOptionsOnResult(Array.from(findResult.room.usernames), {
- sort: sort ? sort : -1,
+ const cursor = RocketChat.models.Subscriptions.findByRoomId(findResult._id, {
+ sort: { 'u.username': sort.username != null ? sort.username : 1 },
skip: offset,
limit: count
});
- const users = RocketChat.models.Users.find({ username: { $in: members } },
- { fields: { _id: 1, username: 1, name: 1, status: 1, utcOffset: 1 } }).fetch();
+ const total = cursor.count();
+
+ const members = cursor.fetch().map(s => s.u && s.u.username);
+
+ const users = RocketChat.models.Users.find({ username: { $in: members } }, {
+ fields: { _id: 1, username: 1, name: 1, status: 1, utcOffset: 1 },
+ sort: { username: sort.username != null ? sort.username : 1 }
+ }).fetch();
return RocketChat.API.v1.success({
members: users,
count: members.length,
offset,
- total: findResult.room.usernames.length
+ total
});
}
});
@@ -275,27 +278,25 @@ RocketChat.API.v1.addRoute(['dm.messages.others', 'im.messages.others'], { authR
RocketChat.API.v1.addRoute(['dm.list', 'im.list'], { authRequired: true }, {
get() {
const { offset, count } = this.getPaginationItems();
- const { sort, fields, query } = this.parseJsonQuery();
- const ourQuery = Object.assign({}, query, {
- t: 'd',
- 'u._id': this.userId
- });
+ const { sort = { name: 1 }, fields } = this.parseJsonQuery();
- let rooms = _.pluck(RocketChat.models.Subscriptions.find(ourQuery).fetch(), '_room');
- const totalCount = rooms.length;
+ // TODO: CACHE: Add Breacking notice since we removed the query param
- rooms = RocketChat.models.Rooms.processQueryOptionsOnResult(rooms, {
- sort: sort ? sort : { name: 1 },
+ const cursor = RocketChat.models.Rooms.findBySubscriptionTypeAndUserId('d', this.userId, {
+ sort,
skip: offset,
limit: count,
fields
});
+ const total = cursor.count();
+ const rooms = cursor.fetch();
+
return RocketChat.API.v1.success({
ims: rooms,
offset,
count: rooms.length,
- total: totalCount
+ total
});
}
});
diff --git a/packages/rocketchat-api/server/v1/subscriptions.js b/packages/rocketchat-api/server/v1/subscriptions.js
index e58fe4094a26..8bc1c57e4fdf 100644
--- a/packages/rocketchat-api/server/v1/subscriptions.js
+++ b/packages/rocketchat-api/server/v1/subscriptions.js
@@ -33,13 +33,7 @@ RocketChat.API.v1.addRoute('subscriptions.getOne', { authRequired: true }, {
return RocketChat.API.v1.failure('The \'roomId\' param is required');
}
- const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, this.userId, {
- fields: {
- _room: 0,
- _user: 0,
- $loki: 0
- }
- });
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, this.userId);
return RocketChat.API.v1.success({
subscription
diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js
index 496833312557..d64b5680aaa5 100644
--- a/packages/rocketchat-api/server/v1/users.js
+++ b/packages/rocketchat-api/server/v1/users.js
@@ -352,26 +352,29 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, {
})
});
- let preferences;
const userId = this.bodyParams.userId ? this.bodyParams.userId : this.userId;
+ const userData = {
+ _id: userId,
+ settings: {
+ preferences: this.bodyParams.data
+ }
+ };
+
if (this.bodyParams.data.language) {
const language = this.bodyParams.data.language;
delete this.bodyParams.data.language;
- preferences = _.extend({ _id: userId, settings: { preferences: this.bodyParams.data }, language });
- } else {
- preferences = _.extend({ _id: userId, settings: { preferences: this.bodyParams.data } });
+ userData.language = language;
}
- // Keep compatibility with old values
- if (preferences.emailNotificationMode === 'all') {
- preferences.emailNotificationMode = 'mentions';
- } else if (preferences.emailNotificationMode === 'disabled') {
- preferences.emailNotificationMode = 'nothing';
- }
-
- Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, preferences));
+ Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, userData));
- return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: preferences }) });
+ return RocketChat.API.v1.success({
+ user: RocketChat.models.Users.findOneById(userId, {
+ fields: {
+ 'settings.preferences': 1
+ }
+ })
+ });
}
});
diff --git a/packages/rocketchat-apps/server/bridges/messages.js b/packages/rocketchat-apps/server/bridges/messages.js
index 22d391e5c581..126b1f1b668b 100644
--- a/packages/rocketchat-apps/server/bridges/messages.js
+++ b/packages/rocketchat-apps/server/bridges/messages.js
@@ -54,7 +54,7 @@ export class AppMessageBridge {
async notifyRoom(room, message, appId) {
console.log(`The App ${ appId } is notifying a room's users.`);
- if (room && room.usernames && Array.isArray(room.usernames)) {
+ if (room) {
const msg = this.orch.getConverters().get('messages').convertAppMessage(message);
const rmsg = Object.assign(msg, {
_id: Random.id(),
@@ -64,12 +64,14 @@ export class AppMessageBridge {
editor: undefined
});
- room.usernames.forEach((u) => {
- const user = RocketChat.models.Users.findOneByUsername(u);
- if (user) {
- RocketChat.Notifications.notifyUser(user._id, 'message', rmsg);
- }
- });
+ const users = RocketChat.models.Subscriptions.findByRoomIdWhenUserIdExists(room._id, { fields: { 'u._id': 1 } })
+ .fetch()
+ .map(s => s.u._id);
+ RocketChat.models.Users.findByIds(users, { fields: { _id: 1 } })
+ .fetch()
+ .forEach(({ _id }) =>
+ RocketChat.Notifications.notifyUser(_id, 'message', rmsg)
+ );
}
}
}
diff --git a/packages/rocketchat-apps/server/bridges/rooms.js b/packages/rocketchat-apps/server/bridges/rooms.js
index d0bece2d7e8e..2db168165233 100644
--- a/packages/rocketchat-apps/server/bridges/rooms.js
+++ b/packages/rocketchat-apps/server/bridges/rooms.js
@@ -24,7 +24,7 @@ export class AppRoomBridge {
let rid;
Meteor.runAsUser(room.creator.id, () => {
- const info = Meteor.call(method, rcRoom.usernames);
+ const info = Meteor.call(method, rcRoom.members);
rid = info.rid;
});
diff --git a/packages/rocketchat-apps/server/converters/rooms.js b/packages/rocketchat-apps/server/converters/rooms.js
index a12e9bcf0499..9fd875755331 100644
--- a/packages/rocketchat-apps/server/converters/rooms.js
+++ b/packages/rocketchat-apps/server/converters/rooms.js
@@ -37,7 +37,7 @@ export class AppRoomsConverter {
name: room.slugifiedName,
t: room.type,
u,
- usernames: room.usernames,
+ members: room.members,
default: typeof room.isDefault === 'undefined' ? false : room.isDefault,
ro: typeof room.isReadOnly === 'undefined' ? false : room.isReadOnly,
sysMes: typeof room.displaySystemMessages === 'undefined' ? true : room.displaySystemMessages,
@@ -64,7 +64,7 @@ export class AppRoomsConverter {
slugifiedName: room.name,
type: this._convertTypeToApp(room.t),
creator,
- usernames: room.usernames,
+ members: room.members,
isDefault: typeof room.default === 'undefined' ? false : room.default,
isReadOnly: typeof room.ro === 'undefined' ? false : room.ro,
displaySystemMessages: typeof room.sysMes === 'undefined' ? true : room.sysMes,
diff --git a/packages/rocketchat-authorization/server/functions/canAccessRoom.js b/packages/rocketchat-authorization/server/functions/canAccessRoom.js
index 31a6e17674de..1084bb8ecf04 100644
--- a/packages/rocketchat-authorization/server/functions/canAccessRoom.js
+++ b/packages/rocketchat-authorization/server/functions/canAccessRoom.js
@@ -12,7 +12,7 @@ RocketChat.authz.roomAccessValidators = [
function(room, user = {}) {
const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id);
if (subscription) {
- return subscription._room;
+ return RocketChat.models.Rooms.findOneById(subscription.rid);
}
}
];
diff --git a/packages/rocketchat-authorization/server/models/Permissions.js b/packages/rocketchat-authorization/server/models/Permissions.js
index a82e0411fca0..220e8d94a827 100644
--- a/packages/rocketchat-authorization/server/models/Permissions.js
+++ b/packages/rocketchat-authorization/server/models/Permissions.js
@@ -29,5 +29,4 @@ class ModelPermissions extends RocketChat.models._Base {
}
}
-RocketChat.models.Permissions = new ModelPermissions('permissions', true);
-RocketChat.models.Permissions.cache.load();
+RocketChat.models.Permissions = new ModelPermissions('permissions');
diff --git a/packages/rocketchat-authorization/server/models/Roles.js b/packages/rocketchat-authorization/server/models/Roles.js
index 8c5f1fed85fa..f93c95883c82 100644
--- a/packages/rocketchat-authorization/server/models/Roles.js
+++ b/packages/rocketchat-authorization/server/models/Roles.js
@@ -65,5 +65,4 @@ class ModelRoles extends RocketChat.models._Base {
}
}
-RocketChat.models.Roles = new ModelRoles('roles', true);
-RocketChat.models.Roles.cache.load();
+RocketChat.models.Roles = new ModelRoles('roles');
diff --git a/packages/rocketchat-authorization/server/publications/permissions.js b/packages/rocketchat-authorization/server/publications/permissions.js
index 029109db025c..1477c91940d7 100644
--- a/packages/rocketchat-authorization/server/publications/permissions.js
+++ b/packages/rocketchat-authorization/server/publications/permissions.js
@@ -1,6 +1,8 @@
Meteor.methods({
'permissions/get'(updatedAt) {
this.unblock();
+ // TODO: should we return this for non logged users?
+ // TODO: we could cache this collection
const records = RocketChat.models.Permissions.find().fetch();
@@ -17,7 +19,17 @@ Meteor.methods({
}
});
+RocketChat.models.Permissions.on('change', ({clientAction, id, data}) => {
+ switch (clientAction) {
+ case 'updated':
+ case 'inserted':
+ data = data || RocketChat.models.Permissions.findOneById(id);
+ break;
-RocketChat.models.Permissions.on('changed', (type, permission) => {
- RocketChat.Notifications.notifyLoggedInThisInstance('permissions-changed', type, permission);
+ case 'removed':
+ data = { _id: id };
+ break;
+ }
+
+ RocketChat.Notifications.notifyLoggedInThisInstance('permissions-changed', clientAction, data);
});
diff --git a/packages/rocketchat-cas/server/cas_server.js b/packages/rocketchat-cas/server/cas_server.js
index 492700a134f3..c5e689b444f9 100644
--- a/packages/rocketchat-cas/server/cas_server.js
+++ b/packages/rocketchat-cas/server/cas_server.js
@@ -233,7 +233,6 @@ Accounts.registerLoginHandler(function(options) {
}
if (!RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, userId)) {
- RocketChat.models.Rooms.addUsernameByName(room_name, result.username);
RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
ts: new Date(),
open: true,
diff --git a/packages/rocketchat-channel-settings/client/views/channelSettings.js b/packages/rocketchat-channel-settings/client/views/channelSettings.js
index 922a44c9d75c..b84796ea3491 100644
--- a/packages/rocketchat-channel-settings/client/views/channelSettings.js
+++ b/packages/rocketchat-channel-settings/client/views/channelSettings.js
@@ -503,9 +503,6 @@ Template.channelSettingsInfo.helpers({
topic() {
return Template.instance().room.topic;
},
- users() {
- return Template.instance().room.usernames;
- },
channelIcon() {
const roomType = Template.instance().room.t;
diff --git a/packages/rocketchat-channel-settings/server/models/Rooms.js b/packages/rocketchat-channel-settings/server/models/Rooms.js
index 07e81e5ff17f..de14f8c365c8 100644
--- a/packages/rocketchat-channel-settings/server/models/Rooms.js
+++ b/packages/rocketchat-channel-settings/server/models/Rooms.js
@@ -16,27 +16,27 @@ RocketChat.models.Rooms.setReadOnlyById = function(_id, readOnly) {
};
const update = {
$set: {
- ro: readOnly
+ ro: readOnly,
+ muted: []
}
};
if (readOnly) {
- RocketChat.models.Subscriptions.findByRoomId(_id).forEach(function(subscription) {
- if (subscription._user == null) {
+ RocketChat.models.Subscriptions.findByRoomIdWhenUsernameExists(_id, { fields: { 'u._id': 1, 'u.username': 1 } }).forEach(function({ u: user }) {
+ if (RocketChat.authz.hasPermission(user._id, 'post-readonly')) {
return;
}
- const user = subscription._user;
- if (RocketChat.authz.hasPermission(user._id, 'post-readonly') === false) {
- if (!update.$set.muted) {
- update.$set.muted = [];
- }
- return update.$set.muted.push(user.username);
- }
+ return update.$set.muted.push(user.username);
});
} else {
update.$unset = {
muted: ''
};
}
+
+ if (update.$set.muted.length === 0) {
+ delete update.$set.muted;
+ }
+
return this.update(query, update);
};
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js
index e16dffa8ab83..423ac8e7813e 100644
--- a/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js
+++ b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js
@@ -14,9 +14,10 @@ const resolver = {
return root.name;
},
members: (root) => {
- return root.usernames.map(
- username => RocketChat.models.Users.findOneByUsername(username)
- );
+ const ids = RocketChat.models.Subscriptions.findByRoomIdWhenUserIdExists(root._id, { fields: { 'u._id': 1 } })
+ .fetch()
+ .map(sub => sub.u._id);
+ return RocketChat.models.Users.findByIds(ids).fetch();
},
owners: (root) => {
// there might be no owner
@@ -26,7 +27,9 @@ const resolver = {
return [RocketChat.models.Users.findOneByUsername(root.u.username)];
},
- numberOfMembers: (root) => (root.usernames || []).length,
+ numberOfMembers: (root) => {
+ return RocketChat.models.Subscriptions.findByRoomId(root._id).count();
+ },
numberOfMessages: property('msgs'),
readOnly: (root) => root.ro === true,
direct: (root) => root.t === 'd',
diff --git a/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js
index 4fdc6e15a309..2b46164bf620 100644
--- a/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js
+++ b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js
@@ -13,7 +13,8 @@ const resolver = {
throw new Error('No user');
}
- const rooms = RocketChat.models.Rooms.findByContainingUsername(user.username, {
+ const roomIds = RocketChat.models.Subscriptions.findByUserId(userId, { fields: { rid: 1 } }).fetch().map(s => s.rid);
+ const rooms = RocketChat.models.Rooms.findByIds(roomIds, {
sort: {
name: 1
},
diff --git a/packages/rocketchat-graphql/server/resolvers/users/User-type.js b/packages/rocketchat-graphql/server/resolvers/users/User-type.js
index d768b78ab7f8..ee4df2393346 100644
--- a/packages/rocketchat-graphql/server/resolvers/users/User-type.js
+++ b/packages/rocketchat-graphql/server/resolvers/users/User-type.js
@@ -21,7 +21,7 @@ const resolver = {
return await RocketChat.models.Rooms.findBySubscriptionUserId(_id).fetch();
}),
directMessages: ({ username }) => {
- return RocketChat.models.Rooms.findByTypeContainingUsername('d', username).fetch();
+ return RocketChat.models.Rooms.findDirectRoomContainingUsername(username).fetch();
}
}
};
diff --git a/packages/rocketchat-integrations/server/lib/triggerHandler.js b/packages/rocketchat-integrations/server/lib/triggerHandler.js
index 36a9b4777634..0894f3fb1ea3 100644
--- a/packages/rocketchat-integrations/server/lib/triggerHandler.js
+++ b/packages/rocketchat-integrations/server/lib/triggerHandler.js
@@ -89,12 +89,11 @@ RocketChat.integrations.triggerHandler = new class RocketChatIntegrationHandler
history.data = { ...data };
if (data.user) {
- history.data.user = _.omit(data.user, ['meta', '$loki', 'services']);
+ history.data.user = _.omit(data.user, ['services']);
}
if (data.room) {
- history.data.room = _.omit(data.room, ['meta', '$loki', 'usernames']);
- history.data.room.usernames = ['this_will_be_filled_in_with_usernames_when_replayed'];
+ history.data.room = data.room;
}
}
diff --git a/packages/rocketchat-integrations/server/lib/validation.js b/packages/rocketchat-integrations/server/lib/validation.js
index 22f83b80a780..22c06a8ce6dd 100644
--- a/packages/rocketchat-integrations/server/lib/validation.js
+++ b/packages/rocketchat-integrations/server/lib/validation.js
@@ -70,7 +70,7 @@ function _verifyUserHasPermissionForChannels(integration, userId, channels) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { function: 'validateOutgoing._verifyUserHasPermissionForChannels' });
}
- if (record.usernames && !RocketChat.authz.hasPermission(userId, 'manage-integrations') && RocketChat.authz.hasPermission(userId, 'manage-own-integrations') && !record.usernames.includes(Meteor.user().username)) {
+ if (!RocketChat.authz.hasAllPermission(userId, 'manage-integrations', 'manage-own-integrations') && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(record._id, userId, { fields: { _id: 1 } })) {
throw new Meteor.Error('error-invalid-channel', 'Invalid Channel', { function: 'validateOutgoing._verifyUserHasPermissionForChannels' });
}
}
diff --git a/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.js b/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.js
index ffababb1d137..c933d9d4de87 100644
--- a/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.js
+++ b/packages/rocketchat-integrations/server/methods/incoming/addIncomingIntegration.js
@@ -70,7 +70,7 @@ Meteor.methods({
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'addIncomingIntegration' });
}
- if (record.usernames && !RocketChat.authz.hasPermission(this.userId, 'manage-integrations') && RocketChat.authz.hasPermission(this.userId, 'manage-own-integrations') && !record.usernames.includes(Meteor.user().username)) {
+ if (!RocketChat.authz.hasAllPermission(this.userId, 'manage-integrations', 'manage-own-integrations') && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(record._id, this.userId, { fields: { _id: 1 } })) {
throw new Meteor.Error('error-invalid-channel', 'Invalid Channel', { method: 'addIncomingIntegration' });
}
}
diff --git a/packages/rocketchat-integrations/server/methods/incoming/updateIncomingIntegration.js b/packages/rocketchat-integrations/server/methods/incoming/updateIncomingIntegration.js
index bb789b816ad8..789c12e3bdaf 100644
--- a/packages/rocketchat-integrations/server/methods/incoming/updateIncomingIntegration.js
+++ b/packages/rocketchat-integrations/server/methods/incoming/updateIncomingIntegration.js
@@ -72,7 +72,7 @@ Meteor.methods({
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'updateIncomingIntegration' });
}
- if (record.usernames && !RocketChat.authz.hasPermission(this.userId, 'manage-integrations') && RocketChat.authz.hasPermission(this.userId, 'manage-own-integrations') && !record.usernames.includes(Meteor.user().username)) {
+ if (!RocketChat.authz.hasAllPermission(this.userId, 'manage-integrations', 'manage-own-integrations') && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(record._id, this.userId, { fields: { _id: 1 } })) {
throw new Meteor.Error('error-invalid-channel', 'Invalid Channel', { method: 'updateIncomingIntegration' });
}
}
diff --git a/packages/rocketchat-integrations/server/processWebhookMessage.js b/packages/rocketchat-integrations/server/processWebhookMessage.js
index 91b3a85f55ab..76aa1e73a672 100644
--- a/packages/rocketchat-integrations/server/processWebhookMessage.js
+++ b/packages/rocketchat-integrations/server/processWebhookMessage.js
@@ -37,7 +37,7 @@ this.processWebhookMessage = function(messageObj, user, defaultValues = { channe
throw new Meteor.Error('invalid-channel');
}
- if (mustBeJoined && !room.usernames.includes(user.username)) {
+ if (mustBeJoined && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id, { fields: { _id: 1 } })) {
// throw new Meteor.Error('invalid-room', 'Invalid room provided to send a message to, must be joined.');
throw new Meteor.Error('invalid-channel'); // Throwing the generic one so people can't "brute force" find rooms
}
diff --git a/packages/rocketchat-lib/client/lib/cachedCollection.js b/packages/rocketchat-lib/client/lib/cachedCollection.js
index d1f6b3484f96..4daa5d35467f 100644
--- a/packages/rocketchat-lib/client/lib/cachedCollection.js
+++ b/packages/rocketchat-lib/client/lib/cachedCollection.js
@@ -213,7 +213,6 @@ class CachedCollection {
Meteor.call(this.methodName, (error, data) => {
this.log(`${ data.length } records loaded from server`);
data.forEach((record) => {
- delete record.$loki;
RocketChat.callbacks.run(`cachedCollection-loadFromServer-${ this.name }`, record, 'changed');
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
@@ -276,7 +275,6 @@ class CachedCollection {
});
for (const record of changes) {
- delete record.$loki;
RocketChat.callbacks.run(`cachedCollection-sync-${ this.name }`, record, record._deletedAt? 'removed' : 'changed');
if (record._deletedAt) {
this.collection.remove({ _id: record._id });
@@ -342,7 +340,6 @@ class CachedCollection {
this.collection.remove(record._id);
RoomManager.close(record.t+record.name);
} else {
- delete record.$loki;
this.collection.upsert({ _id: record._id }, _.omit(record, '_id'));
}
diff --git a/packages/rocketchat-lib/client/lib/openRoom.js b/packages/rocketchat-lib/client/lib/openRoom.js
index 3ca566a57cc4..09dac262d5ea 100644
--- a/packages/rocketchat-lib/client/lib/openRoom.js
+++ b/packages/rocketchat-lib/client/lib/openRoom.js
@@ -42,7 +42,6 @@ function openRoom(type, name) {
Session.set('roomNotFound', {type, name});
return BlazeLayout.render('main', {center: 'roomNotFound'});
} else {
- delete record.$loki;
RocketChat.models.Rooms.upsert({ _id: record._id }, _.omit(record, '_id'));
RoomManager.close(type + name);
return openRoom(type, name);
diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js
index 4592252e5633..e1d0cec3e599 100644
--- a/packages/rocketchat-lib/package.js
+++ b/packages/rocketchat-lib/package.js
@@ -141,9 +141,6 @@ Package.onUse(function(api) {
api.addFiles('server/startup/statsTracker.js', 'server');
- // CACHE
- api.addFiles('server/startup/cache/CacheLoad.js', 'server');
-
// SERVER PUBLICATIONS
api.addFiles('server/publications/settings.js', 'server');
diff --git a/packages/rocketchat-lib/server/functions/Notifications.js b/packages/rocketchat-lib/server/functions/Notifications.js
index 808d0b8bb902..7e0e09f4b7ad 100644
--- a/packages/rocketchat-lib/server/functions/Notifications.js
+++ b/packages/rocketchat-lib/server/functions/Notifications.js
@@ -27,11 +27,6 @@ RocketChat.Notifications = new class {
this.streamLogged.allowRead('logged');
this.streamRoom.allowRead(function(eventName, extraData) {
const [roomId] = eventName.split('/');
- const user = Meteor.users.findOne(this.userId, {
- fields: {
- username: 1
- }
- });
const room = RocketChat.models.Rooms.findOneById(roomId);
if (!room) {
console.warn(`Invalid streamRoom eventName: "${ eventName }"`);
@@ -43,7 +38,8 @@ RocketChat.Notifications = new class {
if (this.userId == null) {
return false;
}
- return room.usernames.indexOf(user.username) > -1;
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, this.userId, { fields: { _id: 1 } });
+ return subscription != null;
});
this.streamRoomUsers.allowRead('none');
this.streamUser.allowRead(function(eventName) {
diff --git a/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js b/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js
index 414e5e3b7588..71718be0b84c 100644
--- a/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js
+++ b/packages/rocketchat-lib/server/functions/addUserToDefaultChannels.js
@@ -5,7 +5,9 @@ RocketChat.addUserToDefaultChannels = function(user, silenced) {
// put user in default rooms
const muted = room.ro && !RocketChat.authz.hasPermission(user._id, 'post-readonly');
- RocketChat.models.Rooms.addUsernameById(room._id, user.username, muted);
+ if (muted) {
+ RocketChat.models.Rooms.muteUsernameByRoomId(room._id, user.username);
+ }
if (!RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id)) {
diff --git a/packages/rocketchat-lib/server/functions/addUserToRoom.js b/packages/rocketchat-lib/server/functions/addUserToRoom.js
index 527b68fab3f8..42a8823c6edc 100644
--- a/packages/rocketchat-lib/server/functions/addUserToRoom.js
+++ b/packages/rocketchat-lib/server/functions/addUserToRoom.js
@@ -13,7 +13,10 @@ RocketChat.addUserToRoom = function(rid, user, inviter, silenced) {
}
const muted = room.ro && !RocketChat.authz.hasPermission(user._id, 'post-readonly');
- RocketChat.models.Rooms.addUsernameById(rid, user.username, muted);
+ if (muted) {
+ RocketChat.models.Rooms.muteUsernameByRoomId(rid, user.username);
+ }
+
RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
ts: now,
open: true,
diff --git a/packages/rocketchat-lib/server/functions/createRoom.js b/packages/rocketchat-lib/server/functions/createRoom.js
index 0aa21c9e96dd..385b4ef43a8e 100644
--- a/packages/rocketchat-lib/server/functions/createRoom.js
+++ b/packages/rocketchat-lib/server/functions/createRoom.js
@@ -31,7 +31,7 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData
fname: name,
t: type,
msgs: 0,
- usernames: members,
+ usersCount: 0,
u: {
_id: owner._id,
username: owner.username
@@ -42,6 +42,10 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData
sysMes: readOnly !== true
});
+ if (type === 'd') {
+ room.usernames = members;
+ }
+
if (Apps && Apps.isLoaded()) {
const prevent = Promise.await(Apps.getBridges().getListenerBridge().roomEvent('IPreRoomCreatePrevent', room));
if (prevent) {
diff --git a/packages/rocketchat-lib/server/functions/deleteUser.js b/packages/rocketchat-lib/server/functions/deleteUser.js
index 362dc83a5014..5a65b0fae5fb 100644
--- a/packages/rocketchat-lib/server/functions/deleteUser.js
+++ b/packages/rocketchat-lib/server/functions/deleteUser.js
@@ -19,7 +19,7 @@ RocketChat.deleteUser = function(userId) {
RocketChat.models.Subscriptions.db.findByUserId(userId).forEach((subscription) => {
const room = RocketChat.models.Rooms.findOneById(subscription.rid);
if (room) {
- if (room.t !== 'c' && room.usernames.length === 1) {
+ if (room.t !== 'c' && RocketChat.models.Subscriptions.findByRoomId(room._id).count() === 1) {
RocketChat.models.Rooms.removeById(subscription.rid); // Remove non-channel rooms with only 1 user (the one being deleted)
}
if (room.t === 'd') {
@@ -30,8 +30,7 @@ RocketChat.deleteUser = function(userId) {
});
RocketChat.models.Subscriptions.removeByUserId(userId); // Remove user subscriptions
- RocketChat.models.Rooms.removeByTypeContainingUsername('d', user.username); // Remove direct rooms with the user
- RocketChat.models.Rooms.removeUsernameFromAll(user.username); // Remove user from all other rooms
+ RocketChat.models.Rooms.removeDirectRoomContainingUsername(user.username); // Remove direct rooms with the user
// removes user's avatar
if (user.avatarOrigin === 'upload' || user.avatarOrigin === 'url') {
diff --git a/packages/rocketchat-lib/server/functions/removeUserFromRoom.js b/packages/rocketchat-lib/server/functions/removeUserFromRoom.js
index 87b9faf5d086..dc910a0a7ab1 100644
--- a/packages/rocketchat-lib/server/functions/removeUserFromRoom.js
+++ b/packages/rocketchat-lib/server/functions/removeUserFromRoom.js
@@ -3,9 +3,10 @@ RocketChat.removeUserFromRoom = function(rid, user) {
if (room) {
RocketChat.callbacks.run('beforeLeaveRoom', user, room);
- RocketChat.models.Rooms.removeUsernameById(rid, user.username);
- if (room.usernames.indexOf(user.username) !== -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, user._id, { fields: { _id: 1 } });
+
+ if (subscription) {
const removedUser = user;
RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(rid, removedUser);
}
@@ -17,6 +18,7 @@ RocketChat.removeUserFromRoom = function(rid, user) {
RocketChat.models.Subscriptions.removeByRoomIdAndUserId(rid, user._id);
Meteor.defer(function() {
+ // TODO: CACHE: maybe a queue?
RocketChat.callbacks.run('afterLeaveRoom', user, room);
});
}
diff --git a/packages/rocketchat-lib/server/functions/sendMessage.js b/packages/rocketchat-lib/server/functions/sendMessage.js
index 321d085641f0..ff3bc8bef8ae 100644
--- a/packages/rocketchat-lib/server/functions/sendMessage.js
+++ b/packages/rocketchat-lib/server/functions/sendMessage.js
@@ -91,15 +91,6 @@ RocketChat.sendMessage = function(user, message, room, upsert = false) {
message.ts = new Date();
}
- if (!room.usernames || room.usernames.length === 0) {
- const updated_room = RocketChat.models.Rooms.findOneById(room._id);
- if (updated_room) {
- room = updated_room;
- } else {
- room.usernames = [];
- }
- }
-
if (RocketChat.settings.get('Message_Read_Receipt_Enabled')) {
message.unread = true;
}
diff --git a/packages/rocketchat-lib/server/functions/setRealName.js b/packages/rocketchat-lib/server/functions/setRealName.js
index da7be9783ca0..8781bfb15658 100644
--- a/packages/rocketchat-lib/server/functions/setRealName.js
+++ b/packages/rocketchat-lib/server/functions/setRealName.js
@@ -17,6 +17,8 @@ RocketChat._setRealName = function(userId, name) {
RocketChat.models.Users.setName(user._id, name);
user.name = name;
+ RocketChat.models.Subscriptions.updateDirectFNameByName(user.username, name);
+
if (RocketChat.settings.get('UI_Use_Real_Name') === true) {
RocketChat.Notifications.notifyLogged('Users:NameChanged', {
_id: user._id,
diff --git a/packages/rocketchat-lib/server/lib/debug.js b/packages/rocketchat-lib/server/lib/debug.js
index 7b0631970320..faf36b1e4a92 100644
--- a/packages/rocketchat-lib/server/lib/debug.js
+++ b/packages/rocketchat-lib/server/lib/debug.js
@@ -46,7 +46,11 @@ const traceConnection = (enable, filter, prefix, name, connection, userId) => {
const wrapMethods = function(name, originalHandler, methodsMap) {
methodsMap[name] = function() {
traceConnection(Log_Trace_Methods, Log_Trace_Methods_Filter, 'method', name, this.connection, this.userId);
- const end = RocketChat.metrics.meteorMethods.startTimer({method: name});
+ const end = RocketChat.metrics.meteorMethods.startTimer({
+ method: name,
+ has_connection: this.connection != null,
+ has_user: this.userId != null
+ });
const args = name === 'ufsWrite' ? Array.prototype.slice.call(arguments, 1) : arguments;
logger.method(name, '-> userId:', Meteor.userId(), ', arguments: ', args);
diff --git a/packages/rocketchat-lib/server/lib/metrics.js b/packages/rocketchat-lib/server/lib/metrics.js
index 61ac0298bd2b..af838ba23d18 100644
--- a/packages/rocketchat-lib/server/lib/metrics.js
+++ b/packages/rocketchat-lib/server/lib/metrics.js
@@ -13,7 +13,7 @@ RocketChat.metrics = {};
RocketChat.metrics.meteorMethods = new client.Summary({
name: 'rocketchat_meteor_methods',
help: 'summary of meteor methods count and time',
- labelNames: ['method']
+ labelNames: ['method', 'has_connection', 'has_user']
});
RocketChat.metrics.rocketchatCallbacks = new client.Summary({
diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
index 675f0f6bf50f..2769f4c91fab 100644
--- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
+++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
@@ -174,7 +174,8 @@ function sendAllNotifications(message, room) {
// Don't fetch all users if room exceeds max members
const maxMembersForNotification = RocketChat.settings.get('Notifications_Max_Room_Members');
- const disableAllMessageNotifications = room.usernames && room.usernames.length > maxMembersForNotification && maxMembersForNotification !== 0;
+ const roomMembersCount = RocketChat.models.Subscriptions.findByRoomId(room._id).count();
+ const disableAllMessageNotifications = roomMembersCount > maxMembersForNotification && maxMembersForNotification !== 0;
const query = {
rid: room._id,
@@ -236,29 +237,23 @@ function sendAllNotifications(message, room) {
// on public channels, if a mentioned user is not member of the channel yet, he will first join the channel and then be notified based on his preferences.
if (room.t === 'c') {
- Promise.all(message.mentions
- .filter(({ _id, username }) => _id !== 'here' && _id !== 'all' && !room.usernames.includes(username))
- .map(async(user) => {
- await callJoinRoom(user, room._id);
-
- return user._id;
- })
- ).then((users) => {
- users.forEach((userId) => {
- const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, userId);
-
- sendNotification({
- subscription,
- sender,
- hasMentionToAll,
- hasMentionToHere,
- message,
- notificationMessage,
- room,
- mentionIds
- });
- });
- });
+ const mentions = message.mentions.filter(({ _id }) => _id !== 'here' && _id !== 'all').map(({ _id }) => _id);
+ Promise.all(RocketChat.models.Subscriptions.findByRoomIdAndUserIds(room._id, mentions)
+ .fetch()
+ .map(async subscription => {
+ await callJoinRoom(subscription.u, room._id);
+ return subscription;
+ })).then(subscriptions => subscriptions.forEach(subscription =>
+ sendNotification({
+ subscription,
+ sender,
+ hasMentionToAll,
+ hasMentionToHere,
+ message,
+ notificationMessage,
+ room,
+ mentionIds
+ })));
}
return message;
diff --git a/packages/rocketchat-lib/server/methods/addUsersToRoom.js b/packages/rocketchat-lib/server/methods/addUsersToRoom.js
index b00c42350d31..5a85068bdc06 100644
--- a/packages/rocketchat-lib/server/methods/addUsersToRoom.js
+++ b/packages/rocketchat-lib/server/methods/addUsersToRoom.js
@@ -16,8 +16,8 @@ Meteor.methods({
// Get user and room details
const room = RocketChat.models.Rooms.findOneById(data.rid);
const userId = Meteor.userId();
- const user = Meteor.user();
- const userInRoom = Array.isArray(room.usernames) && room.usernames.includes(user.username);
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(data.rid, userId, { fields: { _id: 1 } });
+ const userInRoom = subscription != null;
// Can't add to direct room ever
if (room.t === 'd') {
@@ -51,6 +51,7 @@ Meteor.methods({
}
// Validate each user, then add to room
+ const user = Meteor.user();
data.users.forEach((username) => {
const newUser = RocketChat.models.Users.findOneByUsername(username);
if (!newUser) {
@@ -58,7 +59,6 @@ Meteor.methods({
method: 'addUsersToRoom'
});
}
-
RocketChat.addUserToRoom(data.rid, newUser, user);
});
diff --git a/packages/rocketchat-lib/server/methods/getChannelHistory.js b/packages/rocketchat-lib/server/methods/getChannelHistory.js
index b3583cb253ea..a8039a7594f6 100644
--- a/packages/rocketchat-lib/server/methods/getChannelHistory.js
+++ b/packages/rocketchat-lib/server/methods/getChannelHistory.js
@@ -15,7 +15,7 @@ Meteor.methods({
}
//Make sure they can access the room
- if (room.t === 'c' && !RocketChat.authz.hasPermission(fromUserId, 'preview-c-room') && room.usernames.indexOf(room.username) === -1) {
+ if (room.t === 'c' && !RocketChat.authz.hasPermission(fromUserId, 'preview-c-room') && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, fromUserId, { fields: { _id: 1 } })) {
return false;
}
diff --git a/packages/rocketchat-lib/server/methods/leaveRoom.js b/packages/rocketchat-lib/server/methods/leaveRoom.js
index dd13f2e67ba0..c85a44e1fefb 100644
--- a/packages/rocketchat-lib/server/methods/leaveRoom.js
+++ b/packages/rocketchat-lib/server/methods/leaveRoom.js
@@ -16,18 +16,19 @@ Meteor.methods({
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'leaveRoom' });
}
- if (!Array.from(room.usernames || []).includes(user.username)) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, user._id, { fields: { _id: 1 } });
+ if (!subscription) {
throw new Meteor.Error('error-user-not-in-room', 'You are not in this room', { method: 'leaveRoom' });
}
// If user is room owner, check if there are other owners. If there isn't anyone else, warn user to set a new owner.
if (RocketChat.authz.hasRole(user._id, 'owner', room._id)) {
- const numOwners = RocketChat.authz.getUsersInRole('owner', room._id).fetch().length;
+ const numOwners = RocketChat.authz.getUsersInRole('owner', room._id).count();
if (numOwners === 1) {
throw new Meteor.Error('error-you-are-last-owner', 'You are the last owner. Please set new owner before leaving the room.', { method: 'leaveRoom' });
}
}
- return RocketChat.removeUserFromRoom(rid, Meteor.user());
+ return RocketChat.removeUserFromRoom(rid, user);
}
});
diff --git a/packages/rocketchat-lib/server/models/Rooms.js b/packages/rocketchat-lib/server/models/Rooms.js
index 09b04176d229..b714069c78fc 100644
--- a/packages/rocketchat-lib/server/models/Rooms.js
+++ b/packages/rocketchat-lib/server/models/Rooms.js
@@ -7,13 +7,8 @@ class ModelRooms extends RocketChat.models._Base {
this.tryEnsureIndex({ 'name': 1 }, { unique: 1, sparse: 1 });
this.tryEnsureIndex({ 'default': 1 });
- this.tryEnsureIndex({ 'usernames': 1 });
this.tryEnsureIndex({ 't': 1 });
this.tryEnsureIndex({ 'u._id': 1 });
-
- this.cache.ignoreUpdatedFields = ['msgs', 'lm'];
- this.cache.ensureIndex(['t', 'name'], 'unique');
- this.cache.options = {fields: {usernames: 0}};
}
findOneByIdOrName(_idOrName, options) {
@@ -64,28 +59,6 @@ class ModelRooms extends RocketChat.models._Base {
return this.findOne(query, options);
}
- findOneByIdContainingUsername(_id, username, options) {
- const query = {
- _id,
- usernames: username
- };
-
- return this.findOne(query, options);
- }
-
- findOneByNameAndTypeNotContainingUsername(name, type, username, options) {
- const query = {
- name,
- t: type,
- usernames: {
- $ne: username
- }
- };
-
- return this.findOne(query, options);
- }
-
-
// FIND
findWithUsername(username, options) {
@@ -106,6 +79,17 @@ class ModelRooms extends RocketChat.models._Base {
return this.find(query, options);
}
+ findByTypeInIds(type, ids, options) {
+ const query = {
+ _id: {
+ $in: ids
+ },
+ t: type
+ };
+
+ return this.find(query, options);
+ }
+
findByTypes(types, options) {
const query = {
t: {
@@ -123,23 +107,24 @@ class ModelRooms extends RocketChat.models._Base {
}
findBySubscriptionUserId(userId, options) {
- let data;
- if (this.useCache) {
- data = RocketChat.models.Subscriptions.findByUserId(userId).fetch();
- data = data.map(function(item) {
- if (item._room) {
- return item._room;
- }
- console.log('Empty Room for Subscription', item);
- });
- data = data.filter(item => item);
- return this.arrayToCursor(this.processQueryOptionsOnResult(data, options));
- }
+ const data = RocketChat.models.Subscriptions.findByUserId(userId, { fields: { rid: 1 } }).fetch()
+ .map(item => item.rid);
+
+ const query = {
+ _id: {
+ $in: data
+ }
+ };
+
+ return this.find(query, options);
+ }
- data = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch();
- data = data.map(item => item.rid);
+ findBySubscriptionTypeAndUserId(type, userId, options) {
+ const data = RocketChat.models.Subscriptions.findByUserIdAndType(userId, type, { fields: { rid: 1 } }).fetch()
+ .map(item => item.rid);
const query = {
+ t: type,
_id: {
$in: data
}
@@ -149,20 +134,8 @@ class ModelRooms extends RocketChat.models._Base {
}
findBySubscriptionUserIdUpdatedAfter(userId, _updatedAt, options) {
- if (this.useCache) {
- let data = RocketChat.models.Subscriptions.findByUserId(userId).fetch();
- data = data.map(function(item) {
- if (item._room) {
- return item._room;
- }
- console.log('Empty Room for Subscription', item);
- });
- data = data.filter(item => item && item._updatedAt > _updatedAt);
- return this.arrayToCursor(this.processQueryOptionsOnResult(data, options));
- }
-
- let ids = RocketChat.models.Subscriptions.findByUserId(userId, {fields: {rid: 1}}).fetch();
- ids = ids.map(item => item.rid);
+ const ids = RocketChat.models.Subscriptions.findByUserId(userId, { fields: { rid: 1 } }).fetch()
+ .map(item => item.rid);
const query = {
_id: {
@@ -192,45 +165,6 @@ class ModelRooms extends RocketChat.models._Base {
return this.find(query, options);
}
- findByNameContainingTypesWithUsername(name, types, options) {
- const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
-
- const $or = [];
- for (const type of Array.from(types)) {
- const obj = {name: nameRegex, t: type.type};
- if (type.username != null) {
- obj.usernames = type.username;
- }
- if (type.ids != null) {
- obj._id = {$in: type.ids};
- }
- $or.push(obj);
- }
-
- const query = {$or};
-
- return this.find(query, options);
- }
-
- findContainingTypesWithUsername(types, options) {
-
- const $or = [];
- for (const type of Array.from(types)) {
- const obj = {t: type.type};
- if (type.username != null) {
- obj.usernames = type.username;
- }
- if (type.ids != null) {
- obj._id = {$in: type.ids};
- }
- $or.push(obj);
- }
-
- const query = {$or};
-
- return this.find(query, options);
- }
-
findByNameContainingAndTypes(name, types, options) {
const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
@@ -273,35 +207,29 @@ class ModelRooms extends RocketChat.models._Base {
return this._db.find(query, options);
}
- findByNameAndTypesNotContainingUsername(name, types, username, options) {
+ findByNameAndTypesNotInIds(name, types, ids, options) {
const query = {
+ _id: {
+ $ne: ids
+ },
t: {
$in: types
},
- name,
- usernames: {
- $ne: username
- }
+ name
};
// do not use cache
return this._db.find(query, options);
}
- findByNameStartingAndTypes(name, types, options) {
+ findChannelAndPrivateByNameStarting(name, options) {
const nameRegex = new RegExp(`^${ s.trim(s.escapeRegExp(name)) }`, 'i');
const query = {
t: {
- $in: types
+ $in: ['c', 'p']
},
- $or: [
- {name: nameRegex},
- {
- t: 'd',
- usernames: nameRegex
- }
- ]
+ name: nameRegex
};
return this.find(query, options);
@@ -318,62 +246,44 @@ class ModelRooms extends RocketChat.models._Base {
return this.find(query, options);
}
- findByTypeContainingUsername(type, username, options) {
+ findDirectRoomContainingUsername(username, options) {
const query = {
- t: type,
+ t: 'd',
usernames: username
};
return this.find(query, options);
}
- findByTypeContainingUsernames(type, username, options) {
- const query = {
- t: type,
- usernames: { $all: [].concat(username) }
- };
-
- return this.find(query, options);
- }
-
- findByTypesAndNotUserIdContainingUsername(types, userId, username, options) {
+ findByTypeAndName(type, name, options) {
const query = {
- t: {
- $in: types
- },
- uid: {
- $ne: userId
- },
- usernames: username
+ name,
+ t: type
};
return this.find(query, options);
}
- findByContainingUsername(username, options) {
- const query = {usernames: username};
-
- return this.find(query, options);
- }
-
- findByTypeAndName(type, name, options) {
- if (this.useCache) {
- return this.cache.findByIndex('t,name', [type, name], options);
- }
+ findByTypeAndNameContaining(type, name, options) {
+ const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
const query = {
- name,
+ name: nameRegex,
t: type
};
return this.find(query, options);
}
- findByTypeAndNameContainingUsername(type, name, username, options) {
+ findByTypeInIdsAndNameContaining(type, ids, name, options) {
+ const nameRegex = new RegExp(s.trim(s.escapeRegExp(name)), 'i');
+
const query = {
- name,
- t: type,
- usernames: username
+ _id: {
+ $in: ids
+ },
+ name: nameRegex,
+ t: type
};
return this.find(query, options);
@@ -431,98 +341,6 @@ class ModelRooms extends RocketChat.models._Base {
return this.update(query, update);
}
- addUsernameById(_id, username, muted) {
- const query = {_id};
-
- const update = {
- $addToSet: {
- usernames: username
- }
- };
-
- if (muted) {
- update.$addToSet.muted = username;
- }
-
- return this.update(query, update);
- }
-
- addUsernamesById(_id, usernames) {
- const query = {_id};
-
- const update = {
- $addToSet: {
- usernames: {
- $each: usernames
- }
- }
- };
-
- return this.update(query, update);
- }
-
- addUsernameByName(name, username) {
- const query = {name};
-
- const update = {
- $addToSet: {
- usernames: username
- }
- };
-
- return this.update(query, update);
- }
-
- removeUsernameById(_id, username) {
- const query = {_id};
-
- const update = {
- $pull: {
- usernames: username
- }
- };
-
- return this.update(query, update);
- }
-
- removeUsernamesById(_id, usernames) {
- const query = {_id};
-
- const update = {
- $pull: {
- usernames: {
- $in: usernames
- }
- }
- };
-
- return this.update(query, update);
- }
-
- removeUsernameFromAll(username) {
- const query = {usernames: username};
-
- const update = {
- $pull: {
- usernames: username
- }
- };
-
- return this.update(query, update, { multi: true });
- }
-
- removeUsernameByName(name, username) {
- const query = {name};
-
- const update = {
- $pull: {
- usernames: username
- }
- };
-
- return this.update(query, update);
- }
-
setNameById(_id, name, fname) {
const query = {_id};
@@ -581,6 +399,34 @@ class ModelRooms extends RocketChat.models._Base {
return this.update(query, update);
}
+ incUsersCountById(_id, inc = 1) {
+ const query = { _id };
+
+ const update = {
+ $inc: {
+ usersCount: inc
+ }
+ };
+
+ return this.update(query, update);
+ }
+
+ incUsersCountByIds(ids, inc = 1) {
+ const query = {
+ _id: {
+ $in: ids
+ }
+ };
+
+ const update = {
+ $inc: {
+ usersCount: inc
+ }
+ };
+
+ return this.update(query, update, {multi: true});
+ }
+
setLastMessageById(_id, lastMessage) {
const query = {_id};
@@ -801,6 +647,7 @@ class ModelRooms extends RocketChat.models._Base {
t: type,
usernames,
msgs: 0,
+ usersCount: 0,
u: {
_id: user._id,
username: user.username
@@ -820,7 +667,8 @@ class ModelRooms extends RocketChat.models._Base {
t: type,
name,
usernames: [],
- msgs: 0
+ msgs: 0,
+ usersCount: 0
};
_.extend(room, extraData);
@@ -844,9 +692,9 @@ class ModelRooms extends RocketChat.models._Base {
return this.remove(query);
}
- removeByTypeContainingUsername(type, username) {
+ removeDirectRoomContainingUsername(username) {
const query = {
- t: type,
+ t: 'd',
usernames: username
};
diff --git a/packages/rocketchat-lib/server/models/Subscriptions.js b/packages/rocketchat-lib/server/models/Subscriptions.js
index 12d40fedee78..d3bfa893c3dc 100644
--- a/packages/rocketchat-lib/server/models/Subscriptions.js
+++ b/packages/rocketchat-lib/server/models/Subscriptions.js
@@ -3,6 +3,7 @@ class ModelSubscriptions extends RocketChat.models._Base {
super(...arguments);
this.tryEnsureIndex({ 'rid': 1, 'u._id': 1 }, { unique: 1 });
+ this.tryEnsureIndex({ 'rid': 1, 'u.username': 1 });
this.tryEnsureIndex({ 'rid': 1, 'alert': 1, 'u._id': 1 });
this.tryEnsureIndex({ 'rid': 1, 'roles': 1 });
this.tryEnsureIndex({ 'u._id': 1, 'name': 1, 't': 1 });
@@ -20,20 +21,11 @@ class ModelSubscriptions extends RocketChat.models._Base {
this.tryEnsureIndex({ 'autoTranslate': 1 }, { sparse: 1 });
this.tryEnsureIndex({ 'autoTranslateLanguage': 1 }, { sparse: 1 });
this.tryEnsureIndex({ 'userHighlights.0': 1 }, { sparse: 1 });
-
- this.cache.ensureIndex('rid', 'array');
- this.cache.ensureIndex('u._id', 'array');
- this.cache.ensureIndex('name', 'array');
- this.cache.ensureIndex(['rid', 'u._id'], 'unique');
- this.cache.ensureIndex(['name', 'u._id'], 'unique');
}
// FIND ONE
findOneByRoomIdAndUserId(roomId, userId, options) {
- if (this.useCache) {
- return this.cache.findByIndex('rid,u._id', [roomId, userId], options).fetch();
- }
const query = {
rid: roomId,
'u._id': userId
@@ -42,10 +34,16 @@ class ModelSubscriptions extends RocketChat.models._Base {
return this.findOne(query, options);
}
+ findOneByRoomIdAndUsername(roomId, username, options) {
+ const query = {
+ rid: roomId,
+ 'u.username': username
+ };
+
+ return this.findOne(query, options);
+ }
+
findOneByRoomNameAndUserId(roomName, userId) {
- if (this.useCache) {
- return this.cache.findByIndex('name,u._id', [roomName, userId]).fetch();
- }
const query = {
name: roomName,
'u._id': userId
@@ -56,16 +54,32 @@ class ModelSubscriptions extends RocketChat.models._Base {
// FIND
findByUserId(userId, options) {
- if (this.useCache) {
- return this.cache.findByIndex('u._id', userId, options);
- }
-
const query =
{ 'u._id': userId };
return this.find(query, options);
}
+ findByUserIdAndType(userId, type, options) {
+ const query = {
+ 'u._id': userId,
+ t: type
+ };
+
+ return this.find(query, options);
+ }
+
+ findByUserIdAndTypes(userId, types, options) {
+ const query = {
+ 'u._id': userId,
+ t: {
+ $in: types
+ }
+ };
+
+ return this.find(query, options);
+ }
+
findByUserIdUpdatedAfter(userId, updatedAt, options) {
const query = {
'u._id': userId,
@@ -106,21 +120,7 @@ class ModelSubscriptions extends RocketChat.models._Base {
return this.find(query, options);
}
- findByTypeNameAndUserId(type, name, userId, options) {
- const query = {
- t: type,
- name,
- 'u._id': userId
- };
-
- return this.find(query, options);
- }
-
findByRoomId(roomId, options) {
- if (this.useCache) {
- return this.cache.findByIndex('rid', roomId, options);
- }
-
const query =
{ rid: roomId };
@@ -181,6 +181,18 @@ class ModelSubscriptions extends RocketChat.models._Base {
return this.find(query);
}
+ findByRoomIdWhenUserIdExists(rid, options) {
+ const query = { rid, 'u._id': { $exists: 1 } };
+
+ return this.find(query, options);
+ }
+
+ findByRoomIdWhenUsernameExists(rid, options) {
+ const query = { rid, 'u.username': { $exists: 1 } };
+
+ return this.find(query, options);
+ }
+
findUnreadByUserId(userId) {
const query = {
'u._id': userId,
@@ -745,6 +757,21 @@ class ModelSubscriptions extends RocketChat.models._Base {
return this.update(query, update, { multi: true });
}
+ updateDirectFNameByName(name, fname) {
+ const query = {
+ t: 'd',
+ name
+ };
+
+ const update = {
+ $set: {
+ fname
+ }
+ };
+
+ return this.update(query, update, { multi: true });
+ }
+
// INSERT
createWithRoomAndUser(room, user, extraData) {
const subscription = {
@@ -768,23 +795,43 @@ class ModelSubscriptions extends RocketChat.models._Base {
...extraData
};
- return this.insert(subscription);
+ const result = this.insert(subscription);
+
+ RocketChat.models.Rooms.incUsersCountById(room._id);
+
+ return result;
}
// REMOVE
removeByUserId(userId) {
- const query =
- { 'u._id': userId };
+ const query = {
+ 'u._id': userId
+ };
+
+ const roomIds = this.findByUserId(userId).map(s => s.rid);
+
+ const result = this.remove(query);
+
+ if (Match.test(result, Number) && result > 0) {
+ RocketChat.models.Rooms.incUsersCountByIds(roomIds, -1);
+ }
- return this.remove(query);
+ return result;
}
removeByRoomId(roomId) {
- const query =
- { rid: roomId };
+ const query = {
+ rid: roomId
+ };
+
+ const result = this.remove(query);
- return this.remove(query);
+ if (Match.test(result, Number) && result > 0) {
+ RocketChat.models.Rooms.incUsersCountById(roomId, - result);
+ }
+
+ return result;
}
removeByRoomIdAndUserId(roomId, userId) {
@@ -793,7 +840,13 @@ class ModelSubscriptions extends RocketChat.models._Base {
'u._id': userId
};
- return this.remove(query);
+ const result = this.remove(query);
+
+ if (Match.test(result, Number) && result > 0) {
+ RocketChat.models.Rooms.incUsersCountById(roomId, - result);
+ }
+
+ return result;
}
}
diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js
index 5424fb97982d..36ca22f57c1a 100644
--- a/packages/rocketchat-lib/server/models/Users.js
+++ b/packages/rocketchat-lib/server/models/Users.js
@@ -12,8 +12,6 @@ class ModelUsers extends RocketChat.models._Base {
this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 });
this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 });
this.tryEnsureIndex({ 'type': 1 });
-
- this.cache.ensureIndex('username', 'unique');
}
findOneByImportId(_id, options) {
@@ -31,13 +29,13 @@ class ModelUsers extends RocketChat.models._Base {
}
findOneByEmailAddress(emailAddress, options) {
- const query = {'emails.address': new RegExp(`^${ s.escapeRegExp(emailAddress) }$`, 'i')};
+ const query = {'emails.address': new RegExp(`^${ s.escapeRegExp(emailAddress) }$`, 'i')};
return this.findOne(query, options);
}
findOneAdmin(admin, options) {
- const query = {admin};
+ const query = {admin};
return this.findOne(query, options);
}
@@ -52,18 +50,23 @@ class ModelUsers extends RocketChat.models._Base {
}
findOneById(userId, options) {
- const query = {_id: userId};
+ const query = { _id: userId };
return this.findOne(query, options);
}
// FIND
findById(userId) {
- const query = {_id: userId};
+ const query = { _id: userId };
return this.find(query);
}
+ findByIds(users, options) {
+ const query = { _id: { $in: users } };
+ return this.find(query, options);
+ }
+
findUsersNotOffline(options) {
const query = {
username: {
@@ -79,33 +82,7 @@ class ModelUsers extends RocketChat.models._Base {
findByUsername(username, options) {
- const query = {username};
-
- return this.find(query, options);
- }
-
- findUsersByUsernamesWithHighlights(usernames, options) {
- if (this.useCache) {
- const result = {
- fetch() {
- return RocketChat.models.Users.getDynamicView('highlights').data().filter(record => usernames.indexOf(record.username) > -1);
- },
- count() {
- return result.fetch().length;
- },
- forEach(fn) {
- return result.fetch().forEach(fn);
- }
- };
- return result;
- }
-
- const query = {
- username: { $in: usernames },
- 'settings.preferences.highlights.0': {
- $exists: true
- }
- };
+ const query = { username };
return this.find(query, options);
}
@@ -206,13 +183,13 @@ class ModelUsers extends RocketChat.models._Base {
}
findLDAPUsers(options) {
- const query = {ldap: true};
+ const query = {ldap: true};
return this.find(query, options);
}
findCrowdUsers(options) {
- const query = {crowd: true};
+ const query = {crowd: true};
return this.find(query, options);
}
@@ -245,11 +222,40 @@ class ModelUsers extends RocketChat.models._Base {
return this.find(query, options);
}
+ findUsersWithUsernameByIds(ids, options) {
+ const query = {
+ _id: {
+ $in: ids
+ },
+ username: {
+ $exists: 1
+ }
+ };
+
+ return this.find(query, options);
+ }
+
+ findUsersWithUsernameByIdsNotOffline(ids, options) {
+ const query = {
+ _id: {
+ $in: ids
+ },
+ username: {
+ $exists: 1
+ },
+ status: {
+ $in: ['online', 'away', 'busy']
+ }
+ };
+
+ return this.find(query, options);
+ }
+
// UPDATE
addImportIds(_id, importIds) {
importIds = [].concat(importIds);
- const query = {_id};
+ const query = {_id};
const update = {
$addToSet: {
diff --git a/packages/rocketchat-lib/server/models/_Base.js b/packages/rocketchat-lib/server/models/_Base.js
index 6431305c01df..e124e4ca387d 100644
--- a/packages/rocketchat-lib/server/models/_Base.js
+++ b/packages/rocketchat-lib/server/models/_Base.js
@@ -1,42 +1,22 @@
import ModelsBaseDb from './_BaseDb';
-import ModelsBaseCache from './_BaseCache';
-
-RocketChat.models._CacheControl = new Meteor.EnvironmentVariable();
+import objectPath from 'object-path';
+import _ from 'underscore';
class ModelsBase {
- constructor(nameOrModel, useCache) {
+ constructor(nameOrModel) {
this._db = new ModelsBaseDb(nameOrModel, this);
this.model = this._db.model;
this.collectionName = this._db.collectionName;
this.name = this._db.name;
- this._useCache = useCache === true;
-
- this.cache = new ModelsBaseCache(this);
- // TODO_CACHE: remove
- this.on = this.cache.on.bind(this.cache);
- this.emit = this.cache.emit.bind(this.cache);
- this.getDynamicView = this.cache.getDynamicView.bind(this.cache);
- this.processQueryOptionsOnResult = this.cache.processQueryOptionsOnResult.bind(this.cache);
- // END_TODO_CACHE
+ this.on = this._db.on.bind(this._db);
+ this.emit = this._db.emit.bind(this._db);
this.db = this;
-
- if (this._useCache) {
- this.db = new this.constructor(this.model, false);
- }
- }
-
- get useCache() {
- if (RocketChat.models._CacheControl.get() === false) {
- return false;
- }
-
- return this._useCache;
}
get origin() {
- return this.useCache === true ? 'cache' : '_db';
+ return '_db';
}
arrayToCursor(data) {
@@ -139,10 +119,121 @@ class ModelsBase {
return this._db.trashFind(...arguments);
}
+ trashFindOneById(/*_id, options*/) {
+ return this._db.trashFindOneById(...arguments);
+ }
+
trashFindDeletedAfter(/*deletedAt, query, options*/) {
return this._db.trashFindDeletedAfter(...arguments);
}
+ processQueryOptionsOnResult(result, options={}) {
+ if (result === undefined || result === null) {
+ return undefined;
+ }
+
+ if (Array.isArray(result)) {
+ if (options.sort) {
+ result = result.sort((a, b) => {
+ let r = 0;
+ for (const field in options.sort) {
+ if (options.sort.hasOwnProperty(field)) {
+ const direction = options.sort[field];
+ let valueA;
+ let valueB;
+ if (field.indexOf('.') > -1) {
+ valueA = objectPath.get(a, field);
+ valueB = objectPath.get(b, field);
+ } else {
+ valueA = a[field];
+ valueB = b[field];
+ }
+ if (valueA > valueB) {
+ r = direction;
+ break;
+ }
+ if (valueA < valueB) {
+ r = -direction;
+ break;
+ }
+ }
+ }
+ return r;
+ });
+ }
+
+ if (typeof options.skip === 'number') {
+ result.splice(0, options.skip);
+ }
+
+ if (typeof options.limit === 'number' && options.limit !== 0) {
+ result.splice(options.limit);
+ }
+ }
+
+ if (!options.fields) {
+ options.fields = {};
+ }
+
+ const fieldsToRemove = [];
+ const fieldsToGet = [];
+
+ for (const field in options.fields) {
+ if (options.fields.hasOwnProperty(field)) {
+ if (options.fields[field] === 0) {
+ fieldsToRemove.push(field);
+ } else if (options.fields[field] === 1) {
+ fieldsToGet.push(field);
+ }
+ }
+ }
+
+ if (fieldsToRemove.length > 0 && fieldsToGet.length > 0) {
+ console.warn('Can\'t mix remove and get fields');
+ fieldsToRemove.splice(0, fieldsToRemove.length);
+ }
+
+ if (fieldsToGet.length > 0 && fieldsToGet.indexOf('_id') === -1) {
+ fieldsToGet.push('_id');
+ }
+
+ const pickFields = (obj, fields) => {
+ const picked = {};
+ fields.forEach((field) => {
+ if (field.indexOf('.') !== -1) {
+ objectPath.set(picked, field, objectPath.get(obj, field));
+ } else {
+ picked[field] = obj[field];
+ }
+ });
+ return picked;
+ };
+
+ if (fieldsToRemove.length > 0 || fieldsToGet.length > 0) {
+ if (Array.isArray(result)) {
+ result = result.map((record) => {
+ if (fieldsToRemove.length > 0) {
+ return _.omit(record, ...fieldsToRemove);
+ }
+
+ if (fieldsToGet.length > 0) {
+ return pickFields(record, fieldsToGet);
+ }
+ });
+ } else {
+ if (fieldsToRemove.length > 0) {
+ return _.omit(result, ...fieldsToRemove);
+ }
+
+ if (fieldsToGet.length > 0) {
+ return pickFields(result, fieldsToGet);
+ }
+ }
+ }
+
+ return result;
+ }
+
// dinamicTrashFindAfter(method, deletedAt, ...args) {
// const scope = {
// find: (query={}) => {
diff --git a/packages/rocketchat-lib/server/models/_BaseCache.js b/packages/rocketchat-lib/server/models/_BaseCache.js
deleted file mode 100644
index 1e01cabb8661..000000000000
--- a/packages/rocketchat-lib/server/models/_BaseCache.js
+++ /dev/null
@@ -1,950 +0,0 @@
-/* eslint new-cap: 0 */
-import _ from 'underscore';
-import loki from 'lokijs';
-import {EventEmitter} from 'events';
-import objectPath from 'object-path';
-
-const logger = new Logger('BaseCache');
-
-const lokiEq = loki.LokiOps.$eq;
-const lokiNe = loki.LokiOps.$ne;
-
-loki.LokiOps.$eq = function(a, b) {
- if (Array.isArray(a)) {
- return a.indexOf(b) !== -1;
- }
- return lokiEq(a, b);
-};
-
-loki.LokiOps.$ne = function(a, b) {
- if (Array.isArray(a)) {
- return a.indexOf(b) === -1;
- }
- return lokiNe(a, b);
-};
-
-const lokiIn = loki.LokiOps.$in;
-loki.LokiOps.$in = function(a, b) {
- if (Array.isArray(a)) {
- return a.some(subA => lokiIn(subA, b));
- }
- return lokiIn(a, b);
-};
-
-loki.LokiOps.$nin = function(a, b) {
- return !loki.LokiOps.$in(a, b);
-};
-
-loki.LokiOps.$all = function(a, b) {
- return b.every(subB => a.includes(subB));
-};
-
-loki.LokiOps.$exists = function(a, b) {
- if (b) {
- return loki.LokiOps.$ne(a, undefined);
- }
-
- return loki.LokiOps.$eq(a, undefined);
-};
-
-loki.LokiOps.$elemMatch = function(a, b) {
- return _.findWhere(a, b);
-};
-
-const ignore = [
- 'emit',
- 'load',
- 'on',
- 'addToAllIndexes'
-];
-
-function traceMethodCalls(target) {
- target._stats = {};
-
- for (const property in target) {
- if (typeof target[property] === 'function' && ignore.indexOf(property) === -1) {
- target._stats[property] = {
- calls: 0,
- time: 0,
- avg: 0
- };
- const origMethod = target[property];
- target[property] = function(...args) {
-
- if (target.loaded !== true) {
- return origMethod.apply(target, args);
- }
-
- const startTime = RocketChat.statsTracker.now();
- const result = origMethod.apply(target, args);
- const time = Math.round(RocketChat.statsTracker.now() - startTime) / 1000;
- target._stats[property].time += time;
- target._stats[property].calls++;
- target._stats[property].avg = target._stats[property].time / target._stats[property].calls;
-
- return result;
- };
- }
- }
-
- setInterval(function() {
- for (const property in target._stats) {
- if (target._stats.hasOwnProperty(property) && target._stats[property].time > 0) {
- const tags = [`property:${ property }`, `collection:${ target.collectionName }`];
- RocketChat.statsTracker.timing('cache.methods.time', target._stats[property].avg, tags);
- RocketChat.statsTracker.increment('cache.methods.totalTime', target._stats[property].time, tags);
- RocketChat.statsTracker.increment('cache.methods.count', target._stats[property].calls, tags);
- target._stats[property].avg = 0;
- target._stats[property].time = 0;
- target._stats[property].calls = 0;
- }
- }
- }, 10000);
-
- target._getStatsAvg = function() {
- const stats = [];
- for (const property in target._stats) {
- if (target._stats.hasOwnProperty(property)) {
- stats.push([Math.round(target._stats[property].avg*100)/100, property]);
- }
- }
- return _.sortBy(stats, function(record) {
- return record[0];
- });
- };
-}
-
-class Adapter {
- loadDatabase(/*dbname, callback*/) {}
- saveDatabase(/*dbname, dbstring, callback*/) {}
- deleteDatabase(/*dbname, callback*/) {}
-}
-
-const db = new loki('rocket.chat.json', {adapter: Adapter});
-
-class ModelsBaseCache extends EventEmitter {
- constructor(model) {
- super();
-
- traceMethodCalls(this);
-
- this.indexes = {};
- this.ignoreUpdatedFields = ['_updatedAt'];
-
- this.query = {};
- this.options = {};
-
- this.ensureIndex('_id', 'unique');
-
- this.joins = {};
-
- this.on('inserted', (...args) => { this.emit('changed', 'inserted', ...args); });
- this.on('removed', (...args) => { this.emit('changed', 'removed', ...args); });
- this.on('updated', (...args) => { this.emit('changed', 'updated', ...args); });
-
- this.on('beforeinsert', (...args) => { this.emit('beforechange', 'inserted', ...args); });
- this.on('beforeremove', (...args) => { this.emit('beforechange', 'removed', ...args); });
- this.on('beforeupdate', (...args) => { this.emit('beforechange', 'updated', ...args); });
-
- this.on('inserted', (...args) => { this.emit('sync', 'inserted', ...args); });
- this.on('updated', (...args) => { this.emit('sync', 'updated', ...args); });
- this.on('beforeremove', (...args) => { this.emit('sync', 'removed', ...args); });
-
- this.db = db;
-
- this.model = model;
-
- this.collectionName = this.model._db.collectionName;
- this.collection = this.db.addCollection(this.collectionName);
- }
-
- hasOne(join, {field, link}) {
- this.join({join, field, link, multi: false});
- }
-
- hasMany(join, {field, link}) {
- this.join({join, field, link, multi: true});
- }
-
- join({join, field, link, multi}) {
- if (!RocketChat.models[join]) {
- console.log(`Invalid cache model ${ join }`);
- return;
- }
-
- RocketChat.models[join].cache.on('inserted', (record) => {
- this.processRemoteJoinInserted({join, field, link, multi, record});
- });
-
- RocketChat.models[join].cache.on('beforeupdate', (record, diff) => {
- if (diff[link.remote]) {
- this.processRemoteJoinRemoved({join, field, link, multi, record});
- }
- });
-
- RocketChat.models[join].cache.on('updated', (record, diff) => {
- if (diff[link.remote]) {
- this.processRemoteJoinInserted({join, field, link, multi, record});
- }
- });
-
- RocketChat.models[join].cache.on('removed', (record) => {
- this.processRemoteJoinRemoved({join, field, link, multi, record});
- });
-
- this.on('inserted', (localRecord) => {
- this.processLocalJoinInserted({join, field, link, multi, localRecord});
- });
-
- this.on('beforeupdate', (localRecord, diff) => {
- if (diff[link.local]) {
- if (multi === true) {
- localRecord[field] = [];
- } else {
- localRecord[field] = undefined;
- }
- }
- });
-
- this.on('updated', (localRecord, diff) => {
- if (diff[link.local]) {
- this.processLocalJoinInserted({join, field, link, multi, localRecord});
- }
- });
- }
-
- processRemoteJoinInserted({field, link, multi, record}) {
- let localRecords = this._findByIndex(link.local, objectPath.get(record, link.remote));
-
- if (!localRecords) {
- return;
- }
-
- if (!Array.isArray(localRecords)) {
- localRecords = [localRecords];
- }
-
- for (let i = 0; i < localRecords.length; i++) {
- const localRecord = localRecords[i];
- if (multi === true && !localRecord[field]) {
- localRecord[field] = [];
- }
-
- if (typeof link.where === 'function' && link.where(localRecord, record) === false) {
- continue;
- }
-
- let mutableRecord = record;
-
- if (typeof link.transform === 'function') {
- mutableRecord = link.transform(localRecord, mutableRecord);
- }
-
- if (multi === true) {
- localRecord[field].push(mutableRecord);
- } else {
- localRecord[field] = mutableRecord;
- }
-
- this.emit(`join:${ field }:inserted`, localRecord, mutableRecord);
- this.emit(`join:${ field }:changed`, 'inserted', localRecord, mutableRecord);
- }
- }
-
- processLocalJoinInserted({join, field, link, multi, localRecord}) {
- let records = RocketChat.models[join].cache._findByIndex(link.remote, objectPath.get(localRecord, link.local));
-
- if (!Array.isArray(records)) {
- records = [records];
- }
-
- for (let i = 0; i < records.length; i++) {
- let record = records[i];
-
- if (typeof link.where === 'function' && link.where(localRecord, record) === false) {
- continue;
- }
-
- if (typeof link.transform === 'function') {
- record = link.transform(localRecord, record);
- }
-
- if (multi === true) {
- localRecord[field].push(record);
- } else {
- localRecord[field] = record;
- }
-
- this.emit(`join:${ field }:inserted`, localRecord, record);
- this.emit(`join:${ field }:changed`, 'inserted', localRecord, record);
- }
- }
-
- processRemoteJoinRemoved({field, link, multi, record}) {
- let localRecords = this._findByIndex(link.local, objectPath.get(record, link.remote));
-
- if (!localRecords) {
- return;
- }
-
- if (!Array.isArray(localRecords)) {
- localRecords = [localRecords];
- }
-
- for (let i = 0; i < localRecords.length; i++) {
- const localRecord = localRecords[i];
-
- if (multi === true) {
- if (Array.isArray(localRecord[field])) {
- if (typeof link.remove === 'function') {
- link.remove(localRecord[field], record);
- } else if (localRecord[field].indexOf(record) > -1) {
- localRecord[field].splice(localRecord[field].indexOf(record), 1);
- }
- }
- } else {
- localRecord[field] = undefined;
- }
-
- this.emit(`join:${ field }:removed`, localRecord, record);
- this.emit(`join:${ field }:changed`, 'removed', localRecord, record);
- }
- }
-
- ensureIndex(fields, type='array') {
- if (!Array.isArray(fields)) {
- fields = [fields];
- }
-
- this.indexes[fields.join(',')] = {
- type,
- fields,
- data: {}
- };
- }
-
- addToAllIndexes(record) {
- for (const indexName in this.indexes) {
- if (this.indexes.hasOwnProperty(indexName)) {
- this.addToIndex(indexName, record);
- }
- }
- }
-
- addToIndex(indexName, record) {
- const index = this.indexes[indexName];
- if (!index) {
- console.error(`Index not defined ${ indexName }`);
- return;
- }
-
- const keys = [];
- for (const field of index.fields) {
- keys.push(objectPath.get(record, field));
- }
- const key = keys.join('|');
-
- if (index.type === 'unique') {
- index.data[key] = record;
- return;
- }
-
- if (index.type === 'array') {
- if (!index.data[key]) {
- index.data[key] = [];
- }
- index.data[key].push(record);
- return;
- }
- }
-
- removeFromAllIndexes(record) {
- for (const indexName in this.indexes) {
- if (this.indexes.hasOwnProperty(indexName)) {
- this.removeFromIndex(indexName, record);
- }
- }
- }
-
- removeFromIndex(indexName, record) {
- const index = this.indexes[indexName];
- if (!this.indexes[indexName]) {
- console.error(`Index not defined ${ indexName }`);
- return;
- }
-
- if (!index.data) {
- return;
- }
-
- let key = [];
- for (const field of index.fields) {
- key.push(objectPath.get(record, field));
- }
- key = key.join('|');
-
- if (index.type === 'unique') {
- index.data[key] = undefined;
- return;
- }
-
- if (index.type === 'array') {
- if (!index.data[key]) {
- return;
- }
- const i = index.data[key].indexOf(record);
- if (i > -1) {
- index.data[key].splice(i, 1);
- }
- return;
- }
- }
-
- _findByIndex(index, keys) {
- const key = [].concat(keys).join('|');
- if (!this.indexes[index]) {
- return;
- }
-
- if (this.indexes[index].data) {
- const result = this.indexes[index].data[key];
- if (result) {
- return result;
- }
- }
-
- if (this.indexes[index].type === 'array') {
- return [];
- }
- }
-
- findByIndex(index, keys, options={}) {
- return {
- fetch: () => {
- return this.processQueryOptionsOnResult(this._findByIndex(index, keys), options);
- },
-
- count: () => {
- const records = this.findByIndex(index, keys, options).fetch();
- if (Array.isArray(records)) {
- return records.length;
- }
- return !records ? 0 : 1;
- },
-
- forEach: (fn) => {
- const records = this.findByIndex(index, keys, options).fetch();
- if (Array.isArray(records)) {
- return records.forEach(fn);
- }
- if (records) {
- return fn(records);
- }
- }
- };
- }
-
- load() {
- if (this.model._useCache === false) {
- return;
- }
-
- console.log('Will load cache for', this.collectionName);
- this.emit('beforeload');
- this.loaded = false;
- const time = RocketChat.statsTracker.now();
- const data = this.model.db.find(this.query, this.options).fetch();
- for (let i=0; i < data.length; i++) {
- this.insert(data[i]);
- }
- console.log(String(data.length), 'records load from', this.collectionName);
- RocketChat.statsTracker.timing('cache.load', RocketChat.statsTracker.now() - time, [`collection:${ this.collectionName }`]);
-
- this.startSync();
- this.loaded = true;
- this.emit('afterload');
- }
-
- startSync() {
- if (this.model._useCache === false) {
- return;
- }
-
- this.model._db.on('change', ({action, id, data/*, oplog*/}) => {
- switch (action) {
- case 'insert':
- data._id = id;
- this.insert(data);
- break;
-
- case 'remove':
- this.removeById(id);
- break;
-
- case 'update:record':
- this.updateDiffById(id, data);
- break;
-
- case 'update:diff':
- this.updateDiffById(id, data);
- break;
-
- case 'update:query':
- this.update(data.query, data.update, data.options);
- break;
- }
- });
- }
-
- processQueryOptionsOnResult(result, options={}) {
- if (result === undefined || result === null) {
- return undefined;
- }
-
- if (Array.isArray(result)) {
- if (options.sort) {
- result = result.sort((a, b) => {
- let r = 0;
- for (const field in options.sort) {
- if (options.sort.hasOwnProperty(field)) {
- const direction = options.sort[field];
- let valueA;
- let valueB;
- if (field.indexOf('.') > -1) {
- valueA = objectPath.get(a, field);
- valueB = objectPath.get(b, field);
- } else {
- valueA = a[field];
- valueB = b[field];
- }
- if (valueA > valueB) {
- r = direction;
- break;
- }
- if (valueA < valueB) {
- r = -direction;
- break;
- }
- }
- }
- return r;
- });
- }
-
- if (typeof options.skip === 'number') {
- result.splice(0, options.skip);
- }
-
- if (typeof options.limit === 'number' && options.limit !== 0) {
- result.splice(options.limit);
- }
- }
-
- if (!options.fields) {
- options.fields = {};
- }
-
- const fieldsToRemove = [];
- const fieldsToGet = [];
-
- for (const field in options.fields) {
- if (options.fields.hasOwnProperty(field)) {
- if (options.fields[field] === 0) {
- fieldsToRemove.push(field);
- } else if (options.fields[field] === 1) {
- fieldsToGet.push(field);
- }
- }
- }
-
- if (fieldsToRemove.length > 0 && fieldsToGet.length > 0) {
- console.warn('Can\'t mix remove and get fields');
- fieldsToRemove.splice(0, fieldsToRemove.length);
- }
-
- if (fieldsToGet.length > 0 && fieldsToGet.indexOf('_id') === -1) {
- fieldsToGet.push('_id');
- }
-
- const pickFields = (obj, fields) => {
- const picked = {};
- fields.forEach((field) => {
- if (field.indexOf('.') !== -1) {
- objectPath.set(picked, field, objectPath.get(obj, field));
- } else {
- picked[field] = obj[field];
- }
- });
- return picked;
- };
-
- if (fieldsToRemove.length > 0 || fieldsToGet.length > 0) {
- if (Array.isArray(result)) {
- result = result.map((record) => {
- if (fieldsToRemove.length > 0) {
- return _.omit(record, ...fieldsToRemove);
- }
-
- if (fieldsToGet.length > 0) {
- return pickFields(record, fieldsToGet);
- }
- });
- } else {
- if (fieldsToRemove.length > 0) {
- return _.omit(result, ...fieldsToRemove);
- }
-
- if (fieldsToGet.length > 0) {
- return pickFields(result, fieldsToGet);
- }
- }
- }
-
- return result;
- }
-
- processQuery(query, parentField) {
- if (!query) {
- return query;
- }
-
- if (Match.test(query, String)) {
- return {
- _id: query
- };
- }
-
- if (Object.keys(query).length > 1 && parentField !== '$elemMatch') {
- const and = [];
- for (const field in query) {
- if (query.hasOwnProperty(field)) {
- and.push({
- [field]: query[field]
- });
- }
- }
- query = {$and: and};
- }
-
- for (const field in query) {
- if (query.hasOwnProperty(field)) {
- const value = query[field];
- if (value instanceof RegExp && field !== '$regex') {
- query[field] = {
- $regex: value
- };
- }
-
- if (field === '$and' || field === '$or') {
- query[field] = value.map((subValue) => {
- return this.processQuery(subValue, field);
- });
- }
-
- if (Match.test(value, Object) && Object.keys(value).length > 0) {
- query[field] = this.processQuery(value, field);
- }
- }
- }
-
- return query;
- }
-
- find(query, options={}) {
- return {
- fetch: () => {
- try {
- query = this.processQuery(query);
- return this.processQueryOptionsOnResult(this.collection.find(query), options);
- } catch (e) {
- console.error('Exception on cache find for', this.collectionName);
- console.error('Query:', JSON.stringify(query, null, 2));
- console.error('Options:', JSON.stringify(options, null, 2));
- console.error(e.stack);
- throw e;
- }
- },
-
- count: () => {
- try {
- query = this.processQuery(query);
- const { limit, skip } = options;
- return this.processQueryOptionsOnResult(this.collection.find(query), { limit, skip }).length;
- } catch (e) {
- console.error('Exception on cache find for', this.collectionName);
- console.error('Query:', JSON.stringify(query, null, 2));
- console.error('Options:', JSON.stringify(options, null, 2));
- console.error(e.stack);
- throw e;
- }
- },
-
- forEach: (fn) => {
- return this.find(query, options).fetch().forEach(fn);
- },
-
- observe: (obj) => {
- logger.debug(this.collectionName, 'Falling back observe to model with query:', query);
- return this.model.db.find(...arguments).observe(obj);
- },
-
- observeChanges: (obj) => {
- logger.debug(this.collectionName, 'Falling back observeChanges to model with query:', query);
- return this.model.db.find(...arguments).observeChanges(obj);
- },
-
- _publishCursor: (cursor, sub, collection) => {
- logger.debug(this.collectionName, 'Falling back _publishCursor to model with query:', query);
- return this.model.db.find(...arguments)._publishCursor(cursor, sub, collection);
- }
- };
- }
-
- findOne(query, options) {
- try {
- query = this.processQuery(query);
- return this.processQueryOptionsOnResult(this.collection.findOne(query), options);
- } catch (e) {
- console.error('Exception on cache findOne for', this.collectionName);
- console.error('Query:', JSON.stringify(query, null, 2));
- console.error('Options:', JSON.stringify(options, null, 2));
- console.error(e.stack);
- throw e;
- }
- }
-
- findOneById(_id, options) {
- return this.findByIndex('_id', _id, options).fetch();
- }
-
- findOneByIds(ids, options) {
- const query = this.processQuery({ _id: { $in: ids }});
- return this.processQueryOptionsOnResult(this.collection.findOne(query), options);
- }
-
- findWhere(query, options) {
- query = this.processQuery(query);
- return this.processQueryOptionsOnResult(this.collection.findWhere(query), options);
- }
-
- addDynamicView() {
- return this.collection.addDynamicView(...arguments);
- }
-
- getDynamicView() {
- return this.collection.getDynamicView(...arguments);
- }
-
- insert(record) {
- if (Array.isArray(record)) {
- for (const item of record) {
- this.insert(item);
- }
- } else {
- // TODO remove - ignore updates in room.usernames
- if (this.collectionName === 'rocketchat_room' && record.usernames) {
- delete record.usernames;
- }
- this.emit('beforeinsert', record);
- this.addToAllIndexes(record);
- this.collection.insert(record);
- this.emit('inserted', record);
- }
- }
-
- updateDiffById(id, diff) {
- // TODO remove - ignore updates in room.usernames
- if (this.collectionName === 'rocketchat_room' && diff.usernames) {
- delete diff.usernames;
- }
-
- const record = this._findByIndex('_id', id);
- if (!record) {
- console.error('Cache.updateDiffById: No record', this.collectionName, id, diff);
- return;
- }
- this.removeFromAllIndexes(record);
-
- const updatedFields = _.without(Object.keys(diff), ...this.ignoreUpdatedFields);
-
- if (updatedFields.length > 0) {
- this.emit('beforeupdate', record, diff);
- }
-
- for (const key in diff) {
- if (diff.hasOwnProperty(key)) {
- objectPath.set(record, key, diff[key]);
- }
- }
-
- this.collection.update(record);
- this.addToAllIndexes(record);
-
- if (updatedFields.length > 0) {
- this.emit('updated', record, diff);
- }
- }
-
- updateRecord(record, update) {
- // TODO remove - ignore updates in room.usernames
- if (this.collectionName === 'rocketchat_room' && (record.usernames || (record.$set && record.$set.usernames))) {
- delete record.usernames;
- if (record.$set && record.$set.usernames) {
- delete record.$set.usernames;
- }
- }
-
- this.removeFromAllIndexes(record);
-
- const topLevelFields = Object.keys(update).map(field => field.split('.')[0]);
- const updatedFields = _.without(topLevelFields, ...this.ignoreUpdatedFields);
-
- if (updatedFields.length > 0) {
- this.emit('beforeupdate', record, record);
- }
-
- if (update.$set) {
- _.each(update.$set, (value, field) => {
- objectPath.set(record, field, value);
- });
- }
-
- if (update.$unset) {
- _.each(update.$unset, (value, field) => {
- objectPath.del(record, field);
- });
- }
-
- if (update.$min) {
- _.each(update.$min, (value, field) => {
- const curValue = objectPath.get(record, field);
- if (curValue === undefined || value < curValue) {
- objectPath.set(record, field, value);
- }
- });
- }
-
- if (update.$max) {
- _.each(update.$max, (value, field) => {
- const curValue = objectPath.get(record, field);
- if (curValue === undefined || value > curValue) {
- objectPath.set(record, field, value);
- }
- });
- }
-
- if (update.$inc) {
- _.each(update.$inc, (value, field) => {
- let curValue = objectPath.get(record, field);
- if (curValue === undefined) {
- curValue = value;
- } else {
- curValue += value;
- }
- objectPath.set(record, field, curValue);
- });
- }
-
- if (update.$mul) {
- _.each(update.$mul, (value, field) => {
- let curValue = objectPath.get(record, field);
- if (curValue === undefined) {
- curValue = 0;
- } else {
- curValue *= value;
- }
- objectPath.set(record, field, curValue);
- });
- }
-
- if (update.$rename) {
- _.each(update.$rename, (value, field) => {
- const curValue = objectPath.get(record, field);
- if (curValue !== undefined) {
- objectPath.set(record, value, curValue);
- objectPath.del(record, field);
- }
- });
- }
-
- if (update.$pullAll) {
- _.each(update.$pullAll, (value, field) => {
- let curValue = objectPath.get(record, field);
- if (Array.isArray(curValue)) {
- curValue = _.difference(curValue, value);
- objectPath.set(record, field, curValue);
- }
- });
- }
-
- if (update.$pop) {
- _.each(update.$pop, (value, field) => {
- const curValue = objectPath.get(record, field);
- if (Array.isArray(curValue)) {
- if (value === -1) {
- curValue.shift();
- } else {
- curValue.pop();
- }
- objectPath.set(record, field, curValue);
- }
- });
- }
-
- if (update.$addToSet) {
- _.each(update.$addToSet, (value, field) => {
- let curValue = objectPath.get(record, field);
- if (curValue === undefined) {
- curValue = [];
- }
- if (Array.isArray(curValue)) {
- const length = curValue.length;
-
- if (value && value.$each && Array.isArray(value.$each)) {
- for (const valueItem of value.$each) {
- if (curValue.indexOf(valueItem) === -1) {
- curValue.push(valueItem);
- }
- }
- } else if (curValue.indexOf(value) === -1) {
- curValue.push(value);
- }
-
- if (curValue.length > length) {
- objectPath.set(record, field, curValue);
- }
- }
- });
- }
-
- this.collection.update(record);
- this.addToAllIndexes(record);
-
- if (updatedFields.length > 0) {
- this.emit('updated', record, record);
- }
- }
-
- update(query, update, options = {}) {
- let records = options.multi ? this.find(query).fetch() : this.findOne(query) || [];
- if (!Array.isArray(records)) {
- records = [records];
- }
-
- for (const record of records) {
- this.updateRecord(record, update);
- }
- }
-
- removeById(id) {
- const record = this._findByIndex('_id', id);
- if (record) {
- this.emit('beforeremove', record);
- this.collection.removeWhere({_id: id});
- this.removeFromAllIndexes(record);
- this.emit('removed', record);
- }
- }
-}
-
-export default ModelsBaseCache;
diff --git a/packages/rocketchat-lib/server/models/_BaseDb.js b/packages/rocketchat-lib/server/models/_BaseDb.js
index b93f3e917701..a39f0827ca7d 100644
--- a/packages/rocketchat-lib/server/models/_BaseDb.js
+++ b/packages/rocketchat-lib/server/models/_BaseDb.js
@@ -36,9 +36,11 @@ class ModelsBaseDb extends EventEmitter {
this.wrapModel();
+ let alreadyListeningToOplog = false;
// When someone start listening for changes we start oplog if available
- this.once('newListener', (event/*, listener*/) => {
- if (event === 'change') {
+ this.on('newListener', (event/*, listener*/) => {
+ if (event === 'change' && alreadyListeningToOplog === false) {
+ alreadyListeningToOplog = true;
if (isOplogEnabled) {
const query = {
collection: this.collectionName
@@ -98,65 +100,32 @@ class ModelsBaseDb extends EventEmitter {
};
}
+ _doNotMixInclusionAndExclusionFields(options) {
+ if (options && options.fields) {
+ const keys = Object.keys(options.fields);
+ const removeKeys = keys.filter(key => options.fields[key] === 0);
+ if (keys.length > removeKeys.length) {
+ removeKeys.forEach(key => delete options.fields[key]);
+ }
+ }
+ }
+
find() {
+ this._doNotMixInclusionAndExclusionFields(arguments[1]);
return this.model.find(...arguments);
}
findOne() {
+ this._doNotMixInclusionAndExclusionFields(arguments[1]);
return this.model.findOne(...arguments);
}
findOneById(_id, options) {
- return this.model.findOne({ _id }, options);
+ return this.findOne({ _id }, options);
}
findOneByIds(ids, options) {
- return this.model.findOne({ _id: { $in: ids }}, options);
- }
-
- defineSyncStrategy(query, modifier, options) {
- if (this.baseModel.useCache === false) {
- return 'db';
- }
-
- if (options.upsert === true) {
- return 'db';
- }
-
- // const dbModifiers = [
- // '$currentDate',
- // '$bit',
- // '$pull',
- // '$pushAll',
- // '$push',
- // '$setOnInsert'
- // ];
-
- const cacheAllowedModifiers = [
- '$set',
- '$unset',
- '$min',
- '$max',
- '$inc',
- '$mul',
- '$rename',
- '$pullAll',
- '$pop',
- '$addToSet'
- ];
-
- const notAllowedModifiers = Object.keys(modifier).filter(i => i.startsWith('$') && cacheAllowedModifiers.includes(i) === false);
-
- if (notAllowedModifiers.length > 0) {
- return 'db';
- }
-
- const placeholderFields = Object.keys(query).filter(item => item.indexOf('$') > -1);
- if (placeholderFields.length > 0) {
- return 'db';
- }
-
- return 'cache';
+ return this.findOne({ _id: { $in: ids }}, options);
}
updateHasPositionalOperator(update) {
@@ -171,6 +140,7 @@ class ModelsBaseDb extends EventEmitter {
if (action.op.op === 'i') {
this.emit('change', {
action: 'insert',
+ clientAction: 'inserted',
id: action.op.o._id,
data: action.op.o,
oplog: true
@@ -181,7 +151,8 @@ class ModelsBaseDb extends EventEmitter {
if (action.op.op === 'u') {
if (!action.op.o.$set && !action.op.o.$unset) {
this.emit('change', {
- action: 'update:record',
+ action: 'update',
+ clientAction: 'updated',
id: action.id,
data: action.op.o,
oplog: true
@@ -207,9 +178,10 @@ class ModelsBaseDb extends EventEmitter {
}
this.emit('change', {
- action: 'update:diff',
+ action: 'update',
+ clientAction: 'updated',
id: action.id,
- data: diff,
+ diff,
oplog: true
});
return;
@@ -218,6 +190,7 @@ class ModelsBaseDb extends EventEmitter {
if (action.op.op === 'd') {
this.emit('change', {
action: 'remove',
+ clientAction: 'removed',
id: action.id,
oplog: true
});
@@ -229,27 +202,28 @@ class ModelsBaseDb extends EventEmitter {
this.setUpdatedAt(record);
const result = this.originals.insert(...arguments);
+
+ record._id = result;
+
if (!isOplogEnabled && this.listenerCount('change') > 0) {
this.emit('change', {
action: 'insert',
+ clientAction: 'inserted',
id: result,
data: _.extend({}, record),
oplog: false
});
}
- record._id = result;
-
return result;
}
update(query, update, options = {}) {
this.setUpdatedAt(update, true, query);
- const strategy = this.defineSyncStrategy(query, update, options);
let ids = [];
- if (!isOplogEnabled && this.listenerCount('change') > 0 && strategy === 'db') {
- const findOptions = {fields: {_id: 1}};
+ if (!isOplogEnabled && this.listenerCount('change') > 0) {
+ const findOptions = { fields: { _id: 1 } };
let records = options.multi ? this.find(query, findOptions).fetch() : this.findOne(query, findOptions) || [];
if (!Array.isArray(records)) {
records = [records];
@@ -265,53 +239,31 @@ class ModelsBaseDb extends EventEmitter {
}
}
+ // TODO: CACHE: Can we use findAndModify here when oplog is disabled?
const result = this.originals.update(query, update, options);
if (!isOplogEnabled && this.listenerCount('change') > 0) {
- if (strategy === 'db') {
- if (options.upsert === true) {
- if (result.insertedId) {
- this.emit('change', {
- action: 'insert',
- id: result.insertedId,
- data: this.findOne({_id: result.insertedId}),
- oplog: false
- });
- return;
- }
+ if (options.upsert === true && result.insertedId) {
+ this.emit('change', {
+ action: 'insert',
+ clientAction: 'inserted',
+ id: result.insertedId,
+ oplog: false
+ });
- query = {
- _id: {
- $in: ids
- }
- };
- }
+ return result;
+ }
- let records = options.multi ? this.find(query).fetch() : this.findOne(query) || [];
- if (!Array.isArray(records)) {
- records = [records];
- }
- for (const record of records) {
- this.emit('change', {
- action: 'update:record',
- id: record._id,
- data: record,
- oplog: false
- });
- }
- } else {
+ for (const id of ids) {
this.emit('change', {
- action: 'update:query',
- id: undefined,
- data: {
- query,
- update,
- options
- },
+ action: 'update',
+ clientAction: 'updated',
+ id,
oplog: false
});
}
}
+
return result;
}
@@ -342,6 +294,7 @@ class ModelsBaseDb extends EventEmitter {
for (const record of records) {
this.emit('change', {
action: 'remove',
+ clientAction: 'removed',
id: record._id,
data: _.extend({}, record),
oplog: false
@@ -405,6 +358,15 @@ class ModelsBaseDb extends EventEmitter {
return trash.find(query, options);
}
+ trashFindOneById(_id, options) {
+ const query = {
+ _id,
+ __collection__: this.name
+ };
+
+ return trash.findOne(query, options);
+ }
+
trashFindDeletedAfter(deletedAt, query = {}, options) {
query.__collection__ = this.name;
query._deletedAt = {
diff --git a/packages/rocketchat-lib/server/publications/settings.js b/packages/rocketchat-lib/server/publications/settings.js
index 5707468422bf..175ccea3cae7 100644
--- a/packages/rocketchat-lib/server/publications/settings.js
+++ b/packages/rocketchat-lib/server/publications/settings.js
@@ -1,11 +1,8 @@
-import _ from 'underscore';
-
Meteor.methods({
'public-settings/get'(updatedAt) {
this.unblock();
- const records = RocketChat.models.Settings.find().fetch().filter(function(record) {
- return record.hidden !== true && record['public'] === true;
- });
+ const records = RocketChat.models.Settings.findNotHiddenPublic().fetch();
+
if (updatedAt instanceof Date) {
return {
update: records.filter(function(record) {
@@ -34,9 +31,7 @@ Meteor.methods({
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'view-privileged-setting')) {
return [];
}
- const records = RocketChat.models.Settings.find().fetch().filter(function(record) {
- return record.hidden !== true;
- });
+ const records = RocketChat.models.Settings.findNotHidden().fetch();
if (updatedAt instanceof Date) {
return {
update: records.filter(function(record) {
@@ -58,11 +53,30 @@ Meteor.methods({
}
});
-RocketChat.models.Settings.cache.on('changed', function(type, setting) {
- if (setting['public'] === true) {
- RocketChat.Notifications.notifyAllInThisInstance('public-settings-changed', type, _.pick(setting, '_id', 'value', 'editor', 'properties'));
+RocketChat.models.Settings.on('change', ({clientAction, id, data}) => {
+ switch (clientAction) {
+ case 'updated':
+ case 'inserted':
+ const setting = data || RocketChat.models.Settings.findOneById(id);
+ const value = {
+ _id: setting._id,
+ value: setting.value,
+ editor: setting.editor,
+ properties: setting.properties
+ };
+
+ if (setting['public'] === true) {
+ RocketChat.Notifications.notifyAllInThisInstance('public-settings-changed', clientAction, value);
+ } else {
+ RocketChat.Notifications.notifyLoggedInThisInstance('private-settings-changed', clientAction, setting);
+ }
+ break;
+
+ case 'removed':
+ RocketChat.Notifications.notifyLoggedInThisInstance('private-settings-changed', clientAction, { _id: id });
+ RocketChat.Notifications.notifyAllInThisInstance('public-settings-changed', clientAction, { _id: id });
+ break;
}
- return RocketChat.Notifications.notifyLoggedInThisInstance('private-settings-changed', type, setting);
});
RocketChat.Notifications.streamAll.allowRead('private-settings-changed', function() {
diff --git a/packages/rocketchat-lib/server/startup/cache/CacheLoad.js b/packages/rocketchat-lib/server/startup/cache/CacheLoad.js
deleted file mode 100644
index 8f555fc454c7..000000000000
--- a/packages/rocketchat-lib/server/startup/cache/CacheLoad.js
+++ /dev/null
@@ -1,73 +0,0 @@
-RocketChat.models.Rooms.cache.hasMany('Subscriptions', {
- field: 'usernames',
- link: {
- local: '_id',
- remote: 'rid',
- transform(room, subscription) {
- return subscription.u.username;
- },
- remove(arr, subscription) {
- if (arr.indexOf(subscription.u.username) > -1) {
- arr.splice(arr.indexOf(subscription.u.username), 1);
- }
- }
- }
-});
-
-
-RocketChat.models.Subscriptions.cache.hasOne('Rooms', {
- field: '_room',
- link: {
- local: 'rid',
- remote: '_id'
- }
-});
-
-
-RocketChat.models.Subscriptions.cache.hasOne('Users', {
- field: '_user',
- link: {
- local: 'u._id',
- remote: '_id'
- }
-});
-
-RocketChat.models.Subscriptions.cache.hasOne('Users', {
- field: 'fname',
- link: {
- local: 'name',
- remote: 'username',
- where(subscription/*, user*/) {
- return subscription.t === 'd';
- },
- transform(subscription, user) {
- if (user == null || subscription == null) {
- return undefined;
- }
- // Prevent client cache for old subscriptions with new names
- // Cuz when a user change his name, the subscription's _updateAt
- // will not change
- if (subscription._updatedAt < user._updatedAt) {
- subscription._updatedAt = user._updatedAt;
- }
- return user.name;
- }
- }
-});
-
-RocketChat.models.Users.cache.load();
-RocketChat.models.Rooms.cache.load();
-RocketChat.models.Subscriptions.cache.load();
-RocketChat.models.Settings.cache.load();
-
-
-RocketChat.models.Users.cache.addDynamicView('highlights').applyFind({
- 'settings.preferences.highlights': {$size: {$gt: 0}}
-});
-
-RocketChat.models.Subscriptions.cache.addDynamicView('notifications').applyFind({
- $or: [
- {desktopNotifications: {$in: ['all', 'nothing']}},
- {mobilePushNotifications: {$in: ['all', 'nothing']}}
- ]
-});
diff --git a/packages/rocketchat-livechat/server/lib/Livechat.js b/packages/rocketchat-livechat/server/lib/Livechat.js
index 60fb7d4ec52b..9c4efb5620c9 100644
--- a/packages/rocketchat-livechat/server/lib/Livechat.js
+++ b/packages/rocketchat-livechat/server/lib/Livechat.js
@@ -365,8 +365,6 @@ RocketChat.Livechat = {
const servedBy = room.servedBy;
if (agent && agent.agentId !== servedBy._id) {
- room.usernames = _.without(room.usernames, servedBy.username).concat(agent.username);
-
RocketChat.models.Rooms.changeAgentByRoomId(room._id, agent);
const subscriptionData = {
@@ -389,6 +387,7 @@ RocketChat.Livechat = {
RocketChat.models.Subscriptions.removeByRoomIdAndUserId(room._id, servedBy._id);
RocketChat.models.Subscriptions.insert(subscriptionData);
+ RocketChat.models.Rooms.incUsersCountById(room._id);
RocketChat.models.Messages.createUserLeaveWithRoomIdAndUser(room._id, { _id: servedBy._id, username: servedBy.username });
RocketChat.models.Messages.createUserJoinWithRoomIdAndUser(room._id, { _id: agent.agentId, username: agent.username });
diff --git a/packages/rocketchat-livechat/server/lib/QueueMethods.js b/packages/rocketchat-livechat/server/lib/QueueMethods.js
index 0523b98e355b..d167f18df62a 100644
--- a/packages/rocketchat-livechat/server/lib/QueueMethods.js
+++ b/packages/rocketchat-livechat/server/lib/QueueMethods.js
@@ -19,6 +19,7 @@ RocketChat.QueueMethods = {
const room = _.extend({
_id: message.rid,
msgs: 1,
+ usersCount: 1,
lm: new Date(),
fname: (roomInfo && roomInfo.fname) || guest.name || guest.username,
// usernames: [agent.username, guest.username],
@@ -38,6 +39,7 @@ RocketChat.QueueMethods = {
open: true,
waitingResponse: true
}, roomInfo);
+
const subscriptionData = {
rid: message.rid,
fname: guest.name || guest.username,
@@ -57,6 +59,7 @@ RocketChat.QueueMethods = {
};
RocketChat.models.Rooms.insert(room);
+
RocketChat.models.Subscriptions.insert(subscriptionData);
RocketChat.Livechat.stream.emit(room._id, {
@@ -114,9 +117,11 @@ RocketChat.QueueMethods = {
},
t: 'l'
};
+
const room = _.extend({
_id: message.rid,
msgs: 1,
+ usersCount: 0,
lm: new Date(),
fname: guest.name || guest.username,
// usernames: [guest.username],
@@ -132,6 +137,7 @@ RocketChat.QueueMethods = {
open: true,
waitingResponse: true
}, roomInfo);
+
RocketChat.models.LivechatInquiry.insert(inquiry);
RocketChat.models.Rooms.insert(room);
diff --git a/packages/rocketchat-livechat/server/methods/closeRoom.js b/packages/rocketchat-livechat/server/methods/closeRoom.js
index b61350ec9ff9..6013a517a664 100644
--- a/packages/rocketchat-livechat/server/methods/closeRoom.js
+++ b/packages/rocketchat-livechat/server/methods/closeRoom.js
@@ -1,6 +1,7 @@
Meteor.methods({
'livechat:closeRoom'(roomId, comment) {
- if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'close-livechat-room')) {
+ const userId = Meteor.userId();
+ if (!userId || !RocketChat.authz.hasPermission(userId, 'close-livechat-room')) {
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'livechat:closeRoom' });
}
@@ -12,7 +13,8 @@ Meteor.methods({
const user = Meteor.user();
- if ((!room.usernames || room.usernames.indexOf(user.username) === -1) && !RocketChat.authz.hasPermission(Meteor.userId(), 'close-others-livechat-room')) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(roomId, user._id, { _id: 1 });
+ if (!subscription && !RocketChat.authz.hasPermission(userId, 'close-others-livechat-room')) {
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'livechat:closeRoom' });
}
diff --git a/packages/rocketchat-livechat/server/methods/returnAsInquiry.js b/packages/rocketchat-livechat/server/methods/returnAsInquiry.js
index 91abafb0444a..059f2687956a 100644
--- a/packages/rocketchat-livechat/server/methods/returnAsInquiry.js
+++ b/packages/rocketchat-livechat/server/methods/returnAsInquiry.js
@@ -7,11 +7,6 @@ Meteor.methods({
// //delete agent and room subscription
RocketChat.models.Subscriptions.removeByRoomId(rid);
- // remove user from room
- const username = Meteor.user().username;
-
- RocketChat.models.Rooms.removeUsernameById(rid, username);
-
// find inquiry corresponding to room
const inquiry = RocketChat.models.LivechatInquiry.findOne({rid});
diff --git a/packages/rocketchat-livechat/server/methods/takeInquiry.js b/packages/rocketchat-livechat/server/methods/takeInquiry.js
index da199cb84740..14d73a4393a2 100644
--- a/packages/rocketchat-livechat/server/methods/takeInquiry.js
+++ b/packages/rocketchat-livechat/server/methods/takeInquiry.js
@@ -35,7 +35,9 @@ Meteor.methods({
mobilePushNotifications: 'all',
emailNotifications: 'all'
};
+
RocketChat.models.Subscriptions.insert(subscriptionData);
+ RocketChat.models.Rooms.incUsersCountById(inquiry.rid);
// update room
const room = RocketChat.models.Rooms.findOneById(inquiry.rid);
diff --git a/packages/rocketchat-livechat/server/methods/transfer.js b/packages/rocketchat-livechat/server/methods/transfer.js
index e2af06273488..aac6d632a5dd 100644
--- a/packages/rocketchat-livechat/server/methods/transfer.js
+++ b/packages/rocketchat-livechat/server/methods/transfer.js
@@ -18,9 +18,8 @@ Meteor.methods({
const guest = LivechatVisitors.findOneById(room.v._id);
- const user = Meteor.user();
-
- if (room.usernames.indexOf(user.username) === -1 && !RocketChat.authz.hasRole(Meteor.userId(), 'livechat-manager')) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, Meteor.userId(), { fields: { _id: 1 } });
+ if (!subscription && !RocketChat.authz.hasRole(Meteor.userId(), 'livechat-manager')) {
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'livechat:transfer' });
}
diff --git a/packages/rocketchat-livechat/server/publications/visitorHistory.js b/packages/rocketchat-livechat/server/publications/visitorHistory.js
index e90e34fc1470..f46711de7347 100644
--- a/packages/rocketchat-livechat/server/publications/visitorHistory.js
+++ b/packages/rocketchat-livechat/server/publications/visitorHistory.js
@@ -9,9 +9,8 @@ Meteor.publish('livechat:visitorHistory', function({ rid: roomId }) {
const room = RocketChat.models.Rooms.findOneById(roomId);
- const user = RocketChat.models.Users.findOneById(this.userId);
-
- if (room.usernames.indexOf(user.username) === -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, this.userId, { fields: { _id: 1 } });
+ if (!subscription) {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:visitorHistory' }));
}
diff --git a/packages/rocketchat-message-pin/client/actionButton.js b/packages/rocketchat-message-pin/client/actionButton.js
index 407904b6dfe2..02c16203be3f 100644
--- a/packages/rocketchat-message-pin/client/actionButton.js
+++ b/packages/rocketchat-message-pin/client/actionButton.js
@@ -16,7 +16,7 @@ Meteor.startup(function() {
});
},
condition(message) {
- if (!RocketChat.settings.get('Message_AllowPinning') || message.pinned || !RocketChat.models.Subscriptions.findOne({ rid: message.rid }, {fields: {_id: 1}})) {
+ if (!RocketChat.settings.get('Message_AllowPinning') || message.pinned || !RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { _id: 1 } })) {
return false;
}
@@ -41,7 +41,7 @@ Meteor.startup(function() {
});
},
condition(message) {
- if (!RocketChat.settings.get('Message_AllowPinning') || !message.pinned || !RocketChat.models.Subscriptions.findOne({ rid: message.rid }, {fields: {_id: 1}})) {
+ if (!RocketChat.settings.get('Message_AllowPinning') || !message.pinned || !RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { _id: 1 } })) {
return false;
}
@@ -64,7 +64,7 @@ Meteor.startup(function() {
return RoomHistoryManager.getSurroundingMessages(message, 50);
},
condition(message) {
- if (!RocketChat.models.Subscriptions.findOne({ rid: message.rid }, {fields: {_id: 1}})) {
+ if (!RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { _id: 1 } })) {
return false;
}
return true;
@@ -85,7 +85,7 @@ Meteor.startup(function() {
toastr.success(TAPi18n.__('Copied'));
},
condition(message) {
- if (!RocketChat.models.Subscriptions.findOne({ rid: message.rid }, {fields: {_id: 1}})) {
+ if (!RocketChat.models.Subscriptions.findOne({ rid: message.rid }, { fields: { _id: 1 } })) {
return false;
}
return true;
diff --git a/packages/rocketchat-message-pin/server/pinMessage.js b/packages/rocketchat-message-pin/server/pinMessage.js
index 97cd6cdd5b1e..5be88399d572 100644
--- a/packages/rocketchat-message-pin/server/pinMessage.js
+++ b/packages/rocketchat-message-pin/server/pinMessage.js
@@ -33,8 +33,8 @@ Meteor.methods({
});
}
- const room = RocketChat.models.Rooms.findOneById(message.rid);
- if (Array.isArray(room.usernames) && room.usernames.indexOf(Meteor.user().username) === -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId(), { fields: { _id: 1 } });
+ if (!subscription) {
return false;
}
@@ -108,9 +108,8 @@ Meteor.methods({
});
}
- const room = RocketChat.models.Rooms.findOneById(message.rid);
-
- if (Array.isArray(room.usernames) && room.usernames.indexOf(Meteor.user().username) === -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId(), { fields: { _id: 1 } });
+ if (!subscription) {
return false;
}
diff --git a/packages/rocketchat-message-snippet/server/methods/snippetMessage.js b/packages/rocketchat-message-snippet/server/methods/snippetMessage.js
index 6299c81d0b99..d4f590c1c65a 100644
--- a/packages/rocketchat-message-snippet/server/methods/snippetMessage.js
+++ b/packages/rocketchat-message-snippet/server/methods/snippetMessage.js
@@ -1,6 +1,6 @@
Meteor.methods({
snippetMessage(message, filename) {
- if ((typeof Meteor.userId() === 'undefined') || (Meteor.userId() === null)) {
+ if (Meteor.userId() == null) {
//noinspection JSUnresolvedFunction
throw new Meteor.Error('error-invalid-user', 'Invalid user',
{method: 'snippetMessage'});
@@ -12,7 +12,8 @@ Meteor.methods({
return false;
}
- if (Array.isArray(room.usernames) && (room.usernames.indexOf(Meteor.user().username) === -1)) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId(), { fields: { _id: 1 } });
+ if (!subscription) {
return false;
}
diff --git a/packages/rocketchat-message-star/server/starMessage.js b/packages/rocketchat-message-star/server/starMessage.js
index cb8b99ad9eef..230c5af85e2d 100644
--- a/packages/rocketchat-message-star/server/starMessage.js
+++ b/packages/rocketchat-message-star/server/starMessage.js
@@ -13,12 +13,11 @@ Meteor.methods({
});
}
- const room = RocketChat.models.Rooms.findOneById(message.rid);
- if (Array.isArray(room.usernames) && room.usernames.indexOf(Meteor.user().username) === -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(message.rid, Meteor.userId(), { fields: { _id: 1 } });
+ if (!subscription) {
return false;
}
return RocketChat.models.Messages.updateUserStarById(message._id, Meteor.userId(), message.starred);
}
});
-
diff --git a/packages/rocketchat-migrations/migrations.js b/packages/rocketchat-migrations/migrations.js
index bc72ae3b8300..ab31856b9233 100644
--- a/packages/rocketchat-migrations/migrations.js
+++ b/packages/rocketchat-migrations/migrations.js
@@ -272,9 +272,7 @@ Migrations._migrateTo = function(version, rerun) {
log.info(`Running ${ direction }() on version ${ migration.version }${ maybeName() }`);
try {
- RocketChat.models._CacheControl.withValue(false, function() {
- migration[direction](migration);
- });
+ migration[direction](migration);
} catch (e) {
console.log(makeABox([
'ERROR! SERVER STOPPED',
diff --git a/packages/rocketchat-oauth2-server-config/oauth/server/oauth2-server.js b/packages/rocketchat-oauth2-server-config/oauth/server/oauth2-server.js
index ad7e3be83f72..9e4c29460b90 100644
--- a/packages/rocketchat-oauth2-server-config/oauth/server/oauth2-server.js
+++ b/packages/rocketchat-oauth2-server-config/oauth/server/oauth2-server.js
@@ -1,5 +1,4 @@
/*global OAuth2Server */
-import _ from 'underscore';
const oauth2server = new OAuth2Server({
accessTokensCollectionName: 'rocketchat_oauth_access_tokens',
@@ -80,5 +79,5 @@ RocketChat.API.v1.addAuthMethod(function() {
if (user == null) {
return;
}
- return { user: _.omit(user, '$loki') };
+ return { user };
});
diff --git a/packages/rocketchat-search/server/events/events.js b/packages/rocketchat-search/server/events/events.js
index cb562bf4008b..723764d317a8 100644
--- a/packages/rocketchat-search/server/events/events.js
+++ b/packages/rocketchat-search/server/events/events.js
@@ -33,20 +33,31 @@ RocketChat.callbacks.add('afterDeleteMessage', function(m) {
* Listen to user and room changes via cursor
*/
-RocketChat.models.Users.on('changed', (type, user)=>{
- if (type === 'inserted' || type === 'updated') {
- eventService.promoteEvent('user.save', user._id, user);
- }
- if (type === 'removed') {
- eventService.promoteEvent('user.delete', user._id);
+
+RocketChat.models.Users.on('change', ({clientAction, id, data}) => {
+ switch (clientAction) {
+ case 'updated':
+ case 'inserted':
+ const user = data || RocketChat.models.Users.findOneById(id);
+ eventService.promoteEvent('user.save', id, user);
+ break;
+
+ case 'removed':
+ eventService.promoteEvent('user.delete', id);
+ break;
}
});
-RocketChat.models.Rooms.on('changed', (type, room)=>{
- if (type === 'inserted' || type === 'updated') {
- eventService.promoteEvent('room.save', room._id, room);
- }
- if (type === 'removed') {
- eventService.promoteEvent('room.delete', room._id);
+RocketChat.models.Rooms.on('change', ({clientAction, id, data}) => {
+ switch (clientAction) {
+ case 'updated':
+ case 'inserted':
+ const room = data || RocketChat.models.Rooms.findOneById(id);
+ eventService.promoteEvent('room.save', id, room);
+ break;
+
+ case 'removed':
+ eventService.promoteEvent('room.delete', id);
+ break;
}
});
diff --git a/packages/rocketchat-slashcommands-hide/server/hide.js b/packages/rocketchat-slashcommands-hide/server/hide.js
index 4ba92586b561..fade32a23d54 100644
--- a/packages/rocketchat-slashcommands-hide/server/hide.js
+++ b/packages/rocketchat-slashcommands-hide/server/hide.js
@@ -32,7 +32,7 @@ function Hide(command, param, item) {
});
}
- if (!roomObject.usernames.includes(user.username)) {
+ if (!RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id, { fields: { _id: 1 } })) {
return RocketChat.Notifications.notifyUser(user._id, 'message', {
_id: Random.id(),
rid: item.rid,
diff --git a/packages/rocketchat-slashcommands-invite/server/server.js b/packages/rocketchat-slashcommands-invite/server/server.js
index 2dcd6923c5d2..9e5f10c95de3 100644
--- a/packages/rocketchat-slashcommands-invite/server/server.js
+++ b/packages/rocketchat-slashcommands-invite/server/server.js
@@ -10,18 +10,19 @@ function Invite(command, params, item) {
if (command !== 'invite' || !Match.test(params, String)) {
return;
}
- let usernames = params.replace(/@/g, '').split(/[\s,]/).filter((a) => a !== '');
+ const usernames = params.replace(/@/g, '').split(/[\s,]/).filter((a) => a !== '');
if (usernames.length === 0) {
return;
}
- const users = Meteor.users.find({
+ let users = Meteor.users.find({
username: {
$in: usernames
}
});
- const currentUser = Meteor.users.findOne(Meteor.userId());
+ const userId = Meteor.userId();
+ const currentUser = Meteor.users.findOne(userId);
if (users.count() === 0) {
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date,
@@ -32,24 +33,23 @@ function Invite(command, params, item) {
});
return;
}
- usernames = usernames.filter(function(username) {
- if (RocketChat.models.Rooms.findOneByIdContainingUsername(item.rid, username) == null) {
+ users = users.fetch().filter(function(user) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(item.rid, user._id, { fields: { _id: 1 } });
+ if (subscription == null) {
return true;
}
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date,
msg: TAPi18n.__('Username_is_already_in_here', {
postProcess: 'sprintf',
- sprintf: [username]
+ sprintf: [user.username]
}, currentUser.language)
});
return false;
});
- if (usernames.length === 0) {
- return;
- }
+
users.forEach(function(user) {
try {
@@ -59,14 +59,14 @@ function Invite(command, params, item) {
});
} catch ({error}) {
if (error === 'cant-invite-for-direct-room') {
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date,
msg: TAPi18n.__('Cannot_invite_users_to_direct_rooms', null, currentUser.language)
});
} else {
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date,
diff --git a/packages/rocketchat-slashcommands-inviteall/server/server.js b/packages/rocketchat-slashcommands-inviteall/server/server.js
index 133c8200ef18..400b955b5319 100644
--- a/packages/rocketchat-slashcommands-inviteall/server/server.js
+++ b/packages/rocketchat-slashcommands-inviteall/server/server.js
@@ -16,13 +16,13 @@ function inviteAll(type) {
if (!channel) {
return;
}
-
- const currentUser = Meteor.users.findOne(Meteor.userId());
+ const userId = Meteor.userId();
+ const currentUser = Meteor.users.findOne(userId);
const baseChannel = type === 'to' ? RocketChat.models.Rooms.findOneById(item.rid) : RocketChat.models.Rooms.findOneByName(channel);
const targetChannel = type === 'from' ? RocketChat.models.Rooms.findOneById(item.rid) : RocketChat.models.Rooms.findOneByName(channel);
if (!baseChannel) {
- return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ return RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date(),
@@ -32,18 +32,19 @@ function inviteAll(type) {
}, currentUser.language)
});
}
- const users = baseChannel.usernames || [];
+ const cursor = RocketChat.models.Subscriptions.findByRoomIdWhenUsernameExists(baseChannel._id, { fields: { 'u.username': 1 } });
try {
- if (users.length > RocketChat.settings.get('API_User_Limit')) {
+ if (cursor.count() > RocketChat.settings.get('API_User_Limit')) {
throw new Meteor.Error('error-user-limit-exceeded', 'User Limit Exceeded', {
method: 'addAllToRoom'
});
}
+ const users = cursor.fetch().map(s => s.u.username);
if (!targetChannel && ['c', 'p'].indexOf(baseChannel.t) > -1) {
Meteor.call(baseChannel.t === 'c' ? 'createChannel' : 'createPrivateGroup', channel, users);
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date(),
@@ -58,7 +59,7 @@ function inviteAll(type) {
users
});
}
- return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ return RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date(),
@@ -66,7 +67,7 @@ function inviteAll(type) {
});
} catch (e) {
const msg = e.error === 'cant-invite-for-direct-room' ? 'Cannot_invite_users_to_direct_rooms' : e.error;
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date(),
diff --git a/packages/rocketchat-slashcommands-join/server/server.js b/packages/rocketchat-slashcommands-join/server/server.js
index 1cabe1e1a307..4289ec16bc04 100644
--- a/packages/rocketchat-slashcommands-join/server/server.js
+++ b/packages/rocketchat-slashcommands-join/server/server.js
@@ -28,7 +28,9 @@ RocketChat.slashCommands.add('join', function Join(command, params, item) {
}, user.language)
});
}
- if (room.usernames.includes(user.username)) {
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, user._id, { fields: { _id: 1 } });
+ if (subscription) {
throw new Meteor.Error('error-user-already-in-room', 'You are already in the channel', {
method: 'slashCommands'
});
diff --git a/packages/rocketchat-slashcommands-kick/server/server.js b/packages/rocketchat-slashcommands-kick/server/server.js
index 8b6a298838cf..4fffdc7af62d 100644
--- a/packages/rocketchat-slashcommands-kick/server/server.js
+++ b/packages/rocketchat-slashcommands-kick/server/server.js
@@ -9,11 +9,12 @@ const Kick = function(command, params, {rid}) {
if (username === '') {
return;
}
- const user = Meteor.users.findOne(Meteor.userId());
+ const userId = Meteor.userId();
+ const user = Meteor.users.findOne(userId);
const kickedUser = RocketChat.models.Users.findOneByUsername(username);
- const room = RocketChat.models.Rooms.findOneById(rid);
+
if (kickedUser == null) {
- return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ return RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid,
ts: new Date,
@@ -23,8 +24,10 @@ const Kick = function(command, params, {rid}) {
}, user.language)
});
}
- if ((room.usernames || []).includes(username) === false) {
- return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, user._id, { fields: { _id: 1 } });
+ if (!subscription) {
+ return RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid,
ts: new Date,
diff --git a/packages/rocketchat-slashcommands-mute/server/mute.js b/packages/rocketchat-slashcommands-mute/server/mute.js
index 2c477609d797..357aab64c090 100644
--- a/packages/rocketchat-slashcommands-mute/server/mute.js
+++ b/packages/rocketchat-slashcommands-mute/server/mute.js
@@ -11,11 +11,11 @@ RocketChat.slashCommands.add('mute', function Mute(command, params, item) {
if (username === '') {
return;
}
- const user = Meteor.users.findOne(Meteor.userId());
+ const userId = Meteor.userId();
+ const user = Meteor.users.findOne(userId);
const mutedUser = RocketChat.models.Users.findOneByUsername(username);
- const room = RocketChat.models.Rooms.findOneById(item.rid);
if (mutedUser == null) {
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date,
@@ -26,8 +26,10 @@ RocketChat.slashCommands.add('mute', function Mute(command, params, item) {
});
return;
}
- if ((room.usernames || []).includes(username) === false) {
- RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(item.rid, mutedUser._id, { fields: { _id: 1 } });
+ if (!subscription) {
+ RocketChat.Notifications.notifyUser(userId, 'message', {
_id: Random.id(),
rid: item.rid,
ts: new Date,
diff --git a/packages/rocketchat-slashcommands-mute/server/unmute.js b/packages/rocketchat-slashcommands-mute/server/unmute.js
index 1a864ab63f89..8a471bef50ae 100644
--- a/packages/rocketchat-slashcommands-mute/server/unmute.js
+++ b/packages/rocketchat-slashcommands-mute/server/unmute.js
@@ -14,7 +14,6 @@ RocketChat.slashCommands.add('unmute', function Unmute(command, params, item) {
}
const user = Meteor.users.findOne(Meteor.userId());
const unmutedUser = RocketChat.models.Users.findOneByUsername(username);
- const room = RocketChat.models.Rooms.findOneById(item.rid);
if (unmutedUser == null) {
return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
_id: Random.id(),
@@ -26,7 +25,9 @@ RocketChat.slashCommands.add('unmute', function Unmute(command, params, item) {
}, user.language)
});
}
- if ((room.usernames || []).includes(username) === false) {
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(item.rid, unmutedUser._id, { fields: { _id: 1 } });
+ if (!subscription) {
return RocketChat.Notifications.notifyUser(Meteor.userId(), 'message', {
_id: Random.id(),
rid: item.rid,
diff --git a/packages/rocketchat-ui/client/views/app/directory.html b/packages/rocketchat-ui/client/views/app/directory.html
index 765a2867110e..e8450d88a69a 100644
--- a/packages/rocketchat-ui/client/views/app/directory.html
+++ b/packages/rocketchat-ui/client/views/app/directory.html
@@ -18,8 +18,8 @@
{{_ "Name"}} {{> icon icon=(sortIcon 'name')}}
|
-
- {{_ "Users"}}
+ |
+ {{_ "Users"}} {{> icon icon=(sortIcon 'usersCount')}}
|
{{#if showLastMessage}}
diff --git a/packages/rocketchat-ui/client/views/app/directory.js b/packages/rocketchat-ui/client/views/app/directory.js
index 70465f6a6930..3c8a3e68cc9f 100644
--- a/packages/rocketchat-ui/client/views/app/directory.js
+++ b/packages/rocketchat-ui/client/views/app/directory.js
@@ -2,6 +2,10 @@ import moment from 'moment';
import _ from 'underscore';
function timeAgo(time) {
+ if (!time) {
+ return;
+ }
+
const now = new Date();
const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
@@ -14,7 +18,7 @@ function directorySearch(config, cb) {
if (config.type === 'channels') {
return {
name: result.name,
- users: (result.usernames ? result.usernames.length : result.usersCount) || 0,
+ users: result.usersCount || 0,
createdAt: timeAgo(result.ts),
lastMessage: result.lastMessage && timeAgo(result.lastMessage.ts),
description: result.description,
@@ -198,8 +202,8 @@ Template.directory.onRendered(function() {
Template.directory.onCreated(function() {
this.searchText = new ReactiveVar('');
this.searchType = new ReactiveVar('channels');
- this.searchSortBy = new ReactiveVar('name');
- this.sortDirection = new ReactiveVar('asc');
+ this.searchSortBy = new ReactiveVar('usersCount');
+ this.sortDirection = new ReactiveVar('desc');
this.limit = new ReactiveVar(0);
this.page = new ReactiveVar(0);
this.end = new ReactiveVar(false);
diff --git a/packages/rocketchat-user-data-download/server/cronProcessDownloads.js b/packages/rocketchat-user-data-download/server/cronProcessDownloads.js
index 985171edac32..d1f56f6e8dcf 100644
--- a/packages/rocketchat-user-data-download/server/cronProcessDownloads.js
+++ b/packages/rocketchat-user-data-download/server/cronProcessDownloads.js
@@ -37,7 +37,7 @@ const loadUserSubscriptions = function(exportOperation) {
const cursor = RocketChat.models.Subscriptions.findByUserId(exportUserId);
cursor.forEach((subscription) => {
const roomId = subscription.rid;
- const roomData = subscription._room;
+ const roomData = RocketChat.models.Rooms.findOneById(roomId);
let roomName = roomData.name ? roomData.name : roomId;
let userId = null;
diff --git a/server/methods/addAllUserToRoom.js b/server/methods/addAllUserToRoom.js
index 14a6d1a770f0..bf8978303065 100644
--- a/server/methods/addAllUserToRoom.js
+++ b/server/methods/addAllUserToRoom.js
@@ -32,7 +32,6 @@ Meteor.methods({
return;
}
RocketChat.callbacks.run('beforeJoinRoom', user, room);
- RocketChat.models.Rooms.addUsernameById(rid, user.username);
RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
ts: now,
open: true,
diff --git a/server/methods/browseChannels.js b/server/methods/browseChannels.js
index 6f8be8edf325..f92dad8d7523 100644
--- a/server/methods/browseChannels.js
+++ b/server/methods/browseChannels.js
@@ -35,7 +35,7 @@ Meteor.methods({
return;
}
- if (!['name', 'createdAt', ...type === 'channels' ? ['usernames'] : [], ...type === 'users' ? ['username'] : []].includes(sortBy)) {
+ if (!['name', 'createdAt', ...type === 'channels' ? ['usersCount'] : [], ...type === 'users' ? ['username'] : []].includes(sortBy)) {
return;
}
@@ -56,23 +56,19 @@ Meteor.methods({
return;
}
return {
- results: RocketChat.models.Rooms.findByNameAndType(
- regex,
- 'c',
- {
- ...options,
- sort,
- fields: {
- description: 1,
- topic: 1,
- name: 1,
- lastMessage: 1,
- ts: 1,
- archived: 1,
- usernames: 1,
- usersCount: 1
- }
- }).fetch(),
+ results: RocketChat.models.Rooms.findByNameAndType(regex, 'c', {
+ ...options,
+ sort,
+ fields: {
+ description: 1,
+ topic: 1,
+ name: 1,
+ lastMessage: 1,
+ ts: 1,
+ archived: 1,
+ usersCount: 1
+ }
+ }).fetch(),
total: RocketChat.models.Rooms.findByNameAndType(regex, 'c').count()
};
}
diff --git a/server/methods/channelsList.js b/server/methods/channelsList.js
index b8dcea5077e3..9a8d03c57f97 100644
--- a/server/methods/channelsList.js
+++ b/server/methods/channelsList.js
@@ -44,56 +44,50 @@ Meteor.methods({
}
}
- const roomTypes = [];
+ let channels = [];
+
+ const userId = Meteor.userId();
if (channelType !== 'private') {
- if (RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room')) {
- roomTypes.push({
- type: 'c'
- });
- } else if (RocketChat.authz.hasPermission(Meteor.userId(), 'view-joined-room')) {
- const roomIds = _.pluck(RocketChat.models.Subscriptions.findByTypeAndUserId('c', Meteor.userId()).fetch(), 'rid');
- roomTypes.push({
- type: 'c',
- ids: roomIds
- });
+ if (RocketChat.authz.hasPermission(userId, 'view-c-room')) {
+ if (filter) {
+ channels = channels.concat(RocketChat.models.Rooms.findByType('c', options).fetch());
+ } else {
+ channels = channels.concat(RocketChat.models.Rooms.findByTypeAndNameContaining('c', filter, options).fetch());
+ }
+ } else if (RocketChat.authz.hasPermission(userId, 'view-joined-room')) {
+ const roomIds = RocketChat.models.Subscriptions.findByTypeAndUserId('c', userId, {fields: {rid: 1}}).fetch().map(s => s.rid);
+ if (filter) {
+ channels = channels.concat(RocketChat.models.Rooms.findByTypeInIds('c', roomIds, options).fetch());
+ } else {
+ channels = channels.concat(RocketChat.models.Rooms.findByTypeInIdsAndNameContaining('c', roomIds, filter, options).fetch());
+ }
}
}
- if (channelType !== 'public' && RocketChat.authz.hasPermission(Meteor.userId(), 'view-p-room')) {
- const user = RocketChat.models.Users.findOne(Meteor.userId(), {
+ if (channelType !== 'public' && RocketChat.authz.hasPermission(userId, 'view-p-room')) {
+ const user = RocketChat.models.Users.findOne(userId, {
fields: {
username: 1,
'settings.preferences.sidebarGroupByType': 1
}
});
const userPref = RocketChat.getUserPreference(user, 'sidebarGroupByType');
- const globalPref = RocketChat.settings.get('UI_Group_Channels_By_Type');
// needs to negate globalPref because userPref represents its opposite
- const groupByType = userPref !== undefined ? userPref : globalPref;
+ const groupByType = userPref !== undefined ? userPref : RocketChat.settings.get('UI_Group_Channels_By_Type');
if (!groupByType) {
- roomTypes.push({
- type: 'p',
- username: user.username
- });
- }
- }
-
- if (roomTypes.length) {
- if (filter) {
- return {
- channels: RocketChat.models.Rooms.findByNameContainingTypesWithUsername(filter, roomTypes, options).fetch()
- };
+ const roomIds = RocketChat.models.Subscriptions.findByTypeAndUserId('p', userId, {fields: {rid: 1}}).fetch().map(s => s.rid);
+ if (filter) {
+ channels = channels.concat(RocketChat.models.Rooms.findByTypeInIds('p', roomIds, options).fetch());
+ } else {
+ channels = channels.concat(RocketChat.models.Rooms.findByTypeInIdsAndNameContaining('p', roomIds, filter, options).fetch());
+ }
}
-
- return {
- channels: RocketChat.models.Rooms.findContainingTypesWithUsername(roomTypes, options).fetch()
- };
}
return {
- channels: []
+ channels
};
}
});
diff --git a/server/methods/createDirectMessage.js b/server/methods/createDirectMessage.js
index c481160caa4d..8c21d855d031 100644
--- a/server/methods/createDirectMessage.js
+++ b/server/methods/createDirectMessage.js
@@ -50,7 +50,8 @@ Meteor.methods({
$setOnInsert: {
t: 'd',
msgs: 0,
- ts: now
+ ts: now,
+ usersCount: 2
}
});
@@ -64,6 +65,7 @@ Meteor.methods({
open: true
},
$setOnInsert: {
+ fname: to.name,
name: to.username,
t: 'd',
alert: false,
@@ -95,6 +97,7 @@ Meteor.methods({
$and: [{'u._id': to._id}] // work around to solve problems with upsert and dot
}, {
$setOnInsert: {
+ fname: me.username,
name: me.username,
t: 'd',
open: false,
diff --git a/server/methods/getRoomIdByNameOrId.js b/server/methods/getRoomIdByNameOrId.js
index 116e7cfe8d97..67f6baff54c3 100644
--- a/server/methods/getRoomIdByNameOrId.js
+++ b/server/methods/getRoomIdByNameOrId.js
@@ -1,3 +1,4 @@
+// DEPRECATE
Meteor.methods({
getRoomIdByNameOrId(rid) {
check(rid, String);
@@ -16,11 +17,6 @@ Meteor.methods({
});
}
- const user = Meteor.user();
- if (user && user.username && room.usernames.indexOf(user.username) !== -1) {
- return room._id;
- }
-
if (room.t !== 'c' || RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room') !== true) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
method: 'getRoomIdByNameOrId'
diff --git a/server/methods/getRoomNameById.js b/server/methods/getRoomNameById.js
index 1228eda83278..bff4f28cda25 100644
--- a/server/methods/getRoomNameById.js
+++ b/server/methods/getRoomNameById.js
@@ -1,8 +1,8 @@
Meteor.methods({
getRoomNameById(rid) {
check(rid, String);
-
- if (!Meteor.userId()) {
+ const userId = Meteor.userId();
+ if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'getRoomNameById'
});
@@ -16,12 +16,12 @@ Meteor.methods({
});
}
- const user = Meteor.user();
- if (user && user.username && room.usernames.indexOf(user.username) !== -1) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, userId, { fields: { _id: 1 } });
+ if (subscription) {
return room.name;
}
- if (room.t !== 'c' || RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room') !== true) {
+ if (room.t !== 'c' || RocketChat.authz.hasPermission(userId, 'view-c-room') !== true) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', {
method: 'getRoomNameById'
});
diff --git a/server/methods/getUsersOfRoom.js b/server/methods/getUsersOfRoom.js
index 3a6bc5c2e66a..e65391cc2112 100644
--- a/server/methods/getUsersOfRoom.js
+++ b/server/methods/getUsersOfRoom.js
@@ -1,44 +1,30 @@
Meteor.methods({
- getUsersOfRoom(roomId, showAll) {
- if (!Meteor.userId()) {
+ getUsersOfRoom(rid, showAll) {
+ const userId = Meteor.userId();
+ if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getUsersOfRoom' });
}
- const room = Meteor.call('canAccessRoom', roomId, Meteor.userId());
+ const room = Meteor.call('canAccessRoom', rid, userId);
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getUsersOfRoom' });
}
- if (room.broadcast && !RocketChat.authz.hasPermission(Meteor.userId(), 'view-broadcast-member-list', roomId)) {
+ if (room.broadcast && !RocketChat.authz.hasPermission(userId, 'view-broadcast-member-list', rid)) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getUsersOfRoom' });
}
- const filter = (record) => {
- if (!record._user) {
- console.log('Subscription without user', record._id);
- return false;
- }
+ const subscriptions = RocketChat.models.Subscriptions.findByRoomIdWhenUsernameExists(rid, { fields: { 'u._id': 1 } }).fetch();
+ const userIds = subscriptions.map(s => s.u._id); // TODO: CACHE: expensive
+ const options = { fields: { username: 1, name: 1 } };
- if (showAll === true) {
- return true;
- }
-
- return record._user.status !== 'offline';
- };
-
- const map = (record) => {
- return {
- _id: record._user._id,
- username: record._user.username,
- name: record._user.name
- };
- };
-
- const records = RocketChat.models.Subscriptions.findByRoomId(roomId).fetch();
+ const users = showAll === true
+ ? RocketChat.models.Users.findUsersWithUsernameByIds(userIds, options).fetch()
+ : RocketChat.models.Users.findUsersWithUsernameByIdsNotOffline(userIds, options).fetch();
return {
- total: records.length,
- records: records.filter(filter).map(map)
+ total: userIds.length,
+ records: users
};
}
});
diff --git a/server/methods/groupsList.js b/server/methods/groupsList.js
deleted file mode 100644
index a235e9bf44cd..000000000000
--- a/server/methods/groupsList.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import _ from 'underscore';
-import s from 'underscore.string';
-
-Meteor.methods({
- groupsList(nameFilter, limit, sort) {
-
- check(nameFilter, Match.Optional(String));
- check(limit, Match.Optional(Number));
- check(sort, Match.Optional(String));
-
- if (!Meteor.userId()) {
- throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'groupsList' });
- }
-
- const options = {
- fields: { name: 1 },
- sort: { name: 1 }
- };
-
- //Verify the limit param is a number
- if (_.isNumber(limit)) {
- options.limit = limit;
- }
-
- //Verify there is a sort option and it's a string
- if (s.trim(sort)) {
- switch (sort) {
- case 'name':
- options.sort = { name: 1 };
- break;
- case 'msgs':
- options.sort = { msgs: -1 };
- break;
- }
- }
-
- //Determine if they are searching or not, base it upon the name field
- if (nameFilter) {
- return { groups: RocketChat.models.Rooms.findByTypeAndNameContainingUsername('p', new RegExp(s.trim(s.escapeRegExp(nameFilter)), 'i'), Meteor.user().username, options).fetch() };
- } else {
- const roomIds = _.pluck(RocketChat.models.Subscriptions.findByTypeAndUserId('p', Meteor.userId()).fetch(), 'rid');
- return { groups: RocketChat.models.Rooms.findByIds(roomIds, options).fetch() };
- }
- }
-});
diff --git a/server/methods/loadHistory.js b/server/methods/loadHistory.js
index 76ef737b2eef..cd7c0cde20f9 100644
--- a/server/methods/loadHistory.js
+++ b/server/methods/loadHistory.js
@@ -37,7 +37,8 @@ Meteor.methods({
const canAnonymous = RocketChat.settings.get('Accounts_AllowAnonymousRead');
const canPreview = RocketChat.authz.hasPermission(fromId, 'preview-c-room');
- if (room.t === 'c' && !canAnonymous && !canPreview && room.usernames.indexOf(room.username) === -1) {
+
+ if (room.t === 'c' && !canAnonymous && !canPreview && RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(rid, fromId, { fields: { _id: 1 } })) {
return false;
}
diff --git a/server/methods/muteUserInRoom.js b/server/methods/muteUserInRoom.js
index 862ee9a9511d..e6d2b42dba7c 100644
--- a/server/methods/muteUserInRoom.js
+++ b/server/methods/muteUserInRoom.js
@@ -34,7 +34,8 @@ Meteor.methods({
});
}
- if (Array.isArray(room.usernames) === false || room.usernames.includes(data.username) === false) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUsername(data.rid, data.username, { fields: { _id: 1 } });
+ if (!subscription) {
throw new Meteor.Error('error-user-not-in-room', 'User is not in this room', {
method: 'muteUserInRoom'
});
diff --git a/server/methods/removeUserFromRoom.js b/server/methods/removeUserFromRoom.js
index 4a2984d4ebf6..47c7f6a18b9f 100644
--- a/server/methods/removeUserFromRoom.js
+++ b/server/methods/removeUserFromRoom.js
@@ -27,14 +27,15 @@ Meteor.methods({
});
}
- if (Array.isArray(room.usernames) === false || room.usernames.includes(data.username) === false) {
+ const removedUser = RocketChat.models.Users.findOneByUsername(data.username);
+
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(data.rid, removedUser._id, { fields: { _id: 1 } });
+ if (!subscription) {
throw new Meteor.Error('error-user-not-in-room', 'User is not in this room', {
method: 'removeUserFromRoom'
});
}
- const removedUser = RocketChat.models.Users.findOneByUsername(data.username);
-
if (RocketChat.authz.hasRole(removedUser._id, 'owner', room._id)) {
const numOwners = RocketChat.authz.getUsersInRole('owner', room._id).fetch().length;
@@ -45,8 +46,6 @@ Meteor.methods({
}
}
- RocketChat.models.Rooms.removeUsernameById(data.rid, data.username);
-
RocketChat.models.Subscriptions.removeByRoomIdAndUserId(data.rid, removedUser._id);
if (['c', 'p'].includes(room.t) === true) {
diff --git a/server/methods/unmuteUserInRoom.js b/server/methods/unmuteUserInRoom.js
index 3c75b44921f3..dce8f868c909 100644
--- a/server/methods/unmuteUserInRoom.js
+++ b/server/methods/unmuteUserInRoom.js
@@ -28,7 +28,8 @@ Meteor.methods({
});
}
- if (Array.isArray(room.usernames) === false || room.usernames.includes(data.username) === false) {
+ const subscription = RocketChat.models.Subscriptions.findOneByRoomIdAndUsername(data.rid, data.username, { fields: { _id: 1 } });
+ if (!subscription) {
throw new Meteor.Error('error-user-not-in-room', 'User is not in this room', {
method: 'unmuteUserInRoom'
});
diff --git a/server/publications/channelAndPrivateAutocomplete.js b/server/publications/channelAndPrivateAutocomplete.js
index fec41bbeafdc..32f3a8fe717d 100644
--- a/server/publications/channelAndPrivateAutocomplete.js
+++ b/server/publications/channelAndPrivateAutocomplete.js
@@ -19,7 +19,7 @@ Meteor.publish('channelAndPrivateAutocomplete', function(selector) {
}
};
- const cursorHandle = RocketChat.models.Rooms.findByNameStartingAndTypes(selector.name, ['c', 'p'], options).observeChanges({
+ const cursorHandle = RocketChat.models.Rooms.findChannelAndPrivateByNameStarting(selector.name, options).observeChanges({
added(_id, record) {
return pub.added('autocompleteRecords', _id, record);
},
diff --git a/server/publications/room.js b/server/publications/room.js
index a2bfa46da5e8..7d97405597d0 100644
--- a/server/publications/room.js
+++ b/server/publications/room.js
@@ -40,10 +40,9 @@ const fields = {
};
const roomMap = (record) => {
- if (record._room) {
- return _.pick(record._room, ...Object.keys(fields));
+ if (record) {
+ return _.pick(record, ...Object.keys(fields));
}
- console.log('Empty Room for Subscription', record);
return {};
};
@@ -75,7 +74,9 @@ Meteor.methods({
},
getRoomByTypeAndName(type, name) {
- if (!Meteor.userId() && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
+ const userId = Meteor.userId();
+
+ if (!userId && RocketChat.settings.get('Accounts_AllowAnonymousRead') === false) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getRoomByTypeAndName' });
}
@@ -89,36 +90,40 @@ Meteor.methods({
room = RocketChat.models.Rooms.findByTypeAndName(type, name).fetch();
}
- if (!room) {
+ if (!room || room.length === 0) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'getRoomByTypeAndName' });
}
- if (!Meteor.call('canAccessRoom', room._id, Meteor.userId())) {
+ room = room[0];
+
+ if (!Meteor.call('canAccessRoom', room._id, userId)) {
throw new Meteor.Error('error-no-permission', 'No permission', { method: 'getRoomByTypeAndName' });
}
- if (RocketChat.settings.get('Store_Last_Message') && !RocketChat.authz.hasPermission(Meteor.userId(), 'preview-c-room')) {
+ if (RocketChat.settings.get('Store_Last_Message') && !RocketChat.authz.hasPermission(userId, 'preview-c-room')) {
delete room.lastMessage;
}
- return roomMap({ _room: room });
+ return roomMap(room);
}
});
-RocketChat.models.Rooms.cache.on('sync', (type, room/*, diff*/) => {
- const records = RocketChat.models.Subscriptions.findByRoomId(room._id).fetch();
-
- const _room = roomMap({_room: room});
- for (const record of records) {
- RocketChat.Notifications.notifyUserInThisInstance(record.u._id, 'rooms-changed', type, _room);
+RocketChat.models.Rooms.on('change', ({clientAction, id, data}) => {
+ switch (clientAction) {
+ case 'updated':
+ case 'inserted':
+ // Override data cuz we do not publish all fields
+ data = RocketChat.models.Rooms.findOneById(id, { fields });
+ break;
+
+ case 'removed':
+ data = { _id: id };
+ break;
}
-});
-RocketChat.models.Subscriptions.on('changed', (type, subscription/*, diff*/) => {
- if (type === 'inserted' || type === 'removed') {
- const room = RocketChat.models.Rooms.findOneById(subscription.rid);
- if (room) {
- RocketChat.Notifications.notifyUserInThisInstance(subscription.u._id, 'rooms-changed', type, roomMap({_room: room}));
- }
+ if (data) {
+ RocketChat.models.Subscriptions.findByRoomId(id, {fields: {'u._id': 1}}).forEach(({u}) => {
+ RocketChat.Notifications.notifyUserInThisInstance(u._id, 'rooms-changed', clientAction, data);
+ });
}
});
diff --git a/server/publications/spotlight.js b/server/publications/spotlight.js
index 85708e9f7369..57e6c447b89e 100644
--- a/server/publications/spotlight.js
+++ b/server/publications/spotlight.js
@@ -67,15 +67,12 @@ Meteor.methods({
}
if (type.rooms === true && RocketChat.authz.hasPermission(userId, 'view-c-room')) {
- const username = RocketChat.models.Users.findOneById(userId, {
- username: 1
- }).username;
-
const searchableRoomTypes = Object.entries(RocketChat.roomTypes.roomTypes)
.filter((roomType)=>roomType[1].includeInRoomSearch())
.map((roomType)=>roomType[0]);
- result.rooms = fetchRooms(userId, RocketChat.models.Rooms.findByNameAndTypesNotContainingUsername(regex, searchableRoomTypes, username, roomOptions).fetch());
+ const roomIds = RocketChat.models.Subscriptions.findByUserIdAndTypes(userId, searchableRoomTypes, {fields: {rid: 1}}).fetch().map(s => s.rid);
+ result.rooms = fetchRooms(userId, RocketChat.models.Rooms.findByNameAndTypesNotInIds(regex, searchableRoomTypes, roomIds, roomOptions).fetch());
}
} else if (type.users === true && rid) {
const subscriptions = RocketChat.models.Subscriptions.find({
diff --git a/server/publications/subscription.js b/server/publications/subscription.js
index 88758879c124..2ab526a6775b 100644
--- a/server/publications/subscription.js
+++ b/server/publications/subscription.js
@@ -65,17 +65,18 @@ Meteor.methods({
}
});
-RocketChat.models.Subscriptions.on('changed', function(type, subscription) {
- RocketChat.Notifications.notifyUserInThisInstance(subscription.u._id, 'subscriptions-changed', type, RocketChat.models.Subscriptions.processQueryOptionsOnResult(subscription, {
- fields
- }));
-});
+RocketChat.models.Subscriptions.on('change', ({clientAction, id, data}) => {
+ switch (clientAction) {
+ case 'updated':
+ case 'inserted':
+ // Override data cuz we do not publish all fields
+ data = RocketChat.models.Subscriptions.findOneById(id, { fields });
+ break;
+
+ case 'removed':
+ data = RocketChat.models.Subscriptions.trashFindOneById(id, { fields: { u: 1 } });
+ break;
+ }
-// TODO needs improvement
-// We are sending the record again cuz any update on subscription will send the record without the fname (join)
-// Then we need to sent it again listening to the join event.
-RocketChat.models.Subscriptions.on('join:fname:inserted', function(subscription/*, user*/) {
- RocketChat.Notifications.notifyUserInThisInstance(subscription.u._id, 'subscriptions-changed', 'changed', RocketChat.models.Subscriptions.processQueryOptionsOnResult(subscription, {
- fields
- }));
+ RocketChat.Notifications.notifyUserInThisInstance(data.u._id, 'subscriptions-changed', clientAction, data);
});
diff --git a/server/startup/initialData.js b/server/startup/initialData.js
index bada6f920803..97facd5389b8 100644
--- a/server/startup/initialData.js
+++ b/server/startup/initialData.js
@@ -1,7 +1,7 @@
import _ from 'underscore';
Meteor.startup(function() {
- Meteor.defer(() => RocketChat.models._CacheControl.withValue(false, function() {
+ Meteor.defer(() => {
if (!RocketChat.models.Rooms.findOneById('GENERAL')) {
RocketChat.models.Rooms.createWithIdTypeAndName('GENERAL', 'c', 'general', {
'default': true
@@ -201,5 +201,5 @@ Meteor.startup(function() {
return RocketChat.addUserToDefaultChannels(adminUser, true);
}
- }));
+ });
});
diff --git a/server/startup/migrations/v130.js b/server/startup/migrations/v130.js
new file mode 100644
index 000000000000..80b3f63a52a7
--- /dev/null
+++ b/server/startup/migrations/v130.js
@@ -0,0 +1,120 @@
+import Future from 'fibers/future';
+
+RocketChat.Migrations.add({
+ version: 129,
+ up() {
+ RocketChat.models.Rooms._db.originals.update(
+ {
+ t: { $ne: 'd' }
+ },
+ {
+ $unset: { usernames: 1 }
+ },
+ {
+ multi: true
+ }
+ );
+
+ RocketChat.models.Rooms.find(
+ {
+ usersCount: { $exists: false }
+ },
+ {
+ fields: {
+ _id: 1
+ }
+ }
+ ).forEach(({ _id }) => {
+ const usersCount = RocketChat.models.Subscriptions.findByRoomId(
+ _id
+ ).count();
+
+ RocketChat.models.Rooms._db.originals.update(
+ {
+ _id
+ },
+ {
+ $set: {
+ usersCount
+ }
+ }
+ );
+ });
+
+ // Getting all subscriptions and users to memory allow us to process in batches,
+ // all other solutions takes hundreds or thousands times more to process.
+ const subscriptions = RocketChat.models.Subscriptions.find(
+ {
+ t: 'd',
+ name: { $exists: true },
+ fname: { $exists: false }
+ },
+ {
+ fields: {
+ name: 1
+ }
+ }
+ ).fetch();
+
+ const users = RocketChat.models.Users.find(
+ { username: { $exists: true }, name: { $exists: true } },
+ { fields: { username: 1, name: 1 } }
+ ).fetch();
+ const usersByUsername = users.reduce((obj, user) => {
+ obj[user.username] = user.name;
+ return obj;
+ }, {});
+
+ const updateSubscription = subscription => {
+ return new Promise(resolve => {
+ Meteor.defer(() => {
+ const name = usersByUsername[subscription.name];
+
+ if (!name) {
+ return resolve();
+ }
+
+ RocketChat.models.Subscriptions._db.originals.update(
+ {
+ _id: subscription._id
+ },
+ {
+ $set: {
+ fname: name
+ }
+ }
+ );
+
+ resolve();
+ });
+ });
+ };
+
+ // Use FUTURE to process itens in batchs and wait the final one
+ const fut = new Future();
+
+ const processBatch = () => {
+ const itens = subscriptions.splice(0, 1000);
+
+ console.log(
+ 'Migrating',
+ itens.length,
+ 'of',
+ subscriptions.length,
+ 'subscriptions'
+ );
+
+ if (itens.length) {
+ Promise.all(itens.map(s => updateSubscription(s))).then(() => {
+ processBatch();
+ });
+ } else {
+ fut.return();
+ }
+ };
+
+ processBatch();
+
+ fut.wait();
+ }
+});
diff --git a/server/startup/roomPublishes.js b/server/startup/roomPublishes.js
deleted file mode 100644
index 20fb57c259e0..000000000000
--- a/server/startup/roomPublishes.js
+++ /dev/null
@@ -1,92 +0,0 @@
-Meteor.startup(function() {
- RocketChat.roomTypes.setPublish('c', function(identifier) {
- const options = {
- fields: {
- name: 1,
- t: 1,
- cl: 1,
- u: 1,
- usernames: 1,
- topic: 1,
- announcement: 1,
- muted: 1,
- archived: 1,
- ro: 1,
- reactWhenReadOnly: 1,
- jitsiTimeout: 1,
- description: 1,
- sysMes: 1,
- joinCodeRequired: 1,
- streamingOptions: 1
- }
- };
-
- if (RocketChat.authz.hasPermission(this.userId, 'view-c-room')) {
- return RocketChat.models.Rooms.findByTypeAndName('c', identifier, options);
- } else if (RocketChat.authz.hasPermission(this.userId, 'view-joined-room')) {
- const roomId = RocketChat.models.Subscriptions.findByTypeNameAndUserId('c', identifier, this.userId).fetch();
- if (roomId.length > 0) {
- return RocketChat.models.Rooms.findById(roomId[0].rid, options);
- }
- }
-
- return this.ready();
- });
-
- RocketChat.roomTypes.setPublish('p', function(identifier) {
- const options = {
- fields: {
- name: 1,
- t: 1,
- cl: 1,
- u: 1,
- usernames: 1,
- topic: 1,
- announcement: 1,
- muted: 1,
- archived: 1,
- ro: 1,
- reactWhenReadOnly: 1,
- jitsiTimeout: 1,
- description: 1,
- sysMes: 1,
- tokenpass: 1,
- streamingOptions: 1
- }
- };
-
- const user = RocketChat.models.Users.findOneById(this.userId, {
- fields: {
- username: 1
- }
- });
-
- return RocketChat.models.Rooms.findByTypeAndNameContainingUsername('p', identifier, user.username, options);
- });
-
- return RocketChat.roomTypes.setPublish('d', function(identifier) {
- const options = {
- fields: {
- name: 1,
- t: 1,
- cl: 1,
- u: 1,
- usernames: 1,
- topic: 1,
- jitsiTimeout: 1
- }
- };
-
- const user = RocketChat.models.Users.findOneById(this.userId, {
- fields: {
- username: 1
- }
- });
-
- if (RocketChat.authz.hasAtLeastOnePermission(this.userId, ['view-d-room', 'view-joined-room'])) {
- return RocketChat.models.Rooms.findByTypeContainingUsernames('d', [user.username, identifier], options);
- }
-
- return this.ready();
- });
-});
diff --git a/server/stream/messages.js b/server/stream/messages.js
index 71c68bcdfe0d..4f5537cde49b 100644
--- a/server/stream/messages.js
+++ b/server/stream/messages.js
@@ -11,7 +11,7 @@ msgStream.allowRead(function(eventName, args) {
return false;
}
- if (room.t === 'c' && !RocketChat.authz.hasPermission(this.userId, 'preview-c-room') && room.usernames.indexOf(room.username) === -1) {
+ if (room.t === 'c' && !RocketChat.authz.hasPermission(this.userId, 'preview-c-room') && !RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, this.userId, { fields: { _id: 1 } })) {
return false;
}
@@ -32,7 +32,7 @@ msgStream.allowEmit('__my_messages__', function(eventName, msg, options) {
return false;
}
- options.roomParticipant = room.usernames.indexOf(room.username) > -1;
+ options.roomParticipant = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(room._id, this.userId, { fields: { _id: 1 } }) != null;
options.roomType = room.t;
return true;
@@ -63,19 +63,12 @@ Meteor.startup(function() {
}
}
- return RocketChat.models.Messages._db.on('change', function({action, id, data/*, oplog*/}) {
- switch (action) {
- case 'insert':
- data._id = id;
- publishMessage('inserted', data);
- break;
- case 'update:record':
- publishMessage('updated', data);
- break;
- case 'update:diff':
- publishMessage('updated', RocketChat.models.Messages.findOne({
- _id: id
- }));
+ return RocketChat.models.Messages.on('change', function({ clientAction, id, data/*, oplog*/ }) {
+ switch (clientAction) {
+ case 'inserted':
+ case 'updated':
+ const message = data || RocketChat.models.Messages.findOne({ _id: id });
+ publishMessage(clientAction, message);
break;
}
});
diff --git a/tests/end-to-end/api/00-miscellaneous.js b/tests/end-to-end/api/00-miscellaneous.js
index 871ad79bcf7c..26ac0426d051 100644
--- a/tests/end-to-end/api/00-miscellaneous.js
+++ b/tests/end-to-end/api/00-miscellaneous.js
@@ -205,7 +205,7 @@ describe('miscellaneous', function() {
expect(res.body).to.have.property('result').and.to.be.an('array');
expect(res.body.result[0]).to.have.property('_id');
expect(res.body.result[0]).to.have.property('name');
- expect(res.body.result[0]).to.have.property('usernames').and.to.be.an('array');
+ expect(res.body.result[0]).to.have.property('usersCount').and.to.be.an('number');
expect(res.body.result[0]).to.have.property('ts');
})
.end(done);
@@ -232,7 +232,7 @@ describe('miscellaneous', function() {
expect(res.body).to.have.property('result').and.to.be.an('array');
expect(res.body.result[0]).to.have.property('_id');
expect(res.body.result[0]).to.have.property('name');
- expect(res.body.result[0]).to.have.property('usernames').and.to.be.an('array');
+ expect(res.body.result[0]).to.have.property('usersCount').and.to.be.an('number');
expect(res.body.result[0]).to.have.property('ts');
})
.end(done);
diff --git a/tests/end-to-end/api/04-direct-message.js b/tests/end-to-end/api/04-direct-message.js
index 84ee72527554..c17cf64684a0 100644
--- a/tests/end-to-end/api/04-direct-message.js
+++ b/tests/end-to-end/api/04-direct-message.js
@@ -2,7 +2,7 @@
/* globals expect */
/* eslint no-unused-vars: 0 */
-import {getCredentials, api, login, request, credentials, directMessage, log } 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';
@@ -136,4 +136,97 @@ describe('[Direct Messages]', function() {
})
.end(done);
});
+
+ describe('fname property', () => {
+ const username = `fname_${ apiUsername }`;
+ const name = `Name fname_${ apiUsername }`;
+ const updatedName = `Updated Name fname_${ apiUsername }`;
+ const email = `fname_${ apiEmail }`;
+ let userId;
+ let directMessageId;
+
+ before((done) => {
+ request.post(api('users.create'))
+ .set(credentials)
+ .send({
+ email,
+ name,
+ username,
+ password,
+ active: true,
+ roles: ['user'],
+ joinDefaultChannels: true,
+ verified: true
+ })
+ .expect((res) => {
+ userId = res.body.user._id;
+ })
+ .end(done);
+ });
+
+ before((done) => {
+ request.post(api('chat.postMessage'))
+ .set(credentials)
+ .send({
+ channel: `@${ username }`,
+ text: 'This message was sent using the API'
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.nested.property('message.msg', 'This message was sent using the API');
+ expect(res.body).to.have.nested.property('message.rid');
+ directMessageId = res.body.message.rid;
+ })
+ .end(done);
+ });
+
+ it('should have fname property', (done) => {
+ request.get(api('subscriptions.getOne'))
+ .set(credentials)
+ .query({
+ roomId: directMessageId
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body.subscription).to.have.property('name', username);
+ expect(res.body.subscription).to.have.property('fname', name);
+ })
+ .end(done);
+ });
+
+ it('should update user\'s name', (done) => {
+ request.post(api('users.update'))
+ .set(credentials)
+ .send({
+ userId,
+ data: {
+ name: updatedName
+ }
+ })
+ .expect((res) => {
+ expect(res.body.user).to.have.property('name', updatedName);
+ })
+ .end(done);
+ });
+
+ it('should have fname property updated', (done) => {
+ request.get(api('subscriptions.getOne'))
+ .set(credentials)
+ .query({
+ roomId: directMessageId
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body.subscription).to.have.property('name', username);
+ expect(res.body.subscription).to.have.property('fname', updatedName);
+ })
+ .end(done);
+ });
+ });
});
diff --git a/tests/end-to-end/api/11-permissions.js b/tests/end-to-end/api/11-permissions.js
index c7bb2e890355..734aecdd2c2a 100644
--- a/tests/end-to-end/api/11-permissions.js
+++ b/tests/end-to-end/api/11-permissions.js
@@ -23,11 +23,6 @@ describe('[Permissions]', function() {
expect(firstElement).to.have.property('_id');
expect(firstElement).to.have.property('roles').and.to.be.a('array');
expect(firstElement).to.have.property('_updatedAt');
- expect(firstElement).to.have.property('meta');
- expect(firstElement.meta).to.have.property('revision');
- expect(firstElement.meta).to.have.property('created');
- expect(firstElement.meta).to.have.property('version');
- expect(firstElement).to.have.property('$loki');
})
.end(done);
});
@@ -47,11 +42,6 @@ describe('[Permissions]', function() {
expect(firstElement).to.have.property('_id');
expect(firstElement).to.have.property('roles').and.to.be.a('array');
expect(firstElement).to.have.property('_updatedAt');
- expect(firstElement).to.have.property('meta');
- expect(firstElement.meta).to.have.property('revision');
- expect(firstElement.meta).to.have.property('created');
- expect(firstElement.meta).to.have.property('version');
- expect(firstElement).to.have.property('$loki');
})
.end(done);
});
@@ -78,11 +68,6 @@ describe('[Permissions]', function() {
expect(firstElement).to.have.property('_id');
expect(firstElement).to.have.property('roles').and.to.be.a('array');
expect(firstElement).to.have.property('_updatedAt');
- expect(firstElement).to.have.property('meta');
- expect(firstElement.meta).to.have.property('revision');
- expect(firstElement.meta).to.have.property('created');
- expect(firstElement.meta).to.have.property('version');
- expect(firstElement).to.have.property('$loki');
})
.end(done);
});
From f5556046e38a8b08bd0e3f56848b7bc7dce58bfb Mon Sep 17 00:00:00 2001
From: Rodrigo Nascimento
Date: Tue, 10 Jul 2018 21:20:40 -0300
Subject: [PATCH 27/28] Bump version to 0.67.0-rc.0
---
.docker/Dockerfile.rhel | 2 +-
.github/history.json | 253 ++++++++++++
.sandstorm/sandstorm-pkgdef.capnp | 4 +-
.travis/snap.sh | 2 +-
HISTORY.md | 525 ++++--------------------
package.json | 2 +-
packages/rocketchat-lib/rocketchat.info | 2 +-
7 files changed, 337 insertions(+), 453 deletions(-)
diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel
index 3cdb4e368b78..9900c3f3db12 100644
--- a/.docker/Dockerfile.rhel
+++ b/.docker/Dockerfile.rhel
@@ -1,6 +1,6 @@
FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7
-ENV RC_VERSION 0.67.0-develop
+ENV RC_VERSION 0.67.0-rc.0
MAINTAINER buildmaster@rocket.chat
diff --git a/.github/history.json b/.github/history.json
index 71ee92de4bf7..5ece26294f30 100644
--- a/.github/history.json
+++ b/.github/history.json
@@ -16859,6 +16859,259 @@
]
}
]
+ },
+ "0.67.0-rc.0": {
+ "node_version": "8.11.3",
+ "npm_version": "5.6.0",
+ "pull_requests": [
+ {
+ "pr": "10749",
+ "title": "[BREAK] Remove cache layer and internal calculated property `room.usernames`",
+ "userLogin": "rodrigok",
+ "milestone": "0.66.0",
+ "contributors": [
+ "rodrigok",
+ "engelgabriel",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11417",
+ "title": "Merge master into develop & Set version to 0.67.0-develop",
+ "userLogin": "sampaiodiego",
+ "contributors": [
+ "renatobecker",
+ "sampaiodiego",
+ "rodrigok",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11406",
+ "title": "[FIX] Livechat taking inquiry leading to 404 page",
+ "userLogin": "renatobecker",
+ "milestone": "0.66.3",
+ "contributors": [
+ "renatobecker"
+ ]
+ },
+ {
+ "pr": "11398",
+ "title": "[FIX] All messages notifications via email were sent as mention alert",
+ "userLogin": "rodrigok",
+ "milestone": "0.66.3",
+ "contributors": [
+ "rodrigok"
+ ]
+ },
+ {
+ "pr": "11358",
+ "title": "[FIX] sort fname sidenav",
+ "userLogin": "ggazzo",
+ "contributors": [
+ "ggazzo",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11399",
+ "title": "Merge master into develop & Set version to 0.67.0-develop",
+ "userLogin": "rodrigok",
+ "contributors": [
+ "sampaiodiego",
+ "geekgonecrazy",
+ "renatobecker",
+ "rodrigok",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "10918",
+ "title": "[NEW] Additional Livechat iFrame API's",
+ "userLogin": "renatobecker",
+ "milestone": "0.66.0",
+ "contributors": [
+ "renatobecker",
+ "sampaiodiego",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11266",
+ "title": "[FIX] Livechat not sending desktop notifications",
+ "userLogin": "renatobecker",
+ "milestone": "0.66.2",
+ "contributors": [
+ "renatobecker",
+ "sampaiodiego"
+ ]
+ },
+ {
+ "pr": "11319",
+ "title": "[FIX] SVG icons code",
+ "userLogin": "tassoevan",
+ "milestone": "0.67.0",
+ "contributors": [
+ "tassoevan"
+ ]
+ },
+ {
+ "pr": "11365",
+ "title": "[FIX] Remove file snap store doesn't like",
+ "userLogin": "geekgonecrazy",
+ "milestone": "0.66.2",
+ "contributors": [
+ "geekgonecrazy",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11364",
+ "title": "Regression: Fix migration 125 checking for settings field",
+ "userLogin": "sampaiodiego",
+ "milestone": "0.66.2",
+ "contributors": [
+ "sampaiodiego"
+ ]
+ },
+ {
+ "pr": "11359",
+ "title": "Send setting Allow_Marketing_Emails to statistics collector",
+ "userLogin": "rodrigok",
+ "milestone": "0.66.2",
+ "contributors": [
+ "rodrigok"
+ ]
+ },
+ {
+ "pr": "11313",
+ "title": "[FIX] Message popup responsiveness in slash commands",
+ "userLogin": "tassoevan",
+ "milestone": "0.67.0",
+ "contributors": [
+ "tassoevan"
+ ]
+ },
+ {
+ "pr": "9991",
+ "title": "[FIX] web app manifest errors as reported by Chrome DevTools",
+ "userLogin": "justinribeiro",
+ "milestone": "0.67.0",
+ "contributors": [
+ "justinribeiro",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11342",
+ "title": "[FIX] Message attachment's fields with different sizes",
+ "userLogin": "sampaiodiego",
+ "milestone": "0.67.0",
+ "contributors": [
+ "sampaiodiego"
+ ]
+ },
+ {
+ "pr": "11330",
+ "title": "[IMPROVE] Stop sort callbacks on run",
+ "userLogin": "ggazzo",
+ "contributors": [
+ "ggazzo"
+ ]
+ },
+ {
+ "pr": "9754",
+ "title": "[FIX] Parse inline code without space before initial backtick",
+ "userLogin": "c0dzilla",
+ "milestone": "0.67.0",
+ "contributors": [
+ "c0dzilla",
+ "gdelavald",
+ "web-flow",
+ "ggazzo"
+ ]
+ },
+ {
+ "pr": "11348",
+ "title": "Merge master into develop & Set version to 0.67.0-develop",
+ "userLogin": "rodrigok",
+ "contributors": [
+ "sampaiodiego",
+ "rodrigok",
+ "gdelavald",
+ "tassoevan",
+ "Hudell",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11335",
+ "title": "[FIX] Some updates were returning errors when based on queries with position operators",
+ "userLogin": "rodrigok",
+ "milestone": "0.66.1",
+ "contributors": [
+ "rodrigok"
+ ]
+ },
+ {
+ "pr": "11315",
+ "title": "[FIX] SAML attributes with periods are not properly read.",
+ "userLogin": "Hudell",
+ "milestone": "0.66.1",
+ "contributors": [
+ "Hudell",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11333",
+ "title": "[FIX] Outgoing integrations were stopping the oplog tailing sometimes",
+ "userLogin": "rodrigok",
+ "milestone": "0.66.1",
+ "contributors": [
+ "rodrigok"
+ ]
+ },
+ {
+ "pr": "11254",
+ "title": "[IMPROVE] Setup Wizard username validation, step progress and optin/optout",
+ "userLogin": "tassoevan",
+ "milestone": "0.66.1",
+ "contributors": [
+ "tassoevan",
+ "ggazzo",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11267",
+ "title": "[FIX] Livestream muted when audio only option was enabled",
+ "userLogin": "gdelavald",
+ "milestone": "0.66.1",
+ "contributors": [
+ "gdelavald",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "11295",
+ "title": "[FIX] Notification preferences being lost when switching view mode",
+ "userLogin": "sampaiodiego",
+ "milestone": "0.66.1",
+ "contributors": [
+ "sampaiodiego"
+ ]
+ },
+ {
+ "pr": "11290",
+ "title": "Merge master into develop & Set version to 0.67.0-develop",
+ "userLogin": "rodrigok",
+ "contributors": [
+ "rodrigok",
+ "web-flow"
+ ]
+ }
+ ]
}
}
}
\ No newline at end of file
diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp
index e19be14bd112..5706e2fade13 100644
--- a/.sandstorm/sandstorm-pkgdef.capnp
+++ b/.sandstorm/sandstorm-pkgdef.capnp
@@ -19,9 +19,9 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Rocket.Chat"),
- appVersion = 81, # Increment this for every release.
+ appVersion = 82, # Increment this for every release.
- appMarketingVersion = (defaultText = "0.67.0-develop"),
+ appMarketingVersion = (defaultText = "0.67.0-rc.0"),
# Human-readable representation of appVersion. Should match the way you
# identify versions of your app in documentation and marketing.
diff --git a/.travis/snap.sh b/.travis/snap.sh
index 6e54bc03d119..e035853870a9 100755
--- a/.travis/snap.sh
+++ b/.travis/snap.sh
@@ -17,7 +17,7 @@ elif [[ $TRAVIS_TAG ]]; then
RC_VERSION=$TRAVIS_TAG
else
CHANNEL=edge
- RC_VERSION=0.67.0-develop
+ RC_VERSION=0.67.0-rc.0
fi
echo "Preparing to trigger a snap release for $CHANNEL channel"
diff --git a/HISTORY.md b/HISTORY.md
index 4f174f2cd8e4..7a46a946e4a7 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,4 +1,57 @@
+# 0.67.0 (Under Release Candidate Process)
+
+## 0.67.0-rc.0
+`2018-07-10 Β· 1 οΈοΈοΈβ οΈ Β· 1 π Β· 1 π Β· 6 π Β· 4 π Β· 11 π©βπ»π¨βπ»`
+
+### β οΈ BREAKING CHANGES
+
+- Remove cache layer and internal calculated property `room.usernames` ([#10749](https://github.com/RocketChat/Rocket.Chat/pull/10749))
+
+### π New features
+
+- Additional Livechat iFrame API's ([#10918](https://github.com/RocketChat/Rocket.Chat/pull/10918))
+
+### π Improvements
+
+- Stop sort callbacks on run ([#11330](https://github.com/RocketChat/Rocket.Chat/pull/11330))
+
+### π Bug fixes
+
+- sort fname sidenav ([#11358](https://github.com/RocketChat/Rocket.Chat/pull/11358))
+- SVG icons code ([#11319](https://github.com/RocketChat/Rocket.Chat/pull/11319))
+- Message popup responsiveness in slash commands ([#11313](https://github.com/RocketChat/Rocket.Chat/pull/11313))
+- web app manifest errors as reported by Chrome DevTools ([#9991](https://github.com/RocketChat/Rocket.Chat/pull/9991) by [@justinribeiro](https://github.com/justinribeiro))
+- Message attachment's fields with different sizes ([#11342](https://github.com/RocketChat/Rocket.Chat/pull/11342))
+- Parse inline code without space before initial backtick ([#9754](https://github.com/RocketChat/Rocket.Chat/pull/9754) by [@c0dzilla](https://github.com/c0dzilla))
+
+
+π Minor changes
+
+- Merge master into develop & Set version to 0.67.0-develop ([#11417](https://github.com/RocketChat/Rocket.Chat/pull/11417))
+- Merge master into develop & Set version to 0.67.0-develop ([#11399](https://github.com/RocketChat/Rocket.Chat/pull/11399))
+- Merge master into develop & Set version to 0.67.0-develop ([#11348](https://github.com/RocketChat/Rocket.Chat/pull/11348))
+- Merge master into develop & Set version to 0.67.0-develop ([#11290](https://github.com/RocketChat/Rocket.Chat/pull/11290))
+
+
+
+### π©βπ»π¨βπ» Contributors π
+
+- [@c0dzilla](https://github.com/c0dzilla)
+- [@justinribeiro](https://github.com/justinribeiro)
+
+### π©βπ»π¨βπ» Core Team π€
+
+- [@Hudell](https://github.com/Hudell)
+- [@engelgabriel](https://github.com/engelgabriel)
+- [@gdelavald](https://github.com/gdelavald)
+- [@geekgonecrazy](https://github.com/geekgonecrazy)
+- [@ggazzo](https://github.com/ggazzo)
+- [@renatobecker](https://github.com/renatobecker)
+- [@rodrigok](https://github.com/rodrigok)
+- [@sampaiodiego](https://github.com/sampaiodiego)
+- [@tassoevan](https://github.com/tassoevan)
+
# 0.66.3
`2018-07-09 Β· 2 π Β· 2 π©βπ»π¨βπ»`
@@ -44,12 +97,16 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.66.1
-`2018-07-04 Β· 5 π Β· 1 π Β· 6 π©βπ»π¨βπ»`
+`2018-07-04 Β· 1 π Β· 5 π Β· 6 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.11.3`
- NPM: `5.6.0`
+### π Improvements
+
+- Setup Wizard username validation, step progress and optin/optout ([#11254](https://github.com/RocketChat/Rocket.Chat/pull/11254))
+
### π Bug fixes
- Some updates were returning errors when based on queries with position operators ([#11335](https://github.com/RocketChat/Rocket.Chat/pull/11335))
@@ -58,13 +115,6 @@
- Livestream muted when audio only option was enabled ([#11267](https://github.com/RocketChat/Rocket.Chat/pull/11267))
- Notification preferences being lost when switching view mode ([#11295](https://github.com/RocketChat/Rocket.Chat/pull/11295))
-
-π Minor changes
-
-- [IMPROVE] Setup Wizard username validation, step progress and optin/optout ([#11254](https://github.com/RocketChat/Rocket.Chat/pull/11254))
-
-
-
### π©βπ»π¨βπ» Core Team π€
- [@Hudell](https://github.com/Hudell)
@@ -75,7 +125,7 @@
- [@tassoevan](https://github.com/tassoevan)
# 0.66.0
-`2018-06-27 Β· 1 οΈοΈοΈβ οΈ Β· 23 π Β· 61 π Β· 50 π Β· 45 π©βπ»π¨βπ»`
+`2018-06-27 Β· 1 οΈοΈοΈβ οΈ Β· 23 π Β· 3 π Β· 55 π Β· 47 π Β· 45 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.11.3`
@@ -111,9 +161,14 @@
- Changes all 'mergeChannels' to 'groupByType'. ([#10055](https://github.com/RocketChat/Rocket.Chat/pull/10055) by [@mikaelmello](https://github.com/mikaelmello))
- Update WeDeploy deployment ([#10841](https://github.com/RocketChat/Rocket.Chat/pull/10841) by [@jonnilundy](https://github.com/jonnilundy))
+### π Improvements
+
+- Listing of apps in the admin page ([#11166](https://github.com/RocketChat/Rocket.Chat/pull/11166))
+- UI design for Tables and tabs component on Directory ([#11026](https://github.com/RocketChat/Rocket.Chat/pull/11026))
+- User mentions ([#11001](https://github.com/RocketChat/Rocket.Chat/pull/11001) by [@vynmera](https://github.com/vynmera))
+
### π Bug fixes
-- i18n - add semantic markup ([#9534](https://github.com/RocketChat/Rocket.Chat/pull/9534) by [@brylie](https://github.com/brylie))
- Wordpress oauth configuration not loading properly ([#11187](https://github.com/RocketChat/Rocket.Chat/pull/11187))
- REST API: Add more test cases for `/login` ([#10999](https://github.com/RocketChat/Rocket.Chat/pull/10999))
- Wrong font-family order ([#11191](https://github.com/RocketChat/Rocket.Chat/pull/11191) by [@myfonj](https://github.com/myfonj))
@@ -159,13 +214,8 @@
- Allow inviting livechat managers to the same LiveChat room ([#10956](https://github.com/RocketChat/Rocket.Chat/pull/10956))
- Cannot read property 'debug' of undefined when trying to use REST API ([#10805](https://github.com/RocketChat/Rocket.Chat/pull/10805) by [@haffla](https://github.com/haffla))
- Icons svg xml structure ([#10771](https://github.com/RocketChat/Rocket.Chat/pull/10771))
-- Leave room wasn't working as expected ([#10851](https://github.com/RocketChat/Rocket.Chat/pull/10851))
-- Application crashing on startup when trying to log errors to `exceptions` channel ([#10934](https://github.com/RocketChat/Rocket.Chat/pull/10934))
-- Image lazy load was breaking attachments ([#10904](https://github.com/RocketChat/Rocket.Chat/pull/10904))
-- Incomplete email notification link ([#10928](https://github.com/RocketChat/Rocket.Chat/pull/10928))
- Remove outdated 2FA warning for mobile clients ([#10916](https://github.com/RocketChat/Rocket.Chat/pull/10916))
- Update Sandstorm build config ([#10867](https://github.com/RocketChat/Rocket.Chat/pull/10867) by [@ocdtrekkie](https://github.com/ocdtrekkie))
-- i18n - add semantic markup ([#9534](https://github.com/RocketChat/Rocket.Chat/pull/9534) by [@brylie](https://github.com/brylie))
- "blank messages" on iOS < 11 ([#11221](https://github.com/RocketChat/Rocket.Chat/pull/11221))
- "blank" screen on iOS < 11 ([#11199](https://github.com/RocketChat/Rocket.Chat/pull/11199))
- The process was freezing in some cases when HTTP calls exceeds timeout on integrations ([#11253](https://github.com/RocketChat/Rocket.Chat/pull/11253))
@@ -179,16 +229,13 @@
π Minor changes
- Merge master into develop & Set version to 0.66.0-develop ([#11277](https://github.com/RocketChat/Rocket.Chat/pull/11277) by [@brylie](https://github.com/brylie) & [@stuartpb](https://github.com/stuartpb))
-- [IMPROVE] Listing of apps in the admin page ([#11166](https://github.com/RocketChat/Rocket.Chat/pull/11166))
- Regression: Directory css ([#11206](https://github.com/RocketChat/Rocket.Chat/pull/11206))
- LingoHub based on develop ([#11208](https://github.com/RocketChat/Rocket.Chat/pull/11208))
- IRC Federation: RFC2813 implementation (ngIRCd) ([#10113](https://github.com/RocketChat/Rocket.Chat/pull/10113) by [@cpitman](https://github.com/cpitman) & [@lindoelio](https://github.com/lindoelio))
- Add verification to make sure the user exists in REST insert object helper ([#11008](https://github.com/RocketChat/Rocket.Chat/pull/11008))
- Regression: Directory user table infinite scroll doesn't working ([#11200](https://github.com/RocketChat/Rocket.Chat/pull/11200))
-- [IMPROVE] UI design for Tables and tabs component on Directory ([#11026](https://github.com/RocketChat/Rocket.Chat/pull/11026))
- [FIX Readme] Nodejs + Python version spicifications ([#11181](https://github.com/RocketChat/Rocket.Chat/pull/11181) by [@mahdiyari](https://github.com/mahdiyari))
- Regression: sorting direct message by asc on favorites group ([#11090](https://github.com/RocketChat/Rocket.Chat/pull/11090))
-- [IMPROVE] User mentions ([#11001](https://github.com/RocketChat/Rocket.Chat/pull/11001) by [@vynmera](https://github.com/vynmera))
- Fix PR Docker image creation by splitting in two build jobs ([#11107](https://github.com/RocketChat/Rocket.Chat/pull/11107))
- Update v126.js ([#11103](https://github.com/RocketChat/Rocket.Chat/pull/11103))
- Speed up the build time by removing JSON Minify from i18n package ([#11097](https://github.com/RocketChat/Rocket.Chat/pull/11097))
@@ -332,7 +379,7 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.65.0
-`2018-05-28 Β· 17 π Β· 24 π Β· 42 π Β· 29 π©βπ»π¨βπ»`
+`2018-05-28 Β· 13 π Β· 16 π Β· 15 π Β· 25 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.11.1`
@@ -352,10 +399,6 @@
- Now is possible to access files using header authorization (`x-user-id` and `x-auth-token`) ([#10741](https://github.com/RocketChat/Rocket.Chat/pull/10741))
- Add REST API endpoints `channels.counters`, `groups.counters and `im.counters` ([#9679](https://github.com/RocketChat/Rocket.Chat/pull/9679) by [@xbolshe](https://github.com/xbolshe))
- Add REST API endpoints `channels.setCustomFields` and `groups.setCustomFields` ([#9733](https://github.com/RocketChat/Rocket.Chat/pull/9733) by [@xbolshe](https://github.com/xbolshe))
-- Add REST endpoints `channels.roles` & `groups.roles` ([#10607](https://github.com/RocketChat/Rocket.Chat/pull/10607))
-- Add more options for Wordpress OAuth configuration ([#10724](https://github.com/RocketChat/Rocket.Chat/pull/10724))
-- Setup Wizard ([#10523](https://github.com/RocketChat/Rocket.Chat/pull/10523))
-- Improvements to notifications logic ([#10686](https://github.com/RocketChat/Rocket.Chat/pull/10686))
- Add permission `view-broadcast-member-list` ([#10753](https://github.com/RocketChat/Rocket.Chat/pull/10753))
### π Bug fixes
@@ -367,14 +410,6 @@
- Remove outdated translations of Internal Hubot's description of Scripts to Load that were pointing to a non existent address ([#10448](https://github.com/RocketChat/Rocket.Chat/pull/10448))
- UI was not disabling the actions when users has had no permissions to create channels or add users to rooms ([#10564](https://github.com/RocketChat/Rocket.Chat/pull/10564) by [@cfunkles](https://github.com/cfunkles) & [@chuckAtCataworx](https://github.com/chuckAtCataworx))
- Private settings were not being cleared from client cache in some cases ([#10625](https://github.com/RocketChat/Rocket.Chat/pull/10625))
-- Not escaping special chars on mentions ([#10793](https://github.com/RocketChat/Rocket.Chat/pull/10793) by [@erhan-](https://github.com/erhan-))
-- Send a message when muted returns inconsistent result in chat.sendMessage ([#10720](https://github.com/RocketChat/Rocket.Chat/pull/10720))
-- Regression: Empty content on announcement modal ([#10733](https://github.com/RocketChat/Rocket.Chat/pull/10733))
-- Missing attachment description when Rocket.Chat Apps were enabled ([#10705](https://github.com/RocketChat/Rocket.Chat/pull/10705))
-- Improve desktop notification formatting ([#10445](https://github.com/RocketChat/Rocket.Chat/pull/10445) by [@Sameesunkaria](https://github.com/Sameesunkaria))
-- Message box emoji icon was flickering when typing a text ([#10678](https://github.com/RocketChat/Rocket.Chat/pull/10678))
-- Channel owner was being set as muted when creating a read-only channel ([#10665](https://github.com/RocketChat/Rocket.Chat/pull/10665))
-- SAML wasn't working correctly when running multiple instances ([#10681](https://github.com/RocketChat/Rocket.Chat/pull/10681))
- Internal Error when requesting user data download ([#10837](https://github.com/RocketChat/Rocket.Chat/pull/10837))
- Broadcast channels were showing reply button for deleted messages and generating wrong reply links some times ([#10835](https://github.com/RocketChat/Rocket.Chat/pull/10835))
- User's preference `Unread on Top` wasn't working for LiveChat rooms ([#10734](https://github.com/RocketChat/Rocket.Chat/pull/10734))
@@ -389,37 +424,10 @@
π Minor changes
- Release 0.65.0 ([#10893](https://github.com/RocketChat/Rocket.Chat/pull/10893) by [@Sameesunkaria](https://github.com/Sameesunkaria) & [@erhan-](https://github.com/erhan-) & [@peccu](https://github.com/peccu) & [@winterstefan](https://github.com/winterstefan))
-- Release 0.64.2 ([#10812](https://github.com/RocketChat/Rocket.Chat/pull/10812) by [@Sameesunkaria](https://github.com/Sameesunkaria) & [@erhan-](https://github.com/erhan-) & [@peccu](https://github.com/peccu) & [@winterstefan](https://github.com/winterstefan))
-- Release 0.64.1 ([#10660](https://github.com/RocketChat/Rocket.Chat/pull/10660) by [@saplla](https://github.com/saplla))
-- Release 0.64.0 ([#10613](https://github.com/RocketChat/Rocket.Chat/pull/10613) by [@christianh814](https://github.com/christianh814) & [@tttt-conan](https://github.com/tttt-conan))
-- Release 0.63.3 ([#10504](https://github.com/RocketChat/Rocket.Chat/pull/10504))
-- Release 0.63.2 ([#10476](https://github.com/RocketChat/Rocket.Chat/pull/10476))
-- add redhat dockerfile to master ([#10408](https://github.com/RocketChat/Rocket.Chat/pull/10408))
- Apps: Command Previews, Message and Room Removal Events ([#10822](https://github.com/RocketChat/Rocket.Chat/pull/10822))
- Develop sync ([#10815](https://github.com/RocketChat/Rocket.Chat/pull/10815) by [@nsuchy](https://github.com/nsuchy))
- Major dependencies update ([#10661](https://github.com/RocketChat/Rocket.Chat/pull/10661))
- Prevent setup wizard redirects ([#10811](https://github.com/RocketChat/Rocket.Chat/pull/10811))
-- Prometheus: Add metric to track hooks time ([#10798](https://github.com/RocketChat/Rocket.Chat/pull/10798))
-- Regression: Autorun of wizard was not destroyed after completion ([#10802](https://github.com/RocketChat/Rocket.Chat/pull/10802))
-- Prometheus: Fix notification metric ([#10803](https://github.com/RocketChat/Rocket.Chat/pull/10803))
-- Regression: Fix wrong wizard field name ([#10804](https://github.com/RocketChat/Rocket.Chat/pull/10804))
-- Prometheus: Improve metric names ([#10789](https://github.com/RocketChat/Rocket.Chat/pull/10789))
-- Improvement to push notifications on direct messages ([#10788](https://github.com/RocketChat/Rocket.Chat/pull/10788))
-- Better metric for notifications ([#10786](https://github.com/RocketChat/Rocket.Chat/pull/10786))
-- Add badge back to push notifications ([#10779](https://github.com/RocketChat/Rocket.Chat/pull/10779))
-- Wizard improvements ([#10776](https://github.com/RocketChat/Rocket.Chat/pull/10776))
-- Add setting and expose prometheus on port 9100 ([#10766](https://github.com/RocketChat/Rocket.Chat/pull/10766))
-- Regression: Fix notifications for direct messages ([#10760](https://github.com/RocketChat/Rocket.Chat/pull/10760))
-- More improvements on send notifications logic ([#10736](https://github.com/RocketChat/Rocket.Chat/pull/10736))
-- LingoHub based on develop ([#10691](https://github.com/RocketChat/Rocket.Chat/pull/10691))
-- Add `npm run postinstall` into example build script ([#10524](https://github.com/RocketChat/Rocket.Chat/pull/10524) by [@peccu](https://github.com/peccu))
-- Correct links in README file ([#10674](https://github.com/RocketChat/Rocket.Chat/pull/10674) by [@winterstefan](https://github.com/winterstefan))
-- Release 0.64.2 ([#10812](https://github.com/RocketChat/Rocket.Chat/pull/10812) by [@Sameesunkaria](https://github.com/Sameesunkaria) & [@erhan-](https://github.com/erhan-) & [@peccu](https://github.com/peccu) & [@winterstefan](https://github.com/winterstefan))
-- Release 0.64.1 ([#10660](https://github.com/RocketChat/Rocket.Chat/pull/10660) by [@saplla](https://github.com/saplla))
-- Release 0.64.0 ([#10613](https://github.com/RocketChat/Rocket.Chat/pull/10613) by [@christianh814](https://github.com/christianh814) & [@tttt-conan](https://github.com/tttt-conan))
-- Release 0.63.3 ([#10504](https://github.com/RocketChat/Rocket.Chat/pull/10504))
-- Release 0.63.2 ([#10476](https://github.com/RocketChat/Rocket.Chat/pull/10476))
-- add redhat dockerfile to master ([#10408](https://github.com/RocketChat/Rocket.Chat/pull/10408))
- Fix: Regression in REST API endpoint `/me` ([#10833](https://github.com/RocketChat/Rocket.Chat/pull/10833))
- Regression: Fix email notification preference not showing correct selected value ([#10847](https://github.com/RocketChat/Rocket.Chat/pull/10847))
- Apps: Command previews are clickable & Apps Framework is controlled via a setting ([#10853](https://github.com/RocketChat/Rocket.Chat/pull/10853))
@@ -440,14 +448,11 @@
- [@ThomasRoehl](https://github.com/ThomasRoehl)
- [@c0dzilla](https://github.com/c0dzilla)
- [@cfunkles](https://github.com/cfunkles)
-- [@christianh814](https://github.com/christianh814)
- [@chuckAtCataworx](https://github.com/chuckAtCataworx)
- [@erhan-](https://github.com/erhan-)
- [@kos4live](https://github.com/kos4live)
- [@nsuchy](https://github.com/nsuchy)
- [@peccu](https://github.com/peccu)
-- [@saplla](https://github.com/saplla)
-- [@tttt-conan](https://github.com/tttt-conan)
- [@winterstefan](https://github.com/winterstefan)
- [@xbolshe](https://github.com/xbolshe)
@@ -455,7 +460,6 @@
- [@Hudell](https://github.com/Hudell)
- [@MarcosSpessatto](https://github.com/MarcosSpessatto)
-- [@TwizzyDizzy](https://github.com/TwizzyDizzy)
- [@cardoso](https://github.com/cardoso)
- [@engelgabriel](https://github.com/engelgabriel)
- [@gdelavald](https://github.com/gdelavald)
@@ -599,7 +603,7 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.64.0
-`2018-04-28 Β· 2 οΈοΈοΈβ οΈ Β· 18 π Β· 44 π Β· 37 π Β· 30 π©βπ»π¨βπ»`
+`2018-04-28 Β· 2 οΈοΈοΈβ οΈ Β· 18 π Β· 44 π Β· 31 π Β· 30 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.11.1`
@@ -682,9 +686,6 @@
π Minor changes
- Release 0.64.0 ([#10613](https://github.com/RocketChat/Rocket.Chat/pull/10613) by [@christianh814](https://github.com/christianh814) & [@tttt-conan](https://github.com/tttt-conan))
-- Release 0.63.3 ([#10504](https://github.com/RocketChat/Rocket.Chat/pull/10504))
-- Release 0.63.2 ([#10476](https://github.com/RocketChat/Rocket.Chat/pull/10476))
-- add redhat dockerfile to master ([#10408](https://github.com/RocketChat/Rocket.Chat/pull/10408))
- Regression: Various search provider fixes ([#10591](https://github.com/RocketChat/Rocket.Chat/pull/10591) by [@tkurz](https://github.com/tkurz))
- Regression: /api/v1/settings.oauth not sending needed info for SAML & CAS ([#10596](https://github.com/RocketChat/Rocket.Chat/pull/10596))
- Regression: Apps and Livechats not getting along well with each other ([#10598](https://github.com/RocketChat/Rocket.Chat/pull/10598))
@@ -703,9 +704,6 @@
- Remove @core team mention from Pull Request template ([#10384](https://github.com/RocketChat/Rocket.Chat/pull/10384))
- New issue template for *Release Process* ([#10234](https://github.com/RocketChat/Rocket.Chat/pull/10234))
- Master into Develop Branch Sync ([#10376](https://github.com/RocketChat/Rocket.Chat/pull/10376))
-- Release 0.63.3 ([#10504](https://github.com/RocketChat/Rocket.Chat/pull/10504))
-- Release 0.63.2 ([#10476](https://github.com/RocketChat/Rocket.Chat/pull/10476))
-- add redhat dockerfile to master ([#10408](https://github.com/RocketChat/Rocket.Chat/pull/10408))
- LingoHub based on develop ([#10545](https://github.com/RocketChat/Rocket.Chat/pull/10545))
- Regression: Revert announcement structure ([#10544](https://github.com/RocketChat/Rocket.Chat/pull/10544))
- Regression: Upload was not working ([#10543](https://github.com/RocketChat/Rocket.Chat/pull/10543))
@@ -797,7 +795,7 @@
- [@graywolf336](https://github.com/graywolf336)
# 0.63.1
-`2018-04-07 Β· 3 π Β· 18 π©βπ»π¨βπ»`
+`2018-04-07 Β· 1 π Β· 7 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.11.1`
@@ -807,37 +805,24 @@
π Minor changes
- Release 0.63.1 ([#10374](https://github.com/RocketChat/Rocket.Chat/pull/10374) by [@TechyPeople](https://github.com/TechyPeople) & [@kaiiiiiiiii](https://github.com/kaiiiiiiiii) & [@tttt-conan](https://github.com/tttt-conan))
-- Release 0.63.0 ([#10324](https://github.com/RocketChat/Rocket.Chat/pull/10324) by [@Joe-mcgee](https://github.com/Joe-mcgee) & [@TopHattedCat](https://github.com/TopHattedCat) & [@hmagarotto](https://github.com/hmagarotto) & [@kaiiiiiiiii](https://github.com/kaiiiiiiiii) & [@kb0304](https://github.com/kb0304) & [@lunaticmonk](https://github.com/lunaticmonk) & [@ramrami](https://github.com/ramrami))
-- Release 0.63.0 ([#10324](https://github.com/RocketChat/Rocket.Chat/pull/10324) by [@Joe-mcgee](https://github.com/Joe-mcgee) & [@TopHattedCat](https://github.com/TopHattedCat) & [@hmagarotto](https://github.com/hmagarotto) & [@kaiiiiiiiii](https://github.com/kaiiiiiiiii) & [@kb0304](https://github.com/kb0304) & [@lunaticmonk](https://github.com/lunaticmonk) & [@ramrami](https://github.com/ramrami))
### π©βπ»π¨βπ» Contributors π
-- [@Joe-mcgee](https://github.com/Joe-mcgee)
- [@TechyPeople](https://github.com/TechyPeople)
-- [@TopHattedCat](https://github.com/TopHattedCat)
-- [@hmagarotto](https://github.com/hmagarotto)
- [@kaiiiiiiiii](https://github.com/kaiiiiiiiii)
-- [@kb0304](https://github.com/kb0304)
-- [@lunaticmonk](https://github.com/lunaticmonk)
-- [@ramrami](https://github.com/ramrami)
- [@tttt-conan](https://github.com/tttt-conan)
### π©βπ»π¨βπ» Core Team π€
-- [@Hudell](https://github.com/Hudell)
-- [@MarcosSpessatto](https://github.com/MarcosSpessatto)
-- [@engelgabriel](https://github.com/engelgabriel)
- [@geekgonecrazy](https://github.com/geekgonecrazy)
-- [@ggazzo](https://github.com/ggazzo)
- [@graywolf336](https://github.com/graywolf336)
-- [@karlprieb](https://github.com/karlprieb)
- [@rodrigok](https://github.com/rodrigok)
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.63.0
-`2018-04-04 Β· 1 οΈοΈοΈβ οΈ Β· 18 π Β· 48 π Β· 22 π Β· 25 π©βπ»π¨βπ»`
+`2018-04-04 Β· 1 οΈοΈοΈβ οΈ Β· 18 π Β· 30 π Β· 20 π Β· 24 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.11.1`
@@ -870,10 +855,6 @@
### π Bug fixes
-- Delete user without username was removing direct rooms of all users ([#9986](https://github.com/RocketChat/Rocket.Chat/pull/9986))
-- New channel page on medium size screens ([#9988](https://github.com/RocketChat/Rocket.Chat/pull/9988))
-- Empty sidenav when sorting by activity and there is a subscription without room ([#9960](https://github.com/RocketChat/Rocket.Chat/pull/9960))
-- Two factor authentication modal was not showing ([#9982](https://github.com/RocketChat/Rocket.Chat/pull/9982))
- Audio Message UI fixes ([#10303](https://github.com/RocketChat/Rocket.Chat/pull/10303) by [@kb0304](https://github.com/kb0304))
- "View All Members" button inside channel's "User Info" is over sized ([#10012](https://github.com/RocketChat/Rocket.Chat/pull/10012))
- Apostrophe-containing URL misparsed" ([#10242](https://github.com/RocketChat/Rocket.Chat/pull/10242))
@@ -892,24 +873,10 @@
- Nextcloud as custom oauth provider wasn't mapping data correctly ([#10090](https://github.com/RocketChat/Rocket.Chat/pull/10090))
- Missing sidebar default options on admin ([#10016](https://github.com/RocketChat/Rocket.Chat/pull/10016))
- Able to react with invalid emoji ([#8667](https://github.com/RocketChat/Rocket.Chat/pull/8667) by [@mutdmour](https://github.com/mutdmour))
-- Slack Import reports `invalid import file type` due to a call to BSON.native() which is now doesn't exist ([#10071](https://github.com/RocketChat/Rocket.Chat/pull/10071) by [@trongthanh](https://github.com/trongthanh))
-- Verified property of user is always set to false if not supplied ([#9719](https://github.com/RocketChat/Rocket.Chat/pull/9719))
-- Update preferences of users with settings: null was crashing the server ([#10076](https://github.com/RocketChat/Rocket.Chat/pull/10076))
-- REST API: Can't list all public channels when user has permission `view-joined-room` ([#10009](https://github.com/RocketChat/Rocket.Chat/pull/10009))
-- Message editing is crashing the server when read receipts are enabled ([#10061](https://github.com/RocketChat/Rocket.Chat/pull/10061))
-- Download links was duplicating Sub Paths ([#10029](https://github.com/RocketChat/Rocket.Chat/pull/10029))
- User preferences can't be saved when roles are hidden in admin settings ([#10051](https://github.com/RocketChat/Rocket.Chat/pull/10051))
- Browser was auto-filling values when editing another user profile ([#9932](https://github.com/RocketChat/Rocket.Chat/pull/9932) by [@kaiiiiiiiii](https://github.com/kaiiiiiiiii))
- Avatar input was accepting not supported image types ([#10011](https://github.com/RocketChat/Rocket.Chat/pull/10011))
- Initial loading feedback was missing ([#10028](https://github.com/RocketChat/Rocket.Chat/pull/10028))
-- Delete user without username was removing direct rooms of all users ([#9986](https://github.com/RocketChat/Rocket.Chat/pull/9986))
-- Two factor authentication modal was not showing ([#9982](https://github.com/RocketChat/Rocket.Chat/pull/9982))
-- Empty sidenav when sorting by activity and there is a subscription without room ([#9960](https://github.com/RocketChat/Rocket.Chat/pull/9960))
-- New channel page on medium size screens ([#9988](https://github.com/RocketChat/Rocket.Chat/pull/9988))
-- Delete user without username was removing direct rooms of all users ([#9986](https://github.com/RocketChat/Rocket.Chat/pull/9986))
-- New channel page on medium size screens ([#9988](https://github.com/RocketChat/Rocket.Chat/pull/9988))
-- Empty sidenav when sorting by activity and there is a subscription without room ([#9960](https://github.com/RocketChat/Rocket.Chat/pull/9960))
-- Two factor authentication modal was not showing ([#9982](https://github.com/RocketChat/Rocket.Chat/pull/9982))
- File had redirect delay when using external storage services and no option to proxy only avatars ([#10272](https://github.com/RocketChat/Rocket.Chat/pull/10272))
- Missing pt-BR translations ([#10262](https://github.com/RocketChat/Rocket.Chat/pull/10262))
- /me REST endpoint was missing user roles and preferences ([#10240](https://github.com/RocketChat/Rocket.Chat/pull/10240))
@@ -923,7 +890,6 @@
π Minor changes
- Release 0.63.0 ([#10324](https://github.com/RocketChat/Rocket.Chat/pull/10324) by [@Joe-mcgee](https://github.com/Joe-mcgee) & [@TopHattedCat](https://github.com/TopHattedCat) & [@hmagarotto](https://github.com/hmagarotto) & [@kaiiiiiiiii](https://github.com/kaiiiiiiiii) & [@kb0304](https://github.com/kb0304) & [@lunaticmonk](https://github.com/lunaticmonk) & [@ramrami](https://github.com/ramrami))
-- Release 0.62.2 ([#10087](https://github.com/RocketChat/Rocket.Chat/pull/10087))
- Fix: Reaction endpoint/api only working with regular emojis ([#10323](https://github.com/RocketChat/Rocket.Chat/pull/10323))
- Bump snap version to include security fix ([#10313](https://github.com/RocketChat/Rocket.Chat/pull/10313))
- Update Meteor to 1.6.1.1 ([#10314](https://github.com/RocketChat/Rocket.Chat/pull/10314))
@@ -936,7 +902,6 @@
- [OTHER] Reactivate all tests ([#10036](https://github.com/RocketChat/Rocket.Chat/pull/10036))
- [OTHER] Reactivate API tests ([#9844](https://github.com/RocketChat/Rocket.Chat/pull/9844))
- Start 0.63.0-develop / develop sync from master ([#9985](https://github.com/RocketChat/Rocket.Chat/pull/9985))
-- Release 0.62.2 ([#10087](https://github.com/RocketChat/Rocket.Chat/pull/10087))
- Fix: Renaming channels.notifications Get/Post endpoints ([#10257](https://github.com/RocketChat/Rocket.Chat/pull/10257))
- Fix caddy download link to pull from github ([#10260](https://github.com/RocketChat/Rocket.Chat/pull/10260))
- Fix: possible errors on rocket.chat side of the apps ([#10252](https://github.com/RocketChat/Rocket.Chat/pull/10252))
@@ -961,7 +926,6 @@
- [@lunaticmonk](https://github.com/lunaticmonk)
- [@mutdmour](https://github.com/mutdmour)
- [@ramrami](https://github.com/ramrami)
-- [@trongthanh](https://github.com/trongthanh)
- [@ubarsaiyan](https://github.com/ubarsaiyan)
### π©βπ»π¨βπ» Core Team π€
@@ -1040,7 +1004,7 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.62.0
-`2018-02-27 Β· 1 οΈοΈοΈβ οΈ Β· 24 π Β· 32 π Β· 26 π Β· 39 π©βπ»π¨βπ»`
+`2018-02-27 Β· 1 οΈοΈοΈβ οΈ Β· 24 π Β· 29 π Β· 26 π Β· 39 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.9.4`
@@ -1082,14 +1046,11 @@
- Typo on french translation for "Open" ([#9934](https://github.com/RocketChat/Rocket.Chat/pull/9934) by [@sizrar](https://github.com/sizrar))
- Wrong behavior of rooms info's *Read Only* and *Collaborative* buttons ([#9665](https://github.com/RocketChat/Rocket.Chat/pull/9665))
- Close button on file upload bar was not working ([#9662](https://github.com/RocketChat/Rocket.Chat/pull/9662))
-- Livechat conversation not receiving messages when start without form ([#9772](https://github.com/RocketChat/Rocket.Chat/pull/9772))
-- Emoji rendering on last message ([#9776](https://github.com/RocketChat/Rocket.Chat/pull/9776))
- Chrome 64 breaks jitsi-meet iframe ([#9560](https://github.com/RocketChat/Rocket.Chat/pull/9560) by [@speedy01](https://github.com/speedy01))
- Harmonize channel-related actions ([#9697](https://github.com/RocketChat/Rocket.Chat/pull/9697))
- Custom emoji was cropping sometimes ([#9676](https://github.com/RocketChat/Rocket.Chat/pull/9676) by [@anu-007](https://github.com/anu-007))
- Show custom room types icon in channel header ([#9696](https://github.com/RocketChat/Rocket.Chat/pull/9696))
- 'Query' support for channels.list.joined, groups.list, groups.listAll, im.list ([#9424](https://github.com/RocketChat/Rocket.Chat/pull/9424) by [@xbolshe](https://github.com/xbolshe))
-- Livechat issues on external queue and lead capture ([#9750](https://github.com/RocketChat/Rocket.Chat/pull/9750))
- DeprecationWarning: prom-client ... when starting Rocket Chat server ([#9747](https://github.com/RocketChat/Rocket.Chat/pull/9747) by [@jgtoriginal](https://github.com/jgtoriginal))
- API to retrive rooms was returning empty objects ([#9737](https://github.com/RocketChat/Rocket.Chat/pull/9737))
- Chat Message Reactions REST API End Point ([#9487](https://github.com/RocketChat/Rocket.Chat/pull/9487) by [@jgtoriginal](https://github.com/jgtoriginal))
@@ -1234,7 +1195,7 @@
- [@rodrigok](https://github.com/rodrigok)
# 0.61.0
-`2018-01-27 Β· 1 οΈοΈοΈβ οΈ Β· 12 π Β· 55 π Β· 43 π Β· 23 π©βπ»π¨βπ»`
+`2018-01-27 Β· 1 οΈοΈοΈβ οΈ Β· 11 π Β· 13 π Β· 8 π Β· 15 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.9.3`
@@ -1256,15 +1217,10 @@
- Livechat extract lead data from message ([#9135](https://github.com/RocketChat/Rocket.Chat/pull/9135))
- Add impersonate option for livechat triggers ([#9107](https://github.com/RocketChat/Rocket.Chat/pull/9107))
- Add support to external livechat queue service provider ([#9053](https://github.com/RocketChat/Rocket.Chat/pull/9053))
-- Make Custom oauth accept nested usernameField ([#9066](https://github.com/RocketChat/Rocket.Chat/pull/9066))
- Contextual bar mail messages ([#9510](https://github.com/RocketChat/Rocket.Chat/pull/9510))
### π Bug fixes
-- Restore translations from other languages ([#9277](https://github.com/RocketChat/Rocket.Chat/pull/9277))
-- Remove sweetalert from livechat facebook integration page ([#9274](https://github.com/RocketChat/Rocket.Chat/pull/9274))
-- Missing translations ([#9272](https://github.com/RocketChat/Rocket.Chat/pull/9272))
-- File access not working when passing credentials via querystring ([#9262](https://github.com/RocketChat/Rocket.Chat/pull/9262))
- [i18n] add room type translation support for room-changed-privacy message ([#9369](https://github.com/RocketChat/Rocket.Chat/pull/9369) by [@cyclops24](https://github.com/cyclops24))
- Fix livechat register form ([#9452](https://github.com/RocketChat/Rocket.Chat/pull/9452))
- Fix livechat build ([#9451](https://github.com/RocketChat/Rocket.Chat/pull/9451))
@@ -1273,45 +1229,7 @@
- Slash command 'archive' throws exception if the channel does not exist ([#9428](https://github.com/RocketChat/Rocket.Chat/pull/9428) by [@ramrami](https://github.com/ramrami))
- Subscriptions not removed when removing user ([#9432](https://github.com/RocketChat/Rocket.Chat/pull/9432))
- Highlight setting not working correctly ([#9364](https://github.com/RocketChat/Rocket.Chat/pull/9364) by [@cyclops24](https://github.com/cyclops24))
-- announcement hyperlink color ([#9330](https://github.com/RocketChat/Rocket.Chat/pull/9330))
-- popover on safari for iOS ([#9328](https://github.com/RocketChat/Rocket.Chat/pull/9328))
-- last message cutting on bottom ([#9345](https://github.com/RocketChat/Rocket.Chat/pull/9345))
-- Deleting message with store last message not removing ([#9335](https://github.com/RocketChat/Rocket.Chat/pull/9335))
-- custom emoji size on sidebar item ([#9314](https://github.com/RocketChat/Rocket.Chat/pull/9314))
-- svg render on firefox ([#9311](https://github.com/RocketChat/Rocket.Chat/pull/9311))
-- sidebar footer padding ([#9249](https://github.com/RocketChat/Rocket.Chat/pull/9249))
-- LDAP/AD is not importing all users ([#9309](https://github.com/RocketChat/Rocket.Chat/pull/9309))
-- Wrong position of notifications alert in accounts preference page ([#9289](https://github.com/RocketChat/Rocket.Chat/pull/9289) by [@HammyHavoc](https://github.com/HammyHavoc))
-- English Typos ([#9285](https://github.com/RocketChat/Rocket.Chat/pull/9285) by [@HammyHavoc](https://github.com/HammyHavoc))
-- Restore translations from other languages ([#9277](https://github.com/RocketChat/Rocket.Chat/pull/9277))
-- Remove sweetalert from livechat facebook integration page ([#9274](https://github.com/RocketChat/Rocket.Chat/pull/9274))
-- Missing translations ([#9272](https://github.com/RocketChat/Rocket.Chat/pull/9272))
- File access not working when passing credentials via querystring ([#9264](https://github.com/RocketChat/Rocket.Chat/pull/9264))
-- Move emojipicker css to theme package ([#9243](https://github.com/RocketChat/Rocket.Chat/pull/9243))
-- Show modal with announcement ([#9241](https://github.com/RocketChat/Rocket.Chat/pull/9241))
-- "Enter usernames" placeholder is cutting in "create channel" view ([#9194](https://github.com/RocketChat/Rocket.Chat/pull/9194) by [@TheReal1604](https://github.com/TheReal1604))
-- File upload not working on IE and weird on Chrome ([#9206](https://github.com/RocketChat/Rocket.Chat/pull/9206))
-- make the cross icon on user selection at channel creation page work ([#9176](https://github.com/RocketChat/Rocket.Chat/pull/9176) by [@vitor-nagao](https://github.com/vitor-nagao))
-- Made welcome emails more readable ([#9193](https://github.com/RocketChat/Rocket.Chat/pull/9193) by [@HammyHavoc](https://github.com/HammyHavoc))
-- Cursor position when reply on safari ([#9185](https://github.com/RocketChat/Rocket.Chat/pull/9185))
-- Emoji size on last message preview ([#9186](https://github.com/RocketChat/Rocket.Chat/pull/9186))
-- Unread bar position when room have announcement ([#9188](https://github.com/RocketChat/Rocket.Chat/pull/9188))
-- Error when user roles is missing or is invalid ([#9040](https://github.com/RocketChat/Rocket.Chat/pull/9040) by [@paulovitin](https://github.com/paulovitin))
-- Make mentions and menu icons color darker ([#8922](https://github.com/RocketChat/Rocket.Chat/pull/8922))
-- "Use Emoji" preference not working ([#9182](https://github.com/RocketChat/Rocket.Chat/pull/9182))
-- channel create scroll on small screens ([#9168](https://github.com/RocketChat/Rocket.Chat/pull/9168))
-- go to replied message ([#9172](https://github.com/RocketChat/Rocket.Chat/pull/9172))
-- modal data on enter and modal style for file preview ([#9171](https://github.com/RocketChat/Rocket.Chat/pull/9171))
-- show oauth logins when adblock is used ([#9170](https://github.com/RocketChat/Rocket.Chat/pull/9170))
-- Last sent message reoccurs in textbox ([#9169](https://github.com/RocketChat/Rocket.Chat/pull/9169))
-- Update Rocket.Chat for sandstorm ([#9062](https://github.com/RocketChat/Rocket.Chat/pull/9062) by [@peterlee0127](https://github.com/peterlee0127))
-- Importers not recovering when an error occurs ([#9134](https://github.com/RocketChat/Rocket.Chat/pull/9134))
-- Do not block room while loading history ([#9121](https://github.com/RocketChat/Rocket.Chat/pull/9121))
-- Channel page error ([#9091](https://github.com/RocketChat/Rocket.Chat/pull/9091) by [@ggrish](https://github.com/ggrish))
-- Restore translations from other languages ([#9277](https://github.com/RocketChat/Rocket.Chat/pull/9277))
-- Remove sweetalert from livechat facebook integration page ([#9274](https://github.com/RocketChat/Rocket.Chat/pull/9274))
-- Missing translations ([#9272](https://github.com/RocketChat/Rocket.Chat/pull/9272))
-- File access not working when passing credentials via querystring ([#9262](https://github.com/RocketChat/Rocket.Chat/pull/9262))
- Contextual bar redesign ([#9481](https://github.com/RocketChat/Rocket.Chat/pull/9481))
- mention-here is missing i18n text #9455 ([#9456](https://github.com/RocketChat/Rocket.Chat/pull/9456) by [@ryjones](https://github.com/ryjones))
- Fix livechat visitor edit ([#9506](https://github.com/RocketChat/Rocket.Chat/pull/9506))
@@ -1321,45 +1239,10 @@
π Minor changes
- Release 0.61.0 ([#9533](https://github.com/RocketChat/Rocket.Chat/pull/9533) by [@ryjones](https://github.com/ryjones))
-- Release 0.60.4 ([#9377](https://github.com/RocketChat/Rocket.Chat/pull/9377))
-- Release 0.60.3 ([#9320](https://github.com/RocketChat/Rocket.Chat/pull/9320) by [@HammyHavoc](https://github.com/HammyHavoc))
- Add community bot ([#9439](https://github.com/RocketChat/Rocket.Chat/pull/9439))
- Use correct version of Mailparser module ([#9356](https://github.com/RocketChat/Rocket.Chat/pull/9356))
-- Update Marked dependecy to 0.3.9 ([#9346](https://github.com/RocketChat/Rocket.Chat/pull/9346))
-- Fix: English language improvements ([#9299](https://github.com/RocketChat/Rocket.Chat/pull/9299) by [@HammyHavoc](https://github.com/HammyHavoc))
-- Fix: Change 'Wordpress' to 'WordPress ([#9291](https://github.com/RocketChat/Rocket.Chat/pull/9291) by [@HammyHavoc](https://github.com/HammyHavoc))
-- Fix: Improved README.md ([#9290](https://github.com/RocketChat/Rocket.Chat/pull/9290) by [@HammyHavoc](https://github.com/HammyHavoc))
-- Fix: README typo ([#9286](https://github.com/RocketChat/Rocket.Chat/pull/9286) by [@HammyHavoc](https://github.com/HammyHavoc))
- Develop sync - Bump version to 0.61.0-develop ([#9260](https://github.com/RocketChat/Rocket.Chat/pull/9260) by [@cpitman](https://github.com/cpitman))
-- Do not change room icon color when room is unread ([#9257](https://github.com/RocketChat/Rocket.Chat/pull/9257))
-- LingoHub based on develop ([#9256](https://github.com/RocketChat/Rocket.Chat/pull/9256))
-- Fix: Sidebar item on rtl and small devices ([#9247](https://github.com/RocketChat/Rocket.Chat/pull/9247))
-- Add curl, its missing on worker nodes so has to be explicitly added ([#9248](https://github.com/RocketChat/Rocket.Chat/pull/9248))
-- Fix: Unneeded warning in payload of REST API calls ([#9240](https://github.com/RocketChat/Rocket.Chat/pull/9240))
-- Fix: Missing option to set user's avatar from a url ([#9229](https://github.com/RocketChat/Rocket.Chat/pull/9229))
-- Fix: Upload access control too distributed ([#9215](https://github.com/RocketChat/Rocket.Chat/pull/9215))
-- Fix: Username find is matching partially ([#9217](https://github.com/RocketChat/Rocket.Chat/pull/9217))
-- Fix: updating last message on message edit or delete ([#9227](https://github.com/RocketChat/Rocket.Chat/pull/9227))
-- Fix: Rooms and users are using different avatar style ([#9196](https://github.com/RocketChat/Rocket.Chat/pull/9196))
-- Replace postcss-nesting with postcss-nested ([#9200](https://github.com/RocketChat/Rocket.Chat/pull/9200))
-- Dependencies Update ([#9197](https://github.com/RocketChat/Rocket.Chat/pull/9197))
-- Typo: German language file ([#9190](https://github.com/RocketChat/Rocket.Chat/pull/9190) by [@TheReal1604](https://github.com/TheReal1604))
-- Fix: Snippet name to not showing in snippet list ([#9184](https://github.com/RocketChat/Rocket.Chat/pull/9184))
-- Fix/api me only return verified ([#9183](https://github.com/RocketChat/Rocket.Chat/pull/9183))
-- Fix: UI: Descenders of glyphs are cut off ([#9181](https://github.com/RocketChat/Rocket.Chat/pull/9181))
- [Fix] oauth not working because of email array ([#9173](https://github.com/RocketChat/Rocket.Chat/pull/9173))
-- Fix: Click on channel name - hover area bigger than link area ([#9165](https://github.com/RocketChat/Rocket.Chat/pull/9165))
-- Fix: UI: Descenders of glyphs are cut off ([#9166](https://github.com/RocketChat/Rocket.Chat/pull/9166))
-- Fix: Canβt login using LDAP via REST ([#9162](https://github.com/RocketChat/Rocket.Chat/pull/9162))
-- Fix: Unread line ([#9149](https://github.com/RocketChat/Rocket.Chat/pull/9149))
-- Fix test without oplog by waiting a successful login on changing users ([#9146](https://github.com/RocketChat/Rocket.Chat/pull/9146))
-- Fix: Messages being displayed in reverse order ([#9144](https://github.com/RocketChat/Rocket.Chat/pull/9144))
-- Fix: Clear all unreads modal not closing after confirming ([#9137](https://github.com/RocketChat/Rocket.Chat/pull/9137))
-- Fix: Message action quick buttons drops if "new message" divider is being shown ([#9138](https://github.com/RocketChat/Rocket.Chat/pull/9138))
-- Fix: Confirmation modals showing `Send` button ([#9136](https://github.com/RocketChat/Rocket.Chat/pull/9136))
-- Fix: Multiple unread indicators ([#9120](https://github.com/RocketChat/Rocket.Chat/pull/9120))
-- Release 0.60.4 ([#9377](https://github.com/RocketChat/Rocket.Chat/pull/9377))
-- Release 0.60.3 ([#9320](https://github.com/RocketChat/Rocket.Chat/pull/9320) by [@HammyHavoc](https://github.com/HammyHavoc))
- [DOCS] Update the links of our Mobile Apps in Features topic ([#9469](https://github.com/RocketChat/Rocket.Chat/pull/9469))
- Update license ([#9490](https://github.com/RocketChat/Rocket.Chat/pull/9490))
- Prevent NPM package-lock inside livechat ([#9504](https://github.com/RocketChat/Rocket.Chat/pull/9504))
@@ -1368,17 +1251,11 @@
### π©βπ»π¨βπ» Contributors π
-- [@HammyHavoc](https://github.com/HammyHavoc)
-- [@TheReal1604](https://github.com/TheReal1604)
- [@cpitman](https://github.com/cpitman)
- [@cyclops24](https://github.com/cyclops24)
-- [@ggrish](https://github.com/ggrish)
-- [@paulovitin](https://github.com/paulovitin)
-- [@peterlee0127](https://github.com/peterlee0127)
- [@ramrami](https://github.com/ramrami)
- [@rndmh3ro](https://github.com/rndmh3ro)
- [@ryjones](https://github.com/ryjones)
-- [@vitor-nagao](https://github.com/vitor-nagao)
### π©βπ»π¨βπ» Core Team π€
@@ -1388,15 +1265,13 @@
- [@gdelavald](https://github.com/gdelavald)
- [@geekgonecrazy](https://github.com/geekgonecrazy)
- [@ggazzo](https://github.com/ggazzo)
-- [@graywolf336](https://github.com/graywolf336)
- [@karlprieb](https://github.com/karlprieb)
-- [@pierreozoux](https://github.com/pierreozoux)
- [@rafaelks](https://github.com/rafaelks)
- [@rodrigok](https://github.com/rodrigok)
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.60.4
-`2018-01-10 Β· 5 π Β· 4 π Β· 4 π©βπ»π¨βπ»`
+`2018-01-10 Β· 5 π Β· 2 π Β· 3 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.9.3`
@@ -1414,16 +1289,10 @@
π Minor changes
- Release 0.60.4 ([#9377](https://github.com/RocketChat/Rocket.Chat/pull/9377))
-- Release 0.60.3 ([#9320](https://github.com/RocketChat/Rocket.Chat/pull/9320) by [@HammyHavoc](https://github.com/HammyHavoc))
-- Release 0.60.3 ([#9320](https://github.com/RocketChat/Rocket.Chat/pull/9320) by [@HammyHavoc](https://github.com/HammyHavoc))
- Update Marked dependecy to 0.3.9 ([#9346](https://github.com/RocketChat/Rocket.Chat/pull/9346))
-### π©βπ»π¨βπ» Contributors π
-
-- [@HammyHavoc](https://github.com/HammyHavoc)
-
### π©βπ»π¨βπ» Core Team π€
- [@karlprieb](https://github.com/karlprieb)
@@ -1507,7 +1376,7 @@
- [@rodrigok](https://github.com/rodrigok)
# 0.60.0
-`2017-12-27 Β· 33 π Β· 174 π Β· 108 π Β· 71 π©βπ»π¨βπ»`
+`2017-12-27 Β· 27 π Β· 74 π Β· 72 π Β· 59 π©βπ»π¨βπ»`
### Engine versions
- Node: `8.9.3`
@@ -1536,22 +1405,15 @@
- code to get the updated messages ([#8857](https://github.com/RocketChat/Rocket.Chat/pull/8857))
- Rest API endpoints to list, get, and run commands ([#8531](https://github.com/RocketChat/Rocket.Chat/pull/8531))
- Upgrade Meteor to 1.6 ([#8715](https://github.com/RocketChat/Rocket.Chat/pull/8715))
-- Setting to disable MarkDown and enable AutoLinker ([#8459](https://github.com/RocketChat/Rocket.Chat/pull/8459))
- Add settings for allow user direct messages to yourself ([#8066](https://github.com/RocketChat/Rocket.Chat/pull/8066) by [@lindoelio](https://github.com/lindoelio))
- Add sweet alert to video call tab ([#8108](https://github.com/RocketChat/Rocket.Chat/pull/8108))
- Displays QR code for manually entering when enabling 2fa ([#8143](https://github.com/RocketChat/Rocket.Chat/pull/8143))
-- Unify unread and mentions badge ([#8361](https://github.com/RocketChat/Rocket.Chat/pull/8361))
-- make sidebar item width 100% ([#8362](https://github.com/RocketChat/Rocket.Chat/pull/8362))
-- Smaller accountBox ([#8360](https://github.com/RocketChat/Rocket.Chat/pull/8360))
-- Add RD Station integration to livechat ([#8304](https://github.com/RocketChat/Rocket.Chat/pull/8304))
-- Upgrade to meteor 1.5.2 ([#8073](https://github.com/RocketChat/Rocket.Chat/pull/8073))
- Add yunohost.org installation method to Readme.md ([#8037](https://github.com/RocketChat/Rocket.Chat/pull/8037) by [@selamanse](https://github.com/selamanse))
- Modal ([#9092](https://github.com/RocketChat/Rocket.Chat/pull/9092))
- Make Custom oauth accept nested usernameField ([#9066](https://github.com/RocketChat/Rocket.Chat/pull/9066))
### π Bug fixes
-- Channel settings buttons ([#8753](https://github.com/RocketChat/Rocket.Chat/pull/8753))
- Can't react on Read Only rooms even when enabled ([#8925](https://github.com/RocketChat/Rocket.Chat/pull/8925))
- CAS does not share secrets when operating multiple server instances ([#8654](https://github.com/RocketChat/Rocket.Chat/pull/8654) by [@AmShaegar13](https://github.com/AmShaegar13))
- Snippetted messages not working ([#8937](https://github.com/RocketChat/Rocket.Chat/pull/8937))
@@ -1587,7 +1449,6 @@
- Xenforo [BD]API for 'user.user_id; instead of 'id' ([#8968](https://github.com/RocketChat/Rocket.Chat/pull/8968) by [@wesnspace](https://github.com/wesnspace))
- flextab height on smaller screens ([#8994](https://github.com/RocketChat/Rocket.Chat/pull/8994))
- Check for mention-all permission in room scope ([#8931](https://github.com/RocketChat/Rocket.Chat/pull/8931))
-- Channel settings buttons ([#8753](https://github.com/RocketChat/Rocket.Chat/pull/8753))
- fix emoji package path so they show up correctly in browser ([#8822](https://github.com/RocketChat/Rocket.Chat/pull/8822) by [@ryoshimizu](https://github.com/ryoshimizu))
- Set correct Twitter link ([#8830](https://github.com/RocketChat/Rocket.Chat/pull/8830) by [@jotafeldmann](https://github.com/jotafeldmann))
- User email settings on DM ([#8810](https://github.com/RocketChat/Rocket.Chat/pull/8810))
@@ -1600,106 +1461,8 @@
- Sort direct messages by full name if show real names setting enabled ([#8717](https://github.com/RocketChat/Rocket.Chat/pull/8717))
- Improving consistency of UX ([#8796](https://github.com/RocketChat/Rocket.Chat/pull/8796) by [@HammyHavoc](https://github.com/HammyHavoc))
- fixed some typos ([#8787](https://github.com/RocketChat/Rocket.Chat/pull/8787) by [@TheReal1604](https://github.com/TheReal1604))
-- Fix e-mail message forward ([#8645](https://github.com/RocketChat/Rocket.Chat/pull/8645))
-- Audio message icon ([#8648](https://github.com/RocketChat/Rocket.Chat/pull/8648))
-- Highlighted color height issue ([#8431](https://github.com/RocketChat/Rocket.Chat/pull/8431) by [@cyclops24](https://github.com/cyclops24))
-- AmazonS3: Quote file.name for ContentDisposition for files with commas ([#8593](https://github.com/RocketChat/Rocket.Chat/pull/8593))
-- Update pt-BR translation ([#8655](https://github.com/RocketChat/Rocket.Chat/pull/8655) by [@rodorgas](https://github.com/rodorgas))
-- Fix typos ([#8679](https://github.com/RocketChat/Rocket.Chat/pull/8679))
-- LDAP not respecting UTF8 characters & Sync Interval not working ([#8691](https://github.com/RocketChat/Rocket.Chat/pull/8691))
-- Missing scroll at create channel page ([#8637](https://github.com/RocketChat/Rocket.Chat/pull/8637))
-- Message popup menu on mobile/cordova ([#8634](https://github.com/RocketChat/Rocket.Chat/pull/8634))
-- API channel/group.members not sorting ([#8635](https://github.com/RocketChat/Rocket.Chat/pull/8635))
-- LDAP not merging existent users && Wrong id link generation ([#8613](https://github.com/RocketChat/Rocket.Chat/pull/8613))
-- encode filename in url to prevent links breaking ([#8551](https://github.com/RocketChat/Rocket.Chat/pull/8551) by [@joesitton](https://github.com/joesitton))
-- Fix guest pool inquiry taking ([#8577](https://github.com/RocketChat/Rocket.Chat/pull/8577))
- Changed all rocket.chat/docs/ to docs.rocket.chat/ ([#8588](https://github.com/RocketChat/Rocket.Chat/pull/8588) by [@RekkyRek](https://github.com/RekkyRek))
-- Color reset when default value editor is different ([#8543](https://github.com/RocketChat/Rocket.Chat/pull/8543))
-- Wrong colors after migration 103 ([#8547](https://github.com/RocketChat/Rocket.Chat/pull/8547))
-- LDAP login error regression at 0.59.0 ([#8541](https://github.com/RocketChat/Rocket.Chat/pull/8541))
-- Migration 103 wrong converting primrary colors ([#8544](https://github.com/RocketChat/Rocket.Chat/pull/8544))
-- Do not send joinCode field to clients ([#8527](https://github.com/RocketChat/Rocket.Chat/pull/8527))
-- Uncessary route reload break some routes ([#8514](https://github.com/RocketChat/Rocket.Chat/pull/8514))
-- Invalid Code message for password protected channel ([#8491](https://github.com/RocketChat/Rocket.Chat/pull/8491))
-- Wrong message when reseting password and 2FA is enabled ([#8489](https://github.com/RocketChat/Rocket.Chat/pull/8489))
-- LDAP memory issues when pagination is not available ([#8457](https://github.com/RocketChat/Rocket.Chat/pull/8457))
-- Add needed dependency for snaps ([#8389](https://github.com/RocketChat/Rocket.Chat/pull/8389))
-- Slack import failing and not being able to be restarted ([#8390](https://github.com/RocketChat/Rocket.Chat/pull/8390))
-- Sidebar item menu position in RTL ([#8397](https://github.com/RocketChat/Rocket.Chat/pull/8397) by [@cyclops24](https://github.com/cyclops24))
-- disabled katex tooltip on messageBox ([#8386](https://github.com/RocketChat/Rocket.Chat/pull/8386))
-- Duplicate code in rest api letting in a few bugs with the rest api ([#8408](https://github.com/RocketChat/Rocket.Chat/pull/8408))
-- Various LDAP issues & Missing pagination ([#8372](https://github.com/RocketChat/Rocket.Chat/pull/8372))
-- remove accountBox from admin menu ([#8358](https://github.com/RocketChat/Rocket.Chat/pull/8358))
-- Missing i18n translations ([#8357](https://github.com/RocketChat/Rocket.Chat/pull/8357))
-- After deleting the room, cache is not synchronizing ([#8314](https://github.com/RocketChat/Rocket.Chat/pull/8314) by [@szluohua](https://github.com/szluohua))
-- Remove sidebar header on admin embedded version ([#8334](https://github.com/RocketChat/Rocket.Chat/pull/8334))
-- Email Subjects not being sent ([#8317](https://github.com/RocketChat/Rocket.Chat/pull/8317))
-- Put delete action on another popover group ([#8315](https://github.com/RocketChat/Rocket.Chat/pull/8315))
-- Mention unread indicator was removed ([#8316](https://github.com/RocketChat/Rocket.Chat/pull/8316))
-- Execute meteor reset on TRAVIS_TAG builds ([#8310](https://github.com/RocketChat/Rocket.Chat/pull/8310))
-- Wrong file name when upload to AWS S3 ([#8296](https://github.com/RocketChat/Rocket.Chat/pull/8296))
-- TypeError: Cannot read property 't' of undefined ([#8298](https://github.com/RocketChat/Rocket.Chat/pull/8298))
-- Check attachments is defined before accessing first element ([#8295](https://github.com/RocketChat/Rocket.Chat/pull/8295) by [@Darkneon](https://github.com/Darkneon))
-- Amin menu not showing all items & File list breaking line ([#8299](https://github.com/RocketChat/Rocket.Chat/pull/8299))
-- Call buttons with wrong margin on RTL ([#8307](https://github.com/RocketChat/Rocket.Chat/pull/8307))
-- Emoji Picker hidden for reactions in RTL ([#8300](https://github.com/RocketChat/Rocket.Chat/pull/8300))
-- fix color on unread messages ([#8282](https://github.com/RocketChat/Rocket.Chat/pull/8282))
-- Missing placeholder translations ([#8286](https://github.com/RocketChat/Rocket.Chat/pull/8286))
-- "Cancel button" on modal in RTL in Firefox 55 ([#8278](https://github.com/RocketChat/Rocket.Chat/pull/8278) by [@cyclops24](https://github.com/cyclops24))
-- Attachment icons alignment in LTR and RTL ([#8271](https://github.com/RocketChat/Rocket.Chat/pull/8271) by [@cyclops24](https://github.com/cyclops24))
-- [i18n] My Profile & README.md links ([#8270](https://github.com/RocketChat/Rocket.Chat/pull/8270) by [@Rzeszow](https://github.com/Rzeszow))
-- Incorrect URL for login terms when using prefix ([#8211](https://github.com/RocketChat/Rocket.Chat/pull/8211) by [@Darkneon](https://github.com/Darkneon))
-- Scrollbar not using new style ([#8190](https://github.com/RocketChat/Rocket.Chat/pull/8190))
-- User avatar in DM list. ([#8210](https://github.com/RocketChat/Rocket.Chat/pull/8210))
-- Fix iframe login API response (issue #8145) ([#8146](https://github.com/RocketChat/Rocket.Chat/pull/8146) by [@astax-t](https://github.com/astax-t))
-- Issue #8166 where empty analytics setting breaks to load Piwik script ([#8167](https://github.com/RocketChat/Rocket.Chat/pull/8167) by [@ruKurz](https://github.com/ruKurz))
-- Sidebar and RTL alignments ([#8154](https://github.com/RocketChat/Rocket.Chat/pull/8154))
-- "*.members" rest api being useless and only returning usernames ([#8147](https://github.com/RocketChat/Rocket.Chat/pull/8147))
-- Text area lost text when page reloads ([#8159](https://github.com/RocketChat/Rocket.Chat/pull/8159))
-- Add admin audio preferences translations ([#8094](https://github.com/RocketChat/Rocket.Chat/pull/8094))
-- RTL ([#8112](https://github.com/RocketChat/Rocket.Chat/pull/8112))
-- Settings description not showing ([#8122](https://github.com/RocketChat/Rocket.Chat/pull/8122))
-- Not sending email to mentioned users with unchanged preference ([#8059](https://github.com/RocketChat/Rocket.Chat/pull/8059))
-- Dynamic popover ([#8101](https://github.com/RocketChat/Rocket.Chat/pull/8101))
-- Fix setting user avatar on LDAP login ([#8099](https://github.com/RocketChat/Rocket.Chat/pull/8099))
-- Scroll on messagebox ([#8047](https://github.com/RocketChat/Rocket.Chat/pull/8047))
-- Invisible leader bar on hover ([#8048](https://github.com/RocketChat/Rocket.Chat/pull/8048))
-- Fix email on mention ([#7754](https://github.com/RocketChat/Rocket.Chat/pull/7754))
-- Prevent autotranslate tokens race condition ([#8046](https://github.com/RocketChat/Rocket.Chat/pull/8046))
-- Vertical menu on flex-tab ([#7988](https://github.com/RocketChat/Rocket.Chat/pull/7988))
-- message-box autogrow ([#8019](https://github.com/RocketChat/Rocket.Chat/pull/8019))
-- copy to clipboard and update clipboard.js library ([#8039](https://github.com/RocketChat/Rocket.Chat/pull/8039))
-- Recent emojis not updated when adding via text ([#7998](https://github.com/RocketChat/Rocket.Chat/pull/7998))
-- [PL] Polish translation ([#7989](https://github.com/RocketChat/Rocket.Chat/pull/7989) by [@Rzeszow](https://github.com/Rzeszow))
-- Chat box no longer auto-focuses when typing ([#7984](https://github.com/RocketChat/Rocket.Chat/pull/7984))
-- Fix the status on the members list ([#7963](https://github.com/RocketChat/Rocket.Chat/pull/7963))
-- Markdown being rendered in code tags ([#7965](https://github.com/RocketChat/Rocket.Chat/pull/7965))
- Email verification indicator added ([#7923](https://github.com/RocketChat/Rocket.Chat/pull/7923) by [@aditya19496](https://github.com/aditya19496))
-- Show leader on first load ([#7712](https://github.com/RocketChat/Rocket.Chat/pull/7712) by [@danischreiber](https://github.com/danischreiber))
-- Add padding on messages to allow space to the action buttons ([#7971](https://github.com/RocketChat/Rocket.Chat/pull/7971))
-- Small alignment fixes ([#7970](https://github.com/RocketChat/Rocket.Chat/pull/7970))
-- username ellipsis on firefox ([#7953](https://github.com/RocketChat/Rocket.Chat/pull/7953))
-- Document README.md. Drupal repo out of date ([#7948](https://github.com/RocketChat/Rocket.Chat/pull/7948) by [@Lawri-van-Buel](https://github.com/Lawri-van-Buel))
-- Double scroll on 'keyboard shortcuts' menu in sidepanel ([#7927](https://github.com/RocketChat/Rocket.Chat/pull/7927) by [@aditya19496](https://github.com/aditya19496))
-- Broken emoji picker on firefox ([#7943](https://github.com/RocketChat/Rocket.Chat/pull/7943))
-- Broken embedded view layout ([#7944](https://github.com/RocketChat/Rocket.Chat/pull/7944))
-- Fix placeholders in account profile ([#7945](https://github.com/RocketChat/Rocket.Chat/pull/7945) by [@josiasds](https://github.com/josiasds))
-- OTR buttons padding ([#7954](https://github.com/RocketChat/Rocket.Chat/pull/7954))
-- status and active room colors on sidebar ([#7960](https://github.com/RocketChat/Rocket.Chat/pull/7960))
-- Fix google play logo on repo README ([#7912](https://github.com/RocketChat/Rocket.Chat/pull/7912) by [@luizbills](https://github.com/luizbills))
-- Fix livechat toggle UI issue ([#7904](https://github.com/RocketChat/Rocket.Chat/pull/7904))
-- Remove break change in Realtime API ([#7895](https://github.com/RocketChat/Rocket.Chat/pull/7895))
-- Window exception when parsing Markdown on server ([#7893](https://github.com/RocketChat/Rocket.Chat/pull/7893))
-- sidebar buttons and badge paddings ([#7888](https://github.com/RocketChat/Rocket.Chat/pull/7888))
-- hyperlink style on sidebar footer ([#7882](https://github.com/RocketChat/Rocket.Chat/pull/7882))
-- livechat icon ([#7886](https://github.com/RocketChat/Rocket.Chat/pull/7886))
-- Makes text action menu width based on content size ([#7887](https://github.com/RocketChat/Rocket.Chat/pull/7887))
-- message actions over unread bar ([#7885](https://github.com/RocketChat/Rocket.Chat/pull/7885))
-- popover position on mobile ([#7883](https://github.com/RocketChat/Rocket.Chat/pull/7883))
-- search results position on sidebar ([#7881](https://github.com/RocketChat/Rocket.Chat/pull/7881))
-- sidebar paddings ([#7880](https://github.com/RocketChat/Rocket.Chat/pull/7880))
-- Adds default search text padding for emoji search ([#7878](https://github.com/RocketChat/Rocket.Chat/pull/7878))
-- Channel settings buttons ([#8753](https://github.com/RocketChat/Rocket.Chat/pull/8753))
- REST API file upload not respecting size limit ([#9108](https://github.com/RocketChat/Rocket.Chat/pull/9108))
- Creating channels on Firefox ([#9109](https://github.com/RocketChat/Rocket.Chat/pull/9109))
- Some UI problems on 0.60 ([#9095](https://github.com/RocketChat/Rocket.Chat/pull/9095))
@@ -1730,10 +1493,6 @@
π Minor changes
- Release 0.60.0 ([#9259](https://github.com/RocketChat/Rocket.Chat/pull/9259))
-- Fix tag build ([#8973](https://github.com/RocketChat/Rocket.Chat/pull/8973))
-- Fix CircleCI deploy filter ([#8972](https://github.com/RocketChat/Rocket.Chat/pull/8972))
-- Release/0.59.4 ([#8967](https://github.com/RocketChat/Rocket.Chat/pull/8967) by [@cpitman](https://github.com/cpitman))
-- Add CircleCI ([#8685](https://github.com/RocketChat/Rocket.Chat/pull/8685))
- Fix tag build ([#9084](https://github.com/RocketChat/Rocket.Chat/pull/9084))
- Turn off prettyJson if the node environment isn't development ([#9068](https://github.com/RocketChat/Rocket.Chat/pull/9068))
- Fix api regression (exception when deleting user) ([#9049](https://github.com/RocketChat/Rocket.Chat/pull/9049))
@@ -1756,19 +1515,9 @@
- Fix typo ([#8705](https://github.com/RocketChat/Rocket.Chat/pull/8705) by [@rmetzler](https://github.com/rmetzler))
- [Fix] Store Outgoing Integration Result as String in Mongo ([#8413](https://github.com/RocketChat/Rocket.Chat/pull/8413) by [@cpitman](https://github.com/cpitman))
- Update DEMO to OPEN links ([#8793](https://github.com/RocketChat/Rocket.Chat/pull/8793))
-- Add CircleCI ([#8685](https://github.com/RocketChat/Rocket.Chat/pull/8685))
- Fix Travis CI build ([#8750](https://github.com/RocketChat/Rocket.Chat/pull/8750))
- Updated comments. ([#8719](https://github.com/RocketChat/Rocket.Chat/pull/8719) by [@jasonjyu](https://github.com/jasonjyu))
-- removing a duplicate line ([#8434](https://github.com/RocketChat/Rocket.Chat/pull/8434) by [@vikaskedia](https://github.com/vikaskedia))
-- install grpc package manually to fix snap armhf build ([#8653](https://github.com/RocketChat/Rocket.Chat/pull/8653))
- Fix community links in readme ([#8589](https://github.com/RocketChat/Rocket.Chat/pull/8589))
-- Improve room sync speed ([#8529](https://github.com/RocketChat/Rocket.Chat/pull/8529))
-- Fix high CPU load when sending messages on large rooms (regression) ([#8520](https://github.com/RocketChat/Rocket.Chat/pull/8520))
-- Change artifact path ([#8515](https://github.com/RocketChat/Rocket.Chat/pull/8515))
-- Color variables migration ([#8463](https://github.com/RocketChat/Rocket.Chat/pull/8463))
-- Fix: Change password not working in new UI ([#8516](https://github.com/RocketChat/Rocket.Chat/pull/8516))
-- Enable AutoLinker back ([#8490](https://github.com/RocketChat/Rocket.Chat/pull/8490))
-- Improve markdown parser code ([#8451](https://github.com/RocketChat/Rocket.Chat/pull/8451))
- [MOVE] Move favico to client folder ([#8077](https://github.com/RocketChat/Rocket.Chat/pull/8077) by [@vcapretz](https://github.com/vcapretz))
- [MOVE] Move files from emojione to client/server folders ([#8078](https://github.com/RocketChat/Rocket.Chat/pull/8078) by [@vcapretz](https://github.com/vcapretz))
- [MOVE] Move files from slashcommands-unarchive to client/server folders ([#8084](https://github.com/RocketChat/Rocket.Chat/pull/8084) by [@vcapretz](https://github.com/vcapretz))
@@ -1782,33 +1531,11 @@
- [MOVE] Move slackbridge to client/server folders ([#8141](https://github.com/RocketChat/Rocket.Chat/pull/8141) by [@vcapretz](https://github.com/vcapretz))
- [MOVE] Move logger files to client/server folders ([#8150](https://github.com/RocketChat/Rocket.Chat/pull/8150) by [@vcapretz](https://github.com/vcapretz))
- [MOVE] Move timesync files to client/server folders ([#8152](https://github.com/RocketChat/Rocket.Chat/pull/8152) by [@vcapretz](https://github.com/vcapretz))
-- Fix: Account menu position on RTL ([#8416](https://github.com/RocketChat/Rocket.Chat/pull/8416))
-- Fix: Missing LDAP option to show internal logs ([#8417](https://github.com/RocketChat/Rocket.Chat/pull/8417))
-- Fix: Missing LDAP reconnect setting ([#8414](https://github.com/RocketChat/Rocket.Chat/pull/8414))
-- Add i18n Title to snippet messages ([#8394](https://github.com/RocketChat/Rocket.Chat/pull/8394))
-- Fix: Missing settings to configure LDAP size and page limits ([#8398](https://github.com/RocketChat/Rocket.Chat/pull/8398))
-- LingoHub based on develop ([#8375](https://github.com/RocketChat/Rocket.Chat/pull/8375))
-- Update Meteor to 1.5.2.2 ([#8364](https://github.com/RocketChat/Rocket.Chat/pull/8364))
-- Sync translations from LingoHub ([#8363](https://github.com/RocketChat/Rocket.Chat/pull/8363))
-- Remove field `lastActivity` from subscription data ([#8345](https://github.com/RocketChat/Rocket.Chat/pull/8345))
-- Update meteor to 1.5.2.2-rc.0 ([#8355](https://github.com/RocketChat/Rocket.Chat/pull/8355))
-- [FIX-RC] Mobile file upload not working ([#8331](https://github.com/RocketChat/Rocket.Chat/pull/8331))
-- Deps update ([#8273](https://github.com/RocketChat/Rocket.Chat/pull/8273))
-- Fix more rtl issues ([#8194](https://github.com/RocketChat/Rocket.Chat/pull/8194))
-- npm deps update ([#8197](https://github.com/RocketChat/Rocket.Chat/pull/8197))
-- Remove unnecessary returns in cors common ([#8054](https://github.com/RocketChat/Rocket.Chat/pull/8054) by [@Kiran-Rao](https://github.com/Kiran-Rao))
- Adding: How to Install in WeDeploy ([#8036](https://github.com/RocketChat/Rocket.Chat/pull/8036) by [@thompsonemerson](https://github.com/thompsonemerson))
- Revert "npm deps update" ([#7983](https://github.com/RocketChat/Rocket.Chat/pull/7983))
-- [DOCS] Add native mobile app links into README and update button images ([#7909](https://github.com/RocketChat/Rocket.Chat/pull/7909))
- npm deps update ([#7969](https://github.com/RocketChat/Rocket.Chat/pull/7969))
-- Update BlackDuck URL ([#7941](https://github.com/RocketChat/Rocket.Chat/pull/7941))
-- Hide flex-tab close button ([#7894](https://github.com/RocketChat/Rocket.Chat/pull/7894))
- Added RocketChatLauncher (SaaS) ([#6606](https://github.com/RocketChat/Rocket.Chat/pull/6606) by [@designgurudotorg](https://github.com/designgurudotorg))
- Develop sync ([#7866](https://github.com/RocketChat/Rocket.Chat/pull/7866))
-- Fix tag build ([#8973](https://github.com/RocketChat/Rocket.Chat/pull/8973))
-- Fix CircleCI deploy filter ([#8972](https://github.com/RocketChat/Rocket.Chat/pull/8972))
-- Release/0.59.4 ([#8967](https://github.com/RocketChat/Rocket.Chat/pull/8967) by [@cpitman](https://github.com/cpitman))
-- Add CircleCI ([#8685](https://github.com/RocketChat/Rocket.Chat/pull/8685))
- Fix: users listed as online after API login ([#9111](https://github.com/RocketChat/Rocket.Chat/pull/9111))
- Fix regression in api channels.members ([#9110](https://github.com/RocketChat/Rocket.Chat/pull/9110))
- Fix: Clear all unreads modal not closing after confirming ([#9137](https://github.com/RocketChat/Rocket.Chat/pull/9137))
@@ -1845,17 +1572,13 @@
- [@AmShaegar13](https://github.com/AmShaegar13)
- [@Darkneon](https://github.com/Darkneon)
- [@HammyHavoc](https://github.com/HammyHavoc)
-- [@Kiran-Rao](https://github.com/Kiran-Rao)
-- [@Lawri-van-Buel](https://github.com/Lawri-van-Buel)
- [@Pharserror](https://github.com/Pharserror)
- [@RekkyRek](https://github.com/RekkyRek)
-- [@Rzeszow](https://github.com/Rzeszow)
- [@TheReal1604](https://github.com/TheReal1604)
- [@aditya19496](https://github.com/aditya19496)
- [@armand1m](https://github.com/armand1m)
- [@arungalva](https://github.com/arungalva)
- [@ashward](https://github.com/ashward)
-- [@astax-t](https://github.com/astax-t)
- [@ccfang](https://github.com/ccfang)
- [@cpitman](https://github.com/cpitman)
- [@cyclops24](https://github.com/cyclops24)
@@ -1868,11 +1591,9 @@
- [@icosamuel](https://github.com/icosamuel)
- [@jasonjyu](https://github.com/jasonjyu)
- [@joesitton](https://github.com/joesitton)
-- [@josiasds](https://github.com/josiasds)
- [@jotafeldmann](https://github.com/jotafeldmann)
- [@jwilkins](https://github.com/jwilkins)
- [@lindoelio](https://github.com/lindoelio)
-- [@luizbills](https://github.com/luizbills)
- [@mastappl](https://github.com/mastappl)
- [@mritunjaygoutam12](https://github.com/mritunjaygoutam12)
- [@paulovitin](https://github.com/paulovitin)
@@ -1881,8 +1602,6 @@
- [@ramrami](https://github.com/ramrami)
- [@rmetzler](https://github.com/rmetzler)
- [@robbyoconnor](https://github.com/robbyoconnor)
-- [@rodorgas](https://github.com/rodorgas)
-- [@ruKurz](https://github.com/ruKurz)
- [@ryoshimizu](https://github.com/ryoshimizu)
- [@sarbasamuel](https://github.com/sarbasamuel)
- [@satyapramodh](https://github.com/satyapramodh)
@@ -1890,11 +1609,9 @@
- [@selamanse](https://github.com/selamanse)
- [@stalley](https://github.com/stalley)
- [@stefanoverducci](https://github.com/stefanoverducci)
-- [@szluohua](https://github.com/szluohua)
- [@thompsonemerson](https://github.com/thompsonemerson)
- [@torgeirl](https://github.com/torgeirl)
- [@vcapretz](https://github.com/vcapretz)
-- [@vikaskedia](https://github.com/vikaskedia)
- [@vitor-nagao](https://github.com/vitor-nagao)
- [@wesnspace](https://github.com/wesnspace)
- [@wferris722](https://github.com/wferris722)
@@ -1912,10 +1629,8 @@
- [@marceloschmidt](https://github.com/marceloschmidt)
- [@mrsimpson](https://github.com/mrsimpson)
- [@pierreozoux](https://github.com/pierreozoux)
-- [@rafaelks](https://github.com/rafaelks)
- [@rodrigok](https://github.com/rodrigok)
- [@sampaiodiego](https://github.com/sampaiodiego)
-- [@xenithorb](https://github.com/xenithorb)
# 0.59.6
`2017-11-29 Β· 1 π Β· 1 π©βπ»π¨βπ»`
@@ -2068,7 +1783,7 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.59.0
-`2017-10-18 Β· 25 π Β· 131 π Β· 51 π Β· 46 π©βπ»π¨βπ»`
+`2017-10-18 Β· 24 π Β· 116 π Β· 50 π Β· 44 π©βπ»π¨βπ»`
### Engine versions
- Node: `4.8.4`
@@ -2093,7 +1808,6 @@
- Package to render issue numbers into links to an issue tracker. ([#6700](https://github.com/RocketChat/Rocket.Chat/pull/6700) by [@TAdeJong](https://github.com/TAdeJong) & [@TobiasKappe](https://github.com/TobiasKappe))
- Automatically select the first channel ([#7350](https://github.com/RocketChat/Rocket.Chat/pull/7350) by [@antaryami-sahoo](https://github.com/antaryami-sahoo))
- Rocket.Chat UI Redesign ([#7643](https://github.com/RocketChat/Rocket.Chat/pull/7643))
-- Add unread options for direct messages ([#7658](https://github.com/RocketChat/Rocket.Chat/pull/7658))
- Upgrade to meteor 1.5.2 ([#8073](https://github.com/RocketChat/Rocket.Chat/pull/8073))
- Enable read only channel creation ([#8260](https://github.com/RocketChat/Rocket.Chat/pull/8260))
- Add RD Station integration to livechat ([#8304](https://github.com/RocketChat/Rocket.Chat/pull/8304))
@@ -2104,12 +1818,6 @@
### π Bug fixes
-- Duplicate code in rest api letting in a few bugs with the rest api ([#8408](https://github.com/RocketChat/Rocket.Chat/pull/8408))
-- Slack import failing and not being able to be restarted ([#8390](https://github.com/RocketChat/Rocket.Chat/pull/8390))
-- Add needed dependency for snaps ([#8389](https://github.com/RocketChat/Rocket.Chat/pull/8389))
-- Duplicate code in rest api letting in a few bugs with the rest api ([#8408](https://github.com/RocketChat/Rocket.Chat/pull/8408))
-- Slack import failing and not being able to be restarted ([#8390](https://github.com/RocketChat/Rocket.Chat/pull/8390))
-- Add needed dependency for snaps ([#8389](https://github.com/RocketChat/Rocket.Chat/pull/8389))
- File upload on multi-instances using a path prefix ([#7855](https://github.com/RocketChat/Rocket.Chat/pull/7855) by [@Darkneon](https://github.com/Darkneon))
- Fix migration 100 ([#7863](https://github.com/RocketChat/Rocket.Chat/pull/7863))
- Email message forward error ([#7846](https://github.com/RocketChat/Rocket.Chat/pull/7846))
@@ -2125,16 +1833,10 @@
- Update Snap links ([#7778](https://github.com/RocketChat/Rocket.Chat/pull/7778) by [@MichaelGooden](https://github.com/MichaelGooden))
- Remove redundant "do" in "Are you sure ...?" messages. ([#7809](https://github.com/RocketChat/Rocket.Chat/pull/7809) by [@xurizaemon](https://github.com/xurizaemon))
- Fixed function closure syntax allowing validation emails to be sent. ([#7758](https://github.com/RocketChat/Rocket.Chat/pull/7758) by [@snoozan](https://github.com/snoozan))
-- Csv importer: work with more problematic data ([#7456](https://github.com/RocketChat/Rocket.Chat/pull/7456) by [@reist](https://github.com/reist))
- Fix avatar upload fail on Cordova app ([#7656](https://github.com/RocketChat/Rocket.Chat/pull/7656) by [@ccfang](https://github.com/ccfang))
- Make link inside YouTube preview open in new tab ([#7679](https://github.com/RocketChat/Rocket.Chat/pull/7679) by [@1lann](https://github.com/1lann))
- Remove references to non-existent tests ([#7672](https://github.com/RocketChat/Rocket.Chat/pull/7672) by [@Kiran-Rao](https://github.com/Kiran-Rao))
- Example usage of unsubscribe.js ([#7673](https://github.com/RocketChat/Rocket.Chat/pull/7673) by [@Kiran-Rao](https://github.com/Kiran-Rao))
-- Wrong email subject when "All Messages" setting enabled ([#7639](https://github.com/RocketChat/Rocket.Chat/pull/7639))
-- Markdown noopener/noreferrer: use correct HTML attribute ([#7644](https://github.com/RocketChat/Rocket.Chat/pull/7644) by [@jangmarker](https://github.com/jangmarker))
-- Fix room load on first hit ([#7687](https://github.com/RocketChat/Rocket.Chat/pull/7687))
-- Wrong render of snippetβs name ([#7630](https://github.com/RocketChat/Rocket.Chat/pull/7630))
-- Fix messagebox growth ([#7629](https://github.com/RocketChat/Rocket.Chat/pull/7629))
- sidebar paddings ([#7880](https://github.com/RocketChat/Rocket.Chat/pull/7880))
- Adds default search text padding for emoji search ([#7878](https://github.com/RocketChat/Rocket.Chat/pull/7878))
- search results position on sidebar ([#7881](https://github.com/RocketChat/Rocket.Chat/pull/7881))
@@ -2225,11 +1927,8 @@
- Various LDAP issues & Missing pagination ([#8372](https://github.com/RocketChat/Rocket.Chat/pull/8372))
- remove accountBox from admin menu ([#8358](https://github.com/RocketChat/Rocket.Chat/pull/8358))
- Missing i18n translations ([#8357](https://github.com/RocketChat/Rocket.Chat/pull/8357))
-- Add needed dependency for snaps ([#8389](https://github.com/RocketChat/Rocket.Chat/pull/8389))
-- Slack import failing and not being able to be restarted ([#8390](https://github.com/RocketChat/Rocket.Chat/pull/8390))
- Sidebar item menu position in RTL ([#8397](https://github.com/RocketChat/Rocket.Chat/pull/8397) by [@cyclops24](https://github.com/cyclops24))
- disabled katex tooltip on messageBox ([#8386](https://github.com/RocketChat/Rocket.Chat/pull/8386))
-- Duplicate code in rest api letting in a few bugs with the rest api ([#8408](https://github.com/RocketChat/Rocket.Chat/pull/8408))
- LDAP memory issues when pagination is not available ([#8457](https://github.com/RocketChat/Rocket.Chat/pull/8457))
- Uncessary route reload break some routes ([#8514](https://github.com/RocketChat/Rocket.Chat/pull/8514))
- Invalid Code message for password protected channel ([#8491](https://github.com/RocketChat/Rocket.Chat/pull/8491))
@@ -2257,7 +1956,6 @@
- [MOVE] Client folder rocketchat-highlight-words ([#7669](https://github.com/RocketChat/Rocket.Chat/pull/7669) by [@Kiran-Rao](https://github.com/Kiran-Rao))
- [MOVE] Client folder rocketchat-custom-sounds ([#7670](https://github.com/RocketChat/Rocket.Chat/pull/7670) by [@Kiran-Rao](https://github.com/Kiran-Rao))
- [MOVE] Client folder rocketchat-emoji ([#7671](https://github.com/RocketChat/Rocket.Chat/pull/7671) by [@Kiran-Rao](https://github.com/Kiran-Rao))
-- Only use "File Uploaded" prefix on files ([#7652](https://github.com/RocketChat/Rocket.Chat/pull/7652))
- Fix typo in generated URI ([#7661](https://github.com/RocketChat/Rocket.Chat/pull/7661) by [@Rohlik](https://github.com/Rohlik))
- Bump version to 0.59.0-develop ([#7625](https://github.com/RocketChat/Rocket.Chat/pull/7625))
- implemented new page-loader animated icon ([#2](https://github.com/RocketChat/Rocket.Chat/pull/2))
@@ -2314,7 +2012,6 @@
- [@cyclops24](https://github.com/cyclops24)
- [@danischreiber](https://github.com/danischreiber)
- [@goiaba](https://github.com/goiaba)
-- [@jangmarker](https://github.com/jangmarker)
- [@josiasds](https://github.com/josiasds)
- [@luizbills](https://github.com/luizbills)
- [@maarten-v](https://github.com/maarten-v)
@@ -2323,7 +2020,6 @@
- [@nishimaki10](https://github.com/nishimaki10)
- [@pkgodara](https://github.com/pkgodara)
- [@rdebeasi](https://github.com/rdebeasi)
-- [@reist](https://github.com/reist)
- [@ruKurz](https://github.com/ruKurz)
- [@snoozan](https://github.com/snoozan)
- [@szluohua](https://github.com/szluohua)
@@ -2346,23 +2042,12 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.58.4
-`2017-10-05 Β· 3 π Β· 2 π©βπ»π¨βπ»`
+`2017-10-05`
### Engine versions
- Node: `4.8.4`
- NPM: `4.6.1`
-### π Bug fixes
-
-- Duplicate code in rest api letting in a few bugs with the rest api ([#8408](https://github.com/RocketChat/Rocket.Chat/pull/8408))
-- Slack import failing and not being able to be restarted ([#8390](https://github.com/RocketChat/Rocket.Chat/pull/8390))
-- Add needed dependency for snaps ([#8389](https://github.com/RocketChat/Rocket.Chat/pull/8389))
-
-### π©βπ»π¨βπ» Core Team π€
-
-- [@geekgonecrazy](https://github.com/geekgonecrazy)
-- [@graywolf336](https://github.com/graywolf336)
-
# 0.58.2
`2017-08-22 Β· 1 π Β· 2 π©βπ»π¨βπ»`
@@ -2409,7 +2094,7 @@
- [@rodrigok](https://github.com/rodrigok)
# 0.58.0
-`2017-08-16 Β· 1 οΈοΈοΈβ οΈ Β· 27 π Β· 72 π Β· 22 π Β· 33 π©βπ»π¨βπ»`
+`2017-08-16 Β· 1 οΈοΈοΈβ οΈ Β· 26 π Β· 33 π Β· 18 π Β· 32 π©βπ»π¨βπ»`
### Engine versions
- Node: `4.8.4`
@@ -2445,31 +2130,11 @@
- Update meteor to 1.5.1 ([#7496](https://github.com/RocketChat/Rocket.Chat/pull/7496))
- flex-tab now is side by side with message list ([#7448](https://github.com/RocketChat/Rocket.Chat/pull/7448))
- Option to select unread count behavior ([#7477](https://github.com/RocketChat/Rocket.Chat/pull/7477))
-- Force use of MongoDB for spotlight queries ([#7311](https://github.com/RocketChat/Rocket.Chat/pull/7311))
- Add healthchecks in OpenShift templates ([#7184](https://github.com/RocketChat/Rocket.Chat/pull/7184) by [@jfchevrette](https://github.com/jfchevrette))
- Add unread options for direct messages ([#7658](https://github.com/RocketChat/Rocket.Chat/pull/7658))
### π Bug fixes
-- Modernize rate limiting of sendMessage ([#7325](https://github.com/RocketChat/Rocket.Chat/pull/7325) by [@jangmarker](https://github.com/jangmarker))
-- custom soundEdit.html ([#7390](https://github.com/RocketChat/Rocket.Chat/pull/7390) by [@rasos](https://github.com/rasos))
-- Use UTF8 setting for /create command ([#7394](https://github.com/RocketChat/Rocket.Chat/pull/7394))
-- file upload broken when running in subdirectory https://github.com⦠([#7395](https://github.com/RocketChat/Rocket.Chat/pull/7395) by [@ryoshimizu](https://github.com/ryoshimizu))
-- Fix Anonymous User ([#7444](https://github.com/RocketChat/Rocket.Chat/pull/7444))
-- Missing eventName in unUser ([#7533](https://github.com/RocketChat/Rocket.Chat/pull/7533) by [@Darkneon](https://github.com/Darkneon))
-- Fix Join Channel Without Preview Room Permission ([#7535](https://github.com/RocketChat/Rocket.Chat/pull/7535))
-- Improve build script example ([#7555](https://github.com/RocketChat/Rocket.Chat/pull/7555))
-- Slack import failing and not being able to be restarted ([#8390](https://github.com/RocketChat/Rocket.Chat/pull/8390))
-- Duplicate code in rest api letting in a few bugs with the rest api ([#8408](https://github.com/RocketChat/Rocket.Chat/pull/8408))
-- Add needed dependency for snaps ([#8389](https://github.com/RocketChat/Rocket.Chat/pull/8389))
-- Modernize rate limiting of sendMessage ([#7325](https://github.com/RocketChat/Rocket.Chat/pull/7325) by [@jangmarker](https://github.com/jangmarker))
-- custom soundEdit.html ([#7390](https://github.com/RocketChat/Rocket.Chat/pull/7390) by [@rasos](https://github.com/rasos))
-- Use UTF8 setting for /create command ([#7394](https://github.com/RocketChat/Rocket.Chat/pull/7394))
-- file upload broken when running in subdirectory https://github.com⦠([#7395](https://github.com/RocketChat/Rocket.Chat/pull/7395) by [@ryoshimizu](https://github.com/ryoshimizu))
-- Fix Anonymous User ([#7444](https://github.com/RocketChat/Rocket.Chat/pull/7444))
-- Missing eventName in unUser ([#7533](https://github.com/RocketChat/Rocket.Chat/pull/7533) by [@Darkneon](https://github.com/Darkneon))
-- Fix Join Channel Without Preview Room Permission ([#7535](https://github.com/RocketChat/Rocket.Chat/pull/7535))
-- Improve build script example ([#7555](https://github.com/RocketChat/Rocket.Chat/pull/7555))
- Error when updating message with an empty attachment array ([#7624](https://github.com/RocketChat/Rocket.Chat/pull/7624))
- Uploading an unknown file type erroring out ([#7623](https://github.com/RocketChat/Rocket.Chat/pull/7623))
- Error when acessing settings before ready ([#7622](https://github.com/RocketChat/Rocket.Chat/pull/7622))
@@ -2477,44 +2142,24 @@
- The username not being allowed to be passed into the user.setAvatar ([#7620](https://github.com/RocketChat/Rocket.Chat/pull/7620))
- Fix Custom Fields Crashing on Register ([#7617](https://github.com/RocketChat/Rocket.Chat/pull/7617))
- Fix admin room list show the correct i18n type ([#7582](https://github.com/RocketChat/Rocket.Chat/pull/7582) by [@ccfang](https://github.com/ccfang))
-- Missing eventName in unUser ([#7533](https://github.com/RocketChat/Rocket.Chat/pull/7533) by [@Darkneon](https://github.com/Darkneon))
- URL parse error fix for issue #7169 ([#7538](https://github.com/RocketChat/Rocket.Chat/pull/7538) by [@satyapramodh](https://github.com/satyapramodh))
- User avatar image background ([#7572](https://github.com/RocketChat/Rocket.Chat/pull/7572))
-- Improve build script example ([#7555](https://github.com/RocketChat/Rocket.Chat/pull/7555))
-- Fix Join Channel Without Preview Room Permission ([#7535](https://github.com/RocketChat/Rocket.Chat/pull/7535))
- Look for livechat visitor IP address on X-Forwarded-For header ([#7554](https://github.com/RocketChat/Rocket.Chat/pull/7554))
- Revert emojione package version upgrade ([#7557](https://github.com/RocketChat/Rocket.Chat/pull/7557))
- Stop logging mentions object to console ([#7562](https://github.com/RocketChat/Rocket.Chat/pull/7562))
- Fix hiding flex-tab on embedded view ([#7486](https://github.com/RocketChat/Rocket.Chat/pull/7486))
- Fix emoji picker translations ([#7195](https://github.com/RocketChat/Rocket.Chat/pull/7195))
-- Modernize rate limiting of sendMessage ([#7325](https://github.com/RocketChat/Rocket.Chat/pull/7325) by [@jangmarker](https://github.com/jangmarker))
-- custom soundEdit.html ([#7390](https://github.com/RocketChat/Rocket.Chat/pull/7390) by [@rasos](https://github.com/rasos))
-- Use UTF8 setting for /create command ([#7394](https://github.com/RocketChat/Rocket.Chat/pull/7394))
-- file upload broken when running in subdirectory https://github.com⦠([#7395](https://github.com/RocketChat/Rocket.Chat/pull/7395) by [@ryoshimizu](https://github.com/ryoshimizu))
-- Fix Anonymous User ([#7444](https://github.com/RocketChat/Rocket.Chat/pull/7444))
- Issue #7365: added check for the existence of a parameter in the CAS URL ([#7471](https://github.com/RocketChat/Rocket.Chat/pull/7471) by [@wsw70](https://github.com/wsw70))
- Fix Word Placement Anywhere on WebHooks ([#7392](https://github.com/RocketChat/Rocket.Chat/pull/7392))
- Prevent new room status from playing when user status changes ([#7487](https://github.com/RocketChat/Rocket.Chat/pull/7487))
-- S3 uploads not working for custom URLs ([#7443](https://github.com/RocketChat/Rocket.Chat/pull/7443))
-- Fix Private Channel List Submit ([#7432](https://github.com/RocketChat/Rocket.Chat/pull/7432))
-- Fix file upload on Slack import ([#7469](https://github.com/RocketChat/Rocket.Chat/pull/7469))
-- Fix Unread Bar Disappearing ([#7403](https://github.com/RocketChat/Rocket.Chat/pull/7403))
-- Always set LDAP properties on login ([#7472](https://github.com/RocketChat/Rocket.Chat/pull/7472))
- url click events in the cordova app open in external browser or not at all ([#7205](https://github.com/RocketChat/Rocket.Chat/pull/7205) by [@flaviogrossi](https://github.com/flaviogrossi))
-- Fix Emails in User Admin View ([#7431](https://github.com/RocketChat/Rocket.Chat/pull/7431))
-- Fix migration of avatars from version 0.57.0 ([#7428](https://github.com/RocketChat/Rocket.Chat/pull/7428))
- sweetalert alignment on mobile ([#7404](https://github.com/RocketChat/Rocket.Chat/pull/7404))
- Sweet-Alert modal popup position on mobile devices ([#7376](https://github.com/RocketChat/Rocket.Chat/pull/7376) by [@Oliver84](https://github.com/Oliver84))
- Update node-engine in Snap to latest v4 LTS relase: 4.8.3 ([#7355](https://github.com/RocketChat/Rocket.Chat/pull/7355) by [@al3x](https://github.com/al3x))
- Remove warning about 2FA support being unavailable in mobile apps ([#7354](https://github.com/RocketChat/Rocket.Chat/pull/7354) by [@al3x](https://github.com/al3x))
- Fix geolocation button ([#7322](https://github.com/RocketChat/Rocket.Chat/pull/7322))
- Fix Block Delete Message After (n) Minutes ([#7207](https://github.com/RocketChat/Rocket.Chat/pull/7207))
-- Fix jump to unread button ([#7320](https://github.com/RocketChat/Rocket.Chat/pull/7320))
-- Fix Secret Url ([#7321](https://github.com/RocketChat/Rocket.Chat/pull/7321))
- Use I18n on "File Uploaded" ([#7199](https://github.com/RocketChat/Rocket.Chat/pull/7199))
-- "requirePasswordChange" property not being saved when set to false ([#7209](https://github.com/RocketChat/Rocket.Chat/pull/7209))
-- Fix oembed previews not being shown ([#7208](https://github.com/RocketChat/Rocket.Chat/pull/7208))
-- Fix editing others messages ([#7200](https://github.com/RocketChat/Rocket.Chat/pull/7200))
- Fix error on image preview due to undefined description|title ([#7187](https://github.com/RocketChat/Rocket.Chat/pull/7187))
- Fix messagebox growth ([#7629](https://github.com/RocketChat/Rocket.Chat/pull/7629))
- Wrong render of snippetβs name ([#7630](https://github.com/RocketChat/Rocket.Chat/pull/7630))
@@ -2529,8 +2174,6 @@
- Release 0.58.0 ([#7752](https://github.com/RocketChat/Rocket.Chat/pull/7752) by [@flaviogrossi](https://github.com/flaviogrossi) & [@jangmarker](https://github.com/jangmarker) & [@ryoshimizu](https://github.com/ryoshimizu))
- Sync Master with 0.57.3 ([#7690](https://github.com/RocketChat/Rocket.Chat/pull/7690))
-- [Fix] Users and Channels list not respecting permissions ([#7212](https://github.com/RocketChat/Rocket.Chat/pull/7212))
-- [Fix] Users and Channels list not respecting permissions ([#7212](https://github.com/RocketChat/Rocket.Chat/pull/7212))
- Add missing parts of `one click to direct message` ([#7608](https://github.com/RocketChat/Rocket.Chat/pull/7608))
- LingoHub based on develop ([#7613](https://github.com/RocketChat/Rocket.Chat/pull/7613))
- Improve link parser using tokens ([#7615](https://github.com/RocketChat/Rocket.Chat/pull/7615))
@@ -2539,14 +2182,12 @@
- Improve room leader ([#7578](https://github.com/RocketChat/Rocket.Chat/pull/7578))
- Develop sync ([#7590](https://github.com/RocketChat/Rocket.Chat/pull/7590))
- [Fix] Don't save user to DB when a custom field is invalid ([#7513](https://github.com/RocketChat/Rocket.Chat/pull/7513) by [@Darkneon](https://github.com/Darkneon))
-- [Fix] Users and Channels list not respecting permissions ([#7212](https://github.com/RocketChat/Rocket.Chat/pull/7212))
- Develop sync ([#7500](https://github.com/RocketChat/Rocket.Chat/pull/7500) by [@thinkeridea](https://github.com/thinkeridea))
- Better Issue Template ([#7492](https://github.com/RocketChat/Rocket.Chat/pull/7492))
- Add helm chart kubernetes deployment ([#6340](https://github.com/RocketChat/Rocket.Chat/pull/6340))
- Develop sync ([#7363](https://github.com/RocketChat/Rocket.Chat/pull/7363))
- Escape error messages ([#7308](https://github.com/RocketChat/Rocket.Chat/pull/7308))
- update meteor to 1.5.0 ([#7287](https://github.com/RocketChat/Rocket.Chat/pull/7287))
-- Fix the Zapier oAuth return url to the new one ([#7215](https://github.com/RocketChat/Rocket.Chat/pull/7215))
- [New] Add instance id to response headers ([#7211](https://github.com/RocketChat/Rocket.Chat/pull/7211))
- Only use "File Uploaded" prefix on files ([#7652](https://github.com/RocketChat/Rocket.Chat/pull/7652))
@@ -2566,7 +2207,6 @@
- [@jangmarker](https://github.com/jangmarker)
- [@jfchevrette](https://github.com/jfchevrette)
- [@lindoelio](https://github.com/lindoelio)
-- [@rasos](https://github.com/rasos)
- [@reist](https://github.com/reist)
- [@ruKurz](https://github.com/ruKurz)
- [@ryoshimizu](https://github.com/ryoshimizu)
@@ -2686,7 +2326,7 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.57.0
-`2017-07-03 Β· 1 οΈοΈοΈβ οΈ Β· 12 π Β· 45 π Β· 31 π Β· 25 π©βπ»π¨βπ»`
+`2017-07-03 Β· 1 οΈοΈοΈβ οΈ Β· 10 π Β· 44 π Β· 30 π Β· 25 π©βπ»π¨βπ»`
### Engine versions
- Node: `4.8.2`
@@ -2706,8 +2346,6 @@
- postcss parser and cssnext implementation ([#6982](https://github.com/RocketChat/Rocket.Chat/pull/6982))
- Start running unit tests ([#6605](https://github.com/RocketChat/Rocket.Chat/pull/6605))
- Make channel/group delete call answer to roomName ([#6857](https://github.com/RocketChat/Rocket.Chat/pull/6857) by [@reist](https://github.com/reist))
-- Show info about multiple instances at admin page ([#6953](https://github.com/RocketChat/Rocket.Chat/pull/6953))
-- Improve CI/Docker build/release ([#6938](https://github.com/RocketChat/Rocket.Chat/pull/6938))
- Feature/delete any message permission ([#6919](https://github.com/RocketChat/Rocket.Chat/pull/6919) by [@phutchins](https://github.com/phutchins))
- Force use of MongoDB for spotlight queries ([#7311](https://github.com/RocketChat/Rocket.Chat/pull/7311))
@@ -2743,7 +2381,6 @@
- Fix login with Meteor saving an object as email address ([#6974](https://github.com/RocketChat/Rocket.Chat/pull/6974))
- Check that username is not in the room when being muted / unmuted ([#6840](https://github.com/RocketChat/Rocket.Chat/pull/6840) by [@matthewshirley](https://github.com/matthewshirley))
- Use AWS Signature Version 4 signed URLs for uploads ([#6947](https://github.com/RocketChat/Rocket.Chat/pull/6947))
-- make channels.create API check for create-c ([#6968](https://github.com/RocketChat/Rocket.Chat/pull/6968) by [@reist](https://github.com/reist))
- Bugs in `isUserFromParams` helper ([#6904](https://github.com/RocketChat/Rocket.Chat/pull/6904) by [@abrom](https://github.com/abrom))
- Allow image insert from slack through slackbridge ([#6910](https://github.com/RocketChat/Rocket.Chat/pull/6910))
- Slackbridge text replacements ([#6913](https://github.com/RocketChat/Rocket.Chat/pull/6913))
@@ -2785,7 +2422,6 @@
- LingoHub based on develop ([#6978](https://github.com/RocketChat/Rocket.Chat/pull/6978))
- fix the crashing tests ([#6976](https://github.com/RocketChat/Rocket.Chat/pull/6976))
- Convert WebRTC Package to Js ([#6775](https://github.com/RocketChat/Rocket.Chat/pull/6775))
-- [Fix] Error when trying to show preview of undefined filetype ([#6935](https://github.com/RocketChat/Rocket.Chat/pull/6935))
- Remove missing CoffeeScript dependencies ([#7154](https://github.com/RocketChat/Rocket.Chat/pull/7154))
- Switch logic of artifact name ([#7158](https://github.com/RocketChat/Rocket.Chat/pull/7158))
- Fix the Zapier oAuth return url to the new one ([#7215](https://github.com/RocketChat/Rocket.Chat/pull/7215))
@@ -2828,7 +2464,7 @@
- [@sampaiodiego](https://github.com/sampaiodiego)
# 0.56.0
-`2017-05-15 Β· 11 π Β· 21 π Β· 22 π Β· 19 π©βπ»π¨βπ»`
+`2017-05-15 Β· 11 π Β· 19 π Β· 19 π Β· 19 π©βπ»π¨βπ»`
### Engine versions
- Node: `4.8.2`
@@ -2864,8 +2500,6 @@
- CSV importer: require that there is some data in the zip, not ALL data ([#6768](https://github.com/RocketChat/Rocket.Chat/pull/6768) by [@reist](https://github.com/reist))
- Archiving Direct Messages ([#6737](https://github.com/RocketChat/Rocket.Chat/pull/6737))
- Fix Caddy by forcing go 1.7 as needed by one of caddy's dependencies ([#6721](https://github.com/RocketChat/Rocket.Chat/pull/6721))
-- emoji picker exception ([#6709](https://github.com/RocketChat/Rocket.Chat/pull/6709))
-- Fix message types ([#6704](https://github.com/RocketChat/Rocket.Chat/pull/6704))
- Users status on main menu always offline ([#6896](https://github.com/RocketChat/Rocket.Chat/pull/6896))
- Not showing unread count on electron appβs icon ([#6923](https://github.com/RocketChat/Rocket.Chat/pull/6923))
- Compile CSS color variables ([#6939](https://github.com/RocketChat/Rocket.Chat/pull/6939))
@@ -2875,7 +2509,6 @@
π Minor changes
-- [Fix] Bug with incoming integration (0.55.1) ([#6734](https://github.com/RocketChat/Rocket.Chat/pull/6734))
- [New] Snap arm support ([#6842](https://github.com/RocketChat/Rocket.Chat/pull/6842))
- Meteor update ([#6858](https://github.com/RocketChat/Rocket.Chat/pull/6858))
- Converted rocketchat-lib 3 ([#6672](https://github.com/RocketChat/Rocket.Chat/pull/6672))
@@ -2889,13 +2522,11 @@
- Anonymous use ([#5986](https://github.com/RocketChat/Rocket.Chat/pull/5986))
- Breaking long URLS to prevent overflow ([#6368](https://github.com/RocketChat/Rocket.Chat/pull/6368) by [@robertdown](https://github.com/robertdown))
- Rocketchat lib2 ([#6593](https://github.com/RocketChat/Rocket.Chat/pull/6593))
-- [Fix] Bug with incoming integration (0.55.1) ([#6734](https://github.com/RocketChat/Rocket.Chat/pull/6734))
- disable proxy configuration ([#6654](https://github.com/RocketChat/Rocket.Chat/pull/6654) by [@glehmann](https://github.com/glehmann))
- Convert markdown to js ([#6694](https://github.com/RocketChat/Rocket.Chat/pull/6694) by [@ehkasper](https://github.com/ehkasper))
- LingoHub based on develop ([#6715](https://github.com/RocketChat/Rocket.Chat/pull/6715))
- meteor update to 1.4.4 ([#6706](https://github.com/RocketChat/Rocket.Chat/pull/6706))
- LingoHub based on develop ([#6703](https://github.com/RocketChat/Rocket.Chat/pull/6703))
-- [Fix] Bug with incoming integration (0.55.1) ([#6734](https://github.com/RocketChat/Rocket.Chat/pull/6734))
- [Fix] Error when trying to show preview of undefined filetype ([#6935](https://github.com/RocketChat/Rocket.Chat/pull/6935))
diff --git a/package.json b/package.json
index 1d369b2de64f..31bc481fef09 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "Rocket.Chat",
"description": "The Ultimate Open Source WebChat Platform",
- "version": "0.67.0-develop",
+ "version": "0.67.0-rc.0",
"author": {
"name": "Rocket.Chat",
"url": "https://rocket.chat/"
diff --git a/packages/rocketchat-lib/rocketchat.info b/packages/rocketchat-lib/rocketchat.info
index 301d768313e5..fc3b8e95a94b 100644
--- a/packages/rocketchat-lib/rocketchat.info
+++ b/packages/rocketchat-lib/rocketchat.info
@@ -1,3 +1,3 @@
{
- "version": "0.67.0-develop"
+ "version": "0.67.0-rc.0"
}
From f0cddcb5db480044c11227ed1dbd626d300af56a Mon Sep 17 00:00:00 2001
From: Diego Sampaio
Date: Fri, 20 Jul 2018 17:00:38 -0300
Subject: [PATCH 28/28] Bump version to 0.67.0
---
.docker/Dockerfile.rhel | 2 +-
.github/history.json | 21 ++++++++++++++++-----
.sandstorm/sandstorm-pkgdef.capnp | 4 ++--
.travis/snap.sh | 2 +-
HISTORY.md | 9 ++++++---
package.json | 2 +-
packages/rocketchat-lib/rocketchat.info | 2 +-
7 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel
index 392806ab6362..a7002cc1f4d9 100644
--- a/.docker/Dockerfile.rhel
+++ b/.docker/Dockerfile.rhel
@@ -1,6 +1,6 @@
FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7
-ENV RC_VERSION 0.67.0-rc.0
+ENV RC_VERSION 0.67.0
MAINTAINER buildmaster@rocket.chat
diff --git a/.github/history.json b/.github/history.json
index 5ece26294f30..493924bf99a6 100644
--- a/.github/history.json
+++ b/.github/history.json
@@ -16950,7 +16950,6 @@
"pr": "11319",
"title": "[FIX] SVG icons code",
"userLogin": "tassoevan",
- "milestone": "0.67.0",
"contributors": [
"tassoevan"
]
@@ -16987,7 +16986,6 @@
"pr": "11313",
"title": "[FIX] Message popup responsiveness in slash commands",
"userLogin": "tassoevan",
- "milestone": "0.67.0",
"contributors": [
"tassoevan"
]
@@ -16996,7 +16994,7 @@
"pr": "9991",
"title": "[FIX] web app manifest errors as reported by Chrome DevTools",
"userLogin": "justinribeiro",
- "milestone": "0.67.0",
+ "milestone": "0.68.0",
"contributors": [
"justinribeiro",
"web-flow"
@@ -17006,7 +17004,6 @@
"pr": "11342",
"title": "[FIX] Message attachment's fields with different sizes",
"userLogin": "sampaiodiego",
- "milestone": "0.67.0",
"contributors": [
"sampaiodiego"
]
@@ -17023,7 +17020,7 @@
"pr": "9754",
"title": "[FIX] Parse inline code without space before initial backtick",
"userLogin": "c0dzilla",
- "milestone": "0.67.0",
+ "milestone": "0.68.0",
"contributors": [
"c0dzilla",
"gdelavald",
@@ -17112,6 +17109,20 @@
]
}
]
+ },
+ "0.67.0": {
+ "node_version": "8.11.3",
+ "npm_version": "5.6.0",
+ "pull_requests": [
+ {
+ "pr": "11497",
+ "title": "Fix dependency issue in redhat image",
+ "userLogin": "geekgonecrazy",
+ "contributors": [
+ "geekgonecrazy"
+ ]
+ }
+ ]
}
}
}
\ No newline at end of file
diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp
index 5706e2fade13..e3a94c300b53 100644
--- a/.sandstorm/sandstorm-pkgdef.capnp
+++ b/.sandstorm/sandstorm-pkgdef.capnp
@@ -19,9 +19,9 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Rocket.Chat"),
- appVersion = 82, # Increment this for every release.
+ appVersion = 83, # Increment this for every release.
- appMarketingVersion = (defaultText = "0.67.0-rc.0"),
+ appMarketingVersion = (defaultText = "0.67.0"),
# Human-readable representation of appVersion. Should match the way you
# identify versions of your app in documentation and marketing.
diff --git a/.travis/snap.sh b/.travis/snap.sh
index e035853870a9..a8e2b3c3e19a 100755
--- a/.travis/snap.sh
+++ b/.travis/snap.sh
@@ -17,7 +17,7 @@ elif [[ $TRAVIS_TAG ]]; then
RC_VERSION=$TRAVIS_TAG
else
CHANNEL=edge
- RC_VERSION=0.67.0-rc.0
+ RC_VERSION=0.67.0
fi
echo "Preparing to trigger a snap release for $CHANNEL channel"
diff --git a/HISTORY.md b/HISTORY.md
index 7a46a946e4a7..c1d1c8b16a3a 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,8 +1,10 @@
-# 0.67.0 (Under Release Candidate Process)
+# 0.67.0
+`2018-07-20 Β· 1 οΈοΈοΈβ οΈ Β· 1 π Β· 1 π Β· 6 π Β· 5 π Β· 11 π©βπ»π¨βπ»`
-## 0.67.0-rc.0
-`2018-07-10 Β· 1 οΈοΈοΈβ οΈ Β· 1 π Β· 1 π Β· 6 π Β· 4 π Β· 11 π©βπ»π¨βπ»`
+### Engine versions
+- Node: `8.11.3`
+- NPM: `5.6.0`
### β οΈ BREAKING CHANGES
@@ -28,6 +30,7 @@
π Minor changes
+- Fix dependency issue in redhat image ([#11497](https://github.com/RocketChat/Rocket.Chat/pull/11497))
- Merge master into develop & Set version to 0.67.0-develop ([#11417](https://github.com/RocketChat/Rocket.Chat/pull/11417))
- Merge master into develop & Set version to 0.67.0-develop ([#11399](https://github.com/RocketChat/Rocket.Chat/pull/11399))
- Merge master into develop & Set version to 0.67.0-develop ([#11348](https://github.com/RocketChat/Rocket.Chat/pull/11348))
diff --git a/package.json b/package.json
index 31bc481fef09..512a6fc1962b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "Rocket.Chat",
"description": "The Ultimate Open Source WebChat Platform",
- "version": "0.67.0-rc.0",
+ "version": "0.67.0",
"author": {
"name": "Rocket.Chat",
"url": "https://rocket.chat/"
diff --git a/packages/rocketchat-lib/rocketchat.info b/packages/rocketchat-lib/rocketchat.info
index fc3b8e95a94b..010f28401586 100644
--- a/packages/rocketchat-lib/rocketchat.info
+++ b/packages/rocketchat-lib/rocketchat.info
@@ -1,3 +1,3 @@
{
- "version": "0.67.0-rc.0"
+ "version": "0.67.0"
}
|