Skip to content
Snippets Groups Projects
Unverified Commit 5deac49e authored by Guilherme Gazzo's avatar Guilherme Gazzo Committed by GitHub
Browse files

chore: reorganize server imports (#31439)

parent e3252f54
No related branches found
No related tags found
No related merge requests found
Showing
with 321 additions and 298 deletions
import './settings';
import './methods';
import './startup';
export { getStatistics } from './getStatistics';
......@@ -11,140 +11,142 @@ import { callbacks } from '../../../../lib/callbacks';
import { applyLicense, applyLicenseOrRemove } from './applyLicense';
import { getAppCount } from './lib/getAppCount';
settings.watch<string>('Site_Url', (value) => {
if (value) {
void License.setWorkspaceUrl(value);
}
});
License.onValidateLicense(async () => {
await Settings.updateValueById('Enterprise_License', License.encryptedLicense);
await Settings.updateValueById('Enterprise_License_Status', 'Valid');
});
License.onInvalidateLicense(async () => {
await Settings.updateValueById('Enterprise_License_Status', 'Invalid');
});
License.onRemoveLicense(async () => {
await Settings.updateValueById('Enterprise_License', '');
await Settings.updateValueById('Enterprise_License_Status', 'Invalid');
});
/**
* This is a debounced function that will sync the workspace data to the cloud.
* it caches the context, waits for a second and then syncs the data.
*/
const syncByTriggerDebounced = (() => {
let timeout: NodeJS.Timeout | undefined;
const contexts: Set<string> = new Set();
return async (context: string) => {
contexts.add(context);
if (timeout) {
clearTimeout(timeout);
export const startLicense = async () => {
settings.watch<string>('Site_Url', (value) => {
if (value) {
void License.setWorkspaceUrl(value);
}
});
timeout = setTimeout(() => {
timeout = undefined;
void syncByTrigger([...contexts]);
contexts.clear();
}, 1000);
};
})();
License.onValidateLicense(async () => {
await Settings.updateValueById('Enterprise_License', License.encryptedLicense);
await Settings.updateValueById('Enterprise_License_Status', 'Valid');
});
const syncByTrigger = async (contexts: string[]) => {
if (!License.encryptedLicense) {
return;
}
License.onInvalidateLicense(async () => {
await Settings.updateValueById('Enterprise_License_Status', 'Invalid');
});
const existingData = wrapExceptions(() => JSON.parse(settings.get<string>('Enterprise_License_Data'))).catch(() => ({})) ?? {};
License.onRemoveLicense(async () => {
await Settings.updateValueById('Enterprise_License', '');
await Settings.updateValueById('Enterprise_License_Status', 'Invalid');
});
const date = new Date();
/**
* This is a debounced function that will sync the workspace data to the cloud.
* it caches the context, waits for a second and then syncs the data.
*/
const syncByTriggerDebounced = (() => {
let timeout: NodeJS.Timeout | undefined;
const contexts: Set<string> = new Set();
return async (context: string) => {
contexts.add(context);
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
timeout = undefined;
void syncByTrigger([...contexts]);
contexts.clear();
}, 1000);
};
})();
const syncByTrigger = async (contexts: string[]) => {
if (!License.encryptedLicense) {
return;
}
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
const existingData = wrapExceptions(() => JSON.parse(settings.get<string>('Enterprise_License_Data'))).catch(() => ({})) ?? {};
const period = `${year}-${month}-${day}`;
const date = new Date();
const [, , signed] = License.encryptedLicense.split('.');
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
// Check if this sync has already been done. Based on License, behavior.
const period = `${year}-${month}-${day}`;
if ([...contexts.values()].every((context) => existingData.signed === signed && existingData[context] === period)) {
return;
}
const [, , signed] = License.encryptedLicense.split('.');
const obj = Object.fromEntries(contexts.map((context) => [context, period]));
// Check if this sync has already been done. Based on License, behavior.
await Settings.updateValueById(
'Enterprise_License_Data',
JSON.stringify({
...(existingData.signed === signed && existingData),
...existingData,
...obj,
signed,
}),
);
if ([...contexts.values()].every((context) => existingData.signed === signed && existingData[context] === period)) {
return;
}
try {
await syncWorkspace();
} catch (error) {
console.error(error);
}
};
const obj = Object.fromEntries(contexts.map((context) => [context, period]));
await Settings.updateValueById(
'Enterprise_License_Data',
JSON.stringify({
...(existingData.signed === signed && existingData),
...existingData,
...obj,
signed,
}),
);
try {
await syncWorkspace();
} catch (error) {
console.error(error);
}
};
// When settings are loaded, apply the current license if there is one.
settings.onReady(async () => {
if (!(await applyLicense(settings.get<string>('Enterprise_License') ?? '', false))) {
// License from the envvar is always treated as new, because it would have been saved on the setting if it was already in use.
if (process.env.ROCKETCHAT_LICENSE && !License.hasValidLicense()) {
await applyLicense(process.env.ROCKETCHAT_LICENSE, true);
// When settings are loaded, apply the current license if there is one.
settings.onReady(async () => {
if (!(await applyLicense(settings.get<string>('Enterprise_License') ?? '', false))) {
// License from the envvar is always treated as new, because it would have been saved on the setting if it was already in use.
if (process.env.ROCKETCHAT_LICENSE && !License.hasValidLicense()) {
await applyLicense(process.env.ROCKETCHAT_LICENSE, true);
}
}
}
// After the current license is already loaded, watch the setting value to react to new licenses being applied.
settings.change<string>('Enterprise_License', (license) => applyLicenseOrRemove(license, true));
// After the current license is already loaded, watch the setting value to react to new licenses being applied.
settings.change<string>('Enterprise_License', (license) => applyLicenseOrRemove(license, true));
callbacks.add('workspaceLicenseRemoved', () => License.remove());
callbacks.add('workspaceLicenseRemoved', () => License.remove());
callbacks.add('workspaceLicenseChanged', (updatedLicense) => applyLicense(updatedLicense, true));
callbacks.add('workspaceLicenseChanged', (updatedLicense) => applyLicense(updatedLicense, true));
License.onInstall(async () => void api.broadcast('license.actions', {} as Record<Partial<LicenseLimitKind>, boolean>));
License.onInstall(async () => void api.broadcast('license.actions', {} as Record<Partial<LicenseLimitKind>, boolean>));
License.onInvalidate(async () => void api.broadcast('license.actions', {} as Record<Partial<LicenseLimitKind>, boolean>));
License.onInvalidate(async () => void api.broadcast('license.actions', {} as Record<Partial<LicenseLimitKind>, boolean>));
License.onBehaviorTriggered('prevent_action', (context) => syncByTriggerDebounced(`prevent_action_${context.limit}`));
License.onBehaviorTriggered('prevent_action', (context) => syncByTriggerDebounced(`prevent_action_${context.limit}`));
License.onBehaviorTriggered('start_fair_policy', async (context) => syncByTriggerDebounced(`start_fair_policy_${context.limit}`));
License.onBehaviorTriggered('start_fair_policy', async (context) => syncByTriggerDebounced(`start_fair_policy_${context.limit}`));
License.onBehaviorTriggered('disable_modules', async (context) => syncByTriggerDebounced(`disable_modules_${context.limit}`));
License.onBehaviorTriggered('disable_modules', async (context) => syncByTriggerDebounced(`disable_modules_${context.limit}`));
License.onChange(() => api.broadcast('license.sync'));
License.onChange(() => api.broadcast('license.sync'));
License.onBehaviorToggled('prevent_action', (context) => {
if (!context.limit) {
return;
}
void api.broadcast('license.actions', {
[context.limit]: true,
} as Record<Partial<LicenseLimitKind>, boolean>);
});
License.onBehaviorToggled('prevent_action', (context) => {
if (!context.limit) {
return;
}
void api.broadcast('license.actions', {
[context.limit]: true,
} as Record<Partial<LicenseLimitKind>, boolean>);
});
License.onBehaviorToggled('allow_action', (context) => {
if (!context.limit) {
return;
}
void api.broadcast('license.actions', {
[context.limit]: false,
} as Record<Partial<LicenseLimitKind>, boolean>);
License.onBehaviorToggled('allow_action', (context) => {
if (!context.limit) {
return;
}
void api.broadcast('license.actions', {
[context.limit]: false,
} as Record<Partial<LicenseLimitKind>, boolean>);
});
});
});
License.setLicenseLimitCounter('activeUsers', () => Users.getActiveLocalUserCount());
License.setLicenseLimitCounter('guestUsers', () => Users.getActiveLocalGuestCount());
License.setLicenseLimitCounter('roomsPerGuest', async (context) => (context?.userId ? Subscriptions.countByUserId(context.userId) : 0));
License.setLicenseLimitCounter('privateApps', () => getAppCount('private'));
License.setLicenseLimitCounter('marketplaceApps', () => getAppCount('marketplace'));
License.setLicenseLimitCounter('monthlyActiveContacts', () => LivechatVisitors.countVisitorsOnPeriod(moment.utc().format('YYYY-MM')));
License.setLicenseLimitCounter('activeUsers', () => Users.getActiveLocalUserCount());
License.setLicenseLimitCounter('guestUsers', () => Users.getActiveLocalGuestCount());
License.setLicenseLimitCounter('roomsPerGuest', async (context) => (context?.userId ? Subscriptions.countByUserId(context.userId) : 0));
License.setLicenseLimitCounter('privateApps', () => getAppCount('private'));
License.setLicenseLimitCounter('marketplaceApps', () => getAppCount('marketplace'));
License.setLicenseLimitCounter('monthlyActiveContacts', () => LivechatVisitors.countVisitorsOnPeriod(moment.utc().format('YYYY-MM')));
};
import '../app/license/server/index';
import './models/startup';
import '../app/license/server';
import '../app/api-enterprise/server/index';
import '../app/authorization/server/index';
import '../app/canned-responses/server/index';
......@@ -11,3 +12,5 @@ import './requestSeatsRoute';
import './configuration/index';
import './local-services/ldap/service';
import './methods/getReadReceipts';
export { registerEEBroker } from './startup';
......@@ -8,7 +8,7 @@ import('./OmnichannelServiceLevelAgreements');
import('./AuditLog');
import('./ReadReceipts');
await License.onLicense('livechat-enterprise', () => {
void License.onLicense('livechat-enterprise', () => {
import('./CannedResponse');
import('./LivechatTag');
import('./LivechatUnit');
......
import { License } from '@rocket.chat/license';
import { Meteor } from 'meteor/meteor';
import { Apps } from '../../apps';
Meteor.startup(() => {
License.onInvalidateLicense(() => {
License.onInvalidateLicense(async () => {
const { Apps } = await import('../../apps');
void Apps.disableApps();
});
});
......@@ -11,12 +11,14 @@ import { api } from '@rocket.chat/core-services';
import { isRunningMs } from '../../../server/lib/isRunningMs';
// only starts network broker if running in micro services mode
if (isRunningMs()) {
const { broker } = await import('./broker');
export const registerEEBroker = async (): Promise<void> => {
// only starts network broker if running in micro services mode
if (isRunningMs()) {
const { broker } = await import('./broker');
api.setBroker(broker);
void api.start();
} else {
require('./presence');
}
api.setBroker(broker);
void api.start();
} else {
require('./presence');
}
};
import './api/methods';
import '../../personal-access-tokens/server';
......@@ -2,7 +2,9 @@ import type { LogLevelSetting } from '@rocket.chat/logger';
import { logLevel } from '@rocket.chat/logger';
import { Settings } from '@rocket.chat/models';
const LogLevel = await Settings.getValueById('Log_Level');
if (LogLevel) {
logLevel.emit('changed', LogLevel as LogLevelSetting);
}
export const configureLogLevel = async (): Promise<void> => {
const LogLevel = await Settings.getValueById('Log_Level');
if (LogLevel) {
logLevel.emit('changed', LogLevel as LogLevelSetting);
}
};
import './models/startup';
import './configureLogLevel';
import './settings/index';
import '../ee/server/models/startup';
import './services/startup';
import '../app/settings/server';
import '../lib/oauthRedirectUriServer';
/**
* ./settings uses top level await, in theory the settings creation
* and the startup should be done in parallel
*/
import './settings';
import { startLicense } from '../ee/app/license/server/startup';
import { registerEEBroker } from '../ee/server';
import { configureLogLevel } from './configureLogLevel';
import { registerServices } from './services/startup';
import { startup } from './startup';
import './lib/logger/startup';
import './importPackages';
import '../imports/startup/server';
import '../app/lib/server/startup';
import '../ee/server/startup';
import './startup';
import '../ee/server';
import './importPackages';
import './methods';
import './publications';
import './routes';
import '../lib/oauthRedirectUriServer';
import './lib/pushConfig';
import './configuration/accounts_meld';
import './configuration/ldap';
import './methods/OEmbedCacheCleanup';
import './methods/addAllUserToRoom';
import './methods/addRoomLeader';
import './methods/addRoomModerator';
import './methods/addRoomOwner';
import './methods/afterVerifyEmail';
import './methods/browseChannels';
import './methods/canAccessRoom';
import './methods/channelsList';
import './methods/createDirectMessage';
import './methods/deleteFileMessage';
import './methods/deleteUser';
import './methods/eraseRoom';
import './methods/getAvatarSuggestion';
import './methods/getPasswordPolicy';
import './methods/getRoomById';
import './methods/getRoomIdByNameOrId';
import './methods/getRoomNameById';
import './methods/getSetupWizardParameters';
import './methods/getTotalChannels';
import './methods/getUsersOfRoom';
import './methods/hideRoom';
import './methods/ignoreUser';
import './methods/loadHistory';
import './methods/loadLocale';
import './methods/loadMissedMessages';
import './methods/loadNextMessages';
import './methods/loadSurroundingMessages';
import './methods/logoutCleanUp';
import './methods/messageSearch';
import './methods/muteUserInRoom';
import './methods/openRoom';
import './methods/readMessages';
import './methods/readThreads';
import './methods/registerUser';
import './methods/removeRoomLeader';
import './methods/removeRoomModerator';
import './methods/removeRoomOwner';
import './methods/removeUserFromRoom';
import './methods/reportMessage';
import './methods/requestDataDownload';
import './methods/resetAvatar';
import './methods/roomNameExists';
import './methods/saveUserPreferences';
import './methods/saveUserProfile';
import './methods/sendConfirmationEmail';
import './methods/sendForgotPasswordEmail';
import './methods/setAvatarFromService';
import './methods/setUserActiveStatus';
import './methods/setUserPassword';
import './methods/toggleFavorite';
import './methods/unmuteUserInRoom';
import './methods/userPresence';
import './methods/userSetUtcOffset';
import './publications/messages';
import './publications/room';
import './publications/settings';
import './publications/spotlight';
import './publications/subscription';
import './routes/avatar';
import './routes/health';
import './routes/i18n';
import './routes/timesync';
import './routes/userDataDownload';
import './stream/stdout';
import './stream/stdout';
import './features/EmailInbox/index';
await (async () => {
await configureLogLevel();
await registerServices();
await import('../app/settings/server');
await registerEEBroker();
await startup();
await startLicense();
})();
import '../../imports/personal-access-tokens/server/api/methods';
import './OEmbedCacheCleanup';
import './addAllUserToRoom';
import './addRoomLeader';
import './addRoomModerator';
import './addRoomOwner';
import './afterVerifyEmail';
import './browseChannels';
import './canAccessRoom';
import './channelsList';
import './createDirectMessage';
import './deleteFileMessage';
import './deleteUser';
import './eraseRoom';
import './getAvatarSuggestion';
import './getPasswordPolicy';
import './getRoomById';
import './getRoomIdByNameOrId';
import './getRoomNameById';
import './getSetupWizardParameters';
import './getTotalChannels';
import './getUsersOfRoom';
import './hideRoom';
import './ignoreUser';
import './loadHistory';
import './loadLocale';
import './loadMissedMessages';
import './loadNextMessages';
import './loadSurroundingMessages';
import './logoutCleanUp';
import './messageSearch';
import './muteUserInRoom';
import './openRoom';
import './readMessages';
import './readThreads';
import './registerUser';
import './removeRoomLeader';
import './removeRoomModerator';
import './removeRoomOwner';
import './removeUserFromRoom';
import './reportMessage';
import './requestDataDownload';
import './resetAvatar';
import './roomNameExists';
import './saveUserPreferences';
import './saveUserProfile';
import './sendConfirmationEmail';
import './sendForgotPasswordEmail';
import './setAvatarFromService';
import './setUserActiveStatus';
import './setUserPassword';
import './toggleFavorite';
import './unmuteUserInRoom';
import './userPresence';
import './userSetUtcOffset';
import './messages';
import './room';
import './settings';
import './spotlight';
import './subscription';
import './avatar';
import './health';
import './i18n';
import './timesync';
import './userDataDownload';
......@@ -31,38 +31,38 @@ import { UploadService } from './upload/service';
import { VideoConfService } from './video-conference/service';
import { VoipService } from './voip/service';
const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo;
export const registerServices = async (): Promise<void> => {
const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo;
api.registerService(new AppsEngineService());
api.registerService(new AnalyticsService());
api.registerService(new AuthorizationLivechat());
api.registerService(new BannerService());
api.registerService(new CalendarService());
api.registerService(new LDAPService());
api.registerService(new MediaService());
api.registerService(new MeteorService());
api.registerService(new NPSService());
api.registerService(new RoomService());
api.registerService(new SAUMonitorService());
api.registerService(new VoipService(db));
api.registerService(new OmnichannelService());
api.registerService(new OmnichannelVoipService());
api.registerService(new TeamService());
api.registerService(new UiKitCoreAppService());
api.registerService(new PushService());
api.registerService(new DeviceManagementService());
api.registerService(new VideoConfService());
api.registerService(new UploadService());
api.registerService(new MessageService());
api.registerService(new TranslationService());
api.registerService(new SettingsService());
api.registerService(new OmnichannelIntegrationService());
api.registerService(new ImportService());
api.registerService(new OmnichannelAnalyticsService());
api.registerService(new AppsEngineService());
api.registerService(new AnalyticsService());
api.registerService(new AuthorizationLivechat());
api.registerService(new BannerService());
api.registerService(new CalendarService());
api.registerService(new LDAPService());
api.registerService(new MediaService());
api.registerService(new MeteorService());
api.registerService(new NPSService());
api.registerService(new RoomService());
api.registerService(new SAUMonitorService());
api.registerService(new VoipService(db));
api.registerService(new OmnichannelService());
api.registerService(new OmnichannelVoipService());
api.registerService(new TeamService());
api.registerService(new UiKitCoreAppService());
api.registerService(new PushService());
api.registerService(new DeviceManagementService());
api.registerService(new VideoConfService());
api.registerService(new UploadService());
api.registerService(new MessageService());
api.registerService(new TranslationService());
api.registerService(new SettingsService());
api.registerService(new OmnichannelIntegrationService());
api.registerService(new ImportService());
api.registerService(new OmnichannelAnalyticsService());
// if the process is running in micro services mode we don't need to register services that will run separately
if (!isRunningMs()) {
void (async (): Promise<void> => {
// if the process is running in micro services mode we don't need to register services that will run separately
if (!isRunningMs()) {
const { Presence } = await import('@rocket.chat/presence');
const { Authorization } = await import('./authorization/service');
......@@ -75,5 +75,5 @@ if (!isRunningMs()) {
// Always register the service and manage licensing inside the service (tbd)
api.registerService(new QueueWorker(db, Logger));
api.registerService(new OmnichannelTranscript(Logger));
})();
}
}
};
......@@ -37,47 +37,43 @@ import { createVConfSettings } from './video-conference';
import { createWebDavSettings } from './webdav';
import { createWebRTCSettings } from './webrtc';
async function createSettings() {
await Promise.all([
createAccountSettings(),
createAnalyticsSettings(),
createAssetsSettings(),
createBotsSettings(),
createCallCenterSettings(),
createCasSettings(),
createCrowdSettings(),
createEmojiSettings(),
createSoundsSettings(),
createDiscussionsSettings(),
createEmailSettings(),
createE2ESettings(),
createFederationSettings(),
createFileUploadSettings(),
createGeneralSettings(),
createIRCSettings(),
createLdapSettings(),
createLogSettings(),
createLayoutSettings(),
createMessageSettings(),
createMetaSettings(),
createMiscSettings(),
createMobileSettings(),
createOauthSettings(),
createOmniSettings(),
createOTRSettings(),
createPushSettings(),
createRateLimitSettings(),
createRetentionSettings(),
createSetupWSettings(),
createSlackBridgeSettings(),
createSmarshSettings(),
createThreadSettings(),
createTroubleshootSettings(),
createVConfSettings(),
createUserDataSettings(),
createWebDavSettings(),
createWebRTCSettings(),
]);
}
await createSettings();
await Promise.all([
createAccountSettings(),
createAnalyticsSettings(),
createAssetsSettings(),
createBotsSettings(),
createCallCenterSettings(),
createCasSettings(),
createCrowdSettings(),
createEmojiSettings(),
createSoundsSettings(),
createDiscussionsSettings(),
createEmailSettings(),
createE2ESettings(),
createFederationSettings(),
createFileUploadSettings(),
createGeneralSettings(),
createIRCSettings(),
createLdapSettings(),
createLogSettings(),
createLayoutSettings(),
createMessageSettings(),
createMetaSettings(),
createMiscSettings(),
createMobileSettings(),
createOauthSettings(),
createOmniSettings(),
createOTRSettings(),
createPushSettings(),
createRateLimitSettings(),
createRetentionSettings(),
createSetupWSettings(),
createSlackBridgeSettings(),
createSmarshSettings(),
createThreadSettings(),
createTroubleshootSettings(),
createVConfSettings(),
createUserDataSettings(),
createWebDavSettings(),
createWebRTCSettings(),
]);
import './migrations';
import './appcache';
import './callbacks';
import './cron';
......@@ -10,9 +9,13 @@ import '../hooks';
import '../lib/rooms/roomTypes';
import '../lib/settingsRegenerator';
import { isRunningMs } from '../lib/isRunningMs';
import { performMigrationProcedure } from './migrations';
// only starts network broker if running in micro services mode
if (!isRunningMs()) {
require('./localServices');
require('./watchDb');
}
export const startup = async () => {
await performMigrationProcedure();
// only starts network broker if running in micro services mode
if (!isRunningMs()) {
require('./localServices');
require('./watchDb');
}
};
......@@ -37,4 +37,5 @@ import './v300';
import './v301';
import './v303';
import './v304';
import './xrun';
export * from './xrun';
......@@ -6,10 +6,11 @@ const { MIGRATION_VERSION = 'latest' } = process.env;
const [version, ...subcommands] = MIGRATION_VERSION.split(',');
await migrateDatabase(version === 'latest' ? version : parseInt(version), subcommands);
// perform operations when the server is starting with a different version
await onServerVersionChange(async () => {
await upsertPermissions();
await ensureCloudWorkspaceRegistered();
});
export const performMigrationProcedure = async (): Promise<void> => {
await migrateDatabase(version === 'latest' ? version : parseInt(version), subcommands);
// perform operations when the server is starting with a different version
await onServerVersionChange(async () => {
await upsertPermissions();
await ensureCloudWorkspaceRegistered();
});
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment