remove orphaned webhooks when deleting accounts and applications

This commit is contained in:
Dave Horton
2022-04-30 12:17:37 -04:00
parent d32a042c5d
commit 9a126f396e
3 changed files with 62 additions and 5 deletions
+10 -1
View File
@@ -519,7 +519,7 @@ router.delete('/:sid', async(req, res) => {
await validateDelete(req, sid);
const [account] = await promisePool.query('SELECT * FROM accounts WHERE account_sid = ?', sid);
const {sip_realm, stripe_customer_id} = account[0];
const {sip_realm, stripe_customer_id, registration_hook_sid} = account[0];
/* remove dns records */
if (process.env.NODE_ENV !== 'test' || process.env.DME_API_KEY) {
@@ -560,6 +560,15 @@ account_subscriptions WHERE account_sid = ?)
await promisePool.execute('DELETE from applications where account_sid = ?', [sid]);
await promisePool.execute('DELETE from accounts where account_sid = ?', [sid]);
if (registration_hook_sid) {
/* remove registration hook if only used by this account */
const sql = 'SELECT COUNT(*) as count FROM accounts WHERE registration_hook_sid = ?';
const [r] = await promisePool.query(sql, registration_hook_sid);
if (r[0]?.count === 0) {
await promisePool.execute('DELETE from webhooks where webhook_sid = ?', [registration_hook_sid]);
}
}
if (stripe_customer_id) {
const response = await deleteCustomer(logger, stripe_customer_id);
logger.info({response}, `deleted stripe customer_id ${stripe_customer_id} for account_si ${sid}`);
+44 -3
View File
@@ -3,12 +3,12 @@ const {DbErrorBadRequest, DbErrorUnprocessableRequest} = require('../../utils/er
const Application = require('../../models/application');
const Account = require('../../models/account');
const Webhook = require('../../models/webhook');
const {promisePool} = require('../../db');
const decorate = require('./decorate');
const sysError = require('../error');
const preconditions = {
'add': validateAdd,
'update': validateUpdate,
'delete': validateDelete
'update': validateUpdate
};
/* only user-level tokens can add applications */
@@ -59,7 +59,7 @@ async function validateDelete(req, sid) {
if (assignedPhoneNumbers > 0) throw new DbErrorUnprocessableRequest('cannot delete application with phone numbers');
}
decorate(router, Application, ['delete'], preconditions);
decorate(router, Application, [], preconditions);
/* add */
router.post('/', async(req, res) => {
@@ -111,6 +111,47 @@ router.get('/:sid', async(req, res) => {
}
});
/* delete */
router.delete('/:sid', async(req, res) => {
const sid = req.params.sid;
const logger = req.app.locals.logger;
try {
await validateDelete(req, sid);
const [application] = await promisePool.query('SELECT * FROM applications WHERE application_sid = ?', sid);
const {call_hook_sid, call_status_hook_sid, messaging_hook_sid} = application[0];
logger.info({call_hook_sid, call_status_hook_sid, messaging_hook_sid, sid}, 'deleting application');
await promisePool.execute('DELETE from applications where application_sid = ?', [sid]);
if (call_hook_sid) {
/* remove call hook if only used by this app */
const sql = 'SELECT COUNT(*) as count FROM applications WHERE call_hook_sid = ?';
const [r] = await promisePool.query(sql, call_hook_sid);
if (r[0]?.count === 0) {
await promisePool.execute('DELETE from webhooks where webhook_sid = ?', [call_hook_sid]);
}
}
if (call_status_hook_sid) {
const sql = 'SELECT COUNT(*) as count FROM applications WHERE call_status_hook_sid = ?';
const [r] = await promisePool.query(sql, call_status_hook_sid);
if (r[0]?.count === 0) {
await promisePool.execute('DELETE from webhooks where webhook_sid = ?', [call_status_hook_sid]);
}
}
if (messaging_hook_sid) {
const sql = 'SELECT COUNT(*) as count FROM applications WHERE messaging_hook_sid = ?';
const [r] = await promisePool.query(sql, messaging_hook_sid);
if (r[0]?.count === 0) {
await promisePool.execute('DELETE from webhooks where webhook_sid = ?', [messaging_hook_sid]);
}
}
res.status(204).end();
} catch (err) {
sysError(logger, res, err);
}
});
/* update */
router.put('/:sid', async(req, res) => {
const sid = req.params.sid;
+8 -1
View File
@@ -7,9 +7,16 @@ const isAdminScope = (req, res, next) => {
message: 'insufficient privileges'
});
};
const isAdminOrSPScope = (req, res, next) => {
if (req.user.hasScope('admin') || req.user.hasScope('service_provider')) return next();
res.status(403).json({
status: 'fail',
message: 'insufficient privileges'
});
};
api.use('/BetaInviteCodes', isAdminScope, require('./beta-invite-codes'));
api.use('/ServiceProviders', isAdminScope, require('./service-providers'));
api.use('/ServiceProviders', isAdminOrSPScope, require('./service-providers'));
api.use('/VoipCarriers', require('./voip-carriers'));
api.use('/Webhooks', require('./webhooks'));
api.use('/SipGateways', require('./sip-gateways'));