1 import express from 'express'
2 import { logger } from '@server/helpers/logger'
3 import { getFormattedObjects } from '@server/helpers/utils'
4 import { listAvailablePluginsFromIndex } from '@server/lib/plugins/plugin-index'
5 import { PluginManager } from '@server/lib/plugins/plugin-manager'
9 availablePluginsSortValidator,
16 } from '@server/middlewares'
18 existingPluginValidator,
19 installOrUpdatePluginValidator,
20 listAvailablePluginsValidator,
22 uninstallPluginValidator,
23 updatePluginSettingsValidator
24 } from '@server/middlewares/validators/plugins'
25 import { PluginModel } from '@server/models/server/plugin'
28 InstallOrUpdatePlugin,
30 PeertubePluginIndexList,
32 RegisteredServerSettings,
34 } from '@shared/models'
36 const pluginRouter = express.Router()
38 pluginRouter.get('/available',
39 openapiOperationDoc({ operationId: 'getAvailablePlugins' }),
41 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
42 listAvailablePluginsValidator,
44 availablePluginsSortValidator,
47 asyncMiddleware(listAvailablePlugins)
51 openapiOperationDoc({ operationId: 'getPlugins' }),
53 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
59 asyncMiddleware(listPlugins)
62 pluginRouter.get('/:npmName/registered-settings',
64 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
65 asyncMiddleware(existingPluginValidator),
66 getPluginRegisteredSettings
69 pluginRouter.get('/:npmName/public-settings',
70 asyncMiddleware(existingPluginValidator),
71 getPublicPluginSettings
74 pluginRouter.put('/:npmName/settings',
76 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
77 updatePluginSettingsValidator,
78 asyncMiddleware(existingPluginValidator),
79 asyncMiddleware(updatePluginSettings)
82 pluginRouter.get('/:npmName',
84 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
85 asyncMiddleware(existingPluginValidator),
89 pluginRouter.post('/install',
90 openapiOperationDoc({ operationId: 'addPlugin' }),
92 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
93 installOrUpdatePluginValidator,
94 asyncMiddleware(installPlugin)
97 pluginRouter.post('/update',
98 openapiOperationDoc({ operationId: 'updatePlugin' }),
100 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
101 installOrUpdatePluginValidator,
102 asyncMiddleware(updatePlugin)
105 pluginRouter.post('/uninstall',
106 openapiOperationDoc({ operationId: 'uninstallPlugin' }),
108 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
109 uninstallPluginValidator,
110 asyncMiddleware(uninstallPlugin)
113 // ---------------------------------------------------------------------------
119 // ---------------------------------------------------------------------------
121 async function listPlugins (req: express.Request, res: express.Response) {
122 const pluginType = req.query.pluginType
123 const uninstalled = req.query.uninstalled
125 const resultList = await PluginModel.listForApi({
128 start: req.query.start,
129 count: req.query.count,
133 return res.json(getFormattedObjects(resultList.data, resultList.total))
136 function getPlugin (req: express.Request, res: express.Response) {
137 const plugin = res.locals.plugin
139 return res.json(plugin.toFormattedJSON())
142 async function installPlugin (req: express.Request, res: express.Response) {
143 const body: InstallOrUpdatePlugin = req.body
145 const fromDisk = !!body.path
146 const toInstall = body.npmName || body.path
148 const pluginVersion = body.pluginVersion && body.npmName
153 const plugin = await PluginManager.Instance.install(toInstall, pluginVersion, fromDisk)
155 return res.json(plugin.toFormattedJSON())
157 logger.warn('Cannot install plugin %s.', toInstall, { err })
158 return res.fail({ message: 'Cannot install plugin ' + toInstall })
162 async function updatePlugin (req: express.Request, res: express.Response) {
163 const body: InstallOrUpdatePlugin = req.body
165 const fromDisk = !!body.path
166 const toUpdate = body.npmName || body.path
168 const plugin = await PluginManager.Instance.update(toUpdate, fromDisk)
170 return res.json(plugin.toFormattedJSON())
172 logger.warn('Cannot update plugin %s.', toUpdate, { err })
173 return res.fail({ message: 'Cannot update plugin ' + toUpdate })
177 async function uninstallPlugin (req: express.Request, res: express.Response) {
178 const body: ManagePlugin = req.body
180 await PluginManager.Instance.uninstall(body.npmName)
182 return res.status(HttpStatusCode.NO_CONTENT_204).end()
185 function getPublicPluginSettings (req: express.Request, res: express.Response) {
186 const plugin = res.locals.plugin
187 const registeredSettings = PluginManager.Instance.getRegisteredSettings(req.params.npmName)
188 const publicSettings = plugin.getPublicSettings(registeredSettings)
190 const json: PublicServerSetting = { publicSettings }
192 return res.json(json)
195 function getPluginRegisteredSettings (req: express.Request, res: express.Response) {
196 const registeredSettings = PluginManager.Instance.getRegisteredSettings(req.params.npmName)
198 const json: RegisteredServerSettings = { registeredSettings }
200 return res.json(json)
203 async function updatePluginSettings (req: express.Request, res: express.Response) {
204 const plugin = res.locals.plugin
206 plugin.settings = req.body.settings
209 await PluginManager.Instance.onSettingsChanged(plugin.name, plugin.settings)
211 return res.status(HttpStatusCode.NO_CONTENT_204).end()
214 async function listAvailablePlugins (req: express.Request, res: express.Response) {
215 const query: PeertubePluginIndexList = req.query
217 const resultList = await listAvailablePluginsFromIndex(query)
221 status: HttpStatusCode.SERVICE_UNAVAILABLE_503,
222 message: 'Plugin index unavailable. Please retry later'
226 return res.json(resultList)