Files
jambonz-api-server/lib/routes/api/sip-gateways.js
Sam Machin 69046ab5d2 Feat/admin numbers carriers (#532)
* add JAMBONES_ADMIN_CARRIER check to limit creating carriers and numbers

* fix logic
2026-01-07 08:01:44 -05:00

107 lines
3.5 KiB
JavaScript

const router = require('express').Router();
const SipGateway = require('../../models/sip-gateway');
const {DbErrorBadRequest, DbErrorForbidden} = require('../../utils/errors');
//const {parseSipGatewaySid} = require('./utils');
const decorate = require('./decorate');
const sysError = require('../error');
const net = require('net');
const hasWhitespace = (str) => /\s/.test(str);
const checkUserScope = async(req, voip_carrier_sid) => {
const {lookupCarrierBySid} = req.app.locals;
if (!voip_carrier_sid) {
throw new DbErrorBadRequest('missing voip_carrier_sid');
}
if (req.user.hasAdminAuth) return;
if (req.user.hasAccountAuth) {
const carrier = await lookupCarrierBySid(voip_carrier_sid);
if (!carrier) throw new DbErrorBadRequest('invalid voip_carrier_sid');
if (!carrier.account_sid || carrier.account_sid === req.user.account_sid) {
if (req.method !== 'GET' && !carrier.account_sid) {
throw new DbErrorForbidden('insufficient privileges');
}
return;
}
}
if (req.user.hasServiceProviderAuth) {
const carrier = await lookupCarrierBySid(voip_carrier_sid);
if (!carrier) {
throw new DbErrorBadRequest('invalid voip_carrier_sid');
}
if (carrier.service_provider_sid === req.user.service_provider_sid) {
return;
}
}
throw new DbErrorForbidden('insufficient privileges');
};
const validate = async(req, sid) => {
const {lookupSipGatewayBySid} = req.app.locals;
const {netmask, ipv4, inbound, outbound} = req.body;
let voip_carrier_sid;
if (process.env.JAMBONES_ADMIN_CARRIER == 1 && (!req.user.hasScope('service_provider')
&& !req.user.hasScope('admin'))) {
throw new DbErrorBadRequest('insufficient privileges');
}
if (sid) {
const gateway = await lookupSipGatewayBySid(sid);
if (!gateway) throw new DbErrorBadRequest('invalid sip_gateway_sid');
voip_carrier_sid = gateway.voip_carrier_sid;
}
else {
voip_carrier_sid = req.body.voip_carrier_sid;
if (!voip_carrier_sid) throw new DbErrorBadRequest('missing voip_carrier_sid');
}
if (netmask &&
process.env.JAMBONZ_MIN_GATEWAY_NETMASK &&
parseInt(netmask) < process.env.JAMBONZ_MIN_GATEWAY_NETMASK) {
throw new DbErrorBadRequest(
`netmask required to have value equal or greater than ${process.env.JAMBONZ_MIN_GATEWAY_NETMASK}`);
}
if (hasWhitespace(ipv4)) {
throw new DbErrorBadRequest('Gateway must not contain whitespace');
}
if (inbound && !net.isIPv4(ipv4)) {
throw new DbErrorBadRequest('Inbound gateway must be IPv4 address');
}
if (!inbound && outbound && (netmask && netmask != 32)) {
throw new DbErrorBadRequest('For outbound only gateway netmask can only be 32');
}
await checkUserScope(req, voip_carrier_sid);
};
const preconditions = {
'add': validate,
'update': validate,
'delete': validate
};
decorate(router, SipGateway, ['add', 'retrieve', 'update', 'delete'], preconditions);
/* list */
router.get('/', async(req, res) => {
const logger = req.app.locals.logger;
const voip_carrier_sid = req.query.voip_carrier_sid;
try {
await checkUserScope(req, voip_carrier_sid);
if (!voip_carrier_sid) {
logger.info('GET /SipGateways missing voip_carrier_sid param');
return res.status(400).json({message: 'missing voip_carrier_sid query param'});
}
const results = await SipGateway.retrieveForVoipCarrier(voip_carrier_sid);
res.status(200).json(results);
} catch (err) {
sysError(logger, res, err);
}
});
module.exports = router;