Files
jambonz-api-server/lib/routes/api/api-keys.js
T
2022-02-01 20:42:10 -05:00

84 lines
3.1 KiB
JavaScript

const router = require('express').Router();
const {DbErrorBadRequest} = require('../../utils/errors');
const ApiKey = require('../../models/api-key');
const Account = require('../../models/account');
const decorate = require('./decorate');
const { v4: uuidv4 } = require('uuid');
const sysError = require('../error');
const preconditions = {
'add': validateAddToken,
'delete': validateDeleteToken
};
async function validateAddToken(req) {
req.body.token = uuidv4();
if (req.user.hasAdminAuth) return;
if (req.user.hasServiceProviderAuth) {
if (!req.body.service_provider_sid && !req.body.account_sid) {
throw new DbErrorBadRequest('service provider token may not be used to create admin token');
}
else if (req.body.service_provider_sid && req.body.service_provider_sid !== req.user.service_provider_sid) {
throw new DbErrorBadRequest(
'a service provider token can only be used to create tokens for the same service provider');
}
else if (req.body.account_sid) {
const result = await Account.retrieve(req.body.account_sid);
if (result.length === 1 && result[0].service_provider_sid != req.user.service_provider_sid) {
throw new DbErrorBadRequest(
'a service provider token can only be used to create tokens for the same service provider');
}
}
if (req.body.account_sid) delete req.body.service_provider_sid;
else req.body.service_provider_sid = req.user.service_provider_sid;
}
if (req.user.hasAccountAuth) {
if (req.body.account_sid !== req.user.account_sid) {
throw new DbErrorBadRequest(
'an account level token can only be used to create account level tokens for the same account');
}
delete req.body['service_provider_sid'];
req.body['account_sid'] = req.user.account_sid;
}
}
async function validateDeleteToken(req, sid) {
const results = await ApiKey.retrieve(sid);
if (0 == results.length) return;
if (req.user.hasScope('admin')) {
// can do anything
}
else if (req.user.hasScope('service_provider')) {
if (results[0].service_provider_sid === null && results[0].account_sid === null) {
throw new DbErrorBadRequest('a service provider user may not delete an admin token');
}
if (results[0].service_provider_sid && results[0].service_provider_sid != req.user.service_provider_sid) {
throw new DbErrorBadRequest('a service provider user may not delete api key from another service provider');
}
}
else {
if (results[0].account_sid !== req.user.account_sid) {
throw new DbErrorBadRequest('a user may not delete a token associated with a different account');
}
}
}
/**
* need to handle here because response is slightly different than standard for an insert
* (returning the token generated along with the sid)
*/
router.post('/', async(req, res) => {
const logger = req.app.locals.logger;
try {
await validateAddToken(req);
const uuid = await ApiKey.make(req.body);
res.status(201).json({sid: uuid, token: req.body.token});
} catch (err) {
sysError(logger, res, err);
}
});
decorate(router, ApiKey, ['delete'], preconditions);
module.exports = router;