chore: Remove references to EE code from the app events (#31775)

Co-authored-by: Guilherme Gazzo <guilhermegazzo@gmail.com>
pull/31922/head
Pierre Lehnen 2 years ago committed by GitHub
parent 34fd7e74cd
commit a6802cacaf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      apps/meteor/app/authentication/server/startup/index.js
  2. 4
      apps/meteor/app/file-upload/server/lib/FileUpload.ts
  3. 6
      apps/meteor/app/lib/server/functions/addUserToRoom.ts
  4. 11
      apps/meteor/app/lib/server/functions/createDirectRoom.ts
  5. 11
      apps/meteor/app/lib/server/functions/createRoom.ts
  6. 10
      apps/meteor/app/lib/server/functions/deleteMessage.ts
  7. 6
      apps/meteor/app/lib/server/functions/removeUserFromRoom.ts
  8. 4
      apps/meteor/app/lib/server/functions/saveUser.js
  9. 2
      apps/meteor/app/lib/server/functions/sendMessage.ts
  10. 35
      apps/meteor/app/lib/server/functions/updateMessage.ts
  11. 4
      apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts
  12. 10
      apps/meteor/app/livechat/server/lib/Helper.ts
  13. 10
      apps/meteor/app/livechat/server/lib/LivechatTyped.ts
  14. 4
      apps/meteor/app/livechat/server/lib/RoutingManager.ts
  15. 4
      apps/meteor/app/mailer/server/api.ts
  16. 6
      apps/meteor/app/message-pin/server/pinMessage.ts
  17. 4
      apps/meteor/app/message-star/server/starMessage.ts
  18. 4
      apps/meteor/app/reactions/server/setReaction.ts
  19. 15
      apps/meteor/app/statistics/server/lib/getAppsStatistics.js
  20. 4
      apps/meteor/app/threads/server/methods/followMessage.ts
  21. 4
      apps/meteor/app/threads/server/methods/unfollowMessage.ts
  22. 2
      apps/meteor/ee/server/apps/index.ts
  23. 4
      apps/meteor/ee/server/apps/orchestrator.js
  24. 4
      apps/meteor/server/lib/moderation/reportMessage.ts
  25. 4
      apps/meteor/server/methods/deleteUser.ts
  26. 6
      apps/meteor/server/methods/eraseRoom.ts
  27. 4
      apps/meteor/server/methods/logoutCleanUp.ts
  28. 4
      apps/meteor/server/methods/reportMessage.ts
  29. 4
      apps/meteor/server/methods/saveUserProfile.ts
  30. 58
      apps/meteor/server/services/apps-engine/service.ts
  31. 4
      apps/meteor/server/services/video-conference/service.ts
  32. 11
      apps/meteor/server/startup/migrations/v291.ts
  33. 6
      apps/meteor/server/startup/migrations/v292.ts
  34. 6
      apps/meteor/server/startup/migrations/v294.ts
  35. 3
      packages/apps/src/AppsEngine.ts
  36. 8
      packages/apps/src/IAppServerOrchestrator.ts
  37. 48
      packages/apps/src/bridges/IListenerBridge.ts
  38. 3
      packages/apps/src/index.ts
  39. 7
      packages/apps/src/orchestrator.ts
  40. 4
      yarn.lock

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { Roles, Settings, Users } from '@rocket.chat/models';
import { escapeRegExp, escapeHTML } from '@rocket.chat/string-helpers';
import { Accounts } from 'meteor/accounts-base';
@ -5,7 +6,6 @@ import { Match } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';
import { AppEvents, Apps } from '../../../../ee/server/apps/orchestrator';
import { callbacks } from '../../../../lib/callbacks';
import { beforeCreateUserCallback } from '../../../../lib/callbacks/beforeCreateUserCallback';
import { parseCSV } from '../../../../lib/utils/parseCSV';
@ -350,8 +350,8 @@ const insertUserDocAsync = async function (options, user) {
if (!options.skipAppsEngineEvent) {
// `post` triggered events don't need to wait for the promise to resolve
Apps.triggerEvent(AppEvents.IPostUserCreated, { user, performedBy: await safeGetMeteorUser() }).catch((e) => {
Apps.getRocketChatLogger().error('Error while executing post user created event:', e);
Apps?.triggerEvent(AppEvents.IPostUserCreated, { user, performedBy: await safeGetMeteorUser() }).catch((e) => {
Apps?.getRocketChatLogger().error('Error while executing post user created event:', e);
});
}
@ -424,7 +424,7 @@ const validateLoginAttemptAsync = async function (login) {
*/
if (login.type !== 'resume') {
// App IPostUserLoggedIn event hook
await Apps.triggerEvent(AppEvents.IPostUserLoggedIn, login.user);
await Apps?.triggerEvent(AppEvents.IPostUserLoggedIn, login.user);
}
return true;

@ -8,6 +8,7 @@ import stream from 'stream';
import URL from 'url';
import { hashLoginToken } from '@rocket.chat/account-utils';
import { Apps, AppEvents } from '@rocket.chat/apps';
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
import type { IUpload } from '@rocket.chat/core-typings';
import { Users, Avatars, UserDataFiles, Uploads, Settings, Subscriptions, Messages, Rooms } from '@rocket.chat/models';
@ -21,7 +22,6 @@ import sharp from 'sharp';
import type { WritableStreamBuffer } from 'stream-buffers';
import streamBuffers from 'stream-buffers';
import { AppEvents, Apps } from '../../../../ee/server/apps';
import { i18n } from '../../../../server/lib/i18n';
import { SystemLogger } from '../../../../server/lib/logger/system';
import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator';
@ -177,7 +177,7 @@ export const FileUpload = {
// App IPreFileUpload event hook
try {
await Apps.triggerEvent(AppEvents.IPreFileUpload, { file, content: content || Buffer.from([]) });
await Apps?.triggerEvent(AppEvents.IPreFileUpload, { file, content: content || Buffer.from([]) });
} catch (error: any) {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
import { Message, Team } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
@ -5,7 +6,6 @@ import { Subscriptions, Users, Rooms } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import { RoomMemberActions } from '../../../../definition/IRoomTypeConfig';
import { AppEvents, Apps } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig';
import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator';
@ -54,7 +54,7 @@ export const addUserToRoom = async function (
}
try {
await Apps.triggerEvent(AppEvents.IPreRoomUserJoined, room, userToBeAdded, inviter);
await Apps?.triggerEvent(AppEvents.IPreRoomUserJoined, room, userToBeAdded, inviter);
} catch (error: any) {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
@ -118,7 +118,7 @@ export const addUserToRoom = async function (
// Keep the current event
await callbacks.run('afterJoinRoom', userToBeAdded, room);
void Apps.triggerEvent(AppEvents.IPostRoomUserJoined, room, userToBeAdded, inviter);
void Apps?.triggerEvent(AppEvents.IPostRoomUserJoined, room, userToBeAdded, inviter);
});
}

@ -1,3 +1,4 @@
import { AppEvents, Apps } from '@rocket.chat/apps';
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
import type { ISubscriptionExtraData } from '@rocket.chat/core-services';
import type { ICreatedRoom, IRoom, ISubscription, IUser } from '@rocket.chat/core-typings';
@ -6,7 +7,6 @@ import { Random } from '@rocket.chat/random';
import { Meteor } from 'meteor/meteor';
import type { MatchKeysAndValues } from 'mongodb';
import { Apps } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { isTruthy } from '../../../../lib/isTruthy';
import { settings } from '../../../settings/server';
@ -104,7 +104,7 @@ export async function createDirectRoom(
_USERNAMES: usernames,
};
const prevent = await Apps.triggerEvent('IPreRoomCreatePrevent', tmpRoom).catch((error) => {
const prevent = await Apps?.triggerEvent(AppEvents.IPreRoomCreatePrevent, tmpRoom).catch((error) => {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
}
@ -116,7 +116,10 @@ export async function createDirectRoom(
throw new Meteor.Error('error-app-prevented', 'A Rocket.Chat App prevented the room creation.');
}
const result = await Apps.triggerEvent('IPreRoomCreateModify', await Apps.triggerEvent('IPreRoomCreateExtend', tmpRoom));
const result = await Apps?.triggerEvent(
AppEvents.IPreRoomCreateModify,
await Apps?.triggerEvent(AppEvents.IPreRoomCreateExtend, tmpRoom),
);
if (typeof result === 'object') {
Object.assign(roomInfo, result);
@ -170,7 +173,7 @@ export async function createDirectRoom(
await callbacks.run('afterCreateDirectRoom', insertedRoom, { members: roomMembers, creatorId: options?.creator });
void Apps.triggerEvent('IPostRoomCreate', insertedRoom);
void Apps?.triggerEvent(AppEvents.IPostRoomCreate, insertedRoom);
}
return {

@ -1,4 +1,5 @@
/* eslint-disable complexity */
import { AppEvents, Apps } from '@rocket.chat/apps';
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
import { Message, Team } from '@rocket.chat/core-services';
import type { ICreateRoomParams, ISubscriptionExtraData } from '@rocket.chat/core-services';
@ -6,7 +7,6 @@ import type { ICreatedRoom, IUser, IRoom, RoomType } from '@rocket.chat/core-typ
import { Rooms, Subscriptions, Users } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import { Apps } from '../../../../ee/server/apps/orchestrator';
import { callbacks } from '../../../../lib/callbacks';
import { beforeCreateRoomCallback } from '../../../../lib/callbacks/beforeCreateRoomCallback';
import { getSubscriptionAutotranslateDefaultConfig } from '../../../../server/lib/getSubscriptionAutotranslateDefaultConfig';
@ -197,7 +197,7 @@ export const createRoom = async <T extends RoomType>(
_USERNAMES: members,
};
const prevent = await Apps.triggerEvent('IPreRoomCreatePrevent', tmp).catch((error) => {
const prevent = await Apps?.triggerEvent(AppEvents.IPreRoomCreatePrevent, tmp).catch((error) => {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
}
@ -209,7 +209,10 @@ export const createRoom = async <T extends RoomType>(
throw new Meteor.Error('error-app-prevented', 'A Rocket.Chat App prevented the room creation.');
}
const eventResult = await Apps.triggerEvent('IPreRoomCreateModify', await Apps.triggerEvent('IPreRoomCreateExtend', tmp));
const eventResult = await Apps?.triggerEvent(
AppEvents.IPreRoomCreateModify,
await Apps.triggerEvent(AppEvents.IPreRoomCreateExtend, tmp),
);
if (eventResult && typeof eventResult === 'object' && delete eventResult._USERNAMES) {
Object.assign(roomProps, eventResult);
@ -241,7 +244,7 @@ export const createRoom = async <T extends RoomType>(
callbacks.runAsync('federation.afterCreateFederatedRoom', room, { owner, originalMemberList: members });
}
void Apps.triggerEvent('IPostRoomCreate', room);
void Apps?.triggerEvent(AppEvents.IPostRoomCreate, room);
return {
rid: room._id, // backwards compatible
inserted: true,

@ -1,9 +1,9 @@
import { AppEvents, Apps } from '@rocket.chat/apps';
import { api } from '@rocket.chat/core-services';
import type { AtLeast, IMessage, IUser } from '@rocket.chat/core-typings';
import { Messages, Rooms, Uploads, Users, ReadReceipts } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import { Apps } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages';
import { canDeleteMessageAsync } from '../../../authorization/server/functions/canDeleteMessage';
@ -29,14 +29,14 @@ export const deleteMessageValidatingPermission = async (message: AtLeast<IMessag
};
export async function deleteMessage(message: IMessage, user: IUser): Promise<void> {
const deletedMsg = await Messages.findOneById(message._id);
const deletedMsg: IMessage | null = await Messages.findOneById(message._id);
const isThread = (deletedMsg?.tcount || 0) > 0;
const keepHistory = settings.get('Message_KeepHistory') || isThread;
const showDeletedStatus = settings.get('Message_ShowDeletedStatus') || isThread;
const bridges = Apps?.isLoaded() && Apps.getBridges();
if (deletedMsg && bridges) {
const prevent = await bridges.getListenerBridge().messageEvent('IPreMessageDeletePrevent', deletedMsg);
const prevent = await bridges.getListenerBridge().messageEvent(AppEvents.IPreMessageDeletePrevent, deletedMsg);
if (prevent) {
throw new Meteor.Error('error-app-prevented-deleting', 'A Rocket.Chat App prevented the message deleting.');
}
@ -95,7 +95,7 @@ export async function deleteMessage(message: IMessage, user: IUser): Promise<voi
});
}
if (bridges) {
void bridges.getListenerBridge().messageEvent('IPostMessageDeleted', deletedMsg, user);
if (bridges && deletedMsg) {
void bridges.getListenerBridge().messageEvent(AppEvents.IPostMessageDeleted, deletedMsg, user);
}
}

@ -1,10 +1,10 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
import { Message, Team } from '@rocket.chat/core-services';
import type { IUser } from '@rocket.chat/core-typings';
import { Subscriptions, Rooms } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import { AppEvents, Apps } from '../../../../ee/server/apps/orchestrator';
import { afterLeaveRoomCallback } from '../../../../lib/callbacks/afterLeaveRoomCallback';
import { beforeLeaveRoomCallback } from '../../../../lib/callbacks/beforeLeaveRoomCallback';
@ -20,7 +20,7 @@ export const removeUserFromRoom = async function (
}
try {
await Apps.triggerEvent(AppEvents.IPreRoomUserLeave, room, user);
await Apps?.triggerEvent(AppEvents.IPreRoomUserLeave, room, user);
} catch (error: any) {
if (error.name === AppsEngineException.name) {
throw new Meteor.Error('error-app-prevented', error.message);
@ -67,5 +67,5 @@ export const removeUserFromRoom = async function (
// TODO: CACHE: maybe a queue?
await afterLeaveRoomCallback.run(user, room);
await Apps.triggerEvent(AppEvents.IPostRoomUserLeave, room, user);
await Apps?.triggerEvent(AppEvents.IPostRoomUserLeave, room, user);
};

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { isUserFederated } from '@rocket.chat/core-typings';
import { Users } from '@rocket.chat/models';
import Gravatar from 'gravatar';
@ -5,7 +6,6 @@ import { Accounts } from 'meteor/accounts-base';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';
import { AppEvents, Apps } from '../../../../ee/server/apps/orchestrator';
import { callbacks } from '../../../../lib/callbacks';
import { trim } from '../../../../lib/utils/stringUtils';
import { getNewUserRoles } from '../../../../server/services/user/lib/getNewUserRoles';
@ -434,7 +434,7 @@ export const saveUser = async function (userId, userData) {
oldUser: oldUserData,
});
await Apps.triggerEvent(AppEvents.IPostUserUpdated, {
await Apps?.triggerEvent(AppEvents.IPostUserUpdated, {
user: userUpdated,
previousUser: oldUserData,
performedBy: await safeGetMeteorUser(),

@ -1,9 +1,9 @@
import { Apps } from '@rocket.chat/apps';
import { Message } from '@rocket.chat/core-services';
import type { IMessage, IRoom } from '@rocket.chat/core-typings';
import { Messages } from '@rocket.chat/models';
import { Match, check } from 'meteor/check';
import { Apps } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { isRelativeURL } from '../../../../lib/utils/isRelativeURL';
import { isURL } from '../../../../lib/utils/isURL';

@ -1,9 +1,9 @@
import { AppEvents, Apps } from '@rocket.chat/apps';
import { Message } from '@rocket.chat/core-services';
import type { IEditedMessage, IMessage, IUser, AtLeast } from '@rocket.chat/core-typings';
import type { IMessage, IUser, AtLeast } from '@rocket.chat/core-typings';
import { Messages, Rooms } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';
import { Apps } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages';
import { settings } from '../../../settings/server';
@ -16,31 +16,33 @@ export const updateMessage = async function (
previewUrls?: string[],
): Promise<void> {
const originalMessage = originalMsg || (await Messages.findOneById(message._id));
if (!originalMessage) {
throw new Error('Invalid message ID.');
}
let messageData: IMessage = Object.assign({}, originalMessage, message);
// For the Rocket.Chat Apps :)
if (message && Apps && Apps.isLoaded()) {
const appMessage = Object.assign({}, originalMessage, message);
const prevent = await Apps.getBridges()?.getListenerBridge().messageEvent('IPreMessageUpdatedPrevent', appMessage);
const prevent = await Apps.getBridges().getListenerBridge().messageEvent(AppEvents.IPreMessageUpdatedPrevent, messageData);
if (prevent) {
throw new Meteor.Error('error-app-prevented-updating', 'A Rocket.Chat App prevented the message updating.');
}
let result;
result = await Apps.getBridges()?.getListenerBridge().messageEvent('IPreMessageUpdatedExtend', appMessage);
result = await Apps.getBridges()?.getListenerBridge().messageEvent('IPreMessageUpdatedModify', result);
let result = await Apps.getBridges().getListenerBridge().messageEvent(AppEvents.IPreMessageUpdatedExtend, messageData);
result = await Apps.getBridges().getListenerBridge().messageEvent(AppEvents.IPreMessageUpdatedModify, result);
if (typeof result === 'object') {
message = Object.assign(appMessage, result);
Object.assign(messageData, result);
}
}
// If we keep history of edits, insert a new message to store history information
if (settings.get('Message_KeepHistory')) {
await Messages.cloneAndSaveAsHistoryById(message._id, user as Required<Pick<IUser, '_id' | 'username' | 'name'>>);
await Messages.cloneAndSaveAsHistoryById(messageData._id, user as Required<Pick<IUser, '_id' | 'username' | 'name'>>);
}
Object.assign<AtLeast<IMessage, '_id' | 'rid' | 'msg'>, Omit<IEditedMessage, keyof IMessage>>(message, {
Object.assign(messageData, {
editedAt: new Date(),
editedBy: {
_id: user._id,
@ -48,17 +50,16 @@ export const updateMessage = async function (
},
});
parseUrlsInMessage(message, previewUrls);
parseUrlsInMessage(messageData, previewUrls);
const room = await Rooms.findOneById(message.rid);
const room = await Rooms.findOneById(messageData.rid);
if (!room) {
return;
}
// TODO remove type cast
message = await Message.beforeSave({ message: message as IMessage, room, user });
messageData = await Message.beforeSave({ message: messageData, room, user });
const { _id, ...editedMessage } = message;
const { _id, ...editedMessage } = messageData;
if (!editedMessage.msg) {
delete editedMessage.md;
@ -78,7 +79,7 @@ export const updateMessage = async function (
if (Apps?.isLoaded()) {
// This returns a promise, but it won't mutate anything about the message
// so, we don't really care if it is successful or fails
void Apps.getBridges()?.getListenerBridge().messageEvent('IPostMessageUpdated', message);
void Apps.getBridges()?.getListenerBridge().messageEvent(AppEvents.IPostMessageUpdated, messageData);
}
setImmediate(async () => {

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { Users } from '@rocket.chat/models';
import { SHA256 } from '@rocket.chat/sha256';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
@ -5,7 +6,6 @@ import { Accounts } from 'meteor/accounts-base';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { AppEvents, Apps } from '../../../../ee/server/apps/orchestrator';
import { trim } from '../../../../lib/utils/stringUtils';
import { settings } from '../../../settings/server';
import { deleteUser } from '../functions/deleteUser';
@ -66,7 +66,7 @@ Meteor.methods<ServerMethods>({
await deleteUser(uid, confirmRelinquish);
// App IPostUserDeleted event hook
await Apps.triggerEvent(AppEvents.IPostUserDeleted, { user });
await Apps?.triggerEvent(AppEvents.IPostUserDeleted, { user });
return true;
},

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { LivechatTransferEventType } from '@rocket.chat/apps-engine/definition/livechat';
import { api, Message, Omnichannel } from '@rocket.chat/core-services';
import type {
@ -30,7 +31,6 @@ import {
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { Apps, AppEvents } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { validateEmail as validatorFunc } from '../../../../lib/emailValidator';
import { i18n } from '../../../../server/lib/i18n';
@ -118,7 +118,7 @@ export const createLivechatRoom = async (
const roomId = (await Rooms.insertOne(room)).insertedId;
void Apps.triggerEvent(AppEvents.IPostLivechatRoomStarted, room);
void Apps?.triggerEvent(AppEvents.IPostLivechatRoomStarted, room);
await callbacks.run('livechat.newRoom', room);
await sendMessage(guest, { t: 'livechat-started', msg: '', groupable: false }, room);
@ -274,7 +274,7 @@ export const removeAgentFromSubscription = async (rid: string, { _id, username }
await Message.saveSystemMessage('ul', rid, username || '', { _id: user._id, username: user.username, name: user.name });
setImmediate(() => {
void Apps.triggerEvent(AppEvents.IPostLivechatAgentUnassigned, { room, user });
void Apps?.triggerEvent(AppEvents.IPostLivechatAgentUnassigned, { room, user });
});
};
@ -453,7 +453,7 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T
}
setImmediate(() => {
void Apps.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
void Apps?.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
type: LivechatTransferEventType.AGENT,
room: rid,
from: oldServedBy?._id,
@ -483,7 +483,7 @@ export const updateChatDepartment = async ({
]);
setImmediate(() => {
void Apps.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
void Apps?.triggerEvent(AppEvents.IPostLivechatRoomTransferred, {
type: LivechatTransferEventType.DEPARTMENT,
room: rid,
from: oldDepartmentId,

@ -1,6 +1,7 @@
import dns from 'dns';
import * as util from 'util';
import { Apps, AppEvents } from '@rocket.chat/apps';
import { Message, VideoConf, api, Omnichannel } from '@rocket.chat/core-services';
import type {
IOmnichannelRoom,
@ -43,7 +44,6 @@ import moment from 'moment-timezone';
import type { Filter, FindCursor, UpdateFilter } from 'mongodb';
import UAParser from 'ua-parser-js';
import { Apps, AppEvents } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import { trim } from '../../../../lib/utils/stringUtils';
import { i18n } from '../../../../server/lib/i18n';
@ -330,8 +330,8 @@ class LivechatClass {
* @deprecated the `AppEvents.ILivechatRoomClosedHandler` event will be removed
* in the next major version of the Apps-Engine
*/
void Apps.getBridges()?.getListenerBridge().livechatEvent(AppEvents.ILivechatRoomClosedHandler, newRoom);
void Apps.getBridges()?.getListenerBridge().livechatEvent(AppEvents.IPostLivechatRoomClosed, newRoom);
void Apps?.getBridges()?.getListenerBridge().livechatEvent(AppEvents.ILivechatRoomClosedHandler, newRoom);
void Apps?.getBridges()?.getListenerBridge().livechatEvent(AppEvents.IPostLivechatRoomClosed, newRoom);
});
if (process.env.TEST_MODE) {
await callbacks.run('livechat.closeRoom', {
@ -1420,7 +1420,7 @@ class LivechatClass {
const ret = await LivechatVisitors.saveGuestById(_id, updateData);
setImmediate(() => {
void Apps.triggerEvent(AppEvents.IPostLivechatGuestSaved, _id);
void Apps?.triggerEvent(AppEvents.IPostLivechatGuestSaved, _id);
});
return ret;
@ -1786,7 +1786,7 @@ class LivechatClass {
await LivechatRooms.saveRoomById(roomData);
setImmediate(() => {
void Apps.triggerEvent(AppEvents.IPostLivechatRoomSaved, roomData._id);
void Apps?.triggerEvent(AppEvents.IPostLivechatRoomSaved, roomData._id);
});
if (guestData?.name?.trim().length) {

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { Message, Omnichannel } from '@rocket.chat/core-services';
import type {
ILivechatInquiryRecord,
@ -16,7 +17,6 @@ import { LivechatInquiry, LivechatRooms, Subscriptions, Rooms, Users } from '@ro
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { Apps, AppEvents } from '../../../../ee/server/apps';
import { callbacks } from '../../../../lib/callbacks';
import {
createLivechatSubscription,
@ -172,7 +172,7 @@ export const RoutingManager: Routing = {
await dispatchAgentDelegated(rid, agent.agentId);
logger.debug(`Agent ${agent.agentId} assigned to inquriy ${inquiry._id}. Instances notified`);
void Apps.getBridges()?.getListenerBridge().livechatEvent(AppEvents.IPostLivechatAgentAssigned, { room, user });
void Apps?.getBridges()?.getListenerBridge().livechatEvent(AppEvents.IPostLivechatAgentAssigned, { room, user });
return inquiry;
},

@ -1,3 +1,4 @@
import { AppEvents, Apps } from '@rocket.chat/apps';
import type { ISetting } from '@rocket.chat/core-typings';
import { Settings } from '@rocket.chat/models';
import { escapeHTML } from '@rocket.chat/string-helpers';
@ -7,7 +8,6 @@ import { Meteor } from 'meteor/meteor';
import stripHtml from 'string-strip-html';
import _ from 'underscore';
import { Apps } from '../../../ee/server/apps';
import { validateEmail } from '../../../lib/emailValidator';
import { strLeft, strRightBack } from '../../../lib/utils/stringUtils';
import { i18n } from '../../../server/lib/i18n';
@ -170,7 +170,7 @@ export const sendNoWrap = async ({
const email = { to, from, replyTo, subject, html, text, headers };
const eventResult = await Apps.triggerEvent('IPreEmailSent', { email });
const eventResult = await Apps?.triggerEvent(AppEvents.IPreEmailSent, { email });
setImmediate(() => Email.sendAsync(eventResult || email).catch((e) => console.error(e)));
};

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { Message } from '@rocket.chat/core-services';
import { isQuoteAttachment, isRegisterUser } from '@rocket.chat/core-typings';
import type { IMessage, MessageAttachment, MessageQuoteAttachment } from '@rocket.chat/core-typings';
@ -6,7 +7,6 @@ import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { Apps, AppEvents } from '../../../ee/server/apps/orchestrator';
import { isTruthy } from '../../../lib/isTruthy';
import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages';
import { canAccessRoomAsync, roomAccessAttributes } from '../../authorization/server';
@ -129,7 +129,7 @@ Meteor.methods<ServerMethods>({
}
// App IPostMessagePinned event hook
await Apps.triggerEvent(AppEvents.IPostMessagePinned, originalMessage, await Meteor.userAsync(), originalMessage.pinned);
await Apps?.triggerEvent(AppEvents.IPostMessagePinned, originalMessage, await Meteor.userAsync(), originalMessage.pinned);
const msgId = await Message.saveSystemMessage('message_pinned', originalMessage.rid, '', me, {
attachments: [
@ -216,7 +216,7 @@ Meteor.methods<ServerMethods>({
}
// App IPostMessagePinned event hook
await Apps.triggerEvent(AppEvents.IPostMessagePinned, originalMessage, await Meteor.userAsync(), originalMessage.pinned);
await Apps?.triggerEvent(AppEvents.IPostMessagePinned, originalMessage, await Meteor.userAsync(), originalMessage.pinned);
await Messages.setPinnedByIdAndUserId(originalMessage._id, originalMessage.pinnedBy, originalMessage.pinned);
if (settings.get('Message_Read_Receipt_Store_Users')) {

@ -1,9 +1,9 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage } from '@rocket.chat/core-typings';
import { Messages, Subscriptions, Rooms } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import { Apps, AppEvents } from '../../../ee/server/apps/orchestrator';
import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages';
import { canAccessRoomAsync, roomAccessAttributes } from '../../authorization/server';
import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage';
@ -57,7 +57,7 @@ Meteor.methods<ServerMethods>({
await Rooms.updateLastMessageStar(room._id, uid, message.starred);
}
await Apps.triggerEvent(AppEvents.IPostMessageStarred, message, await Meteor.userAsync(), message.starred);
await Apps?.triggerEvent(AppEvents.IPostMessageStarred, message, await Meteor.userAsync(), message.starred);
await Messages.updateUserStarById(message._id, uid, message.starred);

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import { api } from '@rocket.chat/core-services';
import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings';
import { Messages, EmojiCustom, Rooms, Users } from '@rocket.chat/models';
@ -5,7 +6,6 @@ import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';
import { AppEvents, Apps } from '../../../ee/server/apps/orchestrator';
import { callbacks } from '../../../lib/callbacks';
import { i18n } from '../../../server/lib/i18n';
import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages';
@ -106,7 +106,7 @@ async function setReaction(room: IRoom, user: IUser, message: IMessage, reaction
isReacted = true;
}
await Apps.triggerEvent(AppEvents.IPostMessageReacted, message, user, reaction, isReacted);
await Apps?.triggerEvent(AppEvents.IPostMessageReacted, message, user, reaction, isReacted);
void broadcastMessageFromData({
id: message._id,

@ -1,17 +1,18 @@
import { Apps } from '@rocket.chat/apps';
import { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
import { Apps } from '../../../../ee/server/apps';
import { Info } from '../../../utils/rocketchat.info';
export function getAppsStatistics() {
return {
engineVersion: Info.marketplaceApiVersion,
totalInstalled: Apps.isInitialized() && Apps.getManager().get().length,
totalActive: Apps.isInitialized() && Apps.getManager().get({ enabled: true }).length,
totalInstalled: (Apps?.isInitialized() && Apps.getManager().get().length) ?? 0,
totalActive: (Apps?.isInitialized() && Apps.getManager().get({ enabled: true }).length) ?? 0,
totalFailed:
Apps.isInitialized() &&
Apps.getManager()
.get({ disabled: true })
.filter(({ app: { status } }) => status !== AppStatus.MANUALLY_DISABLED).length,
(Apps?.isInitialized() &&
Apps.getManager()
.get({ disabled: true })
.filter(({ app: { status } }) => status !== AppStatus.MANUALLY_DISABLED).length) ??
0,
};
}

@ -1,10 +1,10 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage } from '@rocket.chat/core-typings';
import { Messages } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { Apps, AppEvents } from '../../../../ee/server/apps/orchestrator';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
import { RateLimiter } from '../../../lib/server';
import { settings } from '../../../settings/server';
@ -44,7 +44,7 @@ Meteor.methods<ServerMethods>({
const followResult = await follow({ tmid: message.tmid || message._id, uid });
const isFollowed = true;
await Apps.triggerEvent(AppEvents.IPostMessageFollowed, message, await Meteor.userAsync(), isFollowed);
await Apps?.triggerEvent(AppEvents.IPostMessageFollowed, message, await Meteor.userAsync(), isFollowed);
return followResult;
},

@ -1,10 +1,10 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage } from '@rocket.chat/core-typings';
import { Messages } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { Apps, AppEvents } from '../../../../ee/server/apps/orchestrator';
import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
import { RateLimiter } from '../../../lib/server';
import { settings } from '../../../settings/server';
@ -44,7 +44,7 @@ Meteor.methods<ServerMethods>({
const unfollowResult = await unfollow({ rid: message.rid, tmid: message.tmid || message._id, uid });
const isFollowed = false;
await Apps.triggerEvent(AppEvents.IPostMessageFollowed, message, await Meteor.userAsync(), isFollowed);
await Apps?.triggerEvent(AppEvents.IPostMessageFollowed, message, await Meteor.userAsync(), isFollowed);
return unfollowResult;
},

@ -1,4 +1,4 @@
import './cron';
import './appRequestsCron';
export { Apps, AppEvents } from './orchestrator';
export { Apps } from './orchestrator';

@ -1,5 +1,5 @@
import { registerOrchestrator } from '@rocket.chat/apps';
import { EssentialAppDisabledException } from '@rocket.chat/apps-engine/definition/exceptions';
import { AppInterface } from '@rocket.chat/apps-engine/definition/metadata';
import { AppManager } from '@rocket.chat/apps-engine/server/AppManager';
import { Logger } from '@rocket.chat/logger';
import { AppLogs, Apps as AppsModel, AppsPersistence } from '@rocket.chat/models';
@ -249,8 +249,8 @@ export class AppServerOrchestrator {
}
}
export const AppEvents = AppInterface;
export const Apps = new AppServerOrchestrator();
registerOrchestrator(Apps);
settings.watch('Apps_Framework_Source_Package_Storage_Type', (value) => {
if (!Apps.isInitialized()) {

@ -1,8 +1,8 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage, IUser } from '@rocket.chat/core-typings';
import { Messages, ModerationReports, Rooms, Users } from '@rocket.chat/models';
import { canAccessRoomAsync } from '../../../app/authorization/server/functions/canAccessRoom';
import { AppEvents, Apps } from '../../../ee/server/apps';
export const reportMessage = async (messageId: IMessage['_id'], description: string, uid: IUser['_id']) => {
if (!uid) {
@ -49,7 +49,7 @@ export const reportMessage = async (messageId: IMessage['_id'], description: str
await ModerationReports.createWithMessageDescriptionAndUserId(message, description, roomInfo, reportedBy);
await Apps.triggerEvent(AppEvents.IPostMessageReported, message, user, description);
await Apps?.triggerEvent(AppEvents.IPostMessageReported, message, user, description);
return true;
};

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IUser } from '@rocket.chat/core-typings';
import { Users } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
@ -6,7 +7,6 @@ import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../app/authorization/server/functions/hasPermission';
import { deleteUser } from '../../app/lib/server/functions/deleteUser';
import { AppEvents, Apps } from '../../ee/server/apps/orchestrator';
declare module '@rocket.chat/ui-contexts' {
// eslint-disable-next-line @typescript-eslint/naming-convention
@ -52,7 +52,7 @@ Meteor.methods<ServerMethods>({
await deleteUser(userId, confirmRelinquish, uid);
// App IPostUserDeleted event hook
await Apps.triggerEvent(AppEvents.IPostUserDeleted, { user, performedBy: await Meteor.userAsync() });
await Apps?.triggerEvent(AppEvents.IPostUserDeleted, { user, performedBy: await Meteor.userAsync() });
return true;
},

@ -1,3 +1,4 @@
import { AppEvents, Apps } from '@rocket.chat/apps';
import { Message, Team } from '@rocket.chat/core-services';
import { Rooms } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
@ -7,7 +8,6 @@ import { Meteor } from 'meteor/meteor';
import { hasPermissionAsync } from '../../app/authorization/server/functions/hasPermission';
import { deleteRoom } from '../../app/lib/server/functions/deleteRoom';
import { methodDeprecationLogger } from '../../app/lib/server/lib/deprecationWarningLogger';
import { Apps } from '../../ee/server/apps';
import { roomCoordinator } from '../lib/rooms/roomCoordinator';
export async function eraseRoom(rid: string, uid: string): Promise<void> {
@ -36,7 +36,7 @@ export async function eraseRoom(rid: string, uid: string): Promise<void> {
}
if (Apps?.isLoaded()) {
const prevent = await Apps.getBridges()?.getListenerBridge().roomEvent('IPreRoomDeletePrevent', room);
const prevent = await Apps.getBridges()?.getListenerBridge().roomEvent(AppEvents.IPreRoomDeletePrevent, room);
if (prevent) {
throw new Meteor.Error('error-app-prevented-deleting', 'A Rocket.Chat App prevented the room erasing.');
}
@ -54,7 +54,7 @@ export async function eraseRoom(rid: string, uid: string): Promise<void> {
}
if (Apps?.isLoaded()) {
void Apps.getBridges()?.getListenerBridge().roomEvent('IPostRoomDeleted', room);
void Apps.getBridges()?.getListenerBridge().roomEvent(AppEvents.IPostRoomDeleted, room);
}
}

@ -1,9 +1,9 @@
import { AppEvents, Apps } from '@rocket.chat/apps';
import type { IUser } from '@rocket.chat/core-typings';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
import { AppEvents, Apps } from '../../ee/server/apps/orchestrator';
import { afterLogoutCleanUpCallback } from '../../lib/callbacks/afterLogoutCleanUpCallback';
declare module '@rocket.chat/ui-contexts' {
@ -22,6 +22,6 @@ Meteor.methods<ServerMethods>({
});
// App IPostUserLogout event hook
await Apps.triggerEvent(AppEvents.IPostUserLoggedOut, user);
await Apps?.triggerEvent(AppEvents.IPostUserLoggedOut, user);
},
});

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { IMessage } from '@rocket.chat/core-typings';
import { ModerationReports, Rooms, Users, Messages } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
@ -6,7 +7,6 @@ import { Meteor } from 'meteor/meteor';
import { canAccessRoomAsync } from '../../app/authorization/server/functions/canAccessRoom';
import { methodDeprecationLogger } from '../../app/lib/server/lib/deprecationWarningLogger';
import { AppEvents, Apps } from '../../ee/server/apps';
declare module '@rocket.chat/ui-contexts' {
// eslint-disable-next-line @typescript-eslint/naming-convention
@ -77,7 +77,7 @@ Meteor.methods<ServerMethods>({
await ModerationReports.createWithMessageDescriptionAndUserId(message, description, roomInfo, reportedBy);
await Apps.triggerEvent(AppEvents.IPostMessageReported, message, await Meteor.userAsync(), description);
await Apps?.triggerEvent(AppEvents.IPostMessageReported, message, await Meteor.userAsync(), description);
return true;
},

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { UserStatus } from '@rocket.chat/core-typings';
import { Users } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
@ -12,7 +13,6 @@ import { saveUserIdentity } from '../../app/lib/server/functions/saveUserIdentit
import { passwordPolicy } from '../../app/lib/server/lib/passwordPolicy';
import { settings as rcSettings } from '../../app/settings/server';
import { setUserStatusMethod } from '../../app/user-status/server/methods/setUserStatus';
import { AppEvents, Apps } from '../../ee/server/apps/orchestrator';
import { compareUserPassword } from '../lib/compareUserPassword';
import { compareUserPasswordHistory } from '../lib/compareUserPasswordHistory';
@ -156,7 +156,7 @@ async function saveUserProfile(
// App IPostUserUpdated event hook
const updatedUser = await Users.findOneById(this.userId);
await Apps.triggerEvent(AppEvents.IPostUserUpdated, { user: updatedUser, previousUser: user });
await Apps?.triggerEvent(AppEvents.IPostUserUpdated, { user: updatedUser, previousUser: user });
return true;
}

@ -1,3 +1,4 @@
import { Apps, AppEvents } from '@rocket.chat/apps';
import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
import { AppStatusUtils } from '@rocket.chat/apps-engine/definition/AppStatus';
import type { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
@ -6,7 +7,6 @@ import type { IAppStorageItem } from '@rocket.chat/apps-engine/server/storage';
import type { IAppsEngineService } from '@rocket.chat/core-services';
import { ServiceClassInternal } from '@rocket.chat/core-services';
import { Apps, AppEvents } from '../../../ee/server/apps/orchestrator';
import { SystemLogger } from '../../lib/logger/system';
export class AppsEngineService extends ServiceClassInternal implements IAppsEngineService {
@ -16,7 +16,7 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi
super();
this.onEvent('presence.status', async ({ user, previousStatus }): Promise<void> => {
await Apps.triggerEvent(AppEvents.IPostUserStatusChanged, {
await Apps?.triggerEvent(AppEvents.IPostUserStatusChanged, {
user,
currentStatus: user.status,
previousStatus,
@ -24,68 +24,70 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi
});
this.onEvent('apps.added', async (appId: string): Promise<void> => {
Apps.getRocketChatLogger().debug(`"apps.added" event received for app "${appId}"`);
Apps?.getRocketChatLogger().debug(`"apps.added" event received for app "${appId}"`);
// if the app already exists in this instance, don't load it again
const app = Apps.getManager()?.getOneById(appId);
const app = Apps?.getManager()?.getOneById(appId);
if (app) {
Apps.getRocketChatLogger().info(`"apps.added" event received for app "${appId}", but it already exists in this instance`);
Apps?.getRocketChatLogger().info(`"apps.added" event received for app "${appId}", but it already exists in this instance`);
return;
}
await Apps.getManager()?.addLocal(appId);
await Apps?.getManager()?.addLocal(appId);
});
this.onEvent('apps.removed', async (appId: string): Promise<void> => {
Apps.getRocketChatLogger().debug(`"apps.removed" event received for app "${appId}"`);
const app = Apps.getManager()?.getOneById(appId);
Apps?.getRocketChatLogger().debug(`"apps.removed" event received for app "${appId}"`);
const app = Apps?.getManager()?.getOneById(appId);
if (!app) {
Apps.getRocketChatLogger().info(`"apps.removed" event received for app "${appId}", but it couldn't be found in this instance`);
Apps?.getRocketChatLogger().info(`"apps.removed" event received for app "${appId}", but it couldn't be found in this instance`);
return;
}
await Apps.getManager()?.removeLocal(appId);
await Apps?.getManager()?.removeLocal(appId);
});
this.onEvent('apps.updated', async (appId: string): Promise<void> => {
Apps.getRocketChatLogger().debug(`"apps.updated" event received for app "${appId}"`);
const storageItem = await Apps.getStorage()?.retrieveOne(appId);
Apps?.getRocketChatLogger().debug(`"apps.updated" event received for app "${appId}"`);
const storageItem = await Apps?.getStorage()?.retrieveOne(appId);
if (!storageItem) {
Apps.getRocketChatLogger().info(`"apps.updated" event received for app "${appId}", but it couldn't be found in the storage`);
Apps?.getRocketChatLogger().info(`"apps.updated" event received for app "${appId}", but it couldn't be found in the storage`);
return;
}
const appPackage = await Apps.getAppSourceStorage()?.fetch(storageItem);
const appPackage = await Apps?.getAppSourceStorage()?.fetch(storageItem);
if (!appPackage) {
return;
}
await Apps.getManager()?.updateLocal(storageItem, appPackage);
await Apps?.getManager()?.updateLocal(storageItem, appPackage);
});
this.onEvent('apps.statusUpdate', async (appId: string, status: AppStatus): Promise<void> => {
Apps.getRocketChatLogger().debug(`"apps.statusUpdate" event received for app "${appId}" with status "${status}"`);
const app = Apps.getManager()?.getOneById(appId);
Apps?.getRocketChatLogger().debug(`"apps.statusUpdate" event received for app "${appId}" with status "${status}"`);
const app = Apps?.getManager()?.getOneById(appId);
if (!app) {
Apps.getRocketChatLogger().info(`"apps.statusUpdate" event received for app "${appId}", but it couldn't be found in this instance`);
Apps?.getRocketChatLogger().info(
`"apps.statusUpdate" event received for app "${appId}", but it couldn't be found in this instance`,
);
return;
}
if (app.getStatus() === status) {
Apps.getRocketChatLogger().info(`"apps.statusUpdate" event received for app "${appId}", but the status is the same`);
Apps?.getRocketChatLogger().info(`"apps.statusUpdate" event received for app "${appId}", but the status is the same`);
return;
}
if (AppStatusUtils.isEnabled(status)) {
await Apps.getManager()?.enable(appId).catch(SystemLogger.error);
await Apps?.getManager()?.enable(appId).catch(SystemLogger.error);
} else if (AppStatusUtils.isDisabled(status)) {
await Apps.getManager()?.disable(appId, status, true).catch(SystemLogger.error);
await Apps?.getManager()?.disable(appId, status, true).catch(SystemLogger.error);
}
});
this.onEvent('apps.settingUpdated', async (appId: string, setting): Promise<void> => {
Apps.getRocketChatLogger().debug(`"apps.settingUpdated" event received for app "${appId}"`, { setting });
const app = Apps.getManager()?.getOneById(appId);
Apps?.getRocketChatLogger().debug(`"apps.settingUpdated" event received for app "${appId}"`, { setting });
const app = Apps?.getManager()?.getOneById(appId);
const oldSetting = app?.getStorageItem().settings[setting.id].value;
// avoid updating the setting if the value is the same,
@ -94,30 +96,30 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi
// so we need to convert it to JSON stringified to compare it
if (JSON.stringify(oldSetting) === JSON.stringify(setting.value)) {
Apps.getRocketChatLogger().info(
Apps?.getRocketChatLogger().info(
`"apps.settingUpdated" event received for setting ${setting.id} of app "${appId}", but the setting value is the same`,
);
return;
}
await Apps.getManager()
await Apps?.getManager()
?.getSettingsManager()
.updateAppSetting(appId, setting as any);
});
}
isInitialized(): boolean {
return Apps.isInitialized();
return Boolean(Apps?.isInitialized());
}
async getApps(query: IGetAppsFilter): Promise<IAppInfo[] | undefined> {
return Apps.getManager()
return Apps?.getManager()
?.get(query)
.map((app) => app.getApp().getInfo());
}
async getAppStorageItemById(appId: string): Promise<IAppStorageItem | undefined> {
const app = Apps.getManager()?.getOneById(appId);
const app = Apps?.getManager()?.getOneById(appId);
if (!app) {
return;

@ -1,3 +1,4 @@
import { Apps } from '@rocket.chat/apps';
import type { AppVideoConfProviderManager } from '@rocket.chat/apps-engine/server/managers';
import type { IVideoConfService, VideoConferenceJoinOptions } from '@rocket.chat/core-services';
import { api, ServiceClassInternal } from '@rocket.chat/core-services';
@ -41,7 +42,6 @@ import { settings } from '../../../app/settings/server';
import { updateCounter } from '../../../app/statistics/server/functions/updateStatsCounter';
import { getUserAvatarURL } from '../../../app/utils/server/getUserAvatarURL';
import { getUserPreference } from '../../../app/utils/server/lib/getUserPreference';
import { Apps } from '../../../ee/server/apps';
import { callbacks } from '../../../lib/callbacks';
import { availabilityErrors } from '../../../lib/videoConference/constants';
import { readSecondaryPreferred } from '../../database/readSecondaryPreferred';
@ -832,7 +832,7 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
throw new Error('apps-engine-not-loaded');
}
const manager = Apps.getManager()?.getVideoConfProviderManager();
const manager = Apps?.getManager()?.getVideoConfProviderManager();
if (!manager) {
throw new Error(availabilityErrors.NO_APP);
}

@ -1,8 +1,7 @@
import { Apps, type AppMetadataStorage } from '@rocket.chat/apps';
import type { IAppStorageItem } from '@rocket.chat/apps-engine/server/storage';
import { Settings } from '@rocket.chat/models';
import { Apps } from '../../../ee/server/apps';
import type { AppRealStorage } from '../../../ee/server/apps/storage';
import { addMigration } from '../../lib/migrations';
addMigration({
@ -13,13 +12,17 @@ addMigration({
await Settings.removeById('Apps_Framework_Development_Mode');
await Settings.removeById('Apps_Framework_enabled');
if (!Apps) {
throw new Error('Apps Orchestrator not registered.');
}
Apps.initialize();
const appsStorage = Apps.getStorage() as AppRealStorage;
const appsStorage = Apps.getStorage();
const apps = await appsStorage.retrieveAll();
const promises: Array<ReturnType<AppRealStorage['update']>> = [];
const promises: Array<ReturnType<AppMetadataStorage['update']>> = [];
apps.forEach((app) =>
promises.push(

@ -1,7 +1,7 @@
import { Apps } from '@rocket.chat/apps';
import type { AppSignatureManager } from '@rocket.chat/apps-engine/server/managers/AppSignatureManager';
import type { IAppStorageItem } from '@rocket.chat/apps-engine/server/storage';
import { Apps } from '../../../ee/server/apps';
import type { AppRealStorage } from '../../../ee/server/apps/storage';
import { addMigration } from '../../lib/migrations';
@ -9,6 +9,10 @@ addMigration({
version: 292,
name: 'Add checksum signature to existing apps',
async up() {
if (!Apps) {
throw new Error('Apps Orchestrator not registered.');
}
Apps.initialize();
const sigMan = Apps.getManager()?.getSignatureManager() as AppSignatureManager;

@ -1,13 +1,17 @@
import { Apps } from '@rocket.chat/apps';
import type { AppSignatureManager } from '@rocket.chat/apps-engine/server/managers/AppSignatureManager';
import type { IAppStorageItem } from '@rocket.chat/apps-engine/server/storage';
import { Apps } from '../../../ee/server/apps';
import type { AppRealStorage } from '../../../ee/server/apps/storage';
import { addMigration } from '../../lib/migrations';
addMigration({
version: 294,
async up() {
if (!Apps) {
throw new Error('Apps Orchestrator not registered.');
}
Apps.initialize();
const sigMan = Apps.getManager()?.getSignatureManager() as AppSignatureManager;

@ -8,6 +8,7 @@ export type {
IVisitorPhone as IAppsVisitorPhone,
} from '@rocket.chat/apps-engine/definition/livechat';
export type { IMessage as IAppsMessage } from '@rocket.chat/apps-engine/definition/messages';
export { AppInterface as AppEvents } from '@rocket.chat/apps-engine/definition/metadata';
export type { IUser as IAppsUser } from '@rocket.chat/apps-engine/definition/users';
export type { IRole as IAppsRole } from '@rocket.chat/apps-engine/definition/roles';
export type { IRoom as IAppsRoom } from '@rocket.chat/apps-engine/definition/rooms';
@ -18,3 +19,5 @@ export type {
VideoConference as AppsVideoConference,
} from '@rocket.chat/apps-engine/definition/videoConferences';
export { AppManager } from '@rocket.chat/apps-engine/server/AppManager';
export { AppBridges } from '@rocket.chat/apps-engine/server/bridges';
export { AppMetadataStorage } from '@rocket.chat/apps-engine/server/storage';

@ -1,12 +1,16 @@
import type { AppManager } from '@rocket.chat/apps-engine/server/AppManager';
import type { AppSourceStorage } from '@rocket.chat/apps-engine/server/storage';
import type { Logger } from '@rocket.chat/logger';
import type { IAppsPersistenceModel } from '@rocket.chat/model-typings';
import type { AppBridges, AppEvents, AppMetadataStorage } from './AppsEngine';
import type { IAppServerNotifier } from './IAppServerNotifier';
import type { IAppConvertersMap } from './converters';
export interface IAppServerOrchestrator {
initialize(): void;
isInitialized(): boolean;
isLoaded(): boolean;
getNotifier(): IAppServerNotifier;
isDebugging(): boolean;
debugLog(...args: any[]): void;
@ -14,4 +18,8 @@ export interface IAppServerOrchestrator {
getConverters(): IAppConvertersMap;
getPersistenceModel(): IAppsPersistenceModel;
getRocketChatLogger(): Logger;
triggerEvent(event: AppEvents, ...payload: any[]): Promise<any>;
getBridges(): AppBridges;
getStorage(): AppMetadataStorage;
getAppSourceStorage(): AppSourceStorage;
}

@ -0,0 +1,48 @@
import type { IMessage, IRoom, IUser, ILivechatDepartment, ILivechatVisitor, IOmnichannelRoom } from '@rocket.chat/core-typings';
import type { AppEvents } from '../AppsEngine';
declare module '@rocket.chat/apps-engine/server/bridges' {
interface IListenerBridge {
messageEvent(int: 'IPostMessageDeleted', message: IMessage, userDeleted: IUser): Promise<void>;
messageEvent(int: 'IPostMessageReacted', message: IMessage, userReacted: IUser, reaction: string, isReacted: boolean): Promise<void>;
messageEvent(int: 'IPostMessageFollowed', message: IMessage, userFollowed: IUser, isFollowed: boolean): Promise<void>;
messageEvent(int: 'IPostMessagePinned', message: IMessage, userPinned: IUser, isPinned: boolean): Promise<void>;
messageEvent(int: 'IPostMessageStarred', message: IMessage, userStarred: IUser, isStarred: boolean): Promise<void>;
messageEvent(int: 'IPostMessageReported', message: IMessage, userReported: IUser, reason: boolean): Promise<void>;
messageEvent(
int: 'IPreMessageSentPrevent' | 'IPreMessageDeletePrevent' | 'IPreMessageUpdatedPrevent',
message: IMessage,
): Promise<boolean>;
messageEvent(
int: 'IPreMessageSentExtend' | 'IPreMessageSentModify' | 'IPreMessageUpdatedExtend' | 'IPreMessageUpdatedModify',
message: IMessage,
): Promise<IMessage>;
messageEvent(int: 'IPostMessageSent' | 'IPostMessageUpdated', message: IMessage): Promise<void>;
roomEvent(int: 'IPreRoomUserJoined' | 'IPostRoomUserJoined', room: IRoom, joiningUser: IUser, invitingUser?: IUser): Promise<void>;
roomEvent(int: 'IPreRoomUserLeave' | 'IPostRoomUserLeave', room: IRoom, leavingUser: IUser): Promise<void>;
roomEvent(int: 'IPreRoomCreatePrevent' | 'IPreRoomDeletePrevent', room: IRoom): Promise<boolean>;
roomEvent(int: 'IPreRoomCreateExtend' | 'IPreRoomCreateModify', room: IRoom): Promise<IRoom>;
roomEvent(int: 'IPostRoomCreate' | 'IPostRoomDeleted', room: IRoom): Promise<void>;
livechatEvent(
int: 'IPostLivechatAgentAssigned' | 'IPostLivechatAgentUnassigned',
data: { user: IUser; room: IOmnichannelRoom },
): Promise<void>;
livechatEvent(
int: 'IPostLivechatRoomTransferred',
data: { type: 'agent'; room: IRoom['_id']; from: IUser['_id']; to: IUser['_id'] },
): Promise<void>;
livechatEvent(
int: 'IPostLivechatRoomTransferred',
data: { type: 'department'; room: IRoom['_id']; from: ILivechatDepartment['_id']; to: ILivechatDepartment['_id'] },
): Promise<void>;
livechatEvent(int: 'IPostLivechatGuestSaved', data: ILivechatVisitor['_id']): Promise<void>;
livechatEvent(int: 'IPostLivechatRoomSaved', data: IRoom['_id']): Promise<void>;
livechatEvent(int: 'ILivechatRoomClosedHandler' | 'IPostLivechatRoomStarted' | 'IPostLivechatRoomClosed', data: IRoom): Promise<void>;
livechatEvent(int: AppEvents | AppEvents[keyof AppEvents], data: any): Promise<void>;
}
}

@ -1,4 +1,7 @@
import './bridges/IListenerBridge';
export * from './converters';
export * from './AppsEngine';
export * from './IAppServerNotifier';
export * from './IAppServerOrchestrator';
export * from './orchestrator';

@ -0,0 +1,7 @@
import type { IAppServerOrchestrator } from './IAppServerOrchestrator';
export let Apps: IAppServerOrchestrator | undefined;
export function registerOrchestrator(orch: IAppServerOrchestrator): void {
Apps = orch;
}

@ -39995,7 +39995,7 @@ __metadata:
languageName: node
linkType: hard
"typescript@npm:~5.3.3":
"typescript@npm:~5.3.2, typescript@npm:~5.3.3":
version: 5.3.3
resolution: "typescript@npm:5.3.3"
bin:
@ -40005,7 +40005,7 @@ __metadata:
languageName: node
linkType: hard
"typescript@patch:typescript@~5.3.3#~builtin<compat/typescript>":
"typescript@patch:typescript@~5.3.2#~builtin<compat/typescript>, typescript@patch:typescript@~5.3.3#~builtin<compat/typescript>":
version: 5.3.3
resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin<compat/typescript>::version=5.3.3&hash=85af82"
bin:

Loading…
Cancel
Save