Merge branch 'release/1.4.0' into develop
[oweals/peertube.git] / server / controllers / plugins.ts
1 import * as express from 'express'
2 import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants'
3 import { join } from 'path'
4 import { PluginManager, RegisteredPlugin } from '../lib/plugins/plugin-manager'
5 import { servePluginStaticDirectoryValidator } from '../middlewares/validators/plugins'
6 import { serveThemeCSSValidator } from '../middlewares/validators/themes'
7 import { PluginType } from '../../shared/models/plugins/plugin.type'
8 import { isTestInstance } from '../helpers/core-utils'
9 import { getCompleteLocale, is18nLocale } from '../../shared/models/i18n'
10
11 const sendFileOptions = {
12   maxAge: '30 days',
13   immutable: !isTestInstance()
14 }
15
16 const pluginsRouter = express.Router()
17
18 pluginsRouter.get('/plugins/global.css',
19   servePluginGlobalCSS
20 )
21
22 pluginsRouter.get('/plugins/translations/:locale.json',
23   getPluginTranslations
24 )
25
26 pluginsRouter.get('/plugins/:pluginName/:pluginVersion/static/:staticEndpoint(*)',
27   servePluginStaticDirectoryValidator(PluginType.PLUGIN),
28   servePluginStaticDirectory
29 )
30
31 pluginsRouter.get('/plugins/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)',
32   servePluginStaticDirectoryValidator(PluginType.PLUGIN),
33   servePluginClientScripts
34 )
35
36 pluginsRouter.get('/themes/:pluginName/:pluginVersion/static/:staticEndpoint(*)',
37   servePluginStaticDirectoryValidator(PluginType.THEME),
38   servePluginStaticDirectory
39 )
40
41 pluginsRouter.get('/themes/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)',
42   servePluginStaticDirectoryValidator(PluginType.THEME),
43   servePluginClientScripts
44 )
45
46 pluginsRouter.get('/themes/:themeName/:themeVersion/css/:staticEndpoint(*)',
47   serveThemeCSSValidator,
48   serveThemeCSSDirectory
49 )
50
51 // ---------------------------------------------------------------------------
52
53 export {
54   pluginsRouter
55 }
56
57 // ---------------------------------------------------------------------------
58
59 function servePluginGlobalCSS (req: express.Request, res: express.Response) {
60   // Only cache requests that have a ?hash=... query param
61   const globalCSSOptions = req.query.hash
62     ? sendFileOptions
63     : {}
64
65   return res.sendFile(PLUGIN_GLOBAL_CSS_PATH, globalCSSOptions)
66 }
67
68 function getPluginTranslations (req: express.Request, res: express.Response) {
69   const locale = req.params.locale
70
71   if (is18nLocale(locale)) {
72     const completeLocale = getCompleteLocale(locale)
73     const json = PluginManager.Instance.getTranslations(completeLocale)
74
75     return res.json(json)
76   }
77
78   return res.sendStatus(404)
79 }
80
81 function servePluginStaticDirectory (req: express.Request, res: express.Response) {
82   const plugin: RegisteredPlugin = res.locals.registeredPlugin
83   const staticEndpoint = req.params.staticEndpoint
84
85   const [ directory, ...file ] = staticEndpoint.split('/')
86
87   const staticPath = plugin.staticDirs[directory]
88   if (!staticPath) {
89     return res.sendStatus(404)
90   }
91
92   const filepath = file.join('/')
93   return res.sendFile(join(plugin.path, staticPath, filepath), sendFileOptions)
94 }
95
96 function servePluginClientScripts (req: express.Request, res: express.Response) {
97   const plugin: RegisteredPlugin = res.locals.registeredPlugin
98   const staticEndpoint = req.params.staticEndpoint
99
100   const file = plugin.clientScripts[staticEndpoint]
101   if (!file) {
102     return res.sendStatus(404)
103   }
104
105   return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions)
106 }
107
108 function serveThemeCSSDirectory (req: express.Request, res: express.Response) {
109   const plugin: RegisteredPlugin = res.locals.registeredPlugin
110   const staticEndpoint = req.params.staticEndpoint
111
112   if (plugin.css.includes(staticEndpoint) === false) {
113     return res.sendStatus(404)
114   }
115
116   return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions)
117 }