Merge remote-tracking branch 'origin/develop' into release-candidate

pull/15350/head
Diego Sampaio 6 years ago
commit 9362cf1371
No known key found for this signature in database
GPG Key ID: E060152B30502562
  1. 7
      app/federation/server/functions/helpers.js
  2. 15
      app/federation/server/hooks/afterAddedToRoom.js
  3. 8
      app/federation/server/hooks/afterCreateDirectRoom.js
  4. 19
      app/federation/server/hooks/afterCreateRoom.js
  5. 2
      app/federation/server/hooks/afterRemoveFromRoom.js
  6. 2
      app/federation/server/hooks/beforeDeleteRoom.js
  7. 9
      app/federation/server/normalizers/user.js
  8. 1
      server/startup/migrations/index.js
  9. 99
      server/startup/migrations/v156.js

@ -11,7 +11,8 @@ export function updateEnabled(enabled) {
Settings.updateValueById('FEDERATION_Enabled', enabled);
}
export const isFederated = (resource) => !!resource.federation;
export const checkRoomType = (room) => room.t === 'p' || room.t === 'd';
export const checkRoomDomainsLength = (domains) => domains.length <= 10;
export const hasExternalDomain = ({ federation }) => {
// same test as isFederated(room)
@ -34,7 +35,7 @@ export const getFederatedRoomData = (room) => {
if (room.t === 'd') {
// Check if there is a federated user on this room
hasFederatedUser = room.usernames.find((u) => u.indexOf('@') !== -1);
hasFederatedUser = room.usernames.some(isFullyQualified);
} else {
// Find all subscriptions of this room
subscriptions = Subscriptions.findByRoomIdWhenUsernameExists(room._id).fetch();
@ -51,7 +52,7 @@ export const getFederatedRoomData = (room) => {
users = Users.findUsersWithUsernameByIds(userIds).fetch();
// Check if there is a federated user on this room
hasFederatedUser = users.find((u) => u.username.indexOf('@') !== -1);
hasFederatedUser = users.some((u) => isFullyQualified(u.username));
}
return {

@ -1,11 +1,12 @@
import { logger } from '../lib/logger';
import { getFederatedRoomData, hasExternalDomain, isLocalUser } from '../functions/helpers';
import { getFederatedRoomData, hasExternalDomain, isLocalUser, checkRoomType, checkRoomDomainsLength } from '../functions/helpers';
import { FederationRoomEvents, Subscriptions } from '../../../models/server';
import { normalizers } from '../normalizers';
import { doAfterCreateRoom } from './afterCreateRoom';
import { getFederationDomain } from '../lib/getFederationDomain';
import { dispatchEvent } from '../handler';
async function afterAddedToRoom(involvedUsers, room) {
const { user: addedUser } = involvedUsers;
@ -24,6 +25,11 @@ async function afterAddedToRoom(involvedUsers, room) {
const subscription = Subscriptions.findOneByRoomIdAndUserId(room._id, addedUser._id);
try {
// If the room is not on the allowed types, ignore
if (!checkRoomType(room)) {
throw new Error('Channels cannot be federated');
}
//
// Check if the room is already federated, if it is not, create the genesis event
//
@ -41,6 +47,11 @@ async function afterAddedToRoom(involvedUsers, room) {
// Get the users domains
const domainsAfterAdd = users.map((u) => u.federation.origin);
// Check if the number of domains is allowed
if (!checkRoomDomainsLength(room.federation.domains)) {
throw new Error('Cannot federate rooms with more than 10 domains');
}
//
// Create the user add event
//
@ -57,7 +68,7 @@ async function afterAddedToRoom(involvedUsers, room) {
// Remove the user subscription from the room
Subscriptions.remove({ _id: subscription._id });
logger.client.error(() => `afterAddedToRoom => involvedUsers=${ JSON.stringify(involvedUsers, null, 2) } => Could not add user: ${ err }`);
logger.client.error('afterAddedToRoom => Could not add user:', err);
}
return involvedUsers;

@ -4,16 +4,16 @@ import { normalizers } from '../normalizers';
import { deleteRoom } from '../../../lib/server/functions';
import { getFederationDomain } from '../lib/getFederationDomain';
import { dispatchEvents } from '../handler';
import { hasExternalDomain } from '../functions/helpers';
import { isFullyQualified } from '../functions/helpers';
async function afterCreateDirectRoom(room, extras) {
logger.client.debug(() => `afterCreateDirectRoom => room=${ JSON.stringify(room, null, 2) } extras=${ JSON.stringify(extras, null, 2) }`);
// If the room is federated, ignore
if (!hasExternalDomain(room)) { return room; }
if (room.federation) { return room; }
// Check if there is a federated user on this direct room
const hasFederatedUser = room.usernames.find((u) => u.indexOf('@') !== -1);
const hasFederatedUser = room.usernames.some(isFullyQualified);
// If there are not federated users on this room, ignore it
if (!hasFederatedUser) { return room; }
@ -62,7 +62,7 @@ async function afterCreateDirectRoom(room, extras) {
} catch (err) {
Promise.await(deleteRoom(room._id));
logger.client.error(() => `afterCreateDirectRoom => room=${ JSON.stringify(room, null, 2) } => Could not create federated room: ${ err }`);
logger.client.error('afterCreateDirectRoom => Could not create federated room:', err);
}
return room;

@ -4,6 +4,7 @@ import { normalizers } from '../normalizers';
import { deleteRoom } from '../../../lib/server/functions';
import { getFederationDomain } from '../lib/getFederationDomain';
import { dispatchEvents } from '../handler';
import { checkRoomType, checkRoomDomainsLength } from '../functions/helpers';
export async function doAfterCreateRoom(room, users, subscriptions) {
const normalizedUsers = [];
@ -37,6 +38,11 @@ export async function doAfterCreateRoom(room, users, subscriptions) {
// Normalize room
const normalizedRoom = normalizers.normalizeRoom(room, normalizedUsers);
// Check if the number of domains is allowed
if (!checkRoomDomainsLength(normalizedRoom.federation.domains)) {
throw new Error('Cannot federate rooms with more than 10 domains');
}
// Ensure a genesis event for this room
const genesisEvent = await FederationRoomEvents.createGenesisEvent(getFederationDomain(), normalizedRoom);
@ -66,16 +72,21 @@ async function afterCreateRoom(roomOwner, room) {
const hasFederatedUser = users.find((u) => u.username.indexOf('@') !== -1);
// If there are not federated users on this room, ignore it
if (!hasFederatedUser) { return; }
logger.client.debug(() => `afterCreateRoom => roomOwner=${ JSON.stringify(roomOwner, null, 2) } room=${ JSON.stringify(room, null, 2) }`);
if (!hasFederatedUser) { return roomOwner; }
try {
// If the room is not on the allowed types, ignore
if (!checkRoomType(room)) {
throw new Error('Channels cannot be federated');
}
logger.client.debug(() => `afterCreateRoom => roomOwner=${ JSON.stringify(roomOwner, null, 2) } room=${ JSON.stringify(room, null, 2) }`);
await doAfterCreateRoom(room, users, subscriptions);
} catch (err) {
deleteRoom(room._id);
logger.client.error(() => `afterCreateRoom => room=${ JSON.stringify(room, null, 2) } => Could not create federated room: ${ err }`);
logger.client.error('afterCreateRoom => Could not create federated room:', err);
}
return room;

@ -42,7 +42,7 @@ async function afterRemoveFromRoom(involvedUsers, room) {
// Dispatch the events
dispatchEvent(domainsBeforeRemoval, removeUserEvent);
} catch (err) {
logger.client.error(() => `afterRemoveFromRoom => involvedUsers=${ JSON.stringify(involvedUsers, null, 2) } => Could not add user: ${ err }`);
logger.client.error('afterRemoveFromRoom => Could not add user:', err);
}
return involvedUsers;

@ -21,7 +21,7 @@ async function beforeDeleteRoom(roomId) {
// Dispatch event (async)
dispatchEvent(room.federation.domains, event);
} catch (err) {
logger.client.error(() => `beforeDeleteRoom => room=${ JSON.stringify(room, null, 2) } => Could not remove room: ${ err }`);
logger.client.error('beforeDeleteRoom => Could not remove room:', err);
throw err;
}

@ -7,9 +7,12 @@ import { getFederationDomain } from '../lib/getFederationDomain';
const denormalizeUser = (originalResource) => {
const resource = { ...originalResource };
resource.emails = [{
address: resource.federation.originalInfo.email,
}];
// Only denormalize local emails
if (resource.federation && resource.federation.origin === getFederationDomain()) {
resource.emails = [{
address: resource.federation.originalInfo.email,
}];
}
const [username, domain] = getNameAndDomain(resource.username);

@ -153,4 +153,5 @@ import './v152';
import './v153';
import './v154';
import './v155';
import './v156';
import './xrun';

@ -0,0 +1,99 @@
import { Mongo } from 'meteor/mongo';
import { Migrations } from '../../../app/migrations/server';
import {
Messages,
Rooms,
Subscriptions,
Users,
Uploads,
Settings,
} from '../../../app/models/server';
const validSettings = [
'FEDERATION_Enabled',
'FEDERATION_Domain',
'FEDERATION_Public_Key',
'FEDERATION_Discovery_Method',
'FEDERATION_Test_Setup',
];
const federationEventsCollection = new Mongo.Collection('rocketchat_federation_events');
Migrations.add({
version: 156,
up() {
try {
// Delete all old, deprecated tables
console.log('Migration: drop collection');
Promise.await(federationEventsCollection.rawCollection().drop());
} catch (err) {
// Ignore if the collection does not exist
if (!err.code || err.code !== 26) {
throw err;
}
}
// Make sure we keep only the valid settings
console.log('Migration: remove old settings');
Settings.remove({ $and: [{ _id: /FEDERATION/ }, { _id: { $nin: validSettings } }] });
// Normalize the federation property on all collections
// Update rooms
console.log('Migration: update rooms');
Promise.await(Rooms.model.rawCollection().updateMany({
federation: { $exists: true },
}, {
$unset: { federation: 1 },
}));
// Update all subscriptions
console.log('Migration: update subscriptions');
Promise.await(Subscriptions.model.rawCollection().updateMany({
federation: { $exists: true },
}, {
$unset: { federation: 1 },
}));
// Update all users
console.log('Migration: update remote users');
Users.find({ isRemote: true }).forEach((u) => {
const [name, domain] = u.username.split('@');
const username = `${ name }@old-${ domain }`;
Users.update({ _id: u._id }, {
$unset: { federation: 1, emails: 1, isRemote: 1 },
$set: { username, active: false, status: 'offline' },
});
});
console.log('Migration: update local users');
Promise.await(Users.model.rawCollection().updateMany({
federation: { $exists: true },
}, {
$unset: { federation: 1 },
}));
// Update all messages
// We will not update the mentions and channels here
console.log('Migration: update messages');
Promise.await(Messages.model.rawCollection().updateMany({
federation: { $exists: true },
}, {
$unset: { federation: 1 },
}));
// Update all uploads
console.log('Migration: update uploads');
Promise.await(Uploads.model.rawCollection().updateMany({
federation: { $exists: true },
}, {
$unset: { federation: 1 },
}));
},
down() {
// Down migration does not apply in this case
},
});
Loading…
Cancel
Save