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'
10 availablePluginsSortValidator,
17 } from '@server/middlewares'
19 existingPluginValidator,
20 installOrUpdatePluginValidator,
21 listAvailablePluginsValidator,
23 uninstallPluginValidator,
24 updatePluginSettingsValidator
25 } from '@server/middlewares/validators/plugins'
26 import { PluginModel } from '@server/models/server/plugin'
29 InstallOrUpdatePlugin,
31 PeertubePluginIndexList,
33 RegisteredServerSettings,
35 } from '@shared/models'
37 const pluginRouter = express.Router()
39 pluginRouter.use(apiRateLimiter)
41 pluginRouter.get('/available',
42 openapiOperationDoc({ operationId: 'getAvailablePlugins' }),
44 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
45 listAvailablePluginsValidator,
47 availablePluginsSortValidator,
50 asyncMiddleware(listAvailablePlugins)
54 openapiOperationDoc({ operationId: 'getPlugins' }),
56 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
62 asyncMiddleware(listPlugins)
65 pluginRouter.get('/:npmName/registered-settings',
67 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
68 asyncMiddleware(existingPluginValidator),
69 getPluginRegisteredSettings
72 pluginRouter.get('/:npmName/public-settings',
73 asyncMiddleware(existingPluginValidator),
74 getPublicPluginSettings
77 pluginRouter.put('/:npmName/settings',
79 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
80 updatePluginSettingsValidator,
81 asyncMiddleware(existingPluginValidator),
82 asyncMiddleware(updatePluginSettings)
85 pluginRouter.get('/:npmName',
87 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
88 asyncMiddleware(existingPluginValidator),
92 pluginRouter.post('/install',
93 openapiOperationDoc({ operationId: 'addPlugin' }),
95 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
96 installOrUpdatePluginValidator,
97 asyncMiddleware(installPlugin)
100 pluginRouter.post('/update',
101 openapiOperationDoc({ operationId: 'updatePlugin' }),
103 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
104 installOrUpdatePluginValidator,
105 asyncMiddleware(updatePlugin)
108 pluginRouter.post('/uninstall',
109 openapiOperationDoc({ operationId: 'uninstallPlugin' }),
111 ensureUserHasRight(UserRight.MANAGE_PLUGINS),
112 uninstallPluginValidator,
113 asyncMiddleware(uninstallPlugin)
116 // ---------------------------------------------------------------------------
122 // ---------------------------------------------------------------------------
124 async function listPlugins (req: express.Request, res: express.Response) {
125 const pluginType = req.query.pluginType
126 const uninstalled = req.query.uninstalled
128 const resultList = await PluginModel.listForApi({
131 start: req.query.start,
132 count: req.query.count,
136 return res.json(getFormattedObjects(resultList.data, resultList.total))
139 function getPlugin (req: express.Request, res: express.Response) {
140 const plugin = res.locals.plugin
142 return res.json(plugin.toFormattedJSON())
145 async function installPlugin (req: express.Request, res: express.Response) {
146 const body: InstallOrUpdatePlugin = req.body
148 const fromDisk = !!body.path
149 const toInstall = body.npmName || body.path
151 const pluginVersion = body.pluginVersion && body.npmName
156 const plugin = await PluginManager.Instance.install({ toInstall, version: pluginVersion, fromDisk })
158 return res.json(plugin.toFormattedJSON())
160 logger.warn('Cannot install plugin %s.', toInstall, { err })
161 return res.fail({ message: 'Cannot install plugin ' + toInstall })
165 async function updatePlugin (req: express.Request, res: express.Response) {
166 const body: InstallOrUpdatePlugin = req.body
168 const fromDisk = !!body.path
169 const toUpdate = body.npmName || body.path
171 const plugin = await PluginManager.Instance.update(toUpdate, fromDisk)
173 return res.json(plugin.toFormattedJSON())
175 logger.warn('Cannot update plugin %s.', toUpdate, { err })
176 return res.fail({ message: 'Cannot update plugin ' + toUpdate })
180 async function uninstallPlugin (req: express.Request, res: express.Response) {
181 const body: ManagePlugin = req.body
183 await PluginManager.Instance.uninstall({ npmName: body.npmName })
185 return res.status(HttpStatusCode.NO_CONTENT_204).end()
188 function getPublicPluginSettings (req: express.Request, res: express.Response) {
189 const plugin = res.locals.plugin
190 const registeredSettings = PluginManager.Instance.getRegisteredSettings(req.params.npmName)
191 const publicSettings = plugin.getPublicSettings(registeredSettings)
193 const json: PublicServerSetting = { publicSettings }
195 return res.json(json)
198 function getPluginRegisteredSettings (req: express.Request, res: express.Response) {
199 const registeredSettings = PluginManager.Instance.getRegisteredSettings(req.params.npmName)
201 const json: RegisteredServerSettings = { registeredSettings }
203 return res.json(json)
206 async function updatePluginSettings (req: express.Request, res: express.Response) {
207 const plugin = res.locals.plugin
209 plugin.settings = req.body.settings
212 await PluginManager.Instance.onSettingsChanged(plugin.name, plugin.settings)
214 return res.status(HttpStatusCode.NO_CONTENT_204).end()
217 async function listAvailablePlugins (req: express.Request, res: express.Response) {
218 const query: PeertubePluginIndexList = req.query
220 const resultList = await listAvailablePluginsFromIndex(query)
224 status: HttpStatusCode.SERVICE_UNAVAILABLE_503,
225 message: 'Plugin index unavailable. Please retry later'
229 return res.json(resultList)