diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel
index e0084ee1a1b6..87cd8371574b 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 3.1.0
+ENV RC_VERSION 3.1.1
MAINTAINER buildmaster@rocket.chat
diff --git a/.github/history.json b/.github/history.json
index a77a23b8ba67..0a3e4abf62ba 100644
--- a/.github/history.json
+++ b/.github/history.json
@@ -42397,6 +42397,101 @@
]
}
]
+ },
+ "3.1.1": {
+ "node_version": "12.16.1",
+ "npm_version": "6.13.4",
+ "mongo_versions": [
+ "3.4",
+ "3.6",
+ "4.0"
+ ],
+ "pull_requests": [
+ {
+ "pr": "17278",
+ "title": "[FIX] SAML assertion signature enforcement",
+ "userLogin": "pierre-lehnen-rc",
+ "milestone": "3.1.1",
+ "contributors": [
+ "pierre-lehnen-rc",
+ "sampaiodiego"
+ ]
+ },
+ {
+ "pr": "17299",
+ "title": "[FIX] User search on directory not working correctly",
+ "userLogin": "rodrigok",
+ "milestone": "3.1.1",
+ "contributors": [
+ "rodrigok"
+ ]
+ },
+ {
+ "pr": "17275",
+ "title": "[FIX] 404 error when clicking an username",
+ "userLogin": "pierre-lehnen-rc",
+ "milestone": "3.1.1",
+ "contributors": [
+ "pierre-lehnen-rc"
+ ]
+ },
+ {
+ "pr": "17287",
+ "title": "Update Apps-Engine to stable version",
+ "userLogin": "d-gubert",
+ "milestone": "3.1.1",
+ "contributors": [
+ "d-gubert"
+ ]
+ },
+ {
+ "pr": "17286",
+ "title": "[FIX] Avatar on sidebar when showing real names",
+ "userLogin": "ggazzo",
+ "milestone": "3.1.1",
+ "contributors": [
+ "ggazzo"
+ ]
+ },
+ {
+ "pr": "17283",
+ "title": "[FIX] Directory default tab",
+ "userLogin": "ggazzo",
+ "milestone": "3.1.1",
+ "contributors": [
+ "ggazzo"
+ ]
+ },
+ {
+ "pr": "17282",
+ "title": "[FIX] Discussions created from inside DMs were not working and some errors accessing recently created rooms",
+ "userLogin": "rodrigok",
+ "milestone": "3.1.1",
+ "contributors": [
+ "rodrigok",
+ "sampaiodiego"
+ ]
+ },
+ {
+ "pr": "17288",
+ "title": " [FIX] Omnichannel SMS / WhatsApp integration errors due to missing location data",
+ "userLogin": "renatobecker",
+ "milestone": "3.1.1",
+ "contributors": [
+ "renatobecker",
+ "web-flow"
+ ]
+ },
+ {
+ "pr": "17302",
+ "title": "[FIX] LDAP users lose session on refresh",
+ "userLogin": "pierre-lehnen-rc",
+ "milestone": "3.1.1",
+ "contributors": [
+ "pierre-lehnen-rc"
+ ]
+ }
+ ]
}
}
}
\ No newline at end of file
diff --git a/HISTORY.md b/HISTORY.md
index 81183dfee7ec..16782fa4ff99 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,4 +1,48 @@
+# 3.1.1
+`2020-04-14 ยท 8 ๐ ยท 1 ๐ ยท 6 ๐ฉโ๐ป๐จโ๐ป`
+
+### Engine versions
+- Node: `12.16.1`
+- NPM: `6.13.4`
+- MongoDB: `3.4, 3.6, 4.0`
+
+### ๐ Bug fixes
+
+
+- SAML assertion signature enforcement ([#17278](https://github.com/RocketChat/Rocket.Chat/pull/17278))
+
+- User search on directory not working correctly ([#17299](https://github.com/RocketChat/Rocket.Chat/pull/17299))
+
+- 404 error when clicking an username ([#17275](https://github.com/RocketChat/Rocket.Chat/pull/17275))
+
+- Avatar on sidebar when showing real names ([#17286](https://github.com/RocketChat/Rocket.Chat/pull/17286))
+
+- Directory default tab ([#17283](https://github.com/RocketChat/Rocket.Chat/pull/17283))
+
+- Discussions created from inside DMs were not working and some errors accessing recently created rooms ([#17282](https://github.com/RocketChat/Rocket.Chat/pull/17282))
+
+- Omnichannel SMS / WhatsApp integration errors due to missing location data ([#17288](https://github.com/RocketChat/Rocket.Chat/pull/17288))
+
+- LDAP users lose session on refresh ([#17302](https://github.com/RocketChat/Rocket.Chat/pull/17302))
+
+
+๐ Minor changes
+
+
+- Update Apps-Engine to stable version ([#17287](https://github.com/RocketChat/Rocket.Chat/pull/17287))
+
+
+
+### ๐ฉโ๐ป๐จโ๐ป Core Team ๐ค
+
+- [@d-gubert](https://github.com/d-gubert)
+- [@ggazzo](https://github.com/ggazzo)
+- [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc)
+- [@renatobecker](https://github.com/renatobecker)
+- [@rodrigok](https://github.com/rodrigok)
+- [@sampaiodiego](https://github.com/sampaiodiego)
+
# 3.1.0
`2020-04-09 ยท 23 ๐ ยท 22 ๐ ยท 71 ๐ ยท 86 ๐ ยท 41 ๐ฉโ๐ป๐จโ๐ป`
diff --git a/app/discussion/server/methods/createDiscussion.js b/app/discussion/server/methods/createDiscussion.js
index b15a057adedb..e4287b86a45e 100644
--- a/app/discussion/server/methods/createDiscussion.js
+++ b/app/discussion/server/methods/createDiscussion.js
@@ -5,6 +5,7 @@ import { hasAtLeastOnePermission, canAccessRoom } from '../../../authorization/s
import { Messages, Rooms } from '../../../models/server';
import { createRoom, addUserToRoom, sendMessage, attachMessage } from '../../../lib/server';
import { settings } from '../../../settings/server';
+import { roomTypes } from '../../../utils/server';
const getParentRoom = (rid) => {
const room = Rooms.findOne(rid);
@@ -86,7 +87,8 @@ const create = ({ prid, pmid, t_name, reply, users }) => {
// auto invite the replied message owner
const invitedUsers = message ? [message.u.username, ...users] : users;
- const discussion = createRoom(p_room.t, name, user.username, [...new Set(invitedUsers)], false, {
+ const type = roomTypes.getConfig(p_room.t).getDiscussionType();
+ const discussion = createRoom(type, name, user.username, [...new Set(invitedUsers)], false, {
fname: t_name,
description: message.msg, // TODO discussions remove
topic: p_room.name, // TODO discussions remove
diff --git a/app/ldap/server/loginHandler.js b/app/ldap/server/loginHandler.js
index c563ea950c99..f4c3901c16ca 100644
--- a/app/ldap/server/loginHandler.js
+++ b/app/ldap/server/loginHandler.js
@@ -158,7 +158,7 @@ callbacks.add('beforeValidateLogin', (login) => {
return login;
}
- if (login.type === 'ldap') {
+ if (login.type === 'ldap' || login.type === 'resume') {
return login;
}
diff --git a/app/lib/lib/roomTypes/direct.js b/app/lib/lib/roomTypes/direct.js
index 1a36927ba561..28295be6bcde 100644
--- a/app/lib/lib/roomTypes/direct.js
+++ b/app/lib/lib/roomTypes/direct.js
@@ -186,16 +186,23 @@ export class DirectMessageRoomType extends RoomTypeConfig {
}
getAvatarPath(roomData, subData) {
+ if (!roomData && !subData) {
+ return '';
+ }
+
if (this.isGroupChat(roomData)) {
return getAvatarURL({ username: roomData.uids.length + roomData.usernames.join() });
}
- if (roomData) {
- return getUserAvatarURL(roomData.name || this.roomName(roomData));
+ const sub = subData || Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1 } });
+
+ if (sub && sub.name) {
+ return getUserAvatarURL(sub.name);
}
- const sub = subData || Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1 } });
- return getUserAvatarURL(sub.name || this.roomName(roomData));
+ if (roomData) {
+ return getUserAvatarURL(roomData.name || this.roomName(roomData)); // rooms should have no name for direct messages...
+ }
}
includeInDashboard() {
diff --git a/app/lib/lib/roomTypes/public.js b/app/lib/lib/roomTypes/public.js
index 11d688731eff..8732e6d13d9c 100644
--- a/app/lib/lib/roomTypes/public.js
+++ b/app/lib/lib/roomTypes/public.js
@@ -133,4 +133,8 @@ export class PublicRoomType extends RoomTypeConfig {
return getAvatarURL({ username: `@${ this.roomName(roomData) }` });
}
+
+ getDiscussionType() {
+ return 'c';
+ }
}
diff --git a/app/lib/server/startup/settings.js b/app/lib/server/startup/settings.js
index f067b03c12b3..33bf91e477af 100644
--- a/app/lib/server/startup/settings.js
+++ b/app/lib/server/startup/settings.js
@@ -97,9 +97,8 @@ settings.addGroup('Accounts', function() {
type: 'boolean',
public: true,
});
- this.add('Accounts_SearchFields', '', {
+ this.add('Accounts_SearchFields', 'username, name, bio', {
type: 'string',
- public: true,
});
this.add('Accounts_Directory_DefaultView', 'channels', {
type: 'select',
diff --git a/app/livechat/imports/server/rest/sms.js b/app/livechat/imports/server/rest/sms.js
index 5f600a0de73c..edebecb583a7 100644
--- a/app/livechat/imports/server/rest/sms.js
+++ b/app/livechat/imports/server/rest/sms.js
@@ -40,7 +40,7 @@ const defineVisitor = (smsNumber) => {
};
const normalizeLocationSharing = (payload) => {
- const { extra: { fromLatitude: latitude, fromLongitude: longitude } } = payload;
+ const { extra: { fromLatitude: latitude, fromLongitude: longitude } = { } } = payload;
if (!latitude || !longitude) {
return;
}
diff --git a/app/meteor-accounts-saml/server/saml_rocketchat.js b/app/meteor-accounts-saml/server/saml_rocketchat.js
index c64e00ef5919..b8c788399527 100644
--- a/app/meteor-accounts-saml/server/saml_rocketchat.js
+++ b/app/meteor-accounts-saml/server/saml_rocketchat.js
@@ -62,6 +62,19 @@ Meteor.methods({
multiline: true,
i18nLabel: 'SAML_Custom_Public_Cert',
});
+ settings.add(`SAML_Custom_${ name }_signature_validation_type`, 'All', {
+ type: 'select',
+ values: [
+ { key: 'Response', i18nLabel: 'SAML_Custom_signature_validation_response' },
+ { key: 'Assertion', i18nLabel: 'SAML_Custom_signature_validation_assertion' },
+ { key: 'Either', i18nLabel: 'SAML_Custom_signature_validation_either' },
+ { key: 'All', i18nLabel: 'SAML_Custom_signature_validation_all' },
+ ],
+ group: 'SAML',
+ section: name,
+ i18nLabel: 'SAML_Custom_signature_validation_type',
+ i18nDescription: 'SAML_Custom_signature_validation_type_description',
+ });
settings.add(`SAML_Custom_${ name }_private_key`, '', {
type: 'string',
group: 'SAML',
@@ -238,6 +251,7 @@ const getSamlConfigs = function(service) {
// People often overlook the instruction to remove the header and footer of the certificate on this specific setting, so let's do it for them.
cert: normalizeCert(settings.get(`${ service.key }_cert`)),
},
+ signatureValidationType: settings.get(`${ service.key }_signature_validation_type`),
userDataFieldMap: settings.get(`${ service.key }_user_data_fieldmap`),
allowedClockDrift: settings.get(`${ service.key }_allowed_clock_drift`),
};
@@ -290,6 +304,7 @@ const configureSamlService = function(samlConfigs) {
roleAttributeName: samlConfigs.roleAttributeName,
roleAttributeSync: samlConfigs.roleAttributeSync,
allowedClockDrift: samlConfigs.allowedClockDrift,
+ signatureValidationType: samlConfigs.signatureValidationType,
};
};
diff --git a/app/meteor-accounts-saml/server/saml_utils.js b/app/meteor-accounts-saml/server/saml_utils.js
index 5c68621d281b..532af1f00fa4 100644
--- a/app/meteor-accounts-saml/server/saml_utils.js
+++ b/app/meteor-accounts-saml/server/saml_utils.js
@@ -347,6 +347,10 @@ SAML.prototype.validateSignatureChildren = function(xml, cert, parent) {
signature = sign;
}
+ if (!signature) {
+ return false;
+ }
+
return this.validateSignature(xml, cert, signature);
};
@@ -564,19 +568,43 @@ SAML.prototype.verifySignatures = function(response, assertion, xml) {
return;
}
- debugLog('Verify Document Signature');
- if (!this.validateResponseSignature(xml, this.options.cert, response)) {
- debugLog('Document Signature WRONG');
- throw new Error('Invalid Signature');
+ const signatureType = this.options.signatureValidationType;
+
+ const checkEither = signatureType === 'Either';
+ const checkResponse = signatureType === 'Response' || signatureType === 'All' || checkEither;
+ const checkAssertion = signatureType === 'Assertion' || signatureType === 'All' || checkEither;
+ let anyValidSignature = false;
+
+ if (checkResponse) {
+ debugLog('Verify Document Signature');
+ if (!this.validateResponseSignature(xml, this.options.cert, response)) {
+ if (!checkEither) {
+ debugLog('Document Signature WRONG');
+ throw new Error('Invalid Signature');
+ }
+ } else {
+ anyValidSignature = true;
+ }
+ debugLog('Document Signature OK');
+ }
+
+ if (checkAssertion) {
+ debugLog('Verify Assertion Signature');
+ if (!this.validateAssertionSignature(xml, this.options.cert, assertion)) {
+ if (!checkEither) {
+ debugLog('Assertion Signature WRONG');
+ throw new Error('Invalid Assertion signature');
+ }
+ } else {
+ anyValidSignature = true;
+ }
+ debugLog('Assertion Signature OK');
}
- debugLog('Document Signature OK');
- debugLog('Verify Assertion Signature');
- if (!this.validateAssertionSignature(xml, this.options.cert, assertion)) {
- debugLog('Assertion Signature WRONG');
- throw new Error('Invalid Assertion signature');
+ if (checkEither && !anyValidSignature) {
+ debugLog('No Valid Signature');
+ throw new Error('No valid SAML Signature found');
}
- debugLog('Assertion Signature OK');
};
SAML.prototype.getSubject = function(assertion) {
diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js
index 6930ec7a2b3a..d3139dc097f9 100644
--- a/app/models/server/models/Users.js
+++ b/app/models/server/models/Users.js
@@ -30,7 +30,7 @@ export class Users extends Base {
this.tryEnsureIndex({ roles: 1 }, { sparse: 1 });
this.tryEnsureIndex({ name: 1 });
- this.tryEnsureIndex({ name: 'text', username: 'text', bio: 'text' }, { default_language: 'none', language_override: 'documentLanguage' });
+ this.tryEnsureIndex({ bio: 1 });
this.tryEnsureIndex({ createdAt: 1 });
this.tryEnsureIndex({ lastLogin: 1 });
this.tryEnsureIndex({ status: 1 });
@@ -641,10 +641,7 @@ export class Users extends Base {
const searchFields = forcedSearchFields || settings.get('Accounts_SearchFields').trim().split(',');
const orStmt = _.reduce(searchFields, function(acc, el) {
- el = el.trim();
- if (el && !['name', 'username', 'bio'].includes(el)) {
- acc.push({ [el]: termRegex });
- }
+ acc.push({ [el.trim()]: termRegex });
return acc;
}, []);
@@ -652,10 +649,8 @@ export class Users extends Base {
$and: [
{
active: true,
- $or: [{
- $text: { $search: searchTerm },
- }, ...orStmt],
username: { $exists: true, $nin: exceptions },
+ $or: orStmt,
},
...extraQuery,
],
diff --git a/app/ui/client/views/app/components/Directory/DirectoryTable.js b/app/ui/client/views/app/components/Directory/DirectoryTable.js
index 09925c92e407..96c73164102c 100644
--- a/app/ui/client/views/app/components/Directory/DirectoryTable.js
+++ b/app/ui/client/views/app/components/Directory/DirectoryTable.js
@@ -27,23 +27,23 @@ export function Markdown({ children, ...props }) {
const LoadingRow = ({ cols }) =>
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
{ Array.from({ length: cols - 1 }, (_, i) =>
)}
;
+const style = { minHeight: '40px' };
+
export function DirectoryTable({
data = {},
renderRow,
@@ -79,7 +79,7 @@ export function DirectoryTable({
return <>
-
+
} onChange={handleChange} value={text} />
{channels && !channels.length
diff --git a/app/ui/client/views/app/components/Directory/index.js b/app/ui/client/views/app/components/Directory/index.js
index 5d56e61265a5..fa19dd1834fd 100644
--- a/app/ui/client/views/app/components/Directory/index.js
+++ b/app/ui/client/views/app/components/Directory/index.js
@@ -13,6 +13,8 @@ const avatarBase = { baseUrl: '/avatar/' };
export function DirectoryPage() {
const t = useTranslation();
+ const defaultTab = useSetting('Accounts_Directory_DefaultView');
+
const federationEnabled = useSetting('FEDERATION_Enabled');
const tab = useRouteParameter('tab');
@@ -22,13 +24,13 @@ export function DirectoryPage() {
useEffect(() => {
if (!tab || (tab === 'external' && !federationEnabled)) {
- return goToDirectory.replacingState({ tab: 'channels' });
+ return goToDirectory.replacingState({ tab: defaultTab });
}
- }, [tab, federationEnabled]);
+ }, [tab, federationEnabled, defaultTab]);
return
-
+
{t('Channels')}
{t('Users')}
{ federationEnabled && {t('External_Users')} }
diff --git a/app/ui/client/views/app/room.js b/app/ui/client/views/app/room.js
index 188132a18ccf..8ea44dd8d5d1 100644
--- a/app/ui/client/views/app/room.js
+++ b/app/ui/client/views/app/room.js
@@ -83,7 +83,7 @@ const openProfileTabOrOpenDM = (e, instance, username) => {
}
if (result && result.rid) {
- FlowRouter.go('direct', { username }, FlowRouter.current().queryParams);
+ FlowRouter.go('direct', { rid: result.rid }, FlowRouter.current().queryParams);
}
});
} else {
diff --git a/app/utils/lib/RoomTypeConfig.js b/app/utils/lib/RoomTypeConfig.js
index da578a82402e..bc40944c6b3a 100644
--- a/app/utils/lib/RoomTypeConfig.js
+++ b/app/utils/lib/RoomTypeConfig.js
@@ -299,4 +299,8 @@ export class RoomTypeConfig {
openCustomProfileTab() {
return false;
}
+
+ getDiscussionType() {
+ return 'p';
+ }
}
diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info
index 8d691dd7f54b..67bc530e7a14 100644
--- a/app/utils/rocketchat.info
+++ b/app/utils/rocketchat.info
@@ -1,3 +1,3 @@
{
- "version": "3.1.0"
+ "version": "3.1.1"
}
diff --git a/package-lock.json b/package-lock.json
index 54b8e0fd8dae..de56102c8bf1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2849,9 +2849,9 @@
}
},
"@rocket.chat/apps-engine": {
- "version": "1.13.0-beta.3003",
- "resolved": "https://registry.npmjs.org/@rocket.chat/apps-engine/-/apps-engine-1.13.0-beta.3003.tgz",
- "integrity": "sha512-RGegax9zaDzQta7U1v05JYUgJUhrGlYBYioMdCJRvKs6NrmJNbpdeJ6A0Bu6pNKF9ppMkG17hfxI6xT0MoSd0w==",
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/@rocket.chat/apps-engine/-/apps-engine-1.13.0.tgz",
+ "integrity": "sha512-gU72qk3xhk5UYGmgsp4VLnOOYeAcsc4O8K2rYiLfs1EpBA1tNY+/YtR6Crl5usdU7sRSHUq4Y86pAchepT6aJQ==",
"requires": {
"adm-zip": "^0.4.9",
"cryptiles": "^4.1.3",
diff --git a/package.json b/package.json
index 390186fce3fa..508a8cd18525 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "Rocket.Chat",
"description": "The Ultimate Open Source WebChat Platform",
- "version": "3.1.0",
+ "version": "3.1.1",
"author": {
"name": "Rocket.Chat",
"url": "https://rocket.chat/"
@@ -128,7 +128,7 @@
"@nivo/heatmap": "^0.61.0",
"@nivo/line": "^0.61.1",
"@nivo/pie": "^0.61.1",
- "@rocket.chat/apps-engine": "^1.13.0-beta.3003",
+ "@rocket.chat/apps-engine": "^1.13.0",
"@rocket.chat/fuselage": "^0.7.1",
"@rocket.chat/fuselage-hooks": "^0.7.1",
"@rocket.chat/fuselage-polyfills": "^0.7.1",
diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json
index bef4385c60a0..22e2b31e14be 100644
--- a/packages/rocketchat-i18n/i18n/en.i18n.json
+++ b/packages/rocketchat-i18n/i18n/en.i18n.json
@@ -2930,6 +2930,12 @@
"SAML_Custom_Private_Key": "Private Key Contents",
"SAML_Custom_Provider": "Custom Provider",
"SAML_Custom_EMail_Field": "E-Mail field name",
+ "SAML_Custom_signature_validation_all": "Validate All Signatures",
+ "SAML_Custom_signature_validation_assertion": "Validate Assertion Signature",
+ "SAML_Custom_signature_validation_either": "Validate Either Signature",
+ "SAML_Custom_signature_validation_response": "Validate Response Signature",
+ "SAML_Custom_signature_validation_type": "Signature Validation Type",
+ "SAML_Custom_signature_validation_type_description": "This setting will be ignored if not Custom Certificate is provided.",
"SAML_Custom_user_data_fieldmap": "User Data Field Map",
"SAML_Custom_user_data_fieldmap_description": "Configure how user account fields (like email) are populated from a record in SAML (once found).
As an example, `{\"cn\":\"name\", \"mail\":\"email\"}` will choose a person's human readable name from the cn attribute, and their email from the mail attribute.
Available fields in Rocket.Chat: `name`, `email` and `username`, everything else will be saved as `customFields`.
You can also use a regex to get the field value, like this: `{\"NameID\": { \"field\": \"username\", \"regex\": \"(.*)@.+$\"}, \"email\": \"email\"}`",
"SAML_Custom_Username_Field": "Username field name",
diff --git a/server/startup/migrations/index.js b/server/startup/migrations/index.js
index 60ee4afe9979..1085c8ea77df 100644
--- a/server/startup/migrations/index.js
+++ b/server/startup/migrations/index.js
@@ -180,4 +180,6 @@ import './v179';
import './v180';
import './v181';
import './v182';
+import './v183';
+import './v184';
import './xrun';
diff --git a/server/startup/migrations/v183.js b/server/startup/migrations/v183.js
new file mode 100644
index 000000000000..df71bd061730
--- /dev/null
+++ b/server/startup/migrations/v183.js
@@ -0,0 +1,105 @@
+import { Random } from 'meteor/random';
+
+import { Migrations } from '../../../app/migrations';
+import { Rooms, Messages, Subscriptions, Uploads, Settings, Users } from '../../../app/models/server';
+
+const unifyRooms = (room) => {
+ // verify if other DM already exists
+ const other = Rooms.findOne({
+ _id: { $ne: room._id },
+ t: 'd',
+ uids: room.uids,
+ });
+
+ // we need to at least change the _id of the current room, so remove it
+ Rooms.remove({ _id: room._id });
+
+ const newId = (other && other._id) || Random.id();
+
+ if (!other) {
+ // create the same room with different _id
+ Rooms.insert({
+ ...room,
+ _id: newId,
+ });
+
+ // update subscription to point to new room _id
+ Subscriptions.update({ rid: room._id }, {
+ $set: {
+ rid: newId,
+ },
+ }, { multi: true });
+
+ return newId;
+ }
+
+ // the other room exists already, so just remove the subscription of the wrong room
+ Subscriptions.remove({ rid: room._id });
+
+ return newId;
+};
+
+const fixSelfDMs = () => {
+ Rooms.find({
+ t: 'd',
+ uids: { $size: 1 },
+ }).forEach((room) => {
+ if (!Array.isArray(room.uids) || room._id !== room.uids[0]) {
+ return;
+ }
+
+ const correctId = unifyRooms(room);
+
+ // move things to correct room
+ Messages.update({ rid: room._id }, {
+ $set: {
+ rid: correctId,
+ },
+ }, { multi: true });
+ Uploads.update({ rid: room._id }, {
+ $set: {
+ rid: correctId,
+ },
+ }, { multi: true });
+ });
+};
+
+const fixDiscussions = () => {
+ Rooms.find({ t: 'd', prid: { $exists: true } }, { fields: { _id: 1 } }).forEach(({ _id }) => {
+ const { u } = Messages.findOne({ drid: _id }, { fields: { u: 1 } }) || {};
+
+ Rooms.update({ _id }, {
+ $set: {
+ t: 'p',
+ name: Random.id(),
+ u,
+ ro: false,
+ default: false,
+ sysMes: true,
+ },
+ $unset: {
+ usernames: 1,
+ uids: 1,
+ },
+ });
+ });
+};
+
+const fixUserSearch = () => {
+ const setting = Settings.findOneById('Accounts_SearchFields', { fields: { value: 1 } });
+ const value = setting?.value?.trim();
+ if (value === '' || value === 'username, name') {
+ Settings.updateValueById('Accounts_SearchFields', 'username, name, bio');
+ }
+
+ Users.tryDropIndex('name_text_username_text_bio_text');
+};
+
+Migrations.add({
+ version: 183,
+ up() {
+ fixDiscussions();
+ fixSelfDMs();
+ fixUserSearch();
+ },
+});
diff --git a/server/startup/migrations/v184.js b/server/startup/migrations/v184.js
new file mode 100644
index 000000000000..033cc48f4a68
--- /dev/null
+++ b/server/startup/migrations/v184.js
@@ -0,0 +1,16 @@
+import { Migrations } from '../../../app/migrations';
+import { Settings } from '../../../app/models/server';
+
+Migrations.add({
+ version: 184,
+ up() {
+ // Set SAML signature validation type to 'Either'
+ Settings.upsert({
+ _id: 'SAML_Custom_Default_signature_validation_type',
+ }, {
+ $set: {
+ value: 'Either',
+ },
+ });
+ },
+});