mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
feat(writeapi): token generation/delete routes, ACP updates
This commit is contained in:
@@ -6,5 +6,7 @@
|
||||
|
||||
"uid": "User ID",
|
||||
"uid-help-text": "Specify a User ID to associate with this token. If the user ID is <code>0</code>, it will be considered a <em>master</em> token, which can assume the identity of other users based on the <code>_uid</code> parameter",
|
||||
"description": "Description"
|
||||
"description": "Description",
|
||||
"no-description": "No description specified.",
|
||||
"token-on-save": "Token will be generated once form is saved"
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<form>
|
||||
<input type="hidden" name="token">
|
||||
<input type="hidden" name="token" />
|
||||
<input type="hidden" name="timestamp" />
|
||||
<div class="form-group">
|
||||
<label for="uid">[[admin/settings/api:uid]]</label>
|
||||
<input type="number" name="uid" class="form-control" placeholder="1" min="0" />
|
||||
|
||||
@@ -2,8 +2,16 @@
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<span class="label label-primary">{{{ if uid }}}uid {uid}{{{ else }}}master{{{ end }}}</span>
|
||||
{{{ if token }}}<input type="text" readonly="readonly" value="{token}" size="32" />{{{ else }}}<em class="text-warning">Token will be generated once form is saved</em>{{{ end }}}<br />
|
||||
<small>{description}</small>
|
||||
{{{ if token }}}<input type="text" readonly="readonly" value="{token}" size="32" />{{{ else }}}<em class="text-warning">[[admin/settings/api:token-on-save]]</em>{{{ end }}}<br />
|
||||
<p>
|
||||
{{{ if description }}}
|
||||
{description}
|
||||
{{{ else }}}
|
||||
<em>[[admin/settings/api:no-description]]</em>
|
||||
{{{ end }}}
|
||||
<br />
|
||||
<small>{timestampISO}</small>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-3 text-right">
|
||||
<button type="button" data-type="edit" class="btn btn-info">Edit</button>
|
||||
|
||||
Reference in New Issue
Block a user