Bugfix/fix permissions (#89)

* protect service provider data retrieval so only admin users and appropriate service provider users can access

* allow accounts to access ServiceProvider API but filter response data so they dont see other accounts or data they should not
This commit is contained in:
Dave Horton
2022-12-25 14:52:57 -06:00
committed by GitHub
parent 2000e7de90
commit e75eae4e24
+42 -18
View File
@@ -28,13 +28,28 @@ WHERE voip_carrier_sid IN (
)`;
/* only admin users can add a service provider */
async function validateAdd(req) {
function validateAdd(req) {
if (!req.user.hasAdminAuth) {
throw new DbErrorForbidden('only admin users can add a service provider');
}
}
async function validateUpdate(req) {
async function validateRetrieve(req) {
const service_provider_sid = parseServiceProviderSid(req);
if (req.user.hasScope('admin')) return ;
if (req.user.hasScope('service_provider')) {
if (service_provider_sid === req.user.service_provider_sid) return ;
}
if (req.user.hasScope('account')) {
/* allow account users to retrieve service provider data from parent SP */
const sid = req.user.account_sid;
const [r] = await promisePool.execute('SELECT service_provider_sid from accounts WHERE account_sid = ?', [sid]);
if (r.length === 1 && r[0].service_provider_sid === req.user.service_provider_sid) return;
}
throw new DbErrorForbidden('insufficient permissions to update service provider');
}
function validateUpdate(req) {
if (req.user.hasScope('admin')) return ;
if (req.user.hasScope('service_provider')) {
const service_provider_sid = parseServiceProviderSid(req);
@@ -68,8 +83,12 @@ router.use('/:sid/PredefinedCarriers', hasServiceProviderPermissions, require('.
router.get('/:sid/Accounts', async(req, res) => {
const logger = req.app.locals.logger;
try {
await validateRetrieve(req);
const service_provider_sid = parseServiceProviderSid(req);
const results = await Account.retrieveAll(service_provider_sid);
let results = await Account.retrieveAll(service_provider_sid);
if (req.user.hasScope('account')) {
results = results.filter((r) => r.account_sid === req.user.account_sid);
}
res.status(200).json(results);
} catch (err) {
sysError(logger, res, err);
@@ -78,8 +97,12 @@ router.get('/:sid/Accounts', async(req, res) => {
router.get('/:sid/Applications', async(req, res) => {
const logger = req.app.locals.logger;
try {
await validateRetrieve(req);
const service_provider_sid = parseServiceProviderSid(req);
const results = await Application.retrieveAll(service_provider_sid);
let results = await Application.retrieveAll(service_provider_sid);
if (req.user.hasScope('account')) {
results = results.filter((r) => r.account_sid === req.user.account_sid);
}
res.status(200).json(results);
} catch (err) {
sysError(logger, res, err);
@@ -88,8 +111,12 @@ router.get('/:sid/Applications', async(req, res) => {
router.get('/:sid/PhoneNumbers', async(req, res) => {
const logger = req.app.locals.logger;
try {
await validateRetrieve(req);
const service_provider_sid = parseServiceProviderSid(req);
const results = await PhoneNumber.retrieveAllForSP(service_provider_sid);
let results = await PhoneNumber.retrieveAllForSP(service_provider_sid);
if (req.user.hasScope('account')) {
results = results.filter((r) => r.account_sid === req.user.account_sid);
}
res.status(200).json(results);
} catch (err) {
sysError(logger, res, err);
@@ -98,6 +125,7 @@ router.get('/:sid/PhoneNumbers', async(req, res) => {
router.get('/:sid/VoipCarriers', async(req, res) => {
const logger = req.app.locals.logger;
try {
await validateRetrieve(req);
const service_provider_sid = parseServiceProviderSid(req);
const results = await VoipCarrier.retrieveAllForSP(service_provider_sid);
res.status(200).json(results);
@@ -108,6 +136,7 @@ router.get('/:sid/VoipCarriers', async(req, res) => {
router.post('/:sid/VoipCarriers', async(req, res) => {
const logger = req.app.locals.logger;
try {
validateUpdate(req);
const service_provider_sid = parseServiceProviderSid(req);
const uuid = await VoipCarrier.make({...req.body, service_provider_sid});
res.status(201).json({sid: uuid});
@@ -118,6 +147,7 @@ router.post('/:sid/VoipCarriers', async(req, res) => {
router.put('/:sid/VoipCarriers/:voip_carrier_sid', async(req, res) => {
const logger = req.app.locals.logger;
try {
validateUpdate(req);
const rowsAffected = await VoipCarrier.update(req.params.voip_carrier_sid, req.body);
if (rowsAffected === 0) {
return res.sendStatus(404);
@@ -127,21 +157,15 @@ router.put('/:sid/VoipCarriers/:voip_carrier_sid', async(req, res) => {
sysError(logger, res, err);
}
});
router.get(':sid/Acccounts', async(req, res) => {
const logger = req.app.locals.logger;
try {
const service_provider_sid = parseServiceProviderSid(req);
const results = await Account.retrieveAll(service_provider_sid);
res.status(200).json(results);
} catch (err) {
sysError(logger, res, err);
}
});
router.get('/:sid/ApiKeys', async(req, res) => {
const logger = req.app.locals.logger;
const {sid} = req.params;
try {
const results = await ApiKey.retrieveAllForSP(sid);
await validateRetrieve(req);
let results = await ApiKey.retrieveAllForSP(sid);
if (req.user.hasScope('account')) {
results = results.filter((r) => r.account_sid === req.user.account_sid);
}
res.status(200).json(results);
await ApiKey.updateLastUsed(sid);
} catch (err) {
@@ -153,7 +177,7 @@ router.get('/:sid/ApiKeys', async(req, res) => {
router.post('/', async(req, res) => {
const logger = req.app.locals.logger;
try {
await validateAdd(req);
validateAdd(req);
// create webhooks if provided
const obj = Object.assign({}, req.body);
@@ -208,7 +232,7 @@ router.put('/:sid', async(req, res) => {
const sid = req.params.sid;
const logger = req.app.locals.logger;
try {
await validateUpdate(req);
validateUpdate(req);
// create webhooks if provided
const obj = Object.assign({}, req.body);