snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
10
apps/meteor/ee/server/startup/audit.ts
Normal file
10
apps/meteor/ee/server/startup/audit.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { License } from '@rocket.chat/license';
|
||||
|
||||
import { createPermissions } from '../lib/audit/startup';
|
||||
|
||||
await License.onLicense('auditing', async () => {
|
||||
await import('../lib/audit/methods');
|
||||
await import('../api/audit');
|
||||
|
||||
await createPermissions();
|
||||
});
|
||||
20
apps/meteor/ee/server/startup/deviceManagement.ts
Normal file
20
apps/meteor/ee/server/startup/deviceManagement.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { License } from '@rocket.chat/license';
|
||||
|
||||
import { addSettings } from '../settings/deviceManagement';
|
||||
|
||||
let stopListening: (() => void) | undefined;
|
||||
License.onToggledFeature('device-management', {
|
||||
up: async () => {
|
||||
const { createPermissions, createEmailTemplates } = await import('../lib/deviceManagement/startup');
|
||||
const { listenSessionLogin } = await import('../lib/deviceManagement/session');
|
||||
|
||||
await addSettings();
|
||||
await createPermissions();
|
||||
await createEmailTemplates();
|
||||
stopListening = await listenSessionLogin();
|
||||
},
|
||||
down: async () => {
|
||||
stopListening?.();
|
||||
stopListening = undefined;
|
||||
},
|
||||
});
|
||||
13
apps/meteor/ee/server/startup/engagementDashboard.ts
Normal file
13
apps/meteor/ee/server/startup/engagementDashboard.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { License } from '@rocket.chat/license';
|
||||
|
||||
License.onToggledFeature('engagement-dashboard', {
|
||||
up: async () => {
|
||||
const { prepareAnalytics, attachCallbacks } = await import('../lib/engagementDashboard/startup');
|
||||
await prepareAnalytics();
|
||||
attachCallbacks();
|
||||
},
|
||||
down: async () => {
|
||||
const { detachCallbacks } = await import('../lib/engagementDashboard/startup');
|
||||
detachCallbacks();
|
||||
},
|
||||
});
|
||||
136
apps/meteor/ee/server/startup/federation.ts
Normal file
136
apps/meteor/ee/server/startup/federation.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { api, FederationMatrix as FederationMatrixService } from '@rocket.chat/core-services';
|
||||
import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings';
|
||||
import { FederationMatrix, configureFederationMatrixSettings, setupFederationMatrix } from '@rocket.chat/federation-matrix';
|
||||
import { InstanceStatus } from '@rocket.chat/instance-status';
|
||||
import { License } from '@rocket.chat/license';
|
||||
import { Logger } from '@rocket.chat/logger';
|
||||
import { Users } from '@rocket.chat/models';
|
||||
|
||||
import { i18n } from '../../../server/lib/i18n';
|
||||
import { slashCommands } from '../../../server/lib/utils/slashCommand';
|
||||
import { StreamerCentral } from '../../../server/modules/streamer/streamer.module';
|
||||
import { settings } from '../../../server/settings';
|
||||
import { registerFederationRoutes } from '../api/federation';
|
||||
|
||||
const logger = new Logger('Federation');
|
||||
|
||||
let serviceEnabled = false;
|
||||
|
||||
const configureFederation = async () => {
|
||||
// only registers the typing listener if the service is enabled
|
||||
serviceEnabled = (await License.hasModule('federation')) && settings.get('Federation_Service_Enabled');
|
||||
if (!serviceEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await configureFederationMatrixSettings({
|
||||
instanceId: InstanceStatus.id(),
|
||||
domain: settings.get('Federation_Service_Domain'),
|
||||
signingKey: settings.get('Federation_Service_Matrix_Signing_Key'),
|
||||
signingAlgorithm: settings.get('Federation_Service_Matrix_Signing_Algorithm'),
|
||||
signingVersion: settings.get('Federation_Service_Matrix_Signing_Version'),
|
||||
allowedEncryptedRooms: settings.get('Federation_Service_Join_Encrypted_Rooms'),
|
||||
allowedNonPrivateRooms: settings.get('Federation_Service_Join_Non_Private_Rooms'),
|
||||
processEDUTyping: settings.get('Federation_Service_EDU_Process_Typing'),
|
||||
processEDUPresence: settings.get('Federation_Service_EDU_Process_Presence'),
|
||||
processEDUReceipt: settings.get('Federation_Service_EDU_Process_Receipt'),
|
||||
xmppEnabled: settings.get('Federation_XMPP_Enabled'),
|
||||
xmppBridgeURL: settings.get('Federation_XMPP_Bridge_URL'),
|
||||
xmppBridgeHSToken: settings.get('Federation_XMPP_Bridge_HS_Token'),
|
||||
xmppBridgeASToken: settings.get('Federation_XMPP_Bridge_AS_Token'),
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error({ msg: 'Failed to start federation-matrix service', err });
|
||||
}
|
||||
};
|
||||
|
||||
export const startFederationService = async (): Promise<void> => {
|
||||
api.registerService(new FederationMatrix());
|
||||
|
||||
await registerFederationRoutes();
|
||||
|
||||
// TODO move to service/setup?
|
||||
StreamerCentral.on('broadcast', (name, eventName, args) => {
|
||||
if (!serviceEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (name === 'notify-room' && eventName.endsWith('user-activity')) {
|
||||
const [rid] = eventName.split('/');
|
||||
const [user, activity] = args;
|
||||
void FederationMatrixService.notifyUserTyping(rid, user, activity.includes('user-typing'));
|
||||
}
|
||||
});
|
||||
|
||||
// `setupFederationMatrix()` runs the SDK's `init()`, which registers the DB
|
||||
// collections (including `AppServiceStateCollection`). It must complete
|
||||
// before the settings watcher below, whose initial fire calls `setConfig`
|
||||
// and resolves repositories that depend on those collections.
|
||||
try {
|
||||
await setupFederationMatrix();
|
||||
} catch (err) {
|
||||
logger.error({ msg: 'Failed to setup federation-matrix:', err });
|
||||
}
|
||||
|
||||
settings.watchMultiple(
|
||||
[
|
||||
'Federation_Service_Enabled',
|
||||
'Federation_Service_Domain',
|
||||
'Federation_Service_EDU_Process_Typing',
|
||||
'Federation_Service_EDU_Process_Presence',
|
||||
'Federation_Service_EDU_Process_Receipt',
|
||||
'Federation_Service_Matrix_Signing_Key',
|
||||
'Federation_Service_Matrix_Signing_Algorithm',
|
||||
'Federation_Service_Matrix_Signing_Version',
|
||||
'Federation_Service_Join_Encrypted_Rooms',
|
||||
'Federation_Service_Join_Non_Private_Rooms',
|
||||
'Federation_XMPP_Enabled',
|
||||
'Federation_XMPP_Bridge_URL',
|
||||
'Federation_XMPP_Bridge_HS_Token',
|
||||
'Federation_XMPP_Bridge_AS_Token',
|
||||
],
|
||||
async () => {
|
||||
await configureFederation();
|
||||
},
|
||||
);
|
||||
|
||||
slashCommands.add({
|
||||
command: 'xmpp-join',
|
||||
callback: async ({ params, message, userId }: SlashCommandCallbackParams<'xmpp-join'>): Promise<void> => {
|
||||
// the helper advertises `#channel`, so accept the leading # and strip it before joining
|
||||
const channel = params.trim().replace(/^#/, '');
|
||||
if (!channel) {
|
||||
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
|
||||
msg: i18n.t('Federation_XMPP_Join_Channel_Required', {
|
||||
lng: settings.get('Language') || 'en',
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await Users.findOneById(userId);
|
||||
if (!user) {
|
||||
logger.error({ msg: 'User not found for joining xmpp room', userId });
|
||||
return;
|
||||
}
|
||||
|
||||
const joined = await FederationMatrixService.joinAppServiceRoom(`_xmpp_${channel}`, user);
|
||||
|
||||
const lng = settings.get<string>('Language') || 'en';
|
||||
if (joined) {
|
||||
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
|
||||
msg: `${i18n.t('Federation_XMPP_Join_Channel_Success', { lng })}`,
|
||||
});
|
||||
} else {
|
||||
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
|
||||
msg: `${i18n.t('Federation_XMPP_Join_Channel_Failed', { lng })}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
options: {
|
||||
description: 'Join xmpp rooms',
|
||||
params: '#channel',
|
||||
},
|
||||
});
|
||||
};
|
||||
24
apps/meteor/ee/server/startup/index.ts
Normal file
24
apps/meteor/ee/server/startup/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import '../hooks/auth/callback';
|
||||
import './audit';
|
||||
import './deviceManagement';
|
||||
import './engagementDashboard';
|
||||
import './maxRoomsPerGuest';
|
||||
import './upsell';
|
||||
import './services';
|
||||
import './readReceiptsArchive';
|
||||
import './mcp';
|
||||
import { api } from '@rocket.chat/core-services';
|
||||
|
||||
import { isRunningMs } from '../../../server/lib/isRunningMs';
|
||||
|
||||
export const registerEEBroker = async (): Promise<void> => {
|
||||
// only starts network broker if running in micro services mode
|
||||
if (isRunningMs()) {
|
||||
const { startBroker } = await import('@rocket.chat/network-broker');
|
||||
|
||||
api.setBroker(startBroker());
|
||||
await api.start();
|
||||
} else {
|
||||
require('./presence');
|
||||
}
|
||||
};
|
||||
20
apps/meteor/ee/server/startup/maxRoomsPerGuest.ts
Normal file
20
apps/meteor/ee/server/startup/maxRoomsPerGuest.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { License } from '@rocket.chat/license';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
import { callbacks } from '../../../server/lib/callbacks';
|
||||
import { i18n } from '../../../server/lib/i18n';
|
||||
|
||||
callbacks.add(
|
||||
'beforeAddedToRoom',
|
||||
async ({ user }) => {
|
||||
if (user.roles?.includes('guest')) {
|
||||
// extraCount = 1 checks if adding one more room would exceed the limit
|
||||
// (not if they've already exceeded it, since this runs before adding them to the room)
|
||||
if (await License.shouldPreventAction('roomsPerGuest', 1, { userId: user._id })) {
|
||||
throw new Meteor.Error('error-max-rooms-per-guest-reached', i18n.t('error-max-rooms-per-guest-reached'));
|
||||
}
|
||||
}
|
||||
},
|
||||
callbacks.priority.MEDIUM,
|
||||
'check-max-rooms-per-guest',
|
||||
);
|
||||
7
apps/meteor/ee/server/startup/mcp.ts
Normal file
7
apps/meteor/ee/server/startup/mcp.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { AI_LICENSE_MODULE } from '@rocket.chat/ai-search';
|
||||
import { License } from '@rocket.chat/license';
|
||||
import { Permissions } from '@rocket.chat/models';
|
||||
|
||||
await License.onLicense(AI_LICENSE_MODULE, async () => {
|
||||
await Permissions.create('access-mcp', ['admin']);
|
||||
});
|
||||
64
apps/meteor/ee/server/startup/presence.ts
Normal file
64
apps/meteor/ee/server/startup/presence.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Presence } from '@rocket.chat/core-services';
|
||||
import { InstanceStatus } from '@rocket.chat/instance-status';
|
||||
import { Accounts } from 'meteor/accounts-base';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { throttle } from 'underscore';
|
||||
|
||||
// update connections count every 30 seconds
|
||||
const updateConns = throttle(function _updateConns() {
|
||||
void InstanceStatus.updateConnections(Meteor.server.sessions.size);
|
||||
}, 30000);
|
||||
|
||||
Meteor.startup(() => {
|
||||
const nodeId = InstanceStatus.id();
|
||||
|
||||
Meteor.onConnection((connection) => {
|
||||
const session = Meteor.server.sessions.get(connection.id);
|
||||
|
||||
connection.onClose(async () => {
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
await Presence.removeConnection(session.userId, connection.id, nodeId);
|
||||
updateConns();
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', async () => {
|
||||
await Presence.removeLostConnections(nodeId);
|
||||
});
|
||||
|
||||
Accounts.onLogin((login: any): void => {
|
||||
if (!login.connection.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// validate if it is a real WS connection and is still open
|
||||
const session = Meteor.server.sessions.get(login.connection.id);
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
const _messageReceived = session.heartbeat.messageReceived.bind(session.heartbeat);
|
||||
session.heartbeat.messageReceived = function messageReceived() {
|
||||
if (this._seenPacket === false) {
|
||||
void Presence.updateConnection(login.user._id, login.connection.id).catch((err) => {
|
||||
console.error('Error updating connection presence on heartbeat:', err);
|
||||
});
|
||||
}
|
||||
return _messageReceived();
|
||||
};
|
||||
|
||||
void (async function () {
|
||||
await Presence.newConnection(login.user._id, login.connection.id, nodeId);
|
||||
updateConns();
|
||||
})();
|
||||
});
|
||||
|
||||
Accounts.onLogout((login): void => {
|
||||
void Presence.removeConnection(login.user?._id, login.connection.id, nodeId);
|
||||
|
||||
updateConns();
|
||||
});
|
||||
});
|
||||
7
apps/meteor/ee/server/startup/readReceiptsArchive.ts
Normal file
7
apps/meteor/ee/server/startup/readReceiptsArchive.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { settings } from '../../../server/settings';
|
||||
import { readReceiptsArchiveCron } from '../cron/readReceiptsArchive';
|
||||
|
||||
// Watch for settings changes and update the cron schedule
|
||||
settings.watchMultiple(['Message_Read_Receipt_Archive_Cron', 'Message_Read_Receipt_Archive_Enabled'], async () => {
|
||||
await readReceiptsArchiveCron();
|
||||
});
|
||||
23
apps/meteor/ee/server/startup/services.ts
Normal file
23
apps/meteor/ee/server/startup/services.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { AbacService } from '@rocket.chat/abac';
|
||||
import { api } from '@rocket.chat/core-services';
|
||||
|
||||
import { isRunningMs } from '../../../server/lib/isRunningMs';
|
||||
import { LicenseService } from '../lib/license/license.internalService';
|
||||
import { InstanceService } from '../local-services/instance/service';
|
||||
import { LDAPEEService } from '../local-services/ldap/service';
|
||||
import { MessageReadsService } from '../local-services/message-reads/service';
|
||||
import { OmnichannelEE } from '../local-services/omnichannel.internalService';
|
||||
import { EnterpriseSettings } from '../settings/settings.internalService';
|
||||
|
||||
// TODO consider registering these services only after a valid license is added
|
||||
api.registerService(new EnterpriseSettings());
|
||||
api.registerService(new LDAPEEService());
|
||||
api.registerService(new LicenseService());
|
||||
api.registerService(new MessageReadsService());
|
||||
api.registerService(new OmnichannelEE());
|
||||
|
||||
// when not running micro services we want to start up the instance intercom
|
||||
if (!isRunningMs()) {
|
||||
api.registerService(new AbacService());
|
||||
api.registerService(new InstanceService());
|
||||
}
|
||||
22
apps/meteor/ee/server/startup/upsell.ts
Normal file
22
apps/meteor/ee/server/startup/upsell.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { License } from '@rocket.chat/license';
|
||||
import { Settings } from '@rocket.chat/models';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
import { notifyOnSettingChangedById } from '../../../server/lib/notifyListener';
|
||||
import { updateAuditedBySystem } from '../../../server/settings/lib/auditedSettingUpdates';
|
||||
|
||||
const handleHadTrial = (): void => {
|
||||
if (License.getLicense()?.information.trial) {
|
||||
void (async () => {
|
||||
(
|
||||
await updateAuditedBySystem({
|
||||
reason: 'handleHadTrial',
|
||||
})(Settings.updateValueById, 'Cloud_Workspace_Had_Trial', true)
|
||||
).modifiedCount && void notifyOnSettingChangedById('Cloud_Workspace_Had_Trial');
|
||||
})();
|
||||
}
|
||||
};
|
||||
|
||||
Meteor.startup(() => {
|
||||
License.onValidateLicense(handleHadTrial);
|
||||
});
|
||||
Reference in New Issue
Block a user