aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/helpers/logger.ts51
-rw-r--r--server/lib/plugins/plugin-helpers.ts20
-rw-r--r--server/lib/plugins/plugin-manager.ts150
-rw-r--r--server/lib/plugins/register-helpers.ts180
-rw-r--r--server/typings/plugins/register-server-option.model.ts10
5 files changed, 242 insertions, 169 deletions
diff --git a/server/helpers/logger.ts b/server/helpers/logger.ts
index b8ae28b3f..9553f70e8 100644
--- a/server/helpers/logger.ts
+++ b/server/helpers/logger.ts
@@ -54,9 +54,11 @@ const jsonLoggerFormat = winston.format.printf(info => {
54const timestampFormatter = winston.format.timestamp({ 54const timestampFormatter = winston.format.timestamp({
55 format: 'YYYY-MM-DD HH:mm:ss.SSS' 55 format: 'YYYY-MM-DD HH:mm:ss.SSS'
56}) 56})
57const labelFormatter = winston.format.label({ 57const labelFormatter = (suffix?: string) => {
58 label 58 return winston.format.label({
59}) 59 label: suffix ? `${label} ${suffix}` : label
60 })
61}
60 62
61const fileLoggerOptions: FileTransportOptions = { 63const fileLoggerOptions: FileTransportOptions = {
62 filename: path.join(CONFIG.STORAGE.LOG_DIR, LOG_FILENAME), 64 filename: path.join(CONFIG.STORAGE.LOG_DIR, LOG_FILENAME),
@@ -72,25 +74,29 @@ if (CONFIG.LOG.ROTATION.ENABLED) {
72 fileLoggerOptions.maxFiles = CONFIG.LOG.ROTATION.MAX_FILES 74 fileLoggerOptions.maxFiles = CONFIG.LOG.ROTATION.MAX_FILES
73} 75}
74 76
75const logger = winston.createLogger({ 77const logger = buildLogger()
76 level: CONFIG.LOG.LEVEL, 78
77 format: winston.format.combine( 79function buildLogger (labelSuffix?: string) {
78 labelFormatter, 80 return winston.createLogger({
79 winston.format.splat() 81 level: CONFIG.LOG.LEVEL,
80 ), 82 format: winston.format.combine(
81 transports: [ 83 labelFormatter(labelSuffix),
82 new winston.transports.File(fileLoggerOptions), 84 winston.format.splat()
83 new winston.transports.Console({ 85 ),
84 handleExceptions: true, 86 transports: [
85 format: winston.format.combine( 87 new winston.transports.File(fileLoggerOptions),
86 timestampFormatter, 88 new winston.transports.Console({
87 winston.format.colorize(), 89 handleExceptions: true,
88 consoleLoggerFormat 90 format: winston.format.combine(
89 ) 91 timestampFormatter,
90 }) 92 winston.format.colorize(),
91 ], 93 consoleLoggerFormat
92 exitOnError: true 94 )
93}) 95 })
96 ],
97 exitOnError: true
98 })
99}
94 100
95function bunyanLogFactory (level: string) { 101function bunyanLogFactory (level: string) {
96 return function () { 102 return function () {
@@ -123,6 +129,7 @@ const bunyanLogger = {
123// --------------------------------------------------------------------------- 129// ---------------------------------------------------------------------------
124 130
125export { 131export {
132 buildLogger,
126 timestampFormatter, 133 timestampFormatter,
127 labelFormatter, 134 labelFormatter,
128 consoleLoggerFormat, 135 consoleLoggerFormat,
diff --git a/server/lib/plugins/plugin-helpers.ts b/server/lib/plugins/plugin-helpers.ts
new file mode 100644
index 000000000..36d08d84a
--- /dev/null
+++ b/server/lib/plugins/plugin-helpers.ts
@@ -0,0 +1,20 @@
1import { PluginModel } from '@server/models/server/plugin'
2import { PeerTubeHelpers } from '@server/typings/plugins'
3
4function buildPluginHelpers (npmName: string, plugin: PluginModel): PeerTubeHelpers {
5 const logger = buildLogger(npmName)
6
7 return {
8 logger
9 }
10}
11
12export {
13 buildPluginHelpers
14}
15
16// ---------------------------------------------------------------------------
17
18function buildLogger (npmName: string) {
19 return buildLogger(npmName)
20}
diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts
index 73f7a71ce..44530d203 100644
--- a/server/lib/plugins/plugin-manager.ts
+++ b/server/lib/plugins/plugin-manager.ts
@@ -9,12 +9,10 @@ import {
9 PluginTranslationPaths as PackagePluginTranslations 9 PluginTranslationPaths as PackagePluginTranslations
10} from '../../../shared/models/plugins/plugin-package-json.model' 10} from '../../../shared/models/plugins/plugin-package-json.model'
11import { createReadStream, createWriteStream } from 'fs' 11import { createReadStream, createWriteStream } from 'fs'
12import { PLUGIN_GLOBAL_CSS_PATH, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../../initializers/constants' 12import { PLUGIN_GLOBAL_CSS_PATH } from '../../initializers/constants'
13import { PluginType } from '../../../shared/models/plugins/plugin.type' 13import { PluginType } from '../../../shared/models/plugins/plugin.type'
14import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' 14import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn'
15import { outputFile, readJSON } from 'fs-extra' 15import { outputFile, readJSON } from 'fs-extra'
16import { PluginSettingsManager } from '../../../shared/models/plugins/plugin-settings-manager.model'
17import { PluginStorageManager } from '../../../shared/models/plugins/plugin-storage-manager.model'
18import { ServerHook, ServerHookName, serverHookObject } from '../../../shared/models/plugins/server-hook.model' 16import { ServerHook, ServerHookName, serverHookObject } from '../../../shared/models/plugins/server-hook.model'
19import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' 17import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks'
20import { RegisterServerOptions } from '../../typings/plugins/register-server-option.model' 18import { RegisterServerOptions } from '../../typings/plugins/register-server-option.model'
@@ -22,10 +20,8 @@ import { PluginLibrary } from '../../typings/plugins'
22import { ClientHtml } from '../client-html' 20import { ClientHtml } from '../client-html'
23import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model' 21import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model'
24import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model' 22import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model'
25import { PluginVideoLanguageManager } from '../../../shared/models/plugins/plugin-video-language-manager.model'
26import { PluginVideoCategoryManager } from '../../../shared/models/plugins/plugin-video-category-manager.model'
27import { PluginVideoLicenceManager } from '../../../shared/models/plugins/plugin-video-licence-manager.model'
28import { PluginTranslation } from '../../../shared/models/plugins/plugin-translation.model' 23import { PluginTranslation } from '../../../shared/models/plugins/plugin-translation.model'
24import { buildRegisterHelpers, reinitVideoConstants } from './register-helpers'
29 25
30export interface RegisteredPlugin { 26export interface RegisteredPlugin {
31 npmName: string 27 npmName: string
@@ -54,17 +50,6 @@ export interface HookInformationValue {
54 priority: number 50 priority: number
55} 51}
56 52
57type AlterableVideoConstant = 'language' | 'licence' | 'category'
58type VideoConstant = { [key in number | string]: string }
59type UpdatedVideoConstant = {
60 [name in AlterableVideoConstant]: {
61 [npmName: string]: {
62 added: { key: number | string, label: string }[]
63 deleted: { key: number | string, label: string }[]
64 }
65 }
66}
67
68type PluginLocalesTranslations = { 53type PluginLocalesTranslations = {
69 [locale: string]: PluginTranslation 54 [locale: string]: PluginTranslation
70} 55}
@@ -78,12 +63,6 @@ export class PluginManager implements ServerHook {
78 private hooks: { [name: string]: HookInformationValue[] } = {} 63 private hooks: { [name: string]: HookInformationValue[] } = {}
79 private translations: PluginLocalesTranslations = {} 64 private translations: PluginLocalesTranslations = {}
80 65
81 private readonly updatedVideoConstants: UpdatedVideoConstant = {
82 language: {},
83 licence: {},
84 category: {}
85 }
86
87 private constructor () { 66 private constructor () {
88 } 67 }
89 68
@@ -197,7 +176,7 @@ export class PluginManager implements ServerHook {
197 this.hooks[key] = this.hooks[key].filter(h => h.npmName !== npmName) 176 this.hooks[key] = this.hooks[key].filter(h => h.npmName !== npmName)
198 } 177 }
199 178
200 this.reinitVideoConstants(plugin.npmName) 179 reinitVideoConstants(plugin.npmName)
201 180
202 logger.info('Regenerating registered plugin CSS to global file.') 181 logger.info('Regenerating registered plugin CSS to global file.')
203 await this.regeneratePluginGlobalCSS() 182 await this.regeneratePluginGlobalCSS()
@@ -472,127 +451,12 @@ export class PluginManager implements ServerHook {
472 this.settings[npmName].push(options) 451 this.settings[npmName].push(options)
473 } 452 }
474 453
475 const settingsManager: PluginSettingsManager = { 454 const registerHelpers = buildRegisterHelpers(npmName, plugin)
476 getSetting: (name: string) => PluginModel.getSetting(plugin.name, plugin.type, name),
477 455
478 setSetting: (name: string, value: string) => PluginModel.setSetting(plugin.name, plugin.type, name, value) 456 return Object.assign(registerHelpers, {
479 }
480
481 const storageManager: PluginStorageManager = {
482 getData: (key: string) => PluginModel.getData(plugin.name, plugin.type, key),
483
484 storeData: (key: string, data: any) => PluginModel.storeData(plugin.name, plugin.type, key, data)
485 }
486
487 const videoLanguageManager: PluginVideoLanguageManager = {
488 addLanguage: (key: string, label: string) => this.addConstant({ npmName, type: 'language', obj: VIDEO_LANGUAGES, key, label }),
489
490 deleteLanguage: (key: string) => this.deleteConstant({ npmName, type: 'language', obj: VIDEO_LANGUAGES, key })
491 }
492
493 const videoCategoryManager: PluginVideoCategoryManager = {
494 addCategory: (key: number, label: string) => this.addConstant({ npmName, type: 'category', obj: VIDEO_CATEGORIES, key, label }),
495
496 deleteCategory: (key: number) => this.deleteConstant({ npmName, type: 'category', obj: VIDEO_CATEGORIES, key })
497 }
498
499 const videoLicenceManager: PluginVideoLicenceManager = {
500 addLicence: (key: number, label: string) => this.addConstant({ npmName, type: 'licence', obj: VIDEO_LICENCES, key, label }),
501
502 deleteLicence: (key: number) => this.deleteConstant({ npmName, type: 'licence', obj: VIDEO_LICENCES, key })
503 }
504
505 const peertubeHelpers = {
506 logger
507 }
508
509 return {
510 registerHook, 457 registerHook,
511 registerSetting, 458 registerSetting
512 settingsManager, 459 })
513 storageManager,
514 videoLanguageManager,
515 videoCategoryManager,
516 videoLicenceManager,
517 peertubeHelpers
518 }
519 }
520
521 private addConstant<T extends string | number> (parameters: {
522 npmName: string
523 type: AlterableVideoConstant
524 obj: VideoConstant
525 key: T
526 label: string
527 }) {
528 const { npmName, type, obj, key, label } = parameters
529
530 if (obj[key]) {
531 logger.warn('Cannot add %s %s by plugin %s: key already exists.', type, npmName, key)
532 return false
533 }
534
535 if (!this.updatedVideoConstants[type][npmName]) {
536 this.updatedVideoConstants[type][npmName] = {
537 added: [],
538 deleted: []
539 }
540 }
541
542 this.updatedVideoConstants[type][npmName].added.push({ key, label })
543 obj[key] = label
544
545 return true
546 }
547
548 private deleteConstant<T extends string | number> (parameters: {
549 npmName: string
550 type: AlterableVideoConstant
551 obj: VideoConstant
552 key: T
553 }) {
554 const { npmName, type, obj, key } = parameters
555
556 if (!obj[key]) {
557 logger.warn('Cannot delete %s %s by plugin %s: key does not exist.', type, npmName, key)
558 return false
559 }
560
561 if (!this.updatedVideoConstants[type][npmName]) {
562 this.updatedVideoConstants[type][npmName] = {
563 added: [],
564 deleted: []
565 }
566 }
567
568 this.updatedVideoConstants[type][npmName].deleted.push({ key, label: obj[key] })
569 delete obj[key]
570
571 return true
572 }
573
574 private reinitVideoConstants (npmName: string) {
575 const hash = {
576 language: VIDEO_LANGUAGES,
577 licence: VIDEO_LICENCES,
578 category: VIDEO_CATEGORIES
579 }
580 const types: AlterableVideoConstant[] = [ 'language', 'licence', 'category' ]
581
582 for (const type of types) {
583 const updatedConstants = this.updatedVideoConstants[type][npmName]
584 if (!updatedConstants) continue
585
586 for (const added of updatedConstants.added) {
587 delete hash[type][added.key]
588 }
589
590 for (const deleted of updatedConstants.deleted) {
591 hash[type][deleted.key] = deleted.label
592 }
593
594 delete this.updatedVideoConstants[type][npmName]
595 }
596 } 460 }
597 461
598 private sanitizeAndCheckPackageJSONOrThrow (packageJSON: PluginPackageJson, pluginType: PluginType) { 462 private sanitizeAndCheckPackageJSONOrThrow (packageJSON: PluginPackageJson, pluginType: PluginType) {
diff --git a/server/lib/plugins/register-helpers.ts b/server/lib/plugins/register-helpers.ts
new file mode 100644
index 000000000..58bc96f04
--- /dev/null
+++ b/server/lib/plugins/register-helpers.ts
@@ -0,0 +1,180 @@
1import { PluginSettingsManager } from '@shared/models/plugins/plugin-settings-manager.model'
2import { PluginModel } from '@server/models/server/plugin'
3import { PluginStorageManager } from '@shared/models/plugins/plugin-storage-manager.model'
4import { PluginVideoLanguageManager } from '@shared/models/plugins/plugin-video-language-manager.model'
5import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '@server/initializers/constants'
6import { PluginVideoLicenceManager } from '@shared/models/plugins/plugin-video-licence-manager.model'
7import { PluginVideoCategoryManager } from '@shared/models/plugins/plugin-video-category-manager.model'
8import { RegisterServerOptions } from '@server/typings/plugins'
9import { buildPluginHelpers } from './plugin-helpers'
10import { logger } from '@server/helpers/logger'
11
12type AlterableVideoConstant = 'language' | 'licence' | 'category'
13type VideoConstant = { [key in number | string]: string }
14type UpdatedVideoConstant = {
15 [name in AlterableVideoConstant]: {
16 [npmName: string]: {
17 added: { key: number | string, label: string }[]
18 deleted: { key: number | string, label: string }[]
19 }
20 }
21}
22
23const updatedVideoConstants: UpdatedVideoConstant = {
24 language: {},
25 licence: {},
26 category: {}
27}
28
29function buildRegisterHelpers (npmName: string, plugin: PluginModel): Omit<RegisterServerOptions, 'registerHook' | 'registerSetting'> {
30 const settingsManager = buildSettingsManager(plugin)
31 const storageManager = buildStorageManager(plugin)
32
33 const videoLanguageManager = buildVideoLanguageManager(npmName)
34
35 const videoCategoryManager = buildVideoCategoryManager(npmName)
36 const videoLicenceManager = buildVideoLicenceManager(npmName)
37
38 const peertubeHelpers = buildPluginHelpers(npmName, plugin)
39
40 return {
41 settingsManager,
42 storageManager,
43 videoLanguageManager,
44 videoCategoryManager,
45 videoLicenceManager,
46 peertubeHelpers
47 }
48}
49
50function reinitVideoConstants (npmName: string) {
51 const hash = {
52 language: VIDEO_LANGUAGES,
53 licence: VIDEO_LICENCES,
54 category: VIDEO_CATEGORIES
55 }
56 const types: AlterableVideoConstant[] = [ 'language', 'licence', 'category' ]
57
58 for (const type of types) {
59 const updatedConstants = updatedVideoConstants[type][npmName]
60 if (!updatedConstants) continue
61
62 for (const added of updatedConstants.added) {
63 delete hash[type][added.key]
64 }
65
66 for (const deleted of updatedConstants.deleted) {
67 hash[type][deleted.key] = deleted.label
68 }
69
70 delete updatedVideoConstants[type][npmName]
71 }
72}
73
74export {
75 buildRegisterHelpers,
76 reinitVideoConstants
77}
78
79// ---------------------------------------------------------------------------
80
81function buildSettingsManager (plugin: PluginModel): PluginSettingsManager {
82 return {
83 getSetting: (name: string) => PluginModel.getSetting(plugin.name, plugin.type, name),
84
85 setSetting: (name: string, value: string) => PluginModel.setSetting(plugin.name, plugin.type, name, value)
86 }
87}
88
89function buildStorageManager (plugin: PluginModel): PluginStorageManager {
90 return {
91 getData: (key: string) => PluginModel.getData(plugin.name, plugin.type, key),
92
93 storeData: (key: string, data: any) => PluginModel.storeData(plugin.name, plugin.type, key, data)
94 }
95}
96
97function buildVideoLanguageManager (npmName: string): PluginVideoLanguageManager {
98 return {
99 addLanguage: (key: string, label: string) => addConstant({ npmName, type: 'language', obj: VIDEO_LANGUAGES, key, label }),
100
101 deleteLanguage: (key: string) => deleteConstant({ npmName, type: 'language', obj: VIDEO_LANGUAGES, key })
102 }
103}
104
105function buildVideoCategoryManager (npmName: string): PluginVideoCategoryManager {
106 return {
107 addCategory: (key: number, label: string) => {
108 return addConstant({ npmName, type: 'category', obj: VIDEO_CATEGORIES, key, label })
109 },
110
111 deleteCategory: (key: number) => {
112 return deleteConstant({ npmName, type: 'category', obj: VIDEO_CATEGORIES, key })
113 }
114 }
115}
116
117function buildVideoLicenceManager (npmName: string): PluginVideoLicenceManager {
118 return {
119 addLicence: (key: number, label: string) => {
120 return addConstant({ npmName, type: 'licence', obj: VIDEO_LICENCES, key, label })
121 },
122
123 deleteLicence: (key: number) => {
124 return deleteConstant({ npmName, type: 'licence', obj: VIDEO_LICENCES, key })
125 }
126 }
127}
128
129function addConstant<T extends string | number> (parameters: {
130 npmName: string
131 type: AlterableVideoConstant
132 obj: VideoConstant
133 key: T
134 label: string
135}) {
136 const { npmName, type, obj, key, label } = parameters
137
138 if (obj[key]) {
139 logger.warn('Cannot add %s %s by plugin %s: key already exists.', type, npmName, key)
140 return false
141 }
142
143 if (!updatedVideoConstants[type][npmName]) {
144 updatedVideoConstants[type][npmName] = {
145 added: [],
146 deleted: []
147 }
148 }
149
150 updatedVideoConstants[type][npmName].added.push({ key, label })
151 obj[key] = label
152
153 return true
154}
155
156function deleteConstant<T extends string | number> (parameters: {
157 npmName: string
158 type: AlterableVideoConstant
159 obj: VideoConstant
160 key: T
161}) {
162 const { npmName, type, obj, key } = parameters
163
164 if (!obj[key]) {
165 logger.warn('Cannot delete %s %s by plugin %s: key does not exist.', type, npmName, key)
166 return false
167 }
168
169 if (!updatedVideoConstants[type][npmName]) {
170 updatedVideoConstants[type][npmName] = {
171 added: [],
172 deleted: []
173 }
174 }
175
176 updatedVideoConstants[type][npmName].deleted.push({ key, label: obj[key] })
177 delete obj[key]
178
179 return true
180}
diff --git a/server/typings/plugins/register-server-option.model.ts b/server/typings/plugins/register-server-option.model.ts
index 54753cc01..76ac3cb9a 100644
--- a/server/typings/plugins/register-server-option.model.ts
+++ b/server/typings/plugins/register-server-option.model.ts
@@ -1,4 +1,3 @@
1import { logger } from '../../helpers/logger'
2import { PluginSettingsManager } from '../../../shared/models/plugins/plugin-settings-manager.model' 1import { PluginSettingsManager } from '../../../shared/models/plugins/plugin-settings-manager.model'
3import { PluginStorageManager } from '../../../shared/models/plugins/plugin-storage-manager.model' 2import { PluginStorageManager } from '../../../shared/models/plugins/plugin-storage-manager.model'
4import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model' 3import { RegisterServerHookOptions } from '../../../shared/models/plugins/register-server-hook.model'
@@ -6,6 +5,11 @@ import { RegisterServerSettingOptions } from '../../../shared/models/plugins/reg
6import { PluginVideoCategoryManager } from '../../../shared/models/plugins/plugin-video-category-manager.model' 5import { PluginVideoCategoryManager } from '../../../shared/models/plugins/plugin-video-category-manager.model'
7import { PluginVideoLanguageManager } from '../../../shared/models/plugins/plugin-video-language-manager.model' 6import { PluginVideoLanguageManager } from '../../../shared/models/plugins/plugin-video-language-manager.model'
8import { PluginVideoLicenceManager } from '../../../shared/models/plugins/plugin-video-licence-manager.model' 7import { PluginVideoLicenceManager } from '../../../shared/models/plugins/plugin-video-licence-manager.model'
8import { Logger } from 'winston'
9
10export type PeerTubeHelpers = {
11 logger: Logger
12}
9 13
10export type RegisterServerOptions = { 14export type RegisterServerOptions = {
11 registerHook: (options: RegisterServerHookOptions) => void 15 registerHook: (options: RegisterServerHookOptions) => void
@@ -20,7 +24,5 @@ export type RegisterServerOptions = {
20 videoLanguageManager: PluginVideoLanguageManager 24 videoLanguageManager: PluginVideoLanguageManager
21 videoLicenceManager: PluginVideoLicenceManager 25 videoLicenceManager: PluginVideoLicenceManager
22 26
23 peertubeHelpers: { 27 peertubeHelpers: PeerTubeHelpers
24 logger: typeof logger
25 }
26} 28}