diff --git a/apps/meteor/definition/externals/meteor/meteor.d.ts b/apps/meteor/definition/externals/meteor/meteor.d.ts index a465ad3687b46..a52e0fec2b633 100644 --- a/apps/meteor/definition/externals/meteor/meteor.d.ts +++ b/apps/meteor/definition/externals/meteor/meteor.d.ts @@ -8,7 +8,7 @@ type StringifyBuffers = { declare global { namespace Assets { - function getBinaryAsync(assetPath: string): Promise; + function getBinaryAsync(assetPath: string): Promise; function getTextAsync(assetPath: string): Promise; } diff --git a/apps/meteor/server/startup/initialData.js b/apps/meteor/server/startup/initialData.ts similarity index 83% rename from apps/meteor/server/startup/initialData.js rename to apps/meteor/server/startup/initialData.ts index 7d7a9fdec96d2..be73e6ea2c79d 100644 --- a/apps/meteor/server/startup/initialData.js +++ b/apps/meteor/server/startup/initialData.ts @@ -1,3 +1,4 @@ +import { UserStatus, type IUser } from '@rocket.chat/core-typings'; import { Settings, Rooms, Users, Roles } from '@rocket.chat/models'; import { validateEmail } from '@rocket.chat/tools'; import colors from 'colors/safe'; @@ -16,19 +17,16 @@ import { addUserRolesAsync } from '../lib/roles/addUserRoles'; export async function insertAdminUserFromEnv() { if (process.env.ADMIN_PASS) { if ((await Roles.countUsersInRole('admin')) === 0) { - const adminUser = { - name: 'Administrator', + const adminUser: Partial = { + name: process.env.ADMIN_NAME || 'Administrator', username: 'admin', - status: 'offline', - statusDefault: 'online', + status: UserStatus.OFFLINE, + statusDefault: UserStatus.ONLINE, utcOffset: 0, active: true, + type: 'user', }; - if (process.env.ADMIN_NAME) { - adminUser.name = process.env.ADMIN_NAME; - } - console.log(colors.green(`Name: ${adminUser.name}`)); if (process.env.ADMIN_EMAIL) { @@ -75,8 +73,6 @@ export async function insertAdminUserFromEnv() { console.log(colors.green(`Username: ${adminUser.username}`)); - adminUser.type = 'user'; - const { insertedId: userId } = await Users.create(adminUser); await Accounts.setPasswordAsync(userId, process.env.ADMIN_PASS); @@ -137,8 +133,8 @@ Meteor.startup(async () => { _id: 'rocket.cat', name: 'Rocket.Cat', username: 'rocket.cat', - status: 'online', - statusDefault: 'online', + status: UserStatus.ONLINE, + statusDefault: UserStatus.ONLINE, utcOffset: 0, active: true, type: 'bot', @@ -146,20 +142,23 @@ Meteor.startup(async () => { await addUserRolesAsync('rocket.cat', ['bot']); - const buffer = Buffer.from(await Assets.getBinaryAsync('avatars/rocketcat.png')); + const asset = await Assets.getBinaryAsync('avatars/rocketcat.png'); + if (asset) { + const buffer = Buffer.from(asset); - const rs = RocketChatFile.bufferToStream(buffer, 'utf8'); - const fileStore = FileUpload.getStore('Avatars'); - await fileStore.deleteByName('rocket.cat'); + const rs = RocketChatFile.bufferToStream(buffer); + const fileStore = FileUpload.getStore('Avatars'); + await fileStore.deleteByName('rocket.cat'); - const file = { - userId: 'rocket.cat', - type: 'image/png', - size: buffer.length, - }; + const file = { + userId: 'rocket.cat', + type: 'image/png', + size: buffer.length, + }; - const upload = await fileStore.insert(file, rs); - await Users.setAvatarData('rocket.cat', 'local', upload.etag); + const upload = await fileStore.insert(file, rs); + await Users.setAvatarData('rocket.cat', 'local', upload.etag); + } } } catch (error) { console.log( @@ -211,7 +210,7 @@ Meteor.startup(async () => { if (process.env.TEST_MODE === 'true') { console.log(colors.green('Inserting admin test user:')); - const adminUser = { + const adminUser: Omit = { _id: 'rocketchat.internal.admin.test', name: 'RocketChat Internal Admin Test', username: 'rocketchat.internal.admin.test', @@ -221,23 +220,23 @@ Meteor.startup(async () => { verified: true, }, ], - status: 'offline', - statusDefault: 'online', + status: UserStatus.OFFLINE, + statusDefault: UserStatus.ONLINE, utcOffset: 0, active: true, type: 'user', }; console.log(colors.green(`Name: ${adminUser.name}`)); - console.log(colors.green(`Email: ${adminUser.emails[0].address}`)); + console.log(colors.green(`Email: ${adminUser.emails![0].address}`)); console.log(colors.green(`Username: ${adminUser.username}`)); console.log(colors.green(`Password: ${adminUser._id}`)); - if (await Users.findOneByEmailAddress(adminUser.emails[0].address)) { - throw new Meteor.Error(`Email ${adminUser.emails[0].address} already exists`, "Rocket.Chat can't run in test mode"); + if (await Users.findOneByEmailAddress(adminUser.emails![0].address)) { + throw new Meteor.Error(`Email ${adminUser.emails![0].address} already exists`, "Rocket.Chat can't run in test mode"); } - if (!(await checkUsernameAvailability(adminUser.username))) { + if (!(await checkUsernameAvailability(adminUser.username!))) { throw new Meteor.Error(`Username ${adminUser.username} already exists`, "Rocket.Chat can't run in test mode"); } @@ -252,7 +251,7 @@ Meteor.startup(async () => { void notifyOnSettingChangedById('Show_Setup_Wizard'); } - await addUserToDefaultChannels(adminUser, true); + await addUserToDefaultChannels(adminUser as IUser, true); // Create sample call history for API tests return addCallHistoryTestData('rocketchat.internal.admin.test', 'rocket.cat'); diff --git a/apps/meteor/server/startup/serverRunning.js b/apps/meteor/server/startup/serverRunning.ts similarity index 87% rename from apps/meteor/server/startup/serverRunning.js rename to apps/meteor/server/startup/serverRunning.ts index 9aa0c00e769da..3bb9433ecc4fd 100644 --- a/apps/meteor/server/startup/serverRunning.js +++ b/apps/meteor/server/startup/serverRunning.ts @@ -13,7 +13,7 @@ import { getMongoInfo } from '../../app/utils/server/functions/getMongoInfo'; // import { sendMessagesToAdmins } from '../lib/sendMessagesToAdmins'; import { showErrorBox, showSuccessBox } from '../lib/logger/showBox'; -const exitIfNotBypassed = (ignore, errorCode = 1) => { +const exitIfNotBypassed = (ignore: string | undefined, errorCode = 1) => { if (typeof ignore === 'string' && ['yes', 'true'].includes(ignore.toLowerCase())) { return; } @@ -28,10 +28,16 @@ Meteor.startup(async () => { const { mongoVersion, mongoStorageEngine } = await getMongoInfo(); const desiredNodeVersion = semver.clean(fs.readFileSync(path.join(process.cwd(), '../../.node_version.txt')).toString()); - const desiredNodeVersionMajor = String(semver.parse(desiredNodeVersion).major); + const parsedSemVer = semver.parse(desiredNodeVersion); + if (!parsedSemVer) { + console.error('Failed to parse desired Node.js version from .node_version.txt'); + process.exit(1); + } + + const desiredNodeVersionMajor = String(parsedSemVer.major); return setTimeout(async () => { - let msg = [ + let msg: string | string[] = [ `Rocket.Chat Version: ${Info.version}`, ` NodeJS Version: ${process.versions.node} - ${process.arch}`, ` MongoDB Version: ${mongoVersion}`, @@ -41,11 +47,11 @@ Meteor.startup(async () => { ` Site URL: ${settings.get('Site_Url')}`, ]; - if (Info.commit && Info.commit.hash) { + if (Info.commit?.hash) { msg.push(` Commit Hash: ${Info.commit.hash.substr(0, 10)}`); } - if (Info.commit && Info.commit.branch) { + if (Info.commit?.branch) { msg.push(` Commit Branch: ${Info.commit.branch}`); } @@ -63,7 +69,9 @@ Meteor.startup(async () => { exitIfNotBypassed(process.env.BYPASS_NODEJS_VALIDATION); } - if (semver.satisfies(semver.coerce(mongoVersion), '<7.0.0')) { + const mongoSemver = semver.coerce(mongoVersion); + + if (!mongoSemver || semver.satisfies(mongoSemver, '<7.0.0')) { msg += ['', '', 'YOUR CURRENT MONGODB VERSION IS NOT SUPPORTED BY ROCKET.CHAT,', 'PLEASE UPGRADE TO VERSION 7.0 OR LATER'].join('\n'); showErrorBox('SERVER ERROR', msg); diff --git a/packages/model-typings/src/models/IRoomsModel.ts b/packages/model-typings/src/models/IRoomsModel.ts index 5a89147e47220..2639f6adcb3a7 100644 --- a/packages/model-typings/src/models/IRoomsModel.ts +++ b/packages/model-typings/src/models/IRoomsModel.ts @@ -299,7 +299,7 @@ export interface IRoomsModel extends IBaseModel { saveRetentionOverrideGlobalById(rid: string, retentionOverrideGlobal: boolean): Promise; saveEncryptedById(rid: string, encrypted: boolean): Promise; updateGroupDMsRemovingUsernamesByUsername(username: string, userId: string): Promise; - createWithIdTypeAndName(id: string, type: IRoom['t'], name: string, extraData?: Record): Promise; + createWithIdTypeAndName(id: string, type: IRoom['t'], name: string, extraData?: Record): Promise; createWithFullRoomData(room: Omit): Promise; removeById(rid: string): Promise; removeByIds(rids: string[]): Promise; diff --git a/packages/models/src/models/Rooms.ts b/packages/models/src/models/Rooms.ts index 81edc91ae703e..9bcac18cf72fe 100644 --- a/packages/models/src/models/Rooms.ts +++ b/packages/models/src/models/Rooms.ts @@ -2041,7 +2041,7 @@ export class RoomsRaw extends BaseRaw implements IRoomsModel { _id: IRoom['_id'], type: IRoom['t'], name: IRoom['name'], - extraData?: Record, + extraData?: Record, ): Promise { const room: IRoom = { _id,