From 34cfe8ca9d9d4465e9166db684bee3e258da1322 Mon Sep 17 00:00:00 2001 From: javibookline <98887695+javibookline@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:02:24 +0200 Subject: [PATCH] Handle cases where gateway query at account level returns more than one (#135) * Handle cases where gateway query at account level returns more than one * Change constant variable as it needs to be reassigned * Fix mistake for handling case where sql query returned no match * grammar * Fix linting errors * Avoid checking for duplicates in case there is only one match to avoid stringifying+parsing for nothing --- lib/db-utils.js | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/lib/db-utils.js b/lib/db-utils.js index 6999c5a..2b0a81c 100644 --- a/lib/db-utils.js +++ b/lib/db-utils.js @@ -173,21 +173,51 @@ module.exports = (srf, logger) => { const gw = gwAcc .concat(gwSP) .sort((a, b) => b.netmask - a.netmask); - const selected = gw.find(gatewayMatchesSourceAddress.bind(null, logger, req.source_address)); - if (selected) { + const gateways = gw.filter(gatewayMatchesSourceAddress.bind(null, logger, req.source_address)); + let voip_carriers = gateways.map((gw) => { + return { + voip_carrier_sid: gw.voip_carrier_sid, + name: gw.name, + service_provider_sid: gw.service_provider_sid, + account_sid: gw.account_sid, + application_sid: gw.application_sid + }; + }); + /* remove duplicates, winnow down to voip_carriers, not gateways */ + if (voip_carriers.length > 1) { + voip_carriers = [...new Set(voip_carriers.map(JSON.stringify))].map(JSON.parse); + } + if (voip_carriers.length) { + /* we have one or more matches. Now check for one with a provisioned phone number matching the DID */ + const vc_sids = voip_carriers.map((m) => `'${m.voip_carrier_sid}'`).join(','); const sql = - `SELECT application_sid FROM phone_numbers WHERE number = '${did}' - AND voip_carrier_sid = '${selected.voip_carrier_sid}' + `SELECT * FROM phone_numbers WHERE number = '${did}' + AND voip_carrier_sid IN (${vc_sids}) AND account_sid = '${a[0].account_sid}'`; - logger.debug({selected, sql, did}, 'looking up DID'); + logger.debug({voip_carriers, sql, did}, 'looking up DID'); + const [r] = await pp.query(sql); + if (r.length > 1) { + logger.info({r}, + 'multiple carriers with the same gateway have the same number provisioned for the same account' + + ' -- cannot determine which one to use'); + return { + fromCarrier: true, + error: 'Multiple carriers with the same gateway are attempting to route the same number for this account' + }; + } + /** + * We have one or no routes for this phone number, carrier and account combination + * Either take the matching gateway, or if no route has matched, the first gateway of the ones available. + */ + const gateway = r[0] ? gateways.find((m) => m.voip_carrier_sid === r[0]?.voip_carrier_sid) : gateways[0]; return { fromCarrier: true, - gateway: selected, + gateway: gateway, service_provider_sid: a[0].service_provider_sid, account_sid: a[0].account_sid, - application_sid: r[0]?.application_sid || selected.application_sid, + application_sid: r[0]?.application_sid || gateway.application_sid, account: a[0] }; } @@ -274,7 +304,9 @@ module.exports = (srf, logger) => { }; }); /* remove duplicates, winnow down to voip_carriers, not gateways */ - matches = [...new Set(matches.map(JSON.stringify))].map(JSON.parse); + if (matches.length > 1) { + matches = [...new Set(matches.map(JSON.stringify))].map(JSON.parse); + } if (matches.length) { /* we have one or more matches. Now check for one with a provisioned phone number matching the DID */ const vc_sids = matches.map((m) => `'${m.voip_carrier_sid}'`).join(',');