|
|
|
|
@ -1,4 +1,5 @@ |
|
|
|
|
/* eslint-disable @typescript-eslint/no-var-requires */ |
|
|
|
|
import type { ISetting } from '@rocket.chat/apps-engine/definition/settings'; |
|
|
|
|
import { AppClientManager } from '@rocket.chat/apps-engine/client/AppClientManager'; |
|
|
|
|
import { IApiEndpointMetadata } from '@rocket.chat/apps-engine/definition/api'; |
|
|
|
|
import { AppStatus } from '@rocket.chat/apps-engine/definition/AppStatus'; |
|
|
|
|
@ -6,6 +7,7 @@ import { IPermission } from '@rocket.chat/apps-engine/definition/permissions/IPe |
|
|
|
|
import { IAppStorageItem } from '@rocket.chat/apps-engine/server/storage/IAppStorageItem'; |
|
|
|
|
import { Meteor } from 'meteor/meteor'; |
|
|
|
|
import { Tracker } from 'meteor/tracker'; |
|
|
|
|
import { AppScreenshot, Serialized } from '@rocket.chat/core-typings'; |
|
|
|
|
|
|
|
|
|
import { App } from '../../../client/views/admin/apps/types'; |
|
|
|
|
import { dispatchToastMessage } from '../../../client/lib/toast'; |
|
|
|
|
@ -15,27 +17,23 @@ import { createDeferredValue } from '../lib/misc/DeferredValue'; |
|
|
|
|
import { |
|
|
|
|
IPricingPlan, |
|
|
|
|
EAppPurchaseType, |
|
|
|
|
IAppFromMarketplace, |
|
|
|
|
// IAppFromMarketplace,
|
|
|
|
|
IAppLanguage, |
|
|
|
|
IAppExternalURL, |
|
|
|
|
ICategory, |
|
|
|
|
IDeletedInstalledApp, |
|
|
|
|
IAppSynced, |
|
|
|
|
IAppScreenshots, |
|
|
|
|
// IAppSynced,
|
|
|
|
|
// IAppScreenshots,
|
|
|
|
|
// IScreenshot,
|
|
|
|
|
IAuthor, |
|
|
|
|
IDetailedChangelog, |
|
|
|
|
IDetailedDescription, |
|
|
|
|
ISubscriptionInfo, |
|
|
|
|
ISettingsReturn, |
|
|
|
|
ISettingsPayload, |
|
|
|
|
ISettingsSetReturn, |
|
|
|
|
} from './@types/IOrchestrator'; |
|
|
|
|
import { AppWebsocketReceiver } from './communication'; |
|
|
|
|
import { handleI18nResources } from './i18n'; |
|
|
|
|
import { RealAppsEngineUIHost } from './RealAppsEngineUIHost'; |
|
|
|
|
|
|
|
|
|
const { APIClient } = require('../../utils'); |
|
|
|
|
const { hasAtLeastOnePermission } = require('../../authorization'); |
|
|
|
|
import { APIClient } from '../../utils/client'; |
|
|
|
|
import { hasAtLeastOnePermission } from '../../authorization/client'; |
|
|
|
|
|
|
|
|
|
export interface IAppsFromMarketplace { |
|
|
|
|
price: number; |
|
|
|
|
@ -123,8 +121,9 @@ class AppClientOrchestrator { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public screenshots(appId: string): IAppScreenshots { |
|
|
|
|
return APIClient.get(`/v1/apps/${appId}/screenshots`); |
|
|
|
|
public async screenshots(appId: string): Promise<AppScreenshot[]> { |
|
|
|
|
const { screenshots } = await APIClient.get(`/apps/${appId}/screenshots`); |
|
|
|
|
return screenshots; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public isEnabled(): Promise<boolean> | undefined { |
|
|
|
|
@ -132,79 +131,87 @@ class AppClientOrchestrator { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getApps(): Promise<App[]> { |
|
|
|
|
const { apps } = await APIClient.get('/v1/apps'); |
|
|
|
|
return apps; |
|
|
|
|
const result = await APIClient.get('/apps'); |
|
|
|
|
if ('apps' in result) { |
|
|
|
|
return result.apps; |
|
|
|
|
} |
|
|
|
|
throw new Error('Apps not found'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getAppsFromMarketplace(): Promise<IAppsFromMarketplace[]> { |
|
|
|
|
const appsOverviews: IAppFromMarketplace[] = await APIClient.get('/v1/apps', { marketplace: 'true' }); |
|
|
|
|
return appsOverviews.map((app: IAppFromMarketplace) => { |
|
|
|
|
const { latest, price, pricingPlans, purchaseType, isEnterpriseOnly, modifiedAt } = app; |
|
|
|
|
return { |
|
|
|
|
...latest, |
|
|
|
|
price, |
|
|
|
|
pricingPlans, |
|
|
|
|
purchaseType, |
|
|
|
|
isEnterpriseOnly, |
|
|
|
|
modifiedAt, |
|
|
|
|
}; |
|
|
|
|
}); |
|
|
|
|
public async getAppsFromMarketplace(): Promise<App[]> { |
|
|
|
|
const result = await APIClient.get('/apps', { marketplace: 'true' }); |
|
|
|
|
|
|
|
|
|
if ('apps' in result) { |
|
|
|
|
const { apps: appsOverviews } = result; |
|
|
|
|
return appsOverviews.map((app) => { |
|
|
|
|
const { latest, price, pricingPlans, purchaseType, isEnterpriseOnly, modifiedAt } = app; |
|
|
|
|
return { |
|
|
|
|
...latest, |
|
|
|
|
price, |
|
|
|
|
pricingPlans, |
|
|
|
|
purchaseType, |
|
|
|
|
isEnterpriseOnly, |
|
|
|
|
modifiedAt, |
|
|
|
|
}; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
throw new Error('Apps not found'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getAppsOnBundle(bundleId: string): Promise<App[]> { |
|
|
|
|
const { apps } = await APIClient.get(`/v1/apps/bundles/${bundleId}/apps`); |
|
|
|
|
const { apps } = await APIClient.get(`/apps/bundles/${bundleId}/apps`); |
|
|
|
|
return apps; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getAppsLanguages(): Promise<IAppLanguage> { |
|
|
|
|
const { apps } = await APIClient.get('/v1/apps/languages'); |
|
|
|
|
const { apps } = await APIClient.get('/apps/languages'); |
|
|
|
|
return apps; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getApp(appId: string): Promise<App> { |
|
|
|
|
const { app } = await APIClient.get(`/v1/apps/${appId}`); |
|
|
|
|
const { app } = await APIClient.get(`/apps/${appId}` as any); |
|
|
|
|
return app; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getAppFromMarketplace(appId: string, version: string): Promise<App> { |
|
|
|
|
const { app } = await APIClient.get(`/v1/apps/${appId}`, { |
|
|
|
|
marketplace: 'true', |
|
|
|
|
version, |
|
|
|
|
}); |
|
|
|
|
return app; |
|
|
|
|
const result = await APIClient.get( |
|
|
|
|
`/apps/${appId}` as any, |
|
|
|
|
{ |
|
|
|
|
marketplace: 'true', |
|
|
|
|
version, |
|
|
|
|
} as any, |
|
|
|
|
); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getLatestAppFromMarketplace(appId: string, version: string): Promise<App> { |
|
|
|
|
const { app } = await APIClient.get(`/v1/apps/${appId}`, { |
|
|
|
|
marketplace: 'true', |
|
|
|
|
update: 'true', |
|
|
|
|
appVersion: version, |
|
|
|
|
}); |
|
|
|
|
const { app } = await APIClient.get( |
|
|
|
|
`/apps/${appId}` as any, |
|
|
|
|
{ |
|
|
|
|
marketplace: 'true', |
|
|
|
|
update: 'true', |
|
|
|
|
appVersion: version, |
|
|
|
|
} as any, |
|
|
|
|
); |
|
|
|
|
return app; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getAppSettings(appId: string): Promise<ISettingsReturn> { |
|
|
|
|
const { settings } = await APIClient.get(`/v1/apps/${appId}/settings`); |
|
|
|
|
return settings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async setAppSettings(appId: string, settings: ISettingsPayload): Promise<ISettingsSetReturn> { |
|
|
|
|
const { updated } = await APIClient.post(`/v1/apps/${appId}/settings`, undefined, { settings }); |
|
|
|
|
return updated; |
|
|
|
|
public async setAppSettings(appId: string, settings: ISetting[]): Promise<void> { |
|
|
|
|
await APIClient.post(`/apps/${appId}/settings`, { settings }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getAppApis(appId: string): Promise<IApiEndpointMetadata[]> { |
|
|
|
|
const { apis } = await APIClient.get(`/v1/apps/${appId}/apis`); |
|
|
|
|
const { apis } = await APIClient.get(`/apps/${appId}/apis`); |
|
|
|
|
return apis; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getAppLanguages(appId: string): Promise<IAppStorageItem['languageContent']> { |
|
|
|
|
const { languages } = await APIClient.get(`/v1/apps/${appId}/languages`); |
|
|
|
|
const { languages } = await APIClient.get(`/apps/${appId}/languages`); |
|
|
|
|
return languages; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async installApp(appId: string, version: string, permissionsGranted: IPermission[]): Promise<IDeletedInstalledApp> { |
|
|
|
|
const { app } = await APIClient.post('/v1/apps/', { |
|
|
|
|
public async installApp(appId: string, version: string, permissionsGranted: IPermission[]): Promise<App> { |
|
|
|
|
const { app } = await APIClient.post('/apps', { |
|
|
|
|
appId, |
|
|
|
|
marketplace: true, |
|
|
|
|
version, |
|
|
|
|
@ -214,48 +221,48 @@ class AppClientOrchestrator { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async updateApp(appId: string, version: string, permissionsGranted: IPermission[]): Promise<App> { |
|
|
|
|
const { app } = await APIClient.post(`/v1/apps/${appId}`, { |
|
|
|
|
const result = (await (APIClient.post as any)(`/apps/${appId}` as any, { |
|
|
|
|
appId, |
|
|
|
|
marketplace: true, |
|
|
|
|
version, |
|
|
|
|
permissionsGranted, |
|
|
|
|
}); |
|
|
|
|
return app; |
|
|
|
|
} |
|
|
|
|
})) as any; |
|
|
|
|
|
|
|
|
|
public uninstallApp(appId: string): IDeletedInstalledApp { |
|
|
|
|
return APIClient.delete(`apps/${appId}`); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public syncApp(appId: string): IAppSynced { |
|
|
|
|
return APIClient.post(`/v1/apps/${appId}/sync`); |
|
|
|
|
if ('app' in result) { |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
throw new Error('App not found'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async setAppStatus(appId: string, status: AppStatus): Promise<string> { |
|
|
|
|
const { status: effectiveStatus } = await APIClient.post(`/v1/apps/${appId}/status`, { status }); |
|
|
|
|
const { status: effectiveStatus } = await APIClient.post(`/apps/${appId}/status`, { status }); |
|
|
|
|
return effectiveStatus; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public enableApp(appId: string): Promise<string> { |
|
|
|
|
return this.setAppStatus(appId, AppStatus.MANUALLY_ENABLED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public disableApp(appId: string): Promise<string> { |
|
|
|
|
return this.setAppStatus(appId, AppStatus.MANUALLY_ENABLED); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public buildExternalUrl(appId: string, purchaseType = 'buy', details = false): IAppExternalURL { |
|
|
|
|
return APIClient.get('/v1/apps', { |
|
|
|
|
public async buildExternalUrl(appId: string, purchaseType: 'buy' | 'subscription' = 'buy', details = false): Promise<IAppExternalURL> { |
|
|
|
|
const result = await APIClient.get('/apps', { |
|
|
|
|
buildExternalUrl: 'true', |
|
|
|
|
appId, |
|
|
|
|
purchaseType, |
|
|
|
|
details, |
|
|
|
|
details: `${details}`, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
if ('url' in result) { |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
throw new Error('Failed to build external url'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public async getCategories(): Promise<ICategory[]> { |
|
|
|
|
const categories = await APIClient.get('/v1/apps', { categories: 'true' }); |
|
|
|
|
return categories; |
|
|
|
|
public async getCategories(): Promise<Serialized<ICategory>[]> { |
|
|
|
|
const result = await APIClient.get('/apps', { categories: 'true' }); |
|
|
|
|
if ('categories' in result) { |
|
|
|
|
return result.categories; |
|
|
|
|
} |
|
|
|
|
throw new Error('Categories not found'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public getUIHost(): RealAppsEngineUIHost { |
|
|
|
|
@ -267,7 +274,7 @@ export const Apps = new AppClientOrchestrator(); |
|
|
|
|
|
|
|
|
|
Meteor.startup(() => { |
|
|
|
|
CachedCollectionManager.onLogin(() => { |
|
|
|
|
Meteor.call('apps/is-enabled', (error: Error, isEnabled: boolean) => { |
|
|
|
|
Meteor.call('/apps/is-enabled', (error: Error, isEnabled: boolean) => { |
|
|
|
|
if (error) { |
|
|
|
|
Apps.handleError(error); |
|
|
|
|
return; |
|
|
|
|
@ -279,7 +286,7 @@ Meteor.startup(() => { |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
Tracker.autorun(() => { |
|
|
|
|
const isEnabled = settings.get('Apps_Framework_enabled'); |
|
|
|
|
const isEnabled = settings.get('/Apps_Framework_enabled'); |
|
|
|
|
Apps.load(isEnabled); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
|