diff --git a/public/language/en-GB/admin/settings/api.json b/public/language/en-GB/admin/settings/api.json index fe2f282d4a..ba7d964a04 100644 --- a/public/language/en-GB/admin/settings/api.json +++ b/public/language/en-GB/admin/settings/api.json @@ -6,5 +6,7 @@ "uid": "User ID", "uid-help-text": "Specify a User ID to associate with this token. If the user ID is 0, it will be considered a master token, which can assume the identity of other users based on the _uid parameter", - "description": "Description" + "description": "Description", + "no-description": "No description specified.", + "token-on-save": "Token will be generated once form is saved" } \ No newline at end of file diff --git a/src/controllers/write/users.js b/src/controllers/write/users.js index f571e27fb4..8548f128a7 100644 --- a/src/controllers/write/users.js +++ b/src/controllers/write/users.js @@ -8,6 +8,7 @@ const notifications = require('../../notifications'); const meta = require('../../meta'); const events = require('../../events'); const translator = require('../../translator'); +const utils = require('../../utils'); const db = require('../../database'); const helpers = require('../helpers'); @@ -218,3 +219,40 @@ Users.unban = async (req, res) => { helpers.formatApiResponse(200, res); }; + +Users.generateToken = async (req, res) => { + if (!res.locals.privileges['admin:settings']) { + return helpers.formatApiResponse(403, res, new Error('[[error:no-privileges]]')); + } else if (parseInt(req.params.uid, 10) !== parseInt(req.user.uid, 10)) { + return helpers.formatApiResponse(401, res); + } + + const settings = await meta.settings.get('core.api'); + const newToken = { + token: utils.generateUUID(), + uid: req.user.uid, + description: req.body.description || '', + timestamp: Date.now(), + }; + settings.tokens.push(newToken); + await meta.settings.set('core.api', settings); + helpers.formatApiResponse(200, res, newToken); +}; + +Users.deleteToken = async (req, res) => { + if (!res.locals.privileges['admin:settings']) { + return helpers.formatApiResponse(403, res, new Error('[[error:no-privileges]]')); + } else if (parseInt(req.params.uid, 10) !== parseInt(req.user.uid, 10)) { + return helpers.formatApiResponse(401, res); + } + + const settings = await meta.settings.get('core.api'); + const beforeLen = settings.tokens.length; + settings.tokens = settings.tokens.filter(tokenObj => tokenObj.token !== req.params.token); + if (beforeLen !== settings.tokens.length) { + await meta.settings.set('core.api', settings); + helpers.formatApiResponse(200, res); + } else { + helpers.formatApiResponse(404, res); + } +}; diff --git a/src/middleware/expose.js b/src/middleware/expose.js index 65d0964186..a9532506f8 100644 --- a/src/middleware/expose.js +++ b/src/middleware/expose.js @@ -40,8 +40,8 @@ module.exports = function (middleware) { }; middleware.exposePrivilegeSet = async (req, res, next) => { - // Exposes a user's global privilege set - res.locals.privileges = await privileges.global.get(req.user.uid); + // Exposes a user's global/admin privilege set + res.locals.privileges = { ...await privileges.global.get(req.user.uid), ...await privileges.admin.get(req.user.uid) }; return next(); }; }; diff --git a/src/plugins/index.js b/src/plugins/index.js index 342fdb2f85..47aa0c8635 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -169,6 +169,23 @@ Plugins.reload = async function () { return { plugin, settings, quiet }; }, }); + Plugins.registerHook('core', { + hook: 'filter:settings.get', + method: async ({ plugin, values }) => { + if (plugin === 'core.api' && Array.isArray(values.tokens)) { + values.tokens = values.tokens.map((tokenObj) => { + tokenObj.uid = parseInt(tokenObj.uid, 10); + if (tokenObj.timestamp) { + tokenObj.timestampISO = new Date(parseInt(tokenObj.timestamp, 10)).toISOString(); + } + + return tokenObj; + }); + } + + return { plugin, values }; + }, + }); // Lower priority runs earlier Object.keys(Plugins.loadedHooks).forEach(function (hook) { diff --git a/src/routes/write/users.js b/src/routes/write/users.js index 9b956d545b..0c25de2986 100644 --- a/src/routes/write/users.js +++ b/src/routes/write/users.js @@ -29,51 +29,8 @@ function authenticatedRoutes() { setupApiRoute(router, '/:uid/ban', middleware, [...middlewares, middleware.assertUser, middleware.exposePrivileges], 'put', controllers.write.users.ban); setupApiRoute(router, '/:uid/ban', middleware, [...middlewares, middleware.assertUser, middleware.exposePrivileges], 'delete', controllers.write.users.unban); - /** - * Chat routes were not migrated because chats may get refactored... also the logic is derpy - * It also does not take into account multiple chats for a given user. - */ - // app.route('/:uid/chats') - // .post(apiMiddleware.requireUser, function(req, res) { - // if (!utils.checkRequired(['message'], req, res)) { - // return false; - // } - - // var timestamp = parseInt(req.body.timestamp, 10) || Date.now(); - - // function addMessage(roomId) { - // Messaging.addMessage({ - // uid: req.user.uid, - // roomId: roomId, - // content: req.body.message, - // timestamp: timestamp, - // }, function(err, message) { - // if (parseInt(req.body.quiet, 10) !== 1) { - // Messaging.notifyUsersInRoom(req.user.uid, roomId, message); - // } - - // return errorHandler.handle(err, res, message); - // }); - // } - - // Messaging.canMessageUser(req.user.uid, req.params.uid, function(err) { - // if (err) { - // return errorHandler.handle(err, res); - // } - - // if (req.body.roomId) { - // addMessage(req.body.roomId); - // } else { - // Messaging.newRoom(req.user.uid, [req.params.uid], function(err, roomId) { - // if (err) { - // return errorHandler.handle(err, res); - // } - - // addMessage(roomId); - // }); - // } - // }); - // }); + setupApiRoute(router, '/:uid/tokens', middleware, [...middlewares, middleware.assertUser, middleware.exposePrivilegeSet], 'post', controllers.write.users.generateToken); + setupApiRoute(router, '/:uid/tokens/:token', middleware, [...middlewares, middleware.assertUser, middleware.exposePrivilegeSet], 'delete', controllers.write.users.deleteToken); /** * Implement this later... diff --git a/src/views/admin/partials/api/sorted-list/form.tpl b/src/views/admin/partials/api/sorted-list/form.tpl index 317cef089d..00acbe7c05 100644 --- a/src/views/admin/partials/api/sorted-list/form.tpl +++ b/src/views/admin/partials/api/sorted-list/form.tpl @@ -1,5 +1,6 @@
- + +
diff --git a/src/views/admin/partials/api/sorted-list/item.tpl b/src/views/admin/partials/api/sorted-list/item.tpl index 5615bd2156..8c8daaa11f 100644 --- a/src/views/admin/partials/api/sorted-list/item.tpl +++ b/src/views/admin/partials/api/sorted-list/item.tpl @@ -2,8 +2,16 @@
{{{ if uid }}}uid {uid}{{{ else }}}master{{{ end }}} - {{{ if token }}}{{{ else }}}Token will be generated once form is saved{{{ end }}}
- {description} + {{{ if token }}}{{{ else }}}[[admin/settings/api:token-on-save]]{{{ end }}}
+

+ {{{ if description }}} + {description} + {{{ else }}} + [[admin/settings/api:no-description]] + {{{ end }}} +
+ {timestampISO} +