aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/plugins')
-rw-r--r--server/lib/plugins/plugin-manager.ts122
1 files changed, 121 insertions, 1 deletions
diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts
index 78e8d758f..81554a09e 100644
--- a/server/lib/plugins/plugin-manager.ts
+++ b/server/lib/plugins/plugin-manager.ts
@@ -5,7 +5,7 @@ import { CONFIG } from '../../initializers/config'
5import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' 5import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins'
6import { ClientScript, PluginPackageJson } from '../../../shared/models/plugins/plugin-package-json.model' 6import { ClientScript, PluginPackageJson } from '../../../shared/models/plugins/plugin-package-json.model'
7import { createReadStream, createWriteStream } from 'fs' 7import { createReadStream, createWriteStream } from 'fs'
8import { PLUGIN_GLOBAL_CSS_PATH } from '../../initializers/constants' 8import { PLUGIN_GLOBAL_CSS_PATH, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../../initializers/constants'
9import { PluginType } from '../../../shared/models/plugins/plugin.type' 9import { PluginType } from '../../../shared/models/plugins/plugin.type'
10import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' 10import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn'
11import { outputFile, readJSON } from 'fs-extra' 11import { outputFile, readJSON } from 'fs-extra'
@@ -18,6 +18,9 @@ import { PluginLibrary } from '../../typings/plugins'
18import { ClientHtml } from '../client-html' 18import { ClientHtml } from '../client-html'
19import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model' 19import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model'
20import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model' 20import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model'
21import { PluginVideoLanguageManager } from '../../../shared/models/plugins/plugin-video-language-manager.model'
22import { PluginVideoCategoryManager } from '../../../shared/models/plugins/plugin-video-category-manager.model'
23import { PluginVideoLicenceManager } from '../../../shared/models/plugins/plugin-video-licence-manager.model'
21 24
22export interface RegisteredPlugin { 25export interface RegisteredPlugin {
23 npmName: string 26 npmName: string
@@ -46,6 +49,17 @@ export interface HookInformationValue {
46 priority: number 49 priority: number
47} 50}
48 51
52type AlterableVideoConstant = 'language' | 'licence' | 'category'
53type VideoConstant = { [ key in number | string ]: string }
54type UpdatedVideoConstant = {
55 [ name in AlterableVideoConstant ]: {
56 [ npmName: string ]: {
57 added: { key: number | string, label: string }[],
58 deleted: { key: number | string, label: string }[]
59 }
60 }
61}
62
49export class PluginManager implements ServerHook { 63export class PluginManager implements ServerHook {
50 64
51 private static instance: PluginManager 65 private static instance: PluginManager
@@ -54,6 +68,12 @@ export class PluginManager implements ServerHook {
54 private settings: { [ name: string ]: RegisterServerSettingOptions[] } = {} 68 private settings: { [ name: string ]: RegisterServerSettingOptions[] } = {}
55 private hooks: { [ name: string ]: HookInformationValue[] } = {} 69 private hooks: { [ name: string ]: HookInformationValue[] } = {}
56 70
71 private updatedVideoConstants: UpdatedVideoConstant = {
72 language: {},
73 licence: {},
74 category: {}
75 }
76
57 private constructor () { 77 private constructor () {
58 } 78 }
59 79
@@ -161,6 +181,8 @@ export class PluginManager implements ServerHook {
161 this.hooks[key] = this.hooks[key].filter(h => h.pluginName !== npmName) 181 this.hooks[key] = this.hooks[key].filter(h => h.pluginName !== npmName)
162 } 182 }
163 183
184 this.reinitVideoConstants(plugin.npmName)
185
164 logger.info('Regenerating registered plugin CSS to global file.') 186 logger.info('Regenerating registered plugin CSS to global file.')
165 await this.regeneratePluginGlobalCSS() 187 await this.regeneratePluginGlobalCSS()
166 } 188 }
@@ -427,6 +449,24 @@ export class PluginManager implements ServerHook {
427 storeData: (key: string, data: any) => PluginModel.storeData(plugin.name, plugin.type, key, data) 449 storeData: (key: string, data: any) => PluginModel.storeData(plugin.name, plugin.type, key, data)
428 } 450 }
429 451
452 const videoLanguageManager: PluginVideoLanguageManager = {
453 addLanguage: (key: string, label: string) => this.addConstant({ npmName, type: 'language', obj: VIDEO_LANGUAGES, key, label }),
454
455 deleteLanguage: (key: string) => this.deleteConstant({ npmName, type: 'language', obj: VIDEO_LANGUAGES, key })
456 }
457
458 const videoCategoryManager: PluginVideoCategoryManager= {
459 addCategory: (key: number, label: string) => this.addConstant({ npmName, type: 'category', obj: VIDEO_CATEGORIES, key, label }),
460
461 deleteCategory: (key: number) => this.deleteConstant({ npmName, type: 'category', obj: VIDEO_CATEGORIES, key })
462 }
463
464 const videoLicenceManager: PluginVideoLicenceManager = {
465 addLicence: (key: number, label: string) => this.addConstant({ npmName, type: 'licence', obj: VIDEO_LICENCES, key, label }),
466
467 deleteLicence: (key: number) => this.deleteConstant({ npmName, type: 'licence', obj: VIDEO_LICENCES, key })
468 }
469
430 const peertubeHelpers = { 470 const peertubeHelpers = {
431 logger 471 logger
432 } 472 }
@@ -436,10 +476,90 @@ export class PluginManager implements ServerHook {
436 registerSetting, 476 registerSetting,
437 settingsManager, 477 settingsManager,
438 storageManager, 478 storageManager,
479 videoLanguageManager,
480 videoCategoryManager,
481 videoLicenceManager,
439 peertubeHelpers 482 peertubeHelpers
440 } 483 }
441 } 484 }
442 485
486 private addConstant <T extends string | number> (parameters: {
487 npmName: string,
488 type: AlterableVideoConstant,
489 obj: VideoConstant,
490 key: T,
491 label: string
492 }) {
493 const { npmName, type, obj, key, label } = parameters
494
495 if (obj[key]) {
496 logger.warn('Cannot add %s %s by plugin %s: key already exists.', type, npmName, key)
497 return false
498 }
499
500 if (!this.updatedVideoConstants[type][npmName]) {
501 this.updatedVideoConstants[type][npmName] = {
502 added: [],
503 deleted: []
504 }
505 }
506
507 this.updatedVideoConstants[type][npmName].added.push({ key, label })
508 obj[key] = label
509
510 return true
511 }
512
513 private deleteConstant <T extends string | number> (parameters: {
514 npmName: string,
515 type: AlterableVideoConstant,
516 obj: VideoConstant,
517 key: T
518 }) {
519 const { npmName, type, obj, key } = parameters
520
521 if (!obj[key]) {
522 logger.warn('Cannot delete %s %s by plugin %s: key does not exist.', type, npmName, key)
523 return false
524 }
525
526 if (!this.updatedVideoConstants[type][npmName]) {
527 this.updatedVideoConstants[type][npmName] = {
528 added: [],
529 deleted: []
530 }
531 }
532
533 this.updatedVideoConstants[type][npmName].deleted.push({ key, label: obj[key] })
534 delete obj[key]
535
536 return true
537 }
538
539 private reinitVideoConstants (npmName: string) {
540 const hash = {
541 language: VIDEO_LANGUAGES,
542 licence: VIDEO_LICENCES,
543 category: VIDEO_CATEGORIES
544 }
545 const types: AlterableVideoConstant[] = [ 'language', 'licence', 'category' ]
546
547 for (const type of types) {
548 const updatedConstants = this.updatedVideoConstants[type][npmName]
549 if (!updatedConstants) continue
550
551 for (const added of updatedConstants.added) {
552 delete hash[type][added.key]
553 }
554
555 for (const deleted of updatedConstants.deleted) {
556 hash[type][deleted.key] = deleted.label
557 }
558
559 delete this.updatedVideoConstants[type][npmName]
560 }
561 }
562
443 static get Instance () { 563 static get Instance () {
444 return this.instance || (this.instance = new this()) 564 return this.instance || (this.instance = new this())
445 } 565 }