diff options
Diffstat (limited to 'server/lib/plugins/plugin-manager.ts')
-rw-r--r-- | server/lib/plugins/plugin-manager.ts | 122 |
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' | |||
5 | import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' | 5 | import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' |
6 | import { ClientScript, PluginPackageJson } from '../../../shared/models/plugins/plugin-package-json.model' | 6 | import { ClientScript, PluginPackageJson } from '../../../shared/models/plugins/plugin-package-json.model' |
7 | import { createReadStream, createWriteStream } from 'fs' | 7 | import { createReadStream, createWriteStream } from 'fs' |
8 | import { PLUGIN_GLOBAL_CSS_PATH } from '../../initializers/constants' | 8 | import { PLUGIN_GLOBAL_CSS_PATH, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../../initializers/constants' |
9 | import { PluginType } from '../../../shared/models/plugins/plugin.type' | 9 | import { PluginType } from '../../../shared/models/plugins/plugin.type' |
10 | import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' | 10 | import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' |
11 | import { outputFile, readJSON } from 'fs-extra' | 11 | import { outputFile, readJSON } from 'fs-extra' |
@@ -18,6 +18,9 @@ import { PluginLibrary } from '../../typings/plugins' | |||
18 | import { ClientHtml } from '../client-html' | 18 | import { ClientHtml } from '../client-html' |
19 | import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model' | 19 | import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model' |
20 | import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model' | 20 | import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model' |
21 | import { PluginVideoLanguageManager } from '../../../shared/models/plugins/plugin-video-language-manager.model' | ||
22 | import { PluginVideoCategoryManager } from '../../../shared/models/plugins/plugin-video-category-manager.model' | ||
23 | import { PluginVideoLicenceManager } from '../../../shared/models/plugins/plugin-video-licence-manager.model' | ||
21 | 24 | ||
22 | export interface RegisteredPlugin { | 25 | export 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 | ||
52 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | ||
53 | type VideoConstant = { [ key in number | string ]: string } | ||
54 | type 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 | |||
49 | export class PluginManager implements ServerHook { | 63 | export 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 | } |