]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/plugins.ts
/!\ Use a dedicated config file for development
[github/Chocobozzz/PeerTube.git] / server / controllers / plugins.ts
CommitLineData
41fb13c3 1import express from 'express'
b5f919ac 2import { join } from 'path'
f43db2f4
C
3import { logger } from '@server/helpers/logger'
4import { optionalAuthenticate } from '@server/middlewares/auth'
2d53be02 5import { getCompleteLocale, is18nLocale } from '../../shared/core-utils/i18n'
c0e8b12e 6import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
b5f919ac 7import { PluginType } from '../../shared/models/plugins/plugin.type'
9452d4fd 8import { isProdInstance } from '../helpers/core-utils'
f43db2f4
C
9import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants'
10import { PluginManager, RegisteredPlugin } from '../lib/plugins/plugin-manager'
11import { getExternalAuthValidator, getPluginValidator, pluginStaticDirectoryValidator } from '../middlewares/validators/plugins'
12import { serveThemeCSSValidator } from '../middlewares/validators/themes'
a8b666e9
C
13
14const sendFileOptions = {
15 maxAge: '30 days',
9452d4fd 16 immutable: isProdInstance()
a8b666e9 17}
345da516
C
18
19const pluginsRouter = express.Router()
20
b5f919ac 21pluginsRouter.get('/plugins/global.css',
2c053942 22 servePluginGlobalCSS
345da516
C
23)
24
d75db01f
C
25pluginsRouter.get('/plugins/translations/:locale.json',
26 getPluginTranslations
27)
28
4a8d113b
C
29pluginsRouter.get('/plugins/:pluginName/:pluginVersion/auth/:authName',
30 getPluginValidator(PluginType.PLUGIN),
31 getExternalAuthValidator,
32 handleAuthInPlugin
33)
34
b5f919ac 35pluginsRouter.get('/plugins/:pluginName/:pluginVersion/static/:staticEndpoint(*)',
5e2b2e27
C
36 getPluginValidator(PluginType.PLUGIN),
37 pluginStaticDirectoryValidator,
345da516
C
38 servePluginStaticDirectory
39)
40
b5f919ac 41pluginsRouter.get('/plugins/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)',
5e2b2e27
C
42 getPluginValidator(PluginType.PLUGIN),
43 pluginStaticDirectoryValidator,
345da516
C
44 servePluginClientScripts
45)
46
5e2b2e27
C
47pluginsRouter.use('/plugins/:pluginName/router',
48 getPluginValidator(PluginType.PLUGIN, false),
f17faefb 49 optionalAuthenticate,
5e2b2e27
C
50 servePluginCustomRoutes
51)
52
53pluginsRouter.use('/plugins/:pluginName/:pluginVersion/router',
54 getPluginValidator(PluginType.PLUGIN),
f17faefb 55 optionalAuthenticate,
5e2b2e27
C
56 servePluginCustomRoutes
57)
58
b5f919ac 59pluginsRouter.get('/themes/:pluginName/:pluginVersion/static/:staticEndpoint(*)',
5e2b2e27
C
60 getPluginValidator(PluginType.THEME),
61 pluginStaticDirectoryValidator,
b5f919ac
C
62 servePluginStaticDirectory
63)
64
65pluginsRouter.get('/themes/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)',
5e2b2e27
C
66 getPluginValidator(PluginType.THEME),
67 pluginStaticDirectoryValidator,
b5f919ac
C
68 servePluginClientScripts
69)
70
71pluginsRouter.get('/themes/:themeName/:themeVersion/css/:staticEndpoint(*)',
72 serveThemeCSSValidator,
73 serveThemeCSSDirectory
74)
75
345da516
C
76// ---------------------------------------------------------------------------
77
78export {
79 pluginsRouter
80}
81
82// ---------------------------------------------------------------------------
83
2c053942 84function servePluginGlobalCSS (req: express.Request, res: express.Response) {
a8b666e9
C
85 // Only cache requests that have a ?hash=... query param
86 const globalCSSOptions = req.query.hash
87 ? sendFileOptions
88 : {}
89
90 return res.sendFile(PLUGIN_GLOBAL_CSS_PATH, globalCSSOptions)
2c053942
C
91}
92
d75db01f
C
93function getPluginTranslations (req: express.Request, res: express.Response) {
94 const locale = req.params.locale
95
96 if (is18nLocale(locale)) {
97 const completeLocale = getCompleteLocale(locale)
98 const json = PluginManager.Instance.getTranslations(completeLocale)
99
100 return res.json(json)
101 }
102
76148b27 103 return res.status(HttpStatusCode.NOT_FOUND_404).end()
d75db01f
C
104}
105
345da516
C
106function servePluginStaticDirectory (req: express.Request, res: express.Response) {
107 const plugin: RegisteredPlugin = res.locals.registeredPlugin
108 const staticEndpoint = req.params.staticEndpoint
109
2c053942
C
110 const [ directory, ...file ] = staticEndpoint.split('/')
111
112 const staticPath = plugin.staticDirs[directory]
76148b27 113 if (!staticPath) return res.status(HttpStatusCode.NOT_FOUND_404).end()
345da516 114
2c053942 115 const filepath = file.join('/')
a8b666e9 116 return res.sendFile(join(plugin.path, staticPath, filepath), sendFileOptions)
345da516
C
117}
118
5e2b2e27
C
119function servePluginCustomRoutes (req: express.Request, res: express.Response, next: express.NextFunction) {
120 const plugin: RegisteredPlugin = res.locals.registeredPlugin
121 const router = PluginManager.Instance.getRouter(plugin.npmName)
122
76148b27 123 if (!router) return res.status(HttpStatusCode.NOT_FOUND_404).end()
5e2b2e27
C
124
125 return router(req, res, next)
126}
127
345da516
C
128function servePluginClientScripts (req: express.Request, res: express.Response) {
129 const plugin: RegisteredPlugin = res.locals.registeredPlugin
130 const staticEndpoint = req.params.staticEndpoint
131
2c053942 132 const file = plugin.clientScripts[staticEndpoint]
76148b27 133 if (!file) return res.status(HttpStatusCode.NOT_FOUND_404).end()
2c053942 134
a8b666e9 135 return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions)
345da516 136}
b5f919ac
C
137
138function serveThemeCSSDirectory (req: express.Request, res: express.Response) {
139 const plugin: RegisteredPlugin = res.locals.registeredPlugin
140 const staticEndpoint = req.params.staticEndpoint
141
142 if (plugin.css.includes(staticEndpoint) === false) {
76148b27 143 return res.status(HttpStatusCode.NOT_FOUND_404).end()
b5f919ac
C
144 }
145
a8b666e9 146 return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions)
b5f919ac 147}
4a8d113b
C
148
149function handleAuthInPlugin (req: express.Request, res: express.Response) {
150 const authOptions = res.locals.externalAuth
151
152 try {
153 logger.debug('Forwarding auth plugin request in %s of plugin %s.', authOptions.authName, res.locals.registeredPlugin.npmName)
154 authOptions.onAuthRequest(req, res)
155 } catch (err) {
dadc90bc 156 logger.error('Forward request error in auth %s of plugin %s.', authOptions.authName, res.locals.registeredPlugin.npmName, { err })
4a8d113b
C
157 }
158}