]>
Commit | Line | Data |
---|---|---|
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 { getPluginValidator, pluginStaticDirectoryValidator, getExternalAuthValidator } 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 | import { logger } from '@server/helpers/logger' | |
11 | ||
12 | const sendFileOptions = { | |
13 | maxAge: '30 days', | |
14 | immutable: !isTestInstance() | |
15 | } | |
16 | ||
17 | const pluginsRouter = express.Router() | |
18 | ||
19 | pluginsRouter.get('/plugins/global.css', | |
20 | servePluginGlobalCSS | |
21 | ) | |
22 | ||
23 | pluginsRouter.get('/plugins/translations/:locale.json', | |
24 | getPluginTranslations | |
25 | ) | |
26 | ||
27 | pluginsRouter.get('/plugins/:pluginName/:pluginVersion/auth/:authName', | |
28 | getPluginValidator(PluginType.PLUGIN), | |
29 | getExternalAuthValidator, | |
30 | handleAuthInPlugin | |
31 | ) | |
32 | ||
33 | pluginsRouter.get('/plugins/:pluginName/:pluginVersion/static/:staticEndpoint(*)', | |
34 | getPluginValidator(PluginType.PLUGIN), | |
35 | pluginStaticDirectoryValidator, | |
36 | servePluginStaticDirectory | |
37 | ) | |
38 | ||
39 | pluginsRouter.get('/plugins/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)', | |
40 | getPluginValidator(PluginType.PLUGIN), | |
41 | pluginStaticDirectoryValidator, | |
42 | servePluginClientScripts | |
43 | ) | |
44 | ||
45 | pluginsRouter.use('/plugins/:pluginName/router', | |
46 | getPluginValidator(PluginType.PLUGIN, false), | |
47 | servePluginCustomRoutes | |
48 | ) | |
49 | ||
50 | pluginsRouter.use('/plugins/:pluginName/:pluginVersion/router', | |
51 | getPluginValidator(PluginType.PLUGIN), | |
52 | servePluginCustomRoutes | |
53 | ) | |
54 | ||
55 | pluginsRouter.get('/themes/:pluginName/:pluginVersion/static/:staticEndpoint(*)', | |
56 | getPluginValidator(PluginType.THEME), | |
57 | pluginStaticDirectoryValidator, | |
58 | servePluginStaticDirectory | |
59 | ) | |
60 | ||
61 | pluginsRouter.get('/themes/:pluginName/:pluginVersion/client-scripts/:staticEndpoint(*)', | |
62 | getPluginValidator(PluginType.THEME), | |
63 | pluginStaticDirectoryValidator, | |
64 | servePluginClientScripts | |
65 | ) | |
66 | ||
67 | pluginsRouter.get('/themes/:themeName/:themeVersion/css/:staticEndpoint(*)', | |
68 | serveThemeCSSValidator, | |
69 | serveThemeCSSDirectory | |
70 | ) | |
71 | ||
72 | // --------------------------------------------------------------------------- | |
73 | ||
74 | export { | |
75 | pluginsRouter | |
76 | } | |
77 | ||
78 | // --------------------------------------------------------------------------- | |
79 | ||
80 | function servePluginGlobalCSS (req: express.Request, res: express.Response) { | |
81 | // Only cache requests that have a ?hash=... query param | |
82 | const globalCSSOptions = req.query.hash | |
83 | ? sendFileOptions | |
84 | : {} | |
85 | ||
86 | return res.sendFile(PLUGIN_GLOBAL_CSS_PATH, globalCSSOptions) | |
87 | } | |
88 | ||
89 | function getPluginTranslations (req: express.Request, res: express.Response) { | |
90 | const locale = req.params.locale | |
91 | ||
92 | if (is18nLocale(locale)) { | |
93 | const completeLocale = getCompleteLocale(locale) | |
94 | const json = PluginManager.Instance.getTranslations(completeLocale) | |
95 | ||
96 | return res.json(json) | |
97 | } | |
98 | ||
99 | return res.sendStatus(404) | |
100 | } | |
101 | ||
102 | function servePluginStaticDirectory (req: express.Request, res: express.Response) { | |
103 | const plugin: RegisteredPlugin = res.locals.registeredPlugin | |
104 | const staticEndpoint = req.params.staticEndpoint | |
105 | ||
106 | const [ directory, ...file ] = staticEndpoint.split('/') | |
107 | ||
108 | const staticPath = plugin.staticDirs[directory] | |
109 | if (!staticPath) return res.sendStatus(404) | |
110 | ||
111 | const filepath = file.join('/') | |
112 | return res.sendFile(join(plugin.path, staticPath, filepath), sendFileOptions) | |
113 | } | |
114 | ||
115 | function servePluginCustomRoutes (req: express.Request, res: express.Response, next: express.NextFunction) { | |
116 | const plugin: RegisteredPlugin = res.locals.registeredPlugin | |
117 | const router = PluginManager.Instance.getRouter(plugin.npmName) | |
118 | ||
119 | if (!router) return res.sendStatus(404) | |
120 | ||
121 | return router(req, res, next) | |
122 | } | |
123 | ||
124 | function servePluginClientScripts (req: express.Request, res: express.Response) { | |
125 | const plugin: RegisteredPlugin = res.locals.registeredPlugin | |
126 | const staticEndpoint = req.params.staticEndpoint | |
127 | ||
128 | const file = plugin.clientScripts[staticEndpoint] | |
129 | if (!file) return res.sendStatus(404) | |
130 | ||
131 | return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions) | |
132 | } | |
133 | ||
134 | function serveThemeCSSDirectory (req: express.Request, res: express.Response) { | |
135 | const plugin: RegisteredPlugin = res.locals.registeredPlugin | |
136 | const staticEndpoint = req.params.staticEndpoint | |
137 | ||
138 | if (plugin.css.includes(staticEndpoint) === false) { | |
139 | return res.sendStatus(404) | |
140 | } | |
141 | ||
142 | return res.sendFile(join(plugin.path, staticEndpoint), sendFileOptions) | |
143 | } | |
144 | ||
145 | function handleAuthInPlugin (req: express.Request, res: express.Response) { | |
146 | const authOptions = res.locals.externalAuth | |
147 | ||
148 | try { | |
149 | logger.debug('Forwarding auth plugin request in %s of plugin %s.', authOptions.authName, res.locals.registeredPlugin.npmName) | |
150 | authOptions.onAuthRequest(req, res) | |
151 | } catch (err) { | |
152 | logger.error('Forward request error in auth %s of plugin %s.', authOptions.authName, res.locals.registeredPlugin.npmName, { err }) | |
153 | } | |
154 | } |