allow plugins to implements its own API, fix #283

This commit is contained in:
lesion
2023-06-22 13:48:41 +02:00
parent 64c9c8a0e8
commit b3b87c3802
2 changed files with 57 additions and 39 deletions

View File

@@ -32,6 +32,22 @@ const pluginController = {
res.json() res.json()
}, },
async routeAPI (req, res, next) {
const pluginName = req.params.plugin
const plugin = pluginController.plugins.find(p => p.configuration.name === pluginName)
if (!plugin) {
log.warn(`Plugin ${pluginName} not found`)
return res.sendStatus(404)
}
if (typeof plugin.routeAPI !== 'function') {
log.warn(`Plugin ${pluginName} does not expose a 'routeAPI' function`)
return res.sendStatus(404)
}
return plugin.routeAPI(req, res, next)
},
async testPlugin (req, res) { async testPlugin (req, res) {
const pluginName = req.params.plugin const pluginName = req.params.plugin
const plugin = pluginController.plugins.find(p => p.configuration.name === pluginName) const plugin = pluginController.plugins.find(p => p.configuration.name === pluginName)
@@ -39,7 +55,7 @@ const pluginController = {
log.warn(`Plugin ${pluginName} not found`) log.warn(`Plugin ${pluginName} not found`)
return res.sendStatus(404) return res.sendStatus(404)
} }
if (typeof plugin.onTest !== 'function') { if (typeof plugin.onTest !== 'function') {
log.warn(`Plugin ${pluginName} does not expose an 'onTest' function`) log.warn(`Plugin ${pluginName} does not expose an 'onTest' function`)
return res.sendStatus(404) return res.sendStatus(404)
@@ -122,7 +138,7 @@ const pluginController = {
} }
} catch (e) { } catch (e) {
log.warn(`Unable to load plugin ${pluginFile}: ${String(e)}`) log.warn(`Unable to load plugin ${pluginFile}: ${String(e)}`)
} }
}, },
_load() { _load() {

View File

@@ -31,25 +31,25 @@ module.exports = () => {
const api = express.Router() const api = express.Router()
api.use(express.urlencoded({ extended: false })) api.use(express.urlencoded({ extended: false }))
api.use(express.json()) api.use(express.json())
if (process.env.NODE_ENV !== 'test') { if (process.env.NODE_ENV !== 'test') {
api.use(DDOSProtectionApiRateLimiter) api.use(DDOSProtectionApiRateLimiter)
} }
if (config.status !== 'READY') { if (config.status !== 'READY') {
api.post('/settings', settingsController.setRequest) api.post('/settings', settingsController.setRequest)
api.post('/setup/db', setupController.setupDb) api.post('/setup/db', setupController.setupDb)
api.post('/setup/restart', setupController.restart) api.post('/setup/restart', setupController.restart)
api.post('/settings/smtp', settingsController.testSMTP) api.post('/settings/smtp', settingsController.testSMTP)
api.get('/locale/:locale', localeController.get) api.get('/locale/:locale', localeController.get)
} else { } else {
const { isAuth, isAdmin } = require('./auth') const { isAuth, isAdmin } = require('./auth')
const upload = multer({ storage }) const upload = multer({ storage })
/** /**
* Get current authenticated user * Get current authenticated user
* @category User * @category User
@@ -72,25 +72,25 @@ module.exports = () => {
*/ */
api.get('/ping', (_req, res) => res.sendStatus(200)) api.get('/ping', (_req, res) => res.sendStatus(200))
api.get('/user', isAuth, (req, res) => res.json(req.user)) api.get('/user', isAuth, (req, res) => res.json(req.user))
api.post('/user/recover', SPAMProtectionApiRateLimiter, userController.forgotPassword) api.post('/user/recover', SPAMProtectionApiRateLimiter, userController.forgotPassword)
api.post('/user/check_recover_code', userController.checkRecoverCode) api.post('/user/check_recover_code', userController.checkRecoverCode)
api.post('/user/recover_password', SPAMProtectionApiRateLimiter, userController.updatePasswordWithRecoverCode) api.post('/user/recover_password', SPAMProtectionApiRateLimiter, userController.updatePasswordWithRecoverCode)
// register and add users // register and add users
api.post('/user/register', SPAMProtectionApiRateLimiter, userController.register) api.post('/user/register', SPAMProtectionApiRateLimiter, userController.register)
api.post('/user', isAdmin, userController.create) api.post('/user', isAdmin, userController.create)
// update user // update user
api.put('/user', isAuth, userController.update) api.put('/user', isAuth, userController.update)
// delete user // delete user
api.delete('/user/:id', isAdmin, userController.remove) api.delete('/user/:id', isAdmin, userController.remove)
api.delete('/user', isAuth, userController.remove) api.delete('/user', isAuth, userController.remove)
// get all users // get all users
api.get('/users', isAdmin, userController.getAll) api.get('/users', isAdmin, userController.getAll)
/** /**
* Get events * Get events
* @category Event * @category Event
@@ -110,9 +110,9 @@ module.exports = () => {
* [https://demo.gancio.org/api/events](https://demo.gancio.org/api/events) * [https://demo.gancio.org/api/events](https://demo.gancio.org/api/events)
* [usage example](https://framagit.org/les/gancio/-/blob/master/webcomponents/src/GancioEvents.svelte#L18-42) * [usage example](https://framagit.org/les/gancio/-/blob/master/webcomponents/src/GancioEvents.svelte#L18-42)
*/ */
api.get('/events', cors, eventController.select) api.get('/events', cors, eventController.select)
/** /**
* Add a new event * Add a new event
* @category Event * @category Event
@@ -134,25 +134,25 @@ module.exports = () => {
* @param {array} [recurrent.days] - array of days * @param {array} [recurrent.days] - array of days
* @param {image} [image] - Image * @param {image} [image] - Image
*/ */
// allow anyone to add an event (anon event has to be confirmed, flood protection) // allow anyone to add an event (anon event has to be confirmed, flood protection)
api.post('/event', eventController.isAnonEventAllowed, SPAMProtectionApiRateLimiter, upload.single('image'), eventController.add) api.post('/event', eventController.isAnonEventAllowed, SPAMProtectionApiRateLimiter, upload.single('image'), eventController.add)
// api.get('/event/search', eventController.search) // api.get('/event/search', eventController.search)
api.put('/event', isAuth, upload.single('image'), eventController.update) api.put('/event', isAuth, upload.single('image'), eventController.update)
api.get('/event/import', eventController.isAnonEventAllowed, helpers.importURL) api.get('/event/import', eventController.isAnonEventAllowed, helpers.importURL)
// remove event // remove event
api.delete('/event/:id', isAuth, eventController.remove) api.delete('/event/:id', isAuth, eventController.remove)
// get tags/places // get tags/places
api.get('/event/meta', eventController.searchMeta) api.get('/event/meta', eventController.searchMeta)
// add event notification TODO // add event notification TODO
// api.post('/event/notification', eventController.addNotification) // api.post('/event/notification', eventController.addNotification)
// api.delete('/event/notification/:code', eventController.delNotification) // api.delete('/event/notification/:code', eventController.delNotification)
api.post('/settings', isAdmin, settingsController.setRequest) api.post('/settings', isAdmin, settingsController.setRequest)
api.get('/settings', isAdmin, settingsController.getAll) api.get('/settings', isAdmin, settingsController.getAll)
api.post('/settings/logo', isAdmin, multer({ dest: config.upload_path }).single('logo'), settingsController.setLogo) api.post('/settings/logo', isAdmin, multer({ dest: config.upload_path }).single('logo'), settingsController.setLogo)
@@ -160,21 +160,21 @@ module.exports = () => {
api.post('/settings/headerImage', isAdmin, multer({ dest: config.upload_path }).single('headerImage'), settingsController.setHeaderImage) api.post('/settings/headerImage', isAdmin, multer({ dest: config.upload_path }).single('headerImage'), settingsController.setHeaderImage)
api.post('/settings/smtp', isAdmin, settingsController.testSMTP) api.post('/settings/smtp', isAdmin, settingsController.testSMTP)
api.get('/settings/smtp', isAdmin, settingsController.getSMTPSettings) api.get('/settings/smtp', isAdmin, settingsController.getSMTPSettings)
// get unconfirmed events // get unconfirmed events
api.get('/event/unconfirmed', isAdmin, eventController.getUnconfirmed) api.get('/event/unconfirmed', isAdmin, eventController.getUnconfirmed)
// [un]confirm event // [un]confirm event
api.put('/event/confirm/:event_id', isAuth, eventController.confirm) api.put('/event/confirm/:event_id', isAuth, eventController.confirm)
api.put('/event/unconfirm/:event_id', isAuth, eventController.unconfirm) api.put('/event/unconfirm/:event_id', isAuth, eventController.unconfirm)
// get event // get event
api.get('/event/detail/:event_slug.:format?', cors, eventController.get) api.get('/event/detail/:event_slug.:format?', cors, eventController.get)
// export events (rss/ics) // export events (rss/ics)
api.get('/export/:format', cors, exportController.export) api.get('/export/:format', cors, exportController.export)
// - PLACES // - PLACES
api.get('/places', isAdmin, placeController.getAll) api.get('/places', isAdmin, placeController.getAll)
api.get('/place/:placeName', cors, placeController.getEvents) api.get('/place/:placeName', cors, placeController.getEvents)
@@ -184,15 +184,15 @@ module.exports = () => {
// - GEOCODING // - GEOCODING
api.get('/placeOSM/Nominatim/:place_details', helpers.isGeocodingEnabled, geocodingController.nominatimRateLimit, geocodingController._nominatim) api.get('/placeOSM/Nominatim/:place_details', helpers.isGeocodingEnabled, geocodingController.nominatimRateLimit, geocodingController._nominatim)
api.get('/placeOSM/Photon/:place_details', helpers.isGeocodingEnabled, geocodingController.photonRateLimit, geocodingController._photon) api.get('/placeOSM/Photon/:place_details', helpers.isGeocodingEnabled, geocodingController.photonRateLimit, geocodingController._photon)
// - TAGS // - TAGS
api.get('/tags', isAdmin, tagController.getAll) api.get('/tags', isAdmin, tagController.getAll)
api.get('/tag', cors, tagController.search) api.get('/tag', cors, tagController.search)
api.get('/tag/:tag', cors, tagController.getEvents) api.get('/tag/:tag', cors, tagController.getEvents)
api.delete('/tag/:tag', isAdmin, tagController.remove) api.delete('/tag/:tag', isAdmin, tagController.remove)
api.put('/tag', isAdmin, tagController.updateTag) api.put('/tag', isAdmin, tagController.updateTag)
// - FEDIVERSE INSTANCES, MODERATION, RESOURCES // - FEDIVERSE INSTANCES, MODERATION, RESOURCES
api.get('/instances', isAdmin, instanceController.getAll) api.get('/instances', isAdmin, instanceController.getAll)
api.get('/instances/:instance_domain', isAdmin, instanceController.get) api.get('/instances/:instance_domain', isAdmin, instanceController.get)
@@ -201,13 +201,13 @@ module.exports = () => {
api.put('/resources/:resource_id', isAdmin, resourceController.hide) api.put('/resources/:resource_id', isAdmin, resourceController.hide)
api.delete('/resources/:resource_id', isAdmin, resourceController.remove) api.delete('/resources/:resource_id', isAdmin, resourceController.remove)
api.get('/resources', isAdmin, resourceController.getAll) api.get('/resources', isAdmin, resourceController.getAll)
// - ADMIN ANNOUNCEMENTS // - ADMIN ANNOUNCEMENTS
api.get('/announcements', isAdmin, announceController.getAll) api.get('/announcements', isAdmin, announceController.getAll)
api.post('/announcements', isAdmin, announceController.add) api.post('/announcements', isAdmin, announceController.add)
api.put('/announcements/:announce_id', isAdmin, announceController.update) api.put('/announcements/:announce_id', isAdmin, announceController.update)
api.delete('/announcements/:announce_id', isAdmin, announceController.remove) api.delete('/announcements/:announce_id', isAdmin, announceController.remove)
// - COLLECTIONS // - COLLECTIONS
api.get('/collections/:name', cors, collectionController.getEvents) api.get('/collections/:name', cors, collectionController.getEvents)
api.get('/collections', collectionController.getAll) api.get('/collections', collectionController.getAll)
@@ -216,12 +216,14 @@ module.exports = () => {
api.get('/filter/:collection_id', isAdmin, collectionController.getFilters) api.get('/filter/:collection_id', isAdmin, collectionController.getFilters)
api.post('/filter', isAdmin, collectionController.addFilter) api.post('/filter', isAdmin, collectionController.addFilter)
api.delete('/filter/:id', isAdmin, collectionController.removeFilter) api.delete('/filter/:id', isAdmin, collectionController.removeFilter)
// - PLUGINS // - PLUGINS
api.get('/plugins', isAdmin, pluginController.getAll) api.get('/plugins', isAdmin, pluginController.getAll)
api.post('/plugin/test/:plugin', isAdmin, pluginController.testPlugin) api.post('/plugin/test/:plugin', isAdmin, pluginController.testPlugin)
api.put('/plugin/:plugin', isAdmin, pluginController.togglePlugin) api.put('/plugin/:plugin', isAdmin, pluginController.togglePlugin)
api.use('/plugin/:plugin', pluginController.routeAPI)
// OAUTH // OAUTH
api.get('/clients', isAuth, oauthController.getClients) api.get('/clients', isAuth, oauthController.getClients)
api.get('/client/:client_id', isAuth, oauthController.getClient) api.get('/client/:client_id', isAuth, oauthController.getClient)
@@ -230,9 +232,9 @@ module.exports = () => {
// CUSTOM LOCALE // CUSTOM LOCALE
api.get('/locale/:locale', localeController.get) api.get('/locale/:locale', localeController.get)
} }
api.use((_req, res) => res.sendStatus(404)) api.use((_req, res) => res.sendStatus(404))
// Handle 500 // Handle 500
api.use((error, _req, res, _next) => { api.use((error, _req, res, _next) => {
log.error('[API ERROR]', error) log.error('[API ERROR]', error)