From ad91e7006e41f8ee5b8dcefee30f99e8ca44133a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 10 Jul 2019 16:59:53 +0200 Subject: WIP plugins: plugin settings on server side --- server/lib/plugins/plugin-manager.ts | 111 +++++++++++++++++++++++------------ server/lib/plugins/yarn.ts | 8 ++- 2 files changed, 79 insertions(+), 40 deletions(-) (limited to 'server/lib/plugins') diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index 8496979f8..3d8375acd 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts @@ -1,6 +1,5 @@ import { PluginModel } from '../../models/server/plugin' import { logger } from '../../helpers/logger' -import { RegisterHookOptions } from '../../../shared/models/plugins/register.model' import { basename, join } from 'path' import { CONFIG } from '../../initializers/config' import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' @@ -11,7 +10,9 @@ import { PLUGIN_GLOBAL_CSS_PATH } from '../../initializers/constants' import { PluginType } from '../../../shared/models/plugins/plugin.type' import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' import { outputFile } from 'fs-extra' -import { ServerConfigPlugin } from '../../../shared/models/server' +import { RegisterSettingOptions } from '../../../shared/models/plugins/register-setting.model' +import { RegisterHookOptions } from '../../../shared/models/plugins/register-hook.model' +import { PluginSettingsManager } from '../../../shared/models/plugins/plugin-settings-manager.model' export interface RegisteredPlugin { name: string @@ -43,26 +44,13 @@ export class PluginManager { private static instance: PluginManager private registeredPlugins: { [ name: string ]: RegisteredPlugin } = {} + private settings: { [ name: string ]: RegisterSettingOptions[] } = {} private hooks: { [ name: string ]: HookInformationValue[] } = {} private constructor () { } - async registerPluginsAndThemes () { - await this.resetCSSGlobalFile() - - const plugins = await PluginModel.listEnabledPluginsAndThemes() - - for (const plugin of plugins) { - try { - await this.registerPluginOrTheme(plugin) - } catch (err) { - logger.error('Cannot register plugin %s, skipping.', plugin.name, { err }) - } - } - - this.sortHooksByPriority() - } + // ###################### Getters ###################### getRegisteredPluginOrTheme (name: string) { return this.registeredPlugins[name] @@ -92,6 +80,12 @@ export class PluginManager { return this.getRegisteredPluginsOrThemes(PluginType.THEME) } + getSettings (name: string) { + return this.settings[name] || [] + } + + // ###################### Hooks ###################### + async runHook (hookName: string, param?: any) { let result = param @@ -99,8 +93,11 @@ export class PluginManager { for (const hook of this.hooks[hookName]) { try { - if (wait) result = await hook.handler(param) - else result = hook.handler() + if (wait) { + result = await hook.handler(param) + } else { + result = hook.handler() + } } catch (err) { logger.error('Cannot run hook %s of plugin %s.', hookName, hook.pluginName, { err }) } @@ -109,6 +106,24 @@ export class PluginManager { return result } + // ###################### Registration ###################### + + async registerPluginsAndThemes () { + await this.resetCSSGlobalFile() + + const plugins = await PluginModel.listEnabledPluginsAndThemes() + + for (const plugin of plugins) { + try { + await this.registerPluginOrTheme(plugin) + } catch (err) { + logger.error('Cannot register plugin %s, skipping.', plugin.name, { err }) + } + } + + this.sortHooksByPriority() + } + async unregister (name: string) { const plugin = this.getRegisteredPlugin(name) @@ -133,7 +148,9 @@ export class PluginManager { await this.regeneratePluginGlobalCSS() } - async install (toInstall: string, version: string, fromDisk = false) { + // ###################### Installation ###################### + + async install (toInstall: string, version?: string, fromDisk = false) { let plugin: PluginModel let name: string @@ -206,6 +223,8 @@ export class PluginManager { logger.info('Plugin %s uninstalled.', packageName) } + // ###################### Private register ###################### + private async registerPluginOrTheme (plugin: PluginModel) { logger.info('Registering plugin or theme %s.', plugin.name) @@ -251,13 +270,25 @@ export class PluginManager { }) } + const registerSetting = (options: RegisterSettingOptions) => { + if (!this.settings[plugin.name]) this.settings[plugin.name] = [] + + this.settings[plugin.name].push(options) + } + + const settingsManager: PluginSettingsManager = { + getSetting: (name: string) => PluginModel.getSetting(plugin.name, name), + + setSetting: (name: string, value: string) => PluginModel.setSetting(plugin.name, name, value) + } + const library: PluginLibrary = require(join(pluginPath, packageJSON.library)) if (!isLibraryCodeValid(library)) { throw new Error('Library code is not valid (miss register or unregister function)') } - library.register({ registerHook }) + library.register({ registerHook, registerSetting, settingsManager }) logger.info('Add plugin %s CSS to global file.', plugin.name) @@ -266,13 +297,7 @@ export class PluginManager { return library } - private sortHooksByPriority () { - for (const hookName of Object.keys(this.hooks)) { - this.hooks[hookName].sort((a, b) => { - return b.priority - a.priority - }) - } - } + // ###################### CSS ###################### private resetCSSGlobalFile () { return outputFile(PLUGIN_GLOBAL_CSS_PATH, '') @@ -296,6 +321,26 @@ export class PluginManager { }) } + private async regeneratePluginGlobalCSS () { + await this.resetCSSGlobalFile() + + for (const key of Object.keys(this.registeredPlugins)) { + const plugin = this.registeredPlugins[key] + + await this.addCSSToGlobalFile(plugin.path, plugin.css) + } + } + + // ###################### Utils ###################### + + private sortHooksByPriority () { + for (const hookName of Object.keys(this.hooks)) { + this.hooks[hookName].sort((a, b) => { + return b.priority - a.priority + }) + } + } + private getPackageJSON (pluginName: string, pluginType: PluginType) { const pluginPath = join(this.getPluginPath(pluginName, pluginType), 'package.json') @@ -312,15 +357,7 @@ export class PluginManager { return name.replace(/^peertube-((theme)|(plugin))-/, '') } - private async regeneratePluginGlobalCSS () { - await this.resetCSSGlobalFile() - - for (const key of Object.keys(this.registeredPlugins)) { - const plugin = this.registeredPlugins[key] - - await this.addCSSToGlobalFile(plugin.path, plugin.css) - } - } + // ###################### Private getters ###################### private getRegisteredPluginsOrThemes (type: PluginType) { const plugins: RegisteredPlugin[] = [] diff --git a/server/lib/plugins/yarn.ts b/server/lib/plugins/yarn.ts index 35fe1625f..5fe1c5046 100644 --- a/server/lib/plugins/yarn.ts +++ b/server/lib/plugins/yarn.ts @@ -5,12 +5,14 @@ import { CONFIG } from '../../initializers/config' import { outputJSON, pathExists } from 'fs-extra' import { join } from 'path' -async function installNpmPlugin (name: string, version: string) { +async function installNpmPlugin (name: string, version?: string) { // Security check checkNpmPluginNameOrThrow(name) - checkPluginVersionOrThrow(version) + if (version) checkPluginVersionOrThrow(version) + + let toInstall = name + if (version) toInstall += `@${version}` - const toInstall = `${name}@${version}` await execYarn('add ' + toInstall) } -- cgit v1.2.3