Skip to content

Commit

Permalink
Merge branch 'feat/deno-runtime' into feat/videoconf-handler
Browse files Browse the repository at this point in the history
  • Loading branch information
tapiarafael authored Dec 28, 2023
2 parents 67e4884 + 4a7a913 commit bfc5379
Show file tree
Hide file tree
Showing 17 changed files with 245 additions and 43 deletions.
3 changes: 1 addition & 2 deletions deno-runtime/handlers/app/construct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default async function handleConstructApp(params: unknown): Promise<boole
const [appPackage] = params as [IParseAppPackageResult];

if (!appPackage?.info?.id || !appPackage?.info?.classFile || !appPackage?.files) {
throw new Error('Invalid params', { cause: 'invalid_param_type'});
throw new Error('Invalid params', { cause: 'invalid_param_type' });
}

AppObjectRegistry.set('id', appPackage.info.id);
Expand Down Expand Up @@ -93,4 +93,3 @@ export default async function handleConstructApp(params: unknown): Promise<boole

return true;
}

14 changes: 14 additions & 0 deletions deno-runtime/handlers/app/handleGetStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';

export default function handleGetStatus(): Promise<boolean> {
const app = AppObjectRegistry.get<App>('app');

if (typeof app?.getStatus !== 'function') {
throw new Error('App must contain a getStatus function', {
cause: 'invalid_app',
});
}

return app.getStatus();
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export default async function handleInitialize(): Promise<boolean> {

return true;
}

18 changes: 18 additions & 0 deletions deno-runtime/handlers/app/handleOnDisable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import { AppAccessorsInstance } from '../../lib/accessors/mod.ts';

export default async function handleOnDisable(): Promise<boolean> {
const app = AppObjectRegistry.get<App>('app');

if (typeof app?.onDisable !== 'function') {
throw new Error('App must contain an onDisable function', {
cause: 'invalid_app',
});
}

await app.onDisable(AppAccessorsInstance.getConfigurationModify());

return true;
}

16 changes: 16 additions & 0 deletions deno-runtime/handlers/app/handleOnEnable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';

import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import { AppAccessorsInstance } from '../../lib/accessors/mod.ts';

export default function handleOnEnable(): Promise<boolean> {
const app = AppObjectRegistry.get<App>('app');

if (typeof app?.onEnable !== 'function') {
throw new Error('App must contain an onEnable function', {
cause: 'invalid_app',
});
}

return app.onEnable(AppAccessorsInstance.getEnvironmentRead(), AppAccessorsInstance.getConfigurationModify());
}
29 changes: 29 additions & 0 deletions deno-runtime/handlers/app/handleOnInstall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import { AppAccessorsInstance } from '../../lib/accessors/mod.ts';

export default async function handleOnInstall(params: unknown): Promise<boolean> {
const app = AppObjectRegistry.get<App>('app');

if (typeof app?.onInstall !== 'function') {
throw new Error('App must contain an onInstall function', {
cause: 'invalid_app',
});
}

if (!Array.isArray(params)) {
throw new Error('Invalid params', { cause: 'invalid_param_type' });
}

const [context] = params as [Record<string, unknown>];

await app.onInstall(
context,
AppAccessorsInstance.getReader(),
AppAccessorsInstance.getHttp(),
AppAccessorsInstance.getPersistence(),
AppAccessorsInstance.getModifier(),
);

return true;
}
21 changes: 21 additions & 0 deletions deno-runtime/handlers/app/handleOnPreSettingUpdate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import { AppAccessorsInstance } from '../../lib/accessors/mod.ts';

export default function handleOnPreSettingUpdate(params: unknown): Promise<object> {
const app = AppObjectRegistry.get<App>('app');

if (typeof app?.onPreSettingUpdate !== 'function') {
throw new Error('App must contain an onPreSettingUpdate function', {
cause: 'invalid_app',
});
}

if (!Array.isArray(params)) {
throw new Error('Invalid params', { cause: 'invalid_param_type' });
}

const [setting] = params as [Record<string, unknown>];

return app.onPreSettingUpdate(setting, AppAccessorsInstance.getConfigurationModify(), AppAccessorsInstance.getReader(), AppAccessorsInstance.getHttp());
}
23 changes: 23 additions & 0 deletions deno-runtime/handlers/app/handleOnSettingUpdated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import { AppAccessorsInstance } from '../../lib/accessors/mod.ts';

export default async function handleOnSettingUpdated(params: unknown): Promise<boolean> {
const app = AppObjectRegistry.get<App>('app');

if (typeof app?.onSettingUpdated !== 'function') {
throw new Error('App must contain an onSettingUpdated function', {
cause: 'invalid_app',
});
}

if (!Array.isArray(params)) {
throw new Error('Invalid params', { cause: 'invalid_param_type' });
}

const [setting] = params as [Record<string, unknown>];

await app.onSettingUpdated(setting, AppAccessorsInstance.getConfigurationModify(), AppAccessorsInstance.getReader(), AppAccessorsInstance.getHttp());

return true;
}
29 changes: 29 additions & 0 deletions deno-runtime/handlers/app/handleOnUninstall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import { AppAccessorsInstance } from '../../lib/accessors/mod.ts';

export default async function handleOnUninstall(params: unknown): Promise<boolean> {
const app = AppObjectRegistry.get<App>('app');

if (typeof app?.onUninstall !== 'function') {
throw new Error('App must contain an onUninstall function', {
cause: 'invalid_app',
});
}

if (!Array.isArray(params)) {
throw new Error('Invalid params', { cause: 'invalid_param_type' });
}

const [context] = params as [Record<string, unknown>];

await app.onUninstall(
context,
AppAccessorsInstance.getReader(),
AppAccessorsInstance.getHttp(),
AppAccessorsInstance.getPersistence(),
AppAccessorsInstance.getModifier(),
);

return true;
}
24 changes: 24 additions & 0 deletions deno-runtime/handlers/app/handleSetStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { App } from '@rocket.chat/apps-engine/definition/App.ts';
import { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus.ts';

import { AppObjectRegistry } from '../../AppObjectRegistry.ts';

export default async function handleSetStatus(params: unknown): Promise<null> {
if (!Array.isArray(params) || !Object.values(AppStatus).includes(params[0])) {
throw new Error('Invalid params', { cause: 'invalid_param_type' });
}

const [status] = params as [AppStatus];

const app = AppObjectRegistry.get<App>('app');

if (!app || typeof app['setStatus'] !== 'function') {
throw new Error('App must contain a setStatus function', {
cause: 'invalid_app',
});
}

await app['setStatus'](status);

return null;
}
27 changes: 26 additions & 1 deletion deno-runtime/handlers/app/handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { Defined, JsonRpcError } from 'jsonrpc-lite';

import handleConstructApp from './construct.ts';
import handleInitialize from './initialize.ts';
import handleInitialize from './handleInitialize.ts';
import handleGetStatus from './handleGetStatus.ts';
import handleSetStatus from './handleSetStatus.ts';
import handleOnEnable from './handleOnEnable.ts';
import handleOnInstall from './handleOnInstall.ts';
import handleOnDisable from './handleOnDisable.ts';
import handleOnUninstall from './handleOnUninstall.ts';
import handleOnPreSettingUpdate from './handleOnPreSettingUpdate.ts';
import handleOnSettingUpdated from './handleOnSettingUpdated.ts';

export default async function handleApp(method: string, params: unknown): Promise<Defined | JsonRpcError> {
const [, appMethod] = method.split(':');
Expand All @@ -11,6 +20,22 @@ export default async function handleApp(method: string, params: unknown): Promis
return await handleConstructApp(params);
case 'initialize':
return await handleInitialize();
case 'getStatus':
return await handleGetStatus();
case 'setStatus':
return await handleSetStatus(params);
case 'onEnable':
return await handleOnEnable();
case 'onDisable':
return await handleOnDisable();
case 'onInstall':
return await handleOnInstall(params);
case 'onUninstall':
return await handleOnUninstall(params);
case 'onPreSettingUpdate':
return await handleOnPreSettingUpdate(params);
case 'onSettingUpdated':
return await handleOnSettingUpdated(params);
default:
throw new JsonRpcError('Method not found', -32601);
}
Expand Down
16 changes: 9 additions & 7 deletions deno-runtime/lib/accessors/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import type { IVideoConfProvider } from '@rocket.chat/apps-engine/definition/vid

import * as Messenger from '../messenger.ts';
import { AppObjectRegistry } from '../../AppObjectRegistry.ts';
import { ModifyCreator } from "./modify/ModifyCreator.ts";
import { ModifyUpdater } from "./modify/ModifyUpdater.ts";
import { ModifyExtender } from "./modify/ModifyExtender.ts";
import { ModifyCreator } from './modify/ModifyCreator.ts';
import { ModifyUpdater } from './modify/ModifyUpdater.ts';
import { ModifyExtender } from './modify/ModifyExtender.ts';

const httpMethods = ['get', 'post', 'put', 'delete', 'head', 'options', 'patch'] as const;

Expand Down Expand Up @@ -44,10 +44,12 @@ export class AppAccessors {
get:
(_target: unknown, prop: string) =>
(...params: unknown[]) =>
senderFn({
method: `accessor:${namespace}:${prop}`,
params,
}),
prop === 'toJSON'
? {}
: senderFn({
method: `accessor:${namespace}:${prop}`,
params,
}),
},
) as T;
}
Expand Down
14 changes: 10 additions & 4 deletions deno-runtime/lib/accessors/modify/ModifyCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export class ModifyCreator implements IModifyCreator {
return () => Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
}

if (prop === 'toJSON') {
return () => ({});
}

return (...params: unknown[]) =>
this.senderFn({
method: `accessor:getModifier:getCreator:getLivechatCreator:${prop}`,
Expand All @@ -61,10 +65,12 @@ export class ModifyCreator implements IModifyCreator {
get:
(_target: unknown, prop: string) =>
(...params: unknown[]) =>
this.senderFn({
method: `accessor:getModifier:getCreator:getUploadCreator:${prop}`,
params,
}),
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getCreator:getUploadCreator:${prop}`,
params,
}),
},
) as IUploadCreator;
}
Expand Down
20 changes: 12 additions & 8 deletions deno-runtime/lib/accessors/modify/ModifyUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ export class ModifyUpdater implements IModifyUpdater {
get:
(_target: unknown, prop: string) =>
(...params: unknown[]) =>
this.senderFn({
method: `accessor:getModifier:getUpdater:getLivechatUpdater:${prop}`,
params,
}),
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getUpdater:getLivechatUpdater:${prop}`,
params,
}),
},
) as ILivechatUpdater;
}
Expand All @@ -47,10 +49,12 @@ export class ModifyUpdater implements IModifyUpdater {
get:
(_target: unknown, prop: string) =>
(...params: unknown[]) =>
this.senderFn({
method: `accessor:getModifier:getUpdater:getUserUpdater:${prop}`,
params,
}),
prop === 'toJSON'
? {}
: this.senderFn({
method: `accessor:getModifier:getUpdater:getUserUpdater:${prop}`,
params,
}),
},
) as IUserUpdater;
}
Expand Down
5 changes: 5 additions & 0 deletions src/definition/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,9 @@ export abstract class App implements IApp {
this.logger.debug(`The status is now: ${status}`);
this.status = status;
}

// Avoid leaking references if object is serialized (e.g. to be sent over IPC)
public toJSON(): Record<string, any> {
return this.info;
}
}
22 changes: 4 additions & 18 deletions src/server/AppManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,7 @@ export class AppManager {
}

if (AppStatusUtils.isEnabled(app.getStatus())) {
await app
.call(AppMethod.ONDISABLE, this.accessorManager.getConfigurationModify(app.getID()))
.catch((e) => console.warn('Error while disabling:', e));
await app.call(AppMethod.ONDISABLE).catch((e) => console.warn('Error while disabling:', e));
}

await this.purgeAppConfig(app, { keepScheduledJobs: true });
Expand Down Expand Up @@ -887,14 +885,10 @@ export class AppManager {

private async installApp(storageItem: IAppStorageItem, app: ProxiedApp, user: IUser): Promise<boolean> {
let result: boolean;
const read = this.getAccessorManager().getReader(storageItem.id);
const http = this.getAccessorManager().getHttp(storageItem.id);
const persistence = this.getAccessorManager().getPersistence(storageItem.id);
const modifier = this.getAccessorManager().getModifier(storageItem.id);
const context = { user };

try {
await app.call(AppMethod.ONINSTALL, context, read, http, persistence, modifier);
await app.call(AppMethod.ONINSTALL, context);

result = true;
} catch (e) {
Expand Down Expand Up @@ -1000,11 +994,7 @@ export class AppManager {
await app.validateLicense();
await app.validateInstallation();

enable = (await app.call(
AppMethod.ONENABLE,
this.getAccessorManager().getEnvironmentRead(storageItem.id),
this.getAccessorManager().getConfigurationModify(storageItem.id),
)) as boolean;
enable = (await app.call(AppMethod.ONENABLE)) as boolean;

if (enable) {
status = isManual ? AppStatus.MANUALLY_ENABLED : AppStatus.AUTO_ENABLED;
Expand Down Expand Up @@ -1089,14 +1079,10 @@ export class AppManager {

private async uninstallApp(app: ProxiedApp, user: IUser): Promise<boolean> {
let result: boolean;
const read = this.getAccessorManager().getReader(app.getID());
const http = this.getAccessorManager().getHttp(app.getID());
const persistence = this.getAccessorManager().getPersistence(app.getID());
const modifier = this.getAccessorManager().getModifier(app.getID());
const context = { user };

try {
await app.call(AppMethod.ONUNINSTALL, context, read, http, persistence, modifier);
await app.call(AppMethod.ONUNINSTALL, context);

result = true;
} catch (e) {
Expand Down
Loading

0 comments on commit bfc5379

Please sign in to comment.