From 8e88055c2b48b6d89afb5efc1552b6eab18cf99a Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 24 Oct 2024 16:51:59 -0300 Subject: [PATCH 1/8] prevent loading page on reconnect --- apps/meteor/app/authentication/server/startup/index.js | 2 ++ .../ui-cached-collection/client/models/CachedCollection.ts | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 10ba3fd44154..f1ba181bdf3c 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -23,10 +23,12 @@ import { setAvatarFromServiceWithValidation } from '../../../lib/server/function import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; +import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields'; import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteorUser'; import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; Accounts.config({ + defaultFieldSelector: { ...getBaseUserFields(), services: 1 }, forbidClientAccountCreation: true, }); diff --git a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts index 602a0eddb8ce..10ea6d9453bb 100644 --- a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts +++ b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts @@ -83,6 +83,9 @@ export class CachedCollection extends Emitter< CachedCollectionManager.onLogin(() => { void this.init(); }); + Accounts.onLogout(() => { + this.ready.set(false); + }); } protected get eventName(): `${Name}-changed` | `${string}/${Name}-changed` { @@ -342,8 +345,6 @@ export class CachedCollection extends Emitter< } async init() { - this.ready.set(false); - if (await this.loadFromCache()) { this.trySync(); } else { From 14bd34233823b1c8910d57066865424feb2c52f5 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 24 Oct 2024 17:11:19 -0300 Subject: [PATCH 2/8] send fields via ddp-streamer as well --- ee/apps/ddp-streamer/src/configureServer.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ee/apps/ddp-streamer/src/configureServer.ts b/ee/apps/ddp-streamer/src/configureServer.ts index ed187db498cc..489f9606c07d 100644 --- a/ee/apps/ddp-streamer/src/configureServer.ts +++ b/ee/apps/ddp-streamer/src/configureServer.ts @@ -2,7 +2,9 @@ import { EventEmitter } from 'events'; import { Account, Presence, MeteorService, MeteorError } from '@rocket.chat/core-services'; import { UserStatus } from '@rocket.chat/core-typings'; +import { Users } from '@rocket.chat/models'; +import type { Client } from './Client'; import { Server } from './Server'; import { DDP_EVENTS, WS_ERRORS } from './constants'; import { Autoupdate } from './lib/Autoupdate'; @@ -64,6 +66,19 @@ server.publish(autoUpdateCollection, function () { this.ready(); }); +async function sendUserData(client: Client, userId: string) { + // TODO figure out what fields to send. maybe to to export function getBaseUserFields to a package + const loggedUser = await Users.findOneById(userId, { + projection: { name: 1, username: 1, settings: 1, roles: 1, active: 1, statusLivechat: 1, statusDefault: 1 }, + }); + if (!loggedUser) { + return; + } + + // using setImmediate here so login's method result is sent before we send the user data + setImmediate(async () => server.added(client, 'users', userId, loggedUser)); +} + server.methods({ async 'login'({ resume, user, password }: { resume: string; user: { username: string }; password: string }) { try { @@ -80,6 +95,9 @@ server.methods({ server.emit(DDP_EVENTS.LOGGED, this); + // mimic Meteor's default publication that sends user data after login + await sendUserData(this, result.uid); + return { id: result.uid, token: result.token, From cacfbaefed5d00a30ab61ee578bf7b5c5eec1f57 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 24 Oct 2024 17:11:28 -0300 Subject: [PATCH 3/8] do not send services --- apps/meteor/app/authentication/server/startup/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index f1ba181bdf3c..5c571a298daa 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -28,7 +28,7 @@ import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteor import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; Accounts.config({ - defaultFieldSelector: { ...getBaseUserFields(), services: 1 }, + defaultFieldSelector: getBaseUserFields(), forbidClientAccountCreation: true, }); From f8e4a7465561ac47cdef922d426c850754c6365a Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 24 Oct 2024 18:46:17 -0300 Subject: [PATCH 4/8] fix --- apps/meteor/app/authentication/server/startup/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 5c571a298daa..6879b053c8d2 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -28,9 +28,16 @@ import { safeGetMeteorUser } from '../../../utils/server/functions/safeGetMeteor import { isValidAttemptByUser, isValidLoginAttemptByIp } from '../lib/restrictLoginAttempts'; Accounts.config({ - defaultFieldSelector: getBaseUserFields(), forbidClientAccountCreation: true, }); +/** + * Accounts calls `_initServerPublications` and holds the `_defaultPublishFields`, without Object.assign its not possible + * to extend the projection + * + * the idea is to send all required fields to the client during login + * we tried `defaultFieldsSelector` , but it changes all Meteor.userAsync projections which is undesirable + */ +Object.assign(Accounts._defaultPublishFields.projection, getBaseUserFields()); Meteor.startup(() => { settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => { From 4224644b3f48b852c0ec43fd2082757a38259b68 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 25 Oct 2024 01:25:52 -0300 Subject: [PATCH 5/8] undo temp --- apps/meteor/client/startup/startup.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/meteor/client/startup/startup.ts b/apps/meteor/client/startup/startup.ts index 8d8d8de155b8..45c102a72bf4 100644 --- a/apps/meteor/client/startup/startup.ts +++ b/apps/meteor/client/startup/startup.ts @@ -33,11 +33,9 @@ Meteor.startup(() => { return; } - // TODO: TEMPORARY UNTIL THIS IS FIXED - // BACKEND MS SHOULD SEND USER DATA AFTER LOGIN - // if (Meteor.loggingIn()) { - // return; - // } + if (Meteor.loggingIn()) { + return; + } const user = await synchronizeUserData(uid); if (!user) { From 8231ee5d9f267d2b0ba84f97d8cd8756b044827d Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 25 Oct 2024 01:51:36 -0300 Subject: [PATCH 6/8] ... --- ee/apps/ddp-streamer/src/DDPStreamer.ts | 27 +++++++++++++++++++-- ee/apps/ddp-streamer/src/configureServer.ts | 18 -------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index 275f26ae05e0..7e413e61688d 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -2,6 +2,7 @@ import crypto from 'crypto'; import { MeteorService, Presence, ServiceClass } from '@rocket.chat/core-services'; import { InstanceStatus } from '@rocket.chat/instance-status'; +import { Users } from '@rocket.chat/models'; import polka from 'polka'; import { throttle } from 'underscore'; import WebSocket from 'ws'; @@ -123,12 +124,34 @@ export class DDPStreamer extends ServiceClass { } }); - server.on(DDP_EVENTS.LOGGED, (info) => { + async function sendUserData(client: Client, userId: string) { + // TODO figure out what fields to send. maybe to to export function getBaseUserFields to a package + const loggedUser = await Users.findOneById(userId, { + projection: { name: 1, username: 1, settings: 1, roles: 1, active: 1, statusLivechat: 1, statusDefault: 1 }, + }); + if (!loggedUser) { + return; + } + + // using setImmediate here so login's method result is sent before we send the user data + setImmediate(async () => server.added(client, 'users', userId, loggedUser)); + } + server.on(DDP_EVENTS.LOGGED, async (info: Client) => { const { userId, connection } = info; - Presence.newConnection(userId, connection.id, nodeID); + if (!userId) { + throw new Error('User not logged in'); + } + + await Presence.newConnection(userId, connection.id, nodeID); + this.updateConnections(); + // mimic Meteor's default publication that sends user data after login + await sendUserData(info, userId); + + server.emit('presence', { userId, connection }); + this.api?.broadcast('accounts.login', { userId, connection }); }); diff --git a/ee/apps/ddp-streamer/src/configureServer.ts b/ee/apps/ddp-streamer/src/configureServer.ts index 489f9606c07d..ed187db498cc 100644 --- a/ee/apps/ddp-streamer/src/configureServer.ts +++ b/ee/apps/ddp-streamer/src/configureServer.ts @@ -2,9 +2,7 @@ import { EventEmitter } from 'events'; import { Account, Presence, MeteorService, MeteorError } from '@rocket.chat/core-services'; import { UserStatus } from '@rocket.chat/core-typings'; -import { Users } from '@rocket.chat/models'; -import type { Client } from './Client'; import { Server } from './Server'; import { DDP_EVENTS, WS_ERRORS } from './constants'; import { Autoupdate } from './lib/Autoupdate'; @@ -66,19 +64,6 @@ server.publish(autoUpdateCollection, function () { this.ready(); }); -async function sendUserData(client: Client, userId: string) { - // TODO figure out what fields to send. maybe to to export function getBaseUserFields to a package - const loggedUser = await Users.findOneById(userId, { - projection: { name: 1, username: 1, settings: 1, roles: 1, active: 1, statusLivechat: 1, statusDefault: 1 }, - }); - if (!loggedUser) { - return; - } - - // using setImmediate here so login's method result is sent before we send the user data - setImmediate(async () => server.added(client, 'users', userId, loggedUser)); -} - server.methods({ async 'login'({ resume, user, password }: { resume: string; user: { username: string }; password: string }) { try { @@ -95,9 +80,6 @@ server.methods({ server.emit(DDP_EVENTS.LOGGED, this); - // mimic Meteor's default publication that sends user data after login - await sendUserData(this, result.uid); - return { id: result.uid, token: result.token, From 0a31a88821b00a68e3905c1ca443efdc2606d57c Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 25 Oct 2024 10:28:19 -0300 Subject: [PATCH 7/8] Dido cheater --- apps/meteor/app/authentication/server/startup/index.js | 5 ++++- ee/apps/ddp-streamer/src/DDPStreamer.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 6879b053c8d2..0577ceac0ba7 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -36,8 +36,11 @@ Accounts.config({ * * the idea is to send all required fields to the client during login * we tried `defaultFieldsSelector` , but it changes all Meteor.userAsync projections which is undesirable + * + * + * we are removing the status here because meteor send 'offline' */ -Object.assign(Accounts._defaultPublishFields.projection, getBaseUserFields()); +Object.assign(Accounts._defaultPublishFields.projection, (({ status, ...rest }) => rest)(getBaseUserFields())); Meteor.startup(() => { settings.watchMultiple(['Accounts_LoginExpiration', 'Site_Name', 'From_Email'], () => { diff --git a/ee/apps/ddp-streamer/src/DDPStreamer.ts b/ee/apps/ddp-streamer/src/DDPStreamer.ts index 7e413e61688d..2ba89ced7138 100644 --- a/ee/apps/ddp-streamer/src/DDPStreamer.ts +++ b/ee/apps/ddp-streamer/src/DDPStreamer.ts @@ -127,7 +127,7 @@ export class DDPStreamer extends ServiceClass { async function sendUserData(client: Client, userId: string) { // TODO figure out what fields to send. maybe to to export function getBaseUserFields to a package const loggedUser = await Users.findOneById(userId, { - projection: { name: 1, username: 1, settings: 1, roles: 1, active: 1, statusLivechat: 1, statusDefault: 1 }, + projection: { name: 1, username: 1, settings: 1, roles: 1, active: 1, statusLivechat: 1, statusDefault: 1, status: 1 }, }); if (!loggedUser) { return; From 2ec55ccadc185cc6ddbad0c3c655a13ac66c578b Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 25 Oct 2024 12:31:34 -0400 Subject: [PATCH 8/8] Create pretty-ladybugs-sneeze.md --- .changeset/pretty-ladybugs-sneeze.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/pretty-ladybugs-sneeze.md diff --git a/.changeset/pretty-ladybugs-sneeze.md b/.changeset/pretty-ladybugs-sneeze.md new file mode 100644 index 000000000000..88aa14149dfb --- /dev/null +++ b/.changeset/pretty-ladybugs-sneeze.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/ddp-streamer": patch +--- + +Fixes page loading during reconnections