From 0ed2fd608c68d85e71fdff965ee21f2c423dd933 Mon Sep 17 00:00:00 2001 From: Douglas Gubert Date: Wed, 27 Dec 2023 16:00:44 -0300 Subject: [PATCH] Add handlers for App methods on Deno and refactor their usages on Node (#690) --- deno-runtime/handlers/app/construct.ts | 3 +- deno-runtime/handlers/app/handleGetStatus.ts | 14 +++++++++ deno-runtime/handlers/app/handleOnDisable.ts | 18 ++++++++++++ deno-runtime/handlers/app/handleOnEnable.ts | 16 ++++++++++ deno-runtime/handlers/app/handleOnInstall.ts | 29 +++++++++++++++++++ .../handlers/app/handleOnPreSettingUpdate.ts | 21 ++++++++++++++ .../handlers/app/handleOnSettingUpdated.ts | 23 +++++++++++++++ .../handlers/app/handleOnUninstall.ts | 29 +++++++++++++++++++ deno-runtime/handlers/app/handleSetStatus.ts | 24 +++++++++++++++ deno-runtime/handlers/app/handler.ts | 27 ++++++++++++++++- deno-runtime/handlers/app/initialize.ts | 1 + src/server/AppManager.ts | 22 +++----------- 12 files changed, 206 insertions(+), 21 deletions(-) create mode 100644 deno-runtime/handlers/app/handleGetStatus.ts create mode 100644 deno-runtime/handlers/app/handleOnDisable.ts create mode 100644 deno-runtime/handlers/app/handleOnEnable.ts create mode 100644 deno-runtime/handlers/app/handleOnInstall.ts create mode 100644 deno-runtime/handlers/app/handleOnPreSettingUpdate.ts create mode 100644 deno-runtime/handlers/app/handleOnSettingUpdated.ts create mode 100644 deno-runtime/handlers/app/handleOnUninstall.ts create mode 100644 deno-runtime/handlers/app/handleSetStatus.ts diff --git a/deno-runtime/handlers/app/construct.ts b/deno-runtime/handlers/app/construct.ts index 85e1ce482..e7d214bbf 100644 --- a/deno-runtime/handlers/app/construct.ts +++ b/deno-runtime/handlers/app/construct.ts @@ -48,7 +48,7 @@ export default async function handleConstructApp(params: unknown): Promise { + const app = AppObjectRegistry.get('app'); + + if (typeof app?.getStatus !== 'function') { + throw new Error('App must contain a getStatus function', { + cause: 'invalid_app', + }); + } + + return app.getStatus(); +} diff --git a/deno-runtime/handlers/app/handleOnDisable.ts b/deno-runtime/handlers/app/handleOnDisable.ts new file mode 100644 index 000000000..0b09a2501 --- /dev/null +++ b/deno-runtime/handlers/app/handleOnDisable.ts @@ -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 { + const app = AppObjectRegistry.get('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; +} + diff --git a/deno-runtime/handlers/app/handleOnEnable.ts b/deno-runtime/handlers/app/handleOnEnable.ts new file mode 100644 index 000000000..1bdf84476 --- /dev/null +++ b/deno-runtime/handlers/app/handleOnEnable.ts @@ -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 { + const app = AppObjectRegistry.get('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()); +} diff --git a/deno-runtime/handlers/app/handleOnInstall.ts b/deno-runtime/handlers/app/handleOnInstall.ts new file mode 100644 index 000000000..6a392cd9a --- /dev/null +++ b/deno-runtime/handlers/app/handleOnInstall.ts @@ -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 { + const app = AppObjectRegistry.get('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]; + + await app.onInstall( + context, + AppAccessorsInstance.getReader(), + AppAccessorsInstance.getHttp(), + AppAccessorsInstance.getPersistence(), + AppAccessorsInstance.getModifier(), + ); + + return true; +} diff --git a/deno-runtime/handlers/app/handleOnPreSettingUpdate.ts b/deno-runtime/handlers/app/handleOnPreSettingUpdate.ts new file mode 100644 index 000000000..5d51586ec --- /dev/null +++ b/deno-runtime/handlers/app/handleOnPreSettingUpdate.ts @@ -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 { + const app = AppObjectRegistry.get('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]; + + return app.onPreSettingUpdate(setting, AppAccessorsInstance.getConfigurationModify(), AppAccessorsInstance.getReader(), AppAccessorsInstance.getHttp()); +} diff --git a/deno-runtime/handlers/app/handleOnSettingUpdated.ts b/deno-runtime/handlers/app/handleOnSettingUpdated.ts new file mode 100644 index 000000000..eb76f71f2 --- /dev/null +++ b/deno-runtime/handlers/app/handleOnSettingUpdated.ts @@ -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 { + const app = AppObjectRegistry.get('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]; + + await app.onSettingUpdated(setting, AppAccessorsInstance.getConfigurationModify(), AppAccessorsInstance.getReader(), AppAccessorsInstance.getHttp()); + + return true; +} diff --git a/deno-runtime/handlers/app/handleOnUninstall.ts b/deno-runtime/handlers/app/handleOnUninstall.ts new file mode 100644 index 000000000..e37d63084 --- /dev/null +++ b/deno-runtime/handlers/app/handleOnUninstall.ts @@ -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 { + const app = AppObjectRegistry.get('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]; + + await app.onUninstall( + context, + AppAccessorsInstance.getReader(), + AppAccessorsInstance.getHttp(), + AppAccessorsInstance.getPersistence(), + AppAccessorsInstance.getModifier(), + ); + + return true; +} diff --git a/deno-runtime/handlers/app/handleSetStatus.ts b/deno-runtime/handlers/app/handleSetStatus.ts new file mode 100644 index 000000000..3892809ff --- /dev/null +++ b/deno-runtime/handlers/app/handleSetStatus.ts @@ -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 { + 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'); + + if (!app || typeof app['setStatus'] !== 'function') { + throw new Error('App must contain a setStatus function', { + cause: 'invalid_app', + }); + } + + await app['setStatus'](status); + + return null; +} diff --git a/deno-runtime/handlers/app/handler.ts b/deno-runtime/handlers/app/handler.ts index a8f7d9bf6..c763f2b41 100644 --- a/deno-runtime/handlers/app/handler.ts +++ b/deno-runtime/handlers/app/handler.ts @@ -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 { const [, appMethod] = method.split(':'); @@ -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); } diff --git a/deno-runtime/handlers/app/initialize.ts b/deno-runtime/handlers/app/initialize.ts index d592d2970..ad90d3b01 100644 --- a/deno-runtime/handlers/app/initialize.ts +++ b/deno-runtime/handlers/app/initialize.ts @@ -16,3 +16,4 @@ export default async function handleInitialize(): Promise { return true; } + diff --git a/src/server/AppManager.ts b/src/server/AppManager.ts index 96471290b..59e62e863 100644 --- a/src/server/AppManager.ts +++ b/src/server/AppManager.ts @@ -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 }); @@ -887,14 +885,10 @@ export class AppManager { private async installApp(storageItem: IAppStorageItem, app: ProxiedApp, user: IUser): Promise { 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) { @@ -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; @@ -1089,14 +1079,10 @@ export class AppManager { private async uninstallApp(app: ProxiedApp, user: IUser): Promise { 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) {