X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Flib%2Fplugins%2Fplugin-manager.ts;h=1305f660ff3333ff1c0feec816dd8770c51a85c6;hb=4d526901349b35bfac9811acc45854c65639cee3;hp=c19b4013512c0735dcac883103ad542da84a2622;hpb=1896bca09e088b0da9d5e845407ecebae330618c;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index c19b40135..1305f660f 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts @@ -1,18 +1,20 @@ -import * as express from 'express' +import express from 'express' import { createReadStream, createWriteStream } from 'fs' -import { outputFile, readJSON } from 'fs-extra' +import { ensureDir, outputFile, readJSON } from 'fs-extra' import { basename, join } from 'path' +import { decachePlugin } from '@server/helpers/decache' import { MOAuthTokenUser, MUser } from '@server/types/models' -import { RegisterServerHookOptions } from '@shared/models/plugins/register-server-hook.model' -import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' +import { getCompleteLocale } from '@shared/core-utils' import { - ClientScript, - PluginPackageJson, - PluginTranslationPaths as PackagePluginTranslations -} from '../../../shared/models/plugins/plugin-package-json.model' -import { PluginTranslation } from '../../../shared/models/plugins/plugin-translation.model' + ClientScriptJSON, + PluginPackageJSON, + PluginTranslation, + PluginTranslationPathsJSON, + RegisterServerHookOptions +} from '@shared/models' +import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' import { PluginType } from '../../../shared/models/plugins/plugin.type' -import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server-hook.model' +import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server/server-hook.model' import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' import { logger } from '../../helpers/logger' import { CONFIG } from '../../initializers/config' @@ -35,7 +37,7 @@ export interface RegisteredPlugin { path: string staticDirs: { [name: string]: string } - clientScripts: { [name: string]: ClientScript } + clientScripts: { [name: string]: ClientScriptJSON } css: string[] @@ -188,7 +190,7 @@ export class PluginManager implements ServerHook { return undefined } - onSettingsChanged (name: string, settings: any) { + async onSettingsChanged (name: string, settings: any) { const registered = this.getRegisteredPluginByShortName(name) if (!registered) { logger.error('Cannot find plugin %s to call on settings changed.', name) @@ -196,7 +198,7 @@ export class PluginManager implements ServerHook { for (const cb of registered.registerHelpers.getOnSettingsChangedCallbacks()) { try { - cb(settings) + await cb(settings) } catch (err) { logger.error('Cannot run on settings changed callback for %s.', registered.npmName, { err }) } @@ -275,6 +277,8 @@ export class PluginManager implements ServerHook { logger.info('Regenerating registered plugin CSS to global file.') await this.regeneratePluginGlobalCSS() } + + ClientHtml.invalidCache() } // ###################### Installation ###################### @@ -308,30 +312,43 @@ export class PluginManager implements ServerHook { uninstalled: false, peertubeEngine: packageJSON.engine.peertube }, { returning: true }) - } catch (err) { - logger.error('Cannot install plugin %s, removing it...', toInstall, { err }) + + logger.info('Successful installation of plugin %s.', toInstall) + + await this.registerPluginOrTheme(plugin) + } catch (rootErr) { + logger.error('Cannot install plugin %s, removing it...', toInstall, { err: rootErr }) try { - await removeNpmPlugin(npmName) + await this.uninstall(npmName) } catch (err) { - logger.error('Cannot remove plugin %s after failed installation.', toInstall, { err }) + logger.error('Cannot uninstall plugin %s after failed installation.', toInstall, { err }) + + try { + await removeNpmPlugin(npmName) + } catch (err) { + logger.error('Cannot remove plugin %s after failed installation.', toInstall, { err }) + } } - throw err + throw rootErr } - logger.info('Successful installation of plugin %s.', toInstall) - - await this.registerPluginOrTheme(plugin) - return plugin } - async update (toUpdate: string, version?: string, fromDisk = false) { + async update (toUpdate: string, fromDisk = false) { const npmName = fromDisk ? basename(toUpdate) : toUpdate logger.info('Updating plugin %s.', npmName) + // Use the latest version from DB, to not upgrade to a version that does not support our PeerTube version + let version: string + if (!fromDisk) { + const plugin = await PluginModel.loadByNpmName(toUpdate) + version = plugin.latestVersion + } + // Unregister old hooks await this.unregister(npmName) @@ -383,7 +400,7 @@ export class PluginManager implements ServerHook { registerHelpers = result.registerStore } - const clientScripts: { [id: string]: ClientScript } = {} + const clientScripts: { [id: string]: ClientScriptJSON } = {} for (const c of packageJSON.clientScripts) { clientScripts[c.script] = c } @@ -404,14 +421,16 @@ export class PluginManager implements ServerHook { } await this.addTranslations(plugin, npmName, packageJSON.translations) + + ClientHtml.invalidCache() } - private async registerPlugin (plugin: PluginModel, pluginPath: string, packageJSON: PluginPackageJson) { + private async registerPlugin (plugin: PluginModel, pluginPath: string, packageJSON: PluginPackageJSON) { const npmName = PluginModel.buildNpmName(plugin.name, plugin.type) // Delete cache if needed const modulePath = join(pluginPath, packageJSON.library) - delete require.cache[modulePath] + decachePlugin(pluginPath, modulePath) const library: PluginLibrary = require(modulePath) if (!isLibraryCodeValid(library)) { @@ -419,8 +438,10 @@ export class PluginManager implements ServerHook { } const { registerOptions, registerStore } = this.getRegisterHelpers(npmName, plugin) - library.register(registerOptions) - .catch(err => logger.error('Cannot register plugin %s.', npmName, { err })) + + await ensureDir(registerOptions.peertubeHelpers.plugin.getDataDirectoryPath()) + + await library.register(registerOptions) logger.info('Add plugin %s CSS to global file.', npmName) @@ -431,15 +452,17 @@ export class PluginManager implements ServerHook { // ###################### Translations ###################### - private async addTranslations (plugin: PluginModel, npmName: string, translationPaths: PackagePluginTranslations) { + private async addTranslations (plugin: PluginModel, npmName: string, translationPaths: PluginTranslationPathsJSON) { for (const locale of Object.keys(translationPaths)) { const path = translationPaths[locale] const json = await readJSON(join(this.getPluginPath(plugin.name, plugin.type), path)) - if (!this.translations[locale]) this.translations[locale] = {} - this.translations[locale][npmName] = json + const completeLocale = getCompleteLocale(locale) - logger.info('Added locale %s of plugin %s.', locale, npmName) + if (!this.translations[completeLocale]) this.translations[completeLocale] = {} + this.translations[completeLocale][npmName] = json + + logger.info('Added locale %s of plugin %s.', completeLocale, npmName) } } @@ -454,8 +477,6 @@ export class PluginManager implements ServerHook { // ###################### CSS ###################### private resetCSSGlobalFile () { - ClientHtml.invalidCache() - return outputFile(PLUGIN_GLOBAL_CSS_PATH, '') } @@ -463,8 +484,6 @@ export class PluginManager implements ServerHook { for (const cssPath of cssRelativePaths) { await this.concatFiles(join(pluginPath, cssPath), PLUGIN_GLOBAL_CSS_PATH) } - - ClientHtml.invalidCache() } private concatFiles (input: string, output: string) { @@ -500,7 +519,7 @@ export class PluginManager implements ServerHook { private getPackageJSON (pluginName: string, pluginType: PluginType) { const pluginPath = join(this.getPluginPath(pluginName, pluginType), 'package.json') - return readJSON(pluginPath) as Promise + return readJSON(pluginPath) as Promise } private getPluginPath (pluginName: string, pluginType: PluginType) { @@ -559,7 +578,7 @@ export class PluginManager implements ServerHook { } } - private sanitizeAndCheckPackageJSONOrThrow (packageJSON: PluginPackageJson, pluginType: PluginType) { + private sanitizeAndCheckPackageJSONOrThrow (packageJSON: PluginPackageJSON, pluginType: PluginType) { if (!packageJSON.staticDirs) packageJSON.staticDirs = {} if (!packageJSON.css) packageJSON.css = [] if (!packageJSON.clientScripts) packageJSON.clientScripts = []