Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions apps/meteor/app/apps/server/bridges/activation.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import type { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus';
import type { IAppServerOrchestrator, AppStatus } from '@rocket.chat/apps';
import type { ProxiedApp } from '@rocket.chat/apps-engine/server/ProxiedApp';
import { AppActivationBridge as ActivationBridge } from '@rocket.chat/apps-engine/server/bridges/AppActivationBridge';
import { Users } from '@rocket.chat/models';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';

export class AppActivationBridge extends ActivationBridge {
// eslint-disable-next-line no-empty-function
constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}

Expand Down
5 changes: 2 additions & 3 deletions apps/meteor/app/apps/server/bridges/api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { IAppServerOrchestrator } from '@rocket.chat/apps';
import type { RequestMethod } from '@rocket.chat/apps-engine/definition/accessors';
import type { IApiRequest, IApiEndpoint, IApi } from '@rocket.chat/apps-engine/definition/api';
import { ApiBridge } from '@rocket.chat/apps-engine/server/bridges/ApiBridge';
Expand All @@ -7,7 +8,6 @@ import express from 'express';
import { Meteor } from 'meteor/meteor';
import { WebApp } from 'meteor/webapp';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';
import { authenticationMiddleware } from '../../../api/server/middlewares/authentication';

const apiServer = express();
Expand All @@ -24,8 +24,7 @@ interface IRequestWithPrivateHash extends Request {
export class AppApisBridge extends ApiBridge {
appRouters: Map<string, IRouter>;

// eslint-disable-next-line no-empty-function
constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
this.appRouters = new Map();

Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/apps/server/bridges/cloud.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { IAppServerOrchestrator } from '@rocket.chat/apps';
import type { IWorkspaceToken } from '@rocket.chat/apps-engine/definition/cloud/IWorkspaceToken';
import { CloudWorkspaceBridge } from '@rocket.chat/apps-engine/server/bridges/CloudWorkspaceBridge';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';
import { getWorkspaceAccessTokenWithScope } from '../../../cloud/server';

export class AppCloudBridge extends CloudWorkspaceBridge {
constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}

Expand Down
46 changes: 28 additions & 18 deletions apps/meteor/app/apps/server/bridges/commands.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import type { IAppServerOrchestrator, IAppsRoom, IAppsUser } from '@rocket.chat/apps';
import type { ISlashCommand, ISlashCommandPreview, ISlashCommandPreviewItem } from '@rocket.chat/apps-engine/definition/slashcommands';
import { SlashCommandContext } from '@rocket.chat/apps-engine/definition/slashcommands';
import { CommandBridge } from '@rocket.chat/apps-engine/server/bridges/CommandBridge';
import type { IMessage, RequiredField, SlashCommand, SlashCommandCallbackParams } from '@rocket.chat/core-typings';
import { Meteor } from 'meteor/meteor';

import { Utilities } from '../../../../ee/lib/misc/Utilities';
import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';
import { parseParameters } from '../../../../lib/utils/parseParameters';
import { slashCommands } from '../../../utils/server/slashCommand';

export class AppCommandsBridge extends CommandBridge {
disabledCommands: Map<string, (typeof slashCommands.commands)[string]>;

constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
this.disabledCommands = new Map();
}
Expand Down Expand Up @@ -44,7 +44,7 @@ export class AppCommandsBridge extends CommandBridge {
slashCommands.commands[cmd] = this.disabledCommands.get(cmd) as (typeof slashCommands.commands)[string];
this.disabledCommands.delete(cmd);

this.orch.getNotifier().commandUpdated(cmd);
void this.orch.getNotifier().commandUpdated(cmd);
}

protected async disableCommand(command: string, appId: string): Promise<void> {
Expand All @@ -69,7 +69,7 @@ export class AppCommandsBridge extends CommandBridge {
this.disabledCommands.set(cmd, commandObj);
delete slashCommands.commands[cmd];

this.orch.getNotifier().commandDisabled(cmd);
void this.orch.getNotifier().commandDisabled(cmd);
}

// command: { command, paramsExample, i18nDescription, executor: function }
Expand All @@ -95,7 +95,7 @@ export class AppCommandsBridge extends CommandBridge {
) as (typeof slashCommands.commands)[string]['previewCallback'];

slashCommands.commands[cmd] = item;
this.orch.getNotifier().commandUpdated(cmd);
void this.orch.getNotifier().commandUpdated(cmd);
}

protected async registerCommand(command: ISlashCommand, appId: string): Promise<void> {
Expand All @@ -118,7 +118,7 @@ export class AppCommandsBridge extends CommandBridge {
} as SlashCommand;

slashCommands.commands[command.command.toLowerCase()] = item;
this.orch.getNotifier().commandAdded(command.command.toLowerCase());
void this.orch.getNotifier().commandAdded(command.command.toLowerCase());
}

protected async unregisterCommand(command: string, appId: string): Promise<void> {
Expand All @@ -132,7 +132,7 @@ export class AppCommandsBridge extends CommandBridge {
this.disabledCommands.delete(cmd);
delete slashCommands.commands[cmd];

this.orch.getNotifier().commandRemoved(cmd);
void this.orch.getNotifier().commandRemoved(cmd);
}

private _verifyCommand(command: ISlashCommand): void {
Expand Down Expand Up @@ -162,14 +162,15 @@ export class AppCommandsBridge extends CommandBridge {
}

private async _appCommandExecutor({ command, message, params, triggerId, userId }: SlashCommandCallbackParams<string>): Promise<void> {
const user = await this.orch.getConverters()?.get('users').convertById(userId);
const room = await this.orch.getConverters()?.get('rooms').convertById(message.rid);
// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
const user: IAppsUser | undefined = await this.orch.getConverters()?.get('users').convertById(userId);
const room: IAppsRoom | undefined = await this.orch.getConverters()?.get('rooms').convertById(message.rid);
const threadId = message.tmid;
const parameters = parseParameters(params);

const context = new SlashCommandContext(
Object.freeze(user),
Object.freeze(room),
Object.freeze(user as IAppsUser),
Object.freeze(room as IAppsRoom),
Object.freeze(parameters) as string[],
threadId,
triggerId,
Expand All @@ -183,12 +184,19 @@ export class AppCommandsBridge extends CommandBridge {
parameters: any,
message: RequiredField<Partial<IMessage>, 'rid'>,
): Promise<ISlashCommandPreview | undefined> {
const user = await this.orch.getConverters()?.get('users').convertById(Meteor.userId());
const room = await this.orch.getConverters()?.get('rooms').convertById(message.rid);
// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
const uid = Meteor.userId() as string;
const user: IAppsUser | undefined = await this.orch.getConverters()?.get('users').convertById(uid);
const room: IAppsRoom | undefined = await this.orch.getConverters()?.get('rooms').convertById(message.rid);
const threadId = message.tmid;
const params = parseParameters(parameters);

const context = new SlashCommandContext(Object.freeze(user), Object.freeze(room), Object.freeze(params) as string[], threadId);
const context = new SlashCommandContext(
Object.freeze(user as IAppsUser),
Object.freeze(room as IAppsRoom),
Object.freeze(params) as string[],
threadId,
);
return this.orch.getManager()?.getCommandManager().getPreviews(command, context);
}

Expand All @@ -199,14 +207,16 @@ export class AppCommandsBridge extends CommandBridge {
preview: ISlashCommandPreviewItem,
triggerId: string,
): Promise<void> {
const user = await this.orch.getConverters()?.get('users').convertById(Meteor.userId());
const room = await this.orch.getConverters()?.get('rooms').convertById(message.rid);
// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
const uid = Meteor.userId() as string;
const user: IAppsUser | undefined = await this.orch.getConverters()?.get('users').convertById(uid);
const room: IAppsRoom | undefined = await this.orch.getConverters()?.get('rooms').convertById(message.rid);
const threadId = message.tmid;
const params = parseParameters(parameters);

const context = new SlashCommandContext(
Object.freeze(user),
Object.freeze(room),
Object.freeze(user as IAppsUser),
Object.freeze(room as IAppsRoom),
Object.freeze(params) as string[],
threadId,
triggerId,
Expand Down
11 changes: 6 additions & 5 deletions apps/meteor/app/apps/server/bridges/details.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import type { IAppServerOrchestrator } from '@rocket.chat/apps';
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';
import { AppDetailChangesBridge as DetailChangesBridge } from '@rocket.chat/apps-engine/server/bridges/AppDetailChangesBridge';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';

export class AppDetailChangesBridge extends DetailChangesBridge {
constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}

protected onAppSettingsChange(appId: string, setting: ISetting): void {
const logFailure = () => console.warn('failed to notify about the setting change.', appId);

try {
this.orch.getNotifier().appSettingsChange(appId, setting);
this.orch.getNotifier().appSettingsChange(appId, setting).catch(logFailure);
} catch (e) {
console.warn('failed to notify about the setting change.', appId);
logFailure();
}
}
}
5 changes: 2 additions & 3 deletions apps/meteor/app/apps/server/bridges/environmental.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { IAppServerOrchestrator } from '@rocket.chat/apps';
import { EnvironmentalVariableBridge } from '@rocket.chat/apps-engine/server/bridges/EnvironmentalVariableBridge';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';

export class AppEnvironmentalVariableBridge extends EnvironmentalVariableBridge {
allowed: Array<string>;

constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
this.allowed = ['NODE_ENV', 'ROOT_URL', 'INSTANCE_IP'];
}
Expand Down
5 changes: 2 additions & 3 deletions apps/meteor/app/apps/server/bridges/http.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { IAppServerOrchestrator } from '@rocket.chat/apps';
import type { IHttpResponse } from '@rocket.chat/apps-engine/definition/accessors';
import type { IHttpBridgeRequestInfo } from '@rocket.chat/apps-engine/server/bridges';
import { HttpBridge } from '@rocket.chat/apps-engine/server/bridges/HttpBridge';
import { serverFetch as fetch } from '@rocket.chat/server-fetch';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';

const isGetOrHead = (method: string): boolean => ['GET', 'HEAD'].includes(method.toUpperCase());

// Previously, there was no timeout for HTTP requests.
Expand All @@ -13,7 +12,7 @@ const isGetOrHead = (method: string): boolean => ['GET', 'HEAD'].includes(method
const DEFAULT_TIMEOUT = 3 * 60 * 1000;

export class AppHttpBridge extends HttpBridge {
constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}

Expand Down
17 changes: 10 additions & 7 deletions apps/meteor/app/apps/server/bridges/internal.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings';
import type { IAppServerOrchestrator, IAppsSetting } from '@rocket.chat/apps';
import { InternalBridge } from '@rocket.chat/apps-engine/server/bridges/InternalBridge';
import type { ISubscription } from '@rocket.chat/core-typings';
import type { ISetting, ISubscription } from '@rocket.chat/core-typings';
import { Settings, Subscriptions } from '@rocket.chat/models';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';
import { isTruthy } from '../../../../lib/isTruthy';
import { deasyncPromise } from '../../../../server/deasync/deasync';

export class AppInternalBridge extends InternalBridge {
constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}

Expand Down Expand Up @@ -37,9 +36,13 @@ export class AppInternalBridge extends InternalBridge {
return records.map((s: ISubscription) => s.u.username).filter(isTruthy);
}

protected async getWorkspacePublicKey(): Promise<ISetting> {
const publicKeySetting = await Settings.findOneById('Cloud_Workspace_PublicKey');
protected async getWorkspacePublicKey(): Promise<IAppsSetting> {
// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
const publicKeySetting: ISetting | null = await Settings.findOneById('Cloud_Workspace_PublicKey');

return this.orch.getConverters()?.get('settings').convertToApp(publicKeySetting);
return this.orch
.getConverters()
?.get('settings')
.convertToApp(publicKeySetting as ISetting);
}
}
48 changes: 27 additions & 21 deletions apps/meteor/app/apps/server/bridges/livechat.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
import type { IAppServerOrchestrator, IAppsLivechatMessage } from '@rocket.chat/apps';
import type { IExtraRoomParams } from '@rocket.chat/apps-engine/definition/accessors/ILivechatCreator';
import type {
ILivechatMessage,
IVisitor,
ILivechatRoom,
ILivechatTransferData,
IDepartment,
} from '@rocket.chat/apps-engine/definition/livechat';
import type { IVisitor, ILivechatRoom, ILivechatTransferData, IDepartment } from '@rocket.chat/apps-engine/definition/livechat';
import type { IMessage as IAppsEngineMesage } from '@rocket.chat/apps-engine/definition/messages';
import type { IUser } from '@rocket.chat/apps-engine/definition/users';
import { LivechatBridge } from '@rocket.chat/apps-engine/server/bridges/LivechatBridge';
import type { SelectedAgent } from '@rocket.chat/core-typings';
import type { ILivechatDepartment, IOmnichannelRoom, SelectedAgent, IMessage, ILivechatVisitor } from '@rocket.chat/core-typings';
import { OmnichannelSourceType } from '@rocket.chat/core-typings';
import { LivechatVisitors, LivechatRooms, LivechatDepartment, Users } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';

import type { AppServerOrchestrator } from '../../../../ee/server/apps/orchestrator';
import { callbacks } from '../../../../lib/callbacks';
import { deasyncPromise } from '../../../../server/deasync/deasync';
import { getRoom } from '../../../livechat/server/api/lib/livechat';
import { Livechat as LivechatTyped } from '../../../livechat/server/lib/LivechatTyped';
import { type ILivechatMessage, Livechat as LivechatTyped } from '../../../livechat/server/lib/LivechatTyped';
import { settings } from '../../../settings/server';

export class AppLivechatBridge extends LivechatBridge {
constructor(private readonly orch: AppServerOrchestrator) {
constructor(private readonly orch: IAppServerOrchestrator) {
super();
}

Expand All @@ -36,16 +30,21 @@ export class AppLivechatBridge extends LivechatBridge {
return LivechatTyped.online(departmentId);
}

protected async createMessage(message: ILivechatMessage, appId: string): Promise<string> {
protected async createMessage(message: IAppsLivechatMessage, appId: string): Promise<string> {
this.orch.debugLog(`The App ${appId} is creating a new message.`);

if (!message.token) {
throw new Error('Invalid token for livechat message');
}

// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
const guest = this.orch.getConverters().get('visitors').convertAppVisitor(message.visitor);
const appMessage = (await this.orch.getConverters().get('messages').convertAppMessage(message)) as IMessage | undefined;
const livechatMessage = appMessage as ILivechatMessage | undefined;

const msg = await LivechatTyped.sendMessage({
guest: this.orch.getConverters()?.get('visitors').convertAppVisitor(message.visitor),
message: await this.orch.getConverters()?.get('messages').convertAppMessage(message),
guest: guest as ILivechatVisitor,
message: livechatMessage as ILivechatMessage,
agent: undefined,
roomInfo: {
source: {
Expand All @@ -59,13 +58,16 @@ export class AppLivechatBridge extends LivechatBridge {
return msg._id;
}

protected async getMessageById(messageId: string, appId: string): Promise<ILivechatMessage> {
protected async getMessageById(messageId: string, appId: string): Promise<IAppsLivechatMessage> {
this.orch.debugLog(`The App ${appId} is getting the message: "${messageId}"`);

return this.orch.getConverters()?.get('messages').convertById(messageId);
const message = await this.orch.getConverters().get('messages').convertById(messageId);

// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
return message as IAppsLivechatMessage;
}

protected async updateMessage(message: ILivechatMessage, appId: string): Promise<void> {
protected async updateMessage(message: IAppsLivechatMessage, appId: string): Promise<void> {
this.orch.debugLog(`The App ${appId} is updating a message.`);

const data = {
Expand Down Expand Up @@ -114,7 +116,8 @@ export class AppLivechatBridge extends LivechatBridge {
extraParams: undefined,
});

return this.orch.getConverters()?.get('rooms').convertRoom(result.room);
// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
return this.orch.getConverters()?.get('rooms').convertRoom(result.room) as Promise<ILivechatRoom>;
}

protected async closeRoom(room: ILivechatRoom, comment: string, closer: IUser | undefined, appId: string): Promise<boolean> {
Expand Down Expand Up @@ -152,7 +155,8 @@ export class AppLivechatBridge extends LivechatBridge {
result = await LivechatRooms.findOpenByVisitorToken(visitor.token, {}, extraQuery).toArray();
}

return Promise.all((result as unknown as ILivechatRoom[]).map((room) => this.orch.getConverters()?.get('rooms').convertRoom(room)));
// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
return Promise.all(result.map((room) => this.orch.getConverters()?.get('rooms').convertRoom(room) as Promise<ILivechatRoom>));
}

protected async createVisitor(visitor: IVisitor, appId: string): Promise<string> {
Expand Down Expand Up @@ -208,8 +212,9 @@ export class AppLivechatBridge extends LivechatBridge {
userId = transferredTo._id;
}

// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
return LivechatTyped.transfer(
await this.orch.getConverters()?.get('rooms').convertAppRoom(currentRoom),
(await this.orch.getConverters()?.get('rooms').convertAppRoom(currentRoom)) as IOmnichannelRoom,
this.orch.getConverters()?.get('visitors').convertAppVisitor(visitor),
{ userId, departmentId, transferredBy, transferredTo },
);
Expand Down Expand Up @@ -275,7 +280,8 @@ export class AppLivechatBridge extends LivechatBridge {
this.orch.debugLog(`The App ${appId} is looking for livechat departments.`);

const converter = this.orch.getConverters()?.get('departments');
const boundConverter = converter.convertDepartment.bind(converter);
// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.
const boundConverter = converter.convertDepartment.bind(converter) as (_: ILivechatDepartment) => Promise<IDepartment>;

return Promise.all((await LivechatDepartment.findEnabledWithAgents().toArray()).map(boundConverter));
}
Expand Down
Loading