Feature/sp call limits (#63)

* add api for setting/querying call limits by account and sp

* update an account or sp limit if one exists rather than creating a new one
This commit is contained in:
Dave Horton
2022-09-20 13:12:28 +02:00
committed by GitHub
parent 0a01755a21
commit 052a19cfdc
11 changed files with 595 additions and 38 deletions

View File

@@ -8,6 +8,8 @@ DROP TABLE IF EXISTS account_products;
DROP TABLE IF EXISTS account_subscriptions;
DROP TABLE IF EXISTS account_limits;
DROP TABLE IF EXISTS beta_invite_codes;
DROP TABLE IF EXISTS call_routes;
@@ -38,6 +40,8 @@ DROP TABLE IF EXISTS ms_teams_tenants;
DROP TABLE IF EXISTS signup_history;
DROP TABLE IF EXISTS service_provider_limits;
DROP TABLE IF EXISTS smpp_addresses;
DROP TABLE IF EXISTS speech_credentials;
@@ -88,6 +92,15 @@ pending_reason VARBINARY(52),
PRIMARY KEY (account_subscription_sid)
);
CREATE TABLE account_limits
(
account_limits_sid CHAR(36) NOT NULL UNIQUE ,
account_sid CHAR(36) NOT NULL,
category ENUM('api_rate','voice_call_session', 'device') NOT NULL,
quantity INTEGER NOT NULL,
PRIMARY KEY (account_limits_sid)
);
CREATE TABLE beta_invite_codes
(
invite_code CHAR(6) NOT NULL UNIQUE ,
@@ -236,6 +249,15 @@ signed_up_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (email)
);
CREATE TABLE service_provider_limits
(
service_provider_limits_sid CHAR(36) NOT NULL UNIQUE ,
service_provider_sid CHAR(36) NOT NULL,
category ENUM('api_rate','voice_call_session', 'device') NOT NULL,
quantity INTEGER NOT NULL,
PRIMARY KEY (service_provider_limits_sid)
);
CREATE TABLE smpp_addresses
(
smpp_address_sid CHAR(36) NOT NULL UNIQUE ,
@@ -434,14 +456,17 @@ CREATE INDEX account_subscription_sid_idx ON account_subscriptions (account_subs
CREATE INDEX account_sid_idx ON account_subscriptions (account_sid);
ALTER TABLE account_subscriptions ADD FOREIGN KEY account_sid_idxfk_1 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX account_sid_idx ON account_limits (account_sid);
ALTER TABLE account_limits ADD FOREIGN KEY account_sid_idxfk_2 (account_sid) REFERENCES accounts (account_sid) ON DELETE CASCADE;
CREATE INDEX invite_code_idx ON beta_invite_codes (invite_code);
CREATE INDEX call_route_sid_idx ON call_routes (call_route_sid);
ALTER TABLE call_routes ADD FOREIGN KEY account_sid_idxfk_2 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE call_routes ADD FOREIGN KEY account_sid_idxfk_3 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE call_routes ADD FOREIGN KEY application_sid_idxfk (application_sid) REFERENCES applications (application_sid);
CREATE INDEX dns_record_sid_idx ON dns_records (dns_record_sid);
ALTER TABLE dns_records ADD FOREIGN KEY account_sid_idxfk_3 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE dns_records ADD FOREIGN KEY account_sid_idxfk_4 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX predefined_carrier_sid_idx ON predefined_carriers (predefined_carrier_sid);
CREATE INDEX predefined_sip_gateway_sid_idx ON predefined_sip_gateways (predefined_sip_gateway_sid);
@@ -461,14 +486,14 @@ ALTER TABLE account_products ADD FOREIGN KEY product_sid_idxfk (product_sid) REF
CREATE INDEX account_offer_sid_idx ON account_offers (account_offer_sid);
CREATE INDEX account_sid_idx ON account_offers (account_sid);
ALTER TABLE account_offers ADD FOREIGN KEY account_sid_idxfk_4 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE account_offers ADD FOREIGN KEY account_sid_idxfk_5 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX product_sid_idx ON account_offers (product_sid);
ALTER TABLE account_offers ADD FOREIGN KEY product_sid_idxfk_1 (product_sid) REFERENCES products (product_sid);
CREATE INDEX api_key_sid_idx ON api_keys (api_key_sid);
CREATE INDEX account_sid_idx ON api_keys (account_sid);
ALTER TABLE api_keys ADD FOREIGN KEY account_sid_idxfk_5 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE api_keys ADD FOREIGN KEY account_sid_idxfk_6 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX service_provider_sid_idx ON api_keys (service_provider_sid);
ALTER TABLE api_keys ADD FOREIGN KEY service_provider_sid_idxfk (service_provider_sid) REFERENCES service_providers (service_provider_sid);
@@ -482,41 +507,44 @@ ALTER TABLE sbc_addresses ADD FOREIGN KEY service_provider_sid_idxfk_1 (service_
CREATE INDEX ms_teams_tenant_sid_idx ON ms_teams_tenants (ms_teams_tenant_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY service_provider_sid_idxfk_2 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY account_sid_idxfk_6 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY account_sid_idxfk_7 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE ms_teams_tenants ADD FOREIGN KEY application_sid_idxfk_1 (application_sid) REFERENCES applications (application_sid);
CREATE INDEX tenant_fqdn_idx ON ms_teams_tenants (tenant_fqdn);
CREATE INDEX email_idx ON signup_history (email);
CREATE INDEX service_provider_sid_idx ON service_provider_limits (service_provider_sid);
ALTER TABLE service_provider_limits ADD FOREIGN KEY service_provider_sid_idxfk_3 (service_provider_sid) REFERENCES service_providers (service_provider_sid) ON DELETE CASCADE;
CREATE INDEX smpp_address_sid_idx ON smpp_addresses (smpp_address_sid);
CREATE INDEX service_provider_sid_idx ON smpp_addresses (service_provider_sid);
ALTER TABLE smpp_addresses ADD FOREIGN KEY service_provider_sid_idxfk_3 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE smpp_addresses ADD FOREIGN KEY service_provider_sid_idxfk_4 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE UNIQUE INDEX speech_credentials_idx_1 ON speech_credentials (vendor,account_sid);
CREATE INDEX speech_credential_sid_idx ON speech_credentials (speech_credential_sid);
CREATE INDEX service_provider_sid_idx ON speech_credentials (service_provider_sid);
ALTER TABLE speech_credentials ADD FOREIGN KEY service_provider_sid_idxfk_4 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE speech_credentials ADD FOREIGN KEY service_provider_sid_idxfk_5 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE INDEX account_sid_idx ON speech_credentials (account_sid);
ALTER TABLE speech_credentials ADD FOREIGN KEY account_sid_idxfk_7 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE speech_credentials ADD FOREIGN KEY account_sid_idxfk_8 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX user_sid_idx ON users (user_sid);
CREATE INDEX email_idx ON users (email);
CREATE INDEX phone_idx ON users (phone);
CREATE INDEX account_sid_idx ON users (account_sid);
ALTER TABLE users ADD FOREIGN KEY account_sid_idxfk_8 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE users ADD FOREIGN KEY account_sid_idxfk_9 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX service_provider_sid_idx ON users (service_provider_sid);
ALTER TABLE users ADD FOREIGN KEY service_provider_sid_idxfk_5 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE users ADD FOREIGN KEY service_provider_sid_idxfk_6 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE INDEX email_activation_code_idx ON users (email_activation_code);
CREATE INDEX voip_carrier_sid_idx ON voip_carriers (voip_carrier_sid);
CREATE INDEX account_sid_idx ON voip_carriers (account_sid);
ALTER TABLE voip_carriers ADD FOREIGN KEY account_sid_idxfk_9 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE voip_carriers ADD FOREIGN KEY account_sid_idxfk_10 (account_sid) REFERENCES accounts (account_sid);
CREATE INDEX service_provider_sid_idx ON voip_carriers (service_provider_sid);
ALTER TABLE voip_carriers ADD FOREIGN KEY service_provider_sid_idxfk_6 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE voip_carriers ADD FOREIGN KEY service_provider_sid_idxfk_7 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE voip_carriers ADD FOREIGN KEY application_sid_idxfk_2 (application_sid) REFERENCES applications (application_sid);
@@ -529,12 +557,12 @@ CREATE INDEX number_idx ON phone_numbers (number);
CREATE INDEX voip_carrier_sid_idx ON phone_numbers (voip_carrier_sid);
ALTER TABLE phone_numbers ADD FOREIGN KEY voip_carrier_sid_idxfk_1 (voip_carrier_sid) REFERENCES voip_carriers (voip_carrier_sid);
ALTER TABLE phone_numbers ADD FOREIGN KEY account_sid_idxfk_10 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE phone_numbers ADD FOREIGN KEY account_sid_idxfk_11 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE phone_numbers ADD FOREIGN KEY application_sid_idxfk_3 (application_sid) REFERENCES applications (application_sid);
CREATE INDEX service_provider_sid_idx ON phone_numbers (service_provider_sid);
ALTER TABLE phone_numbers ADD FOREIGN KEY service_provider_sid_idxfk_7 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE phone_numbers ADD FOREIGN KEY service_provider_sid_idxfk_8 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE INDEX sip_gateway_idx_hostport ON sip_gateways (ipv4,port);
@@ -550,10 +578,10 @@ CREATE UNIQUE INDEX applications_idx_name ON applications (account_sid,name);
CREATE INDEX application_sid_idx ON applications (application_sid);
CREATE INDEX service_provider_sid_idx ON applications (service_provider_sid);
ALTER TABLE applications ADD FOREIGN KEY service_provider_sid_idxfk_8 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE applications ADD FOREIGN KEY service_provider_sid_idxfk_9 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
CREATE INDEX account_sid_idx ON applications (account_sid);
ALTER TABLE applications ADD FOREIGN KEY account_sid_idxfk_11 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE applications ADD FOREIGN KEY account_sid_idxfk_12 (account_sid) REFERENCES accounts (account_sid);
ALTER TABLE applications ADD FOREIGN KEY call_hook_sid_idxfk (call_hook_sid) REFERENCES webhooks (webhook_sid);
@@ -569,7 +597,7 @@ ALTER TABLE service_providers ADD FOREIGN KEY registration_hook_sid_idxfk (regis
CREATE INDEX account_sid_idx ON accounts (account_sid);
CREATE INDEX sip_realm_idx ON accounts (sip_realm);
CREATE INDEX service_provider_sid_idx ON accounts (service_provider_sid);
ALTER TABLE accounts ADD FOREIGN KEY service_provider_sid_idxfk_9 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE accounts ADD FOREIGN KEY service_provider_sid_idxfk_10 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
ALTER TABLE accounts ADD FOREIGN KEY registration_hook_sid_idxfk_1 (registration_hook_sid) REFERENCES webhooks (webhook_sid);

View File

@@ -95,8 +95,8 @@
<name><![CDATA[account_products]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1791.00</x>
<y>608.00</y>
<x>1823.00</x>
<y>738.00</y>
</location>
<size>
<width>294.00</width>
@@ -233,8 +233,8 @@
<name><![CDATA[account_static_ips]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1334.00</x>
<y>1169.00</y>
<x>1333.00</x>
<y>1267.00</y>
</location>
<size>
<width>298.00</width>
@@ -287,8 +287,8 @@
<name><![CDATA[users]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1745.00</x>
<y>19.00</y>
<x>1769.00</x>
<y>16.00</y>
</location>
<size>
<width>316.00</width>
@@ -757,12 +757,63 @@
<ui.treeExpanded><![CDATA[1]]></ui.treeExpanded>
<uid><![CDATA[3EDF89A0-FD38-4DF9-BB65-E0FCD0A678BE]]></uid>
</SQLTable>
<SQLTable>
<name><![CDATA[account_limits]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1334.00</x>
<y>325.00</y>
</location>
<size>
<width>352.00</width>
<height>100.00</height>
</size>
<zorder>30</zorder>
<SQLField>
<name><![CDATA[account_limits_sid]]></name>
<type><![CDATA[CHAR(36)]]></type>
<primaryKey>1</primaryKey>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[F717BEE1-C530-4C3B-A35F-F4AB0A797B7A]]></uid>
<unique><![CDATA[1]]></unique>
</SQLField>
<SQLField>
<name><![CDATA[account_sid]]></name>
<type><![CDATA[CHAR(36)]]></type>
<referencesField>account_sid</referencesField>
<referencesTable>accounts</referencesTable>
<deleteAction>1</deleteAction>
<referencesField><![CDATA[account_sid]]></referencesField>
<referencesTable><![CDATA[accounts]]></referencesTable>
<sourceCardinality>4</sourceCardinality>
<destinationCardinality>1</destinationCardinality>
<referencesFieldUID><![CDATA[1342FAFA-C15C-429B-809B-C6C55F9FA5B6]]></referencesFieldUID>
<referencesTableUID><![CDATA[985D6997-B1A7-4AB3-80F4-4D59B45480C8]]></referencesTableUID>
<indexed><![CDATA[1]]></indexed>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[F350FCA7-C536-47EB-A9A3-CEE9CDA00DAD]]></uid>
</SQLField>
<SQLField>
<name><![CDATA[category]]></name>
<type><![CDATA[ENUM('api_rate','voice_call_session', 'device')]]></type>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[9724C27F-3B51-453A-99B8-313480D4A63A]]></uid>
</SQLField>
<SQLField>
<name><![CDATA[quantity]]></name>
<type><![CDATA[INTEGER]]></type>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[EA4C1A7E-68ED-41D5-9EE9-345DD61F00C7]]></uid>
</SQLField>
<ui.treeExpanded><![CDATA[1]]></ui.treeExpanded>
<uid><![CDATA[4893A0F0-BE1B-4322-9034-644528E802DE]]></uid>
</SQLTable>
<SQLTable>
<name><![CDATA[speech_credentials]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1354.00</x>
<y>821.00</y>
<x>1328.00</x>
<y>958.00</y>
</location>
<size>
<width>368.00</width>
@@ -909,8 +960,8 @@
<name><![CDATA[account_offers]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1386.00</x>
<y>333.00</y>
<x>1330.00</x>
<y>514.00</y>
</location>
<size>
<width>276.00</width>
@@ -966,6 +1017,57 @@
<ui.treeExpanded><![CDATA[1]]></ui.treeExpanded>
<uid><![CDATA[51A02EFE-AA51-46EF-8671-E8B2F1FC5F8D]]></uid>
</SQLTable>
<SQLTable>
<name><![CDATA[service_provider_limits]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1327.00</x>
<y>205.00</y>
</location>
<size>
<width>352.00</width>
<height>100.00</height>
</size>
<zorder>29</zorder>
<SQLField>
<name><![CDATA[service_provider_limits_sid]]></name>
<type><![CDATA[CHAR(36)]]></type>
<primaryKey>1</primaryKey>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[DE7EA932-0467-4D5F-8311-CADB7E7D6D17]]></uid>
<unique><![CDATA[1]]></unique>
</SQLField>
<SQLField>
<name><![CDATA[service_provider_sid]]></name>
<type><![CDATA[CHAR(36)]]></type>
<referencesField>service_provider_sid</referencesField>
<referencesTable>service_providers</referencesTable>
<deleteAction>1</deleteAction>
<referencesField><![CDATA[service_provider_sid]]></referencesField>
<referencesTable><![CDATA[service_providers]]></referencesTable>
<sourceCardinality>4</sourceCardinality>
<destinationCardinality>1</destinationCardinality>
<referencesFieldUID><![CDATA[58E1702C-6A95-4B17-8C08-8A3810EA16A1]]></referencesFieldUID>
<referencesTableUID><![CDATA[F294B51E-F867-47CA-BC1F-F70BDF8170FF]]></referencesTableUID>
<indexed><![CDATA[1]]></indexed>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[E1C82BD4-FA34-40C7-8236-EC924C9CF7D5]]></uid>
</SQLField>
<SQLField>
<name><![CDATA[category]]></name>
<type><![CDATA[ENUM('api_rate','voice_call_session', 'device')]]></type>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[72BFA408-371D-4B21-8DA0-A56644FCD92C]]></uid>
</SQLField>
<SQLField>
<name><![CDATA[quantity]]></name>
<type><![CDATA[INTEGER]]></type>
<notNull><![CDATA[1]]></notNull>
<uid><![CDATA[2EA3A57F-7EF7-4958-B06B-62B0279BB87E]]></uid>
</SQLField>
<ui.treeExpanded><![CDATA[1]]></ui.treeExpanded>
<uid><![CDATA[5784AC2F-BEBC-466F-9818-F9A7D227A5B5]]></uid>
</SQLTable>
<SQLTable>
<name><![CDATA[webhooks]]></name>
<schema><![CDATA[]]></schema>
@@ -1226,8 +1328,8 @@
<name><![CDATA[beta_invite_codes]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1796.00</x>
<y>780.00</y>
<x>1860.00</x>
<y>897.00</y>
</location>
<size>
<width>232.00</width>
@@ -1599,8 +1701,8 @@
<name><![CDATA[products]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1779.00</x>
<y>427.00</y>
<x>1842.00</x>
<y>550.00</y>
</location>
<size>
<width>352.00</width>
@@ -2146,8 +2248,8 @@
<name><![CDATA[account_subscriptions]]></name>
<schema><![CDATA[]]></schema>
<location>
<x>1367.00</x>
<y>477.00</y>
<x>1324.00</x>
<y>637.00</y>
</location>
<size>
<width>322.00</width>
@@ -2455,7 +2557,7 @@
<windowHeight><![CDATA[833.000000]]></windowHeight>
<windowLocationX><![CDATA[0.000000]]></windowLocationX>
<windowLocationY><![CDATA[111.000000]]></windowLocationY>
<windowScrollOrigin><![CDATA[{172, 109}]]></windowScrollOrigin>
<windowScrollOrigin><![CDATA[{462, 81}]]></windowScrollOrigin>
<windowWidth><![CDATA[1512.000000]]></windowWidth>
</SQLDocumentInfo>
<AllowsIndexRenamingOnInsert><![CDATA[1]]></AllowsIndexRenamingOnInsert>

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env node
/* eslint-disable max-len */
const assert = require('assert');
const mysql = require('mysql2/promise');
const {readFile} = require('fs/promises');
@@ -25,8 +26,34 @@ const opts = {
const sql = {
'7006': [
'ALTER TABLE `accounts` ADD COLUMN `siprec_hook_sid` CHAR(36)',
// eslint-disable-next-line max-len
'ALTER TABLE accounts ADD FOREIGN KEY siprec_hook_sid_idxfk (siprec_hook_sid) REFERENCES applications (application_sid)'
],
'7007': [
`CREATE TABLE service_provider_limits
(service_provider_limits_sid CHAR(36) NOT NULL UNIQUE,
service_provider_sid CHAR(36) NOT NULL,
category ENUM('api_rate','voice_call_session', 'device') NOT NULL,
quantity INTEGER NOT NULL,
PRIMARY KEY (service_provider_limits_sid)
)`,
`CREATE TABLE account_limits
(
account_limits_sid CHAR(36) NOT NULL UNIQUE ,
account_sid CHAR(36) NOT NULL,
category ENUM('api_rate','voice_call_session', 'device') NOT NULL,
quantity INTEGER NOT NULL,
PRIMARY KEY (account_limits_sid)
)`,
'CREATE INDEX service_provider_sid_idx ON service_provider_limits (service_provider_sid)',
`ALTER TABLE service_provider_limits
ADD FOREIGN KEY service_provider_sid_idxfk_3 (service_provider_sid)
REFERENCES service_providers (service_provider_sid)
ON DELETE CASCADE`,
'CREATE INDEX account_sid_idx ON account_limits (account_sid)',
`ALTER TABLE account_limits
ADD FOREIGN KEY account_sid_idxfk_2 (account_sid)
REFERENCES accounts (account_sid)
ON DELETE CASCADE`
]
};
@@ -54,6 +81,7 @@ const doIt = async() => {
logger.info(`current schema value: ${val}`);
if (val < 7006) upgrades.push(...sql['7006']);
if (val < 7007) upgrades.push(...sql['7007']);
// perform all upgrades
logger.info({upgrades}, 'applying schema upgrades..');

View File

@@ -0,0 +1,33 @@
const Model = require('./model');
class AccountLimits extends Model {
constructor() {
super();
}
}
AccountLimits.table = 'account_limits';
AccountLimits.fields = [
{
name: 'account_limits_sid',
type: 'string',
primaryKey: true
},
{
name: 'account_sid',
type: 'string',
required: true
},
{
name: 'category',
type: 'string',
required: true
},
{
name: 'quantity',
type: 'number',
required: true
}
];
module.exports = AccountLimits;

View File

@@ -0,0 +1,33 @@
const Model = require('./model');
class ServiceProviderLimits extends Model {
constructor() {
super();
}
}
ServiceProviderLimits.table = 'service_provider_limits';
ServiceProviderLimits.fields = [
{
name: 'service_provider_limits_sid',
type: 'string',
primaryKey: true
},
{
name: 'service_provider_sid',
type: 'string',
required: true
},
{
name: 'category',
type: 'string',
required: true
},
{
name: 'quantity',
type: 'number',
required: true
}
];
module.exports = ServiceProviderLimits;

View File

@@ -51,6 +51,7 @@ router.use('/:sid/Alerts', hasAccountPermissions, require('./alerts'));
router.use('/:sid/Charges', hasAccountPermissions, require('./charges'));
router.use('/:sid/SipRealms', hasAccountPermissions, require('./sip-realm'));
router.use('/:sid/PredefinedCarriers', hasAccountPermissions, require('./add-from-predefined-carrier'));
router.use('/:sid/Limits', hasAccountPermissions, require('./limits'));
router.get('/:sid/Applications', async(req, res) => {
const logger = req.app.locals.logger;
try {

128
lib/routes/api/limits.js Normal file
View File

@@ -0,0 +1,128 @@
const router = require('express').Router();
const sysError = require('../error');
const AccountLimits = require('../../models/account-limits');
const ServiceProviderLimits = require('../../models/service-provider-limits');
const {parseAccountSid, parseServiceProviderSid} = require('./utils');
const {promisePool} = require('../../db');
const sqlDeleteSPLimits = `
DELETE FROM service_provider_limits
WHERE service_provider_sid = ?
`;
const sqlDeleteSPLimitsByCategory = `
DELETE FROM service_provider_limits
WHERE service_provider_sid = ?
AND category = ?
`;
const sqlDeleteAccountLimits = `
DELETE FROM account_limits
WHERE account_sid = ?
`;
const sqlDeleteAccountLimitsByCategory = `
DELETE FROM account_limits
WHERE account_sid = ?
AND category = ?
`;
router.post('/', async(req, res) => {
const logger = req.app.locals.logger;
const {
category,
quantity
} = req.body;
const account_sid = parseAccountSid(req);
let service_provider_sid;
if (!account_sid) {
if (!req.user.hasServiceProviderAuth) {
logger.error('POST /SpeechCredentials invalid credentials');
return res.send(403);
}
service_provider_sid = parseServiceProviderSid(req);
}
try {
let uuid;
if (account_sid) {
const existing = (await AccountLimits.retrieveAll(account_sid) || [])
.find((el) => el.category === category);
if (existing) {
uuid = existing.account_limits_sid;
await AccountLimits.update(uuid, {category, quantity});
}
else {
uuid = await AccountLimits.make({
account_sid,
category,
quantity
});
}
}
else {
const existing = (await ServiceProviderLimits.retrieveAll(service_provider_sid) || [])
.find((el) => el.category === category);
if (existing) {
uuid = existing.service_provider_limits_sid;
await ServiceProviderLimits.update(uuid, {category, quantity});
}
else {
uuid = await ServiceProviderLimits.make({
service_provider_sid,
category,
quantity
});
}
}
res.status(201).json({sid: uuid});
} catch (err) {
sysError(logger, res, err);
}
});
/**
* retrieve all limits for an account or service provider
*/
router.get('/', async(req, res) => {
let service_provider_sid;
const account_sid = parseAccountSid(req);
if (!account_sid) service_provider_sid = parseServiceProviderSid(req);
const logger = req.app.locals.logger;
try {
const limits = account_sid ?
await AccountLimits.retrieveAll(account_sid) :
await ServiceProviderLimits.retrieveAll(service_provider_sid);
if (req.query?.category) {
return res.status(200).json(limits.filter((el) => el.category === req.query.category));
}
res.status(200).json(limits);
} catch (err) {
sysError(logger, res, err);
}
});
router.delete('/', async(req, res) => {
const logger = req.app.locals.logger;
const account_sid = parseAccountSid(req);
const {category} = req.query;
const service_provider_sid = parseServiceProviderSid(req);
try {
if (account_sid) {
if (category) {
await promisePool.execute(sqlDeleteAccountLimitsByCategory, [account_sid, category]);
}
else {
await promisePool.execute(sqlDeleteAccountLimits, [account_sid]);
}
}
else {
if (category) {
await promisePool.execute(sqlDeleteSPLimitsByCategory, [service_provider_sid, category]);
}
else {
await promisePool.execute(sqlDeleteSPLimits, [service_provider_sid]);
}
}
res.status(204).end();
} catch (err) {
sysError(logger, res, err);
}
});
module.exports = router;

View File

@@ -44,6 +44,7 @@ decorate(router, ServiceProvider, ['delete'], preconditions);
router.use('/:sid/RecentCalls', hasServiceProviderPermissions, require('./recent-calls'));
router.use('/:sid/Alerts', hasServiceProviderPermissions, require('./alerts'));
router.use('/:sid/SpeechCredentials', hasServiceProviderPermissions, require('./speech-credentials'));
router.use('/:sid/Limits', hasServiceProviderPermissions, require('./limits'));
router.use('/:sid/PredefinedCarriers', hasServiceProviderPermissions, require('./add-from-predefined-carrier'));
router.get('/:sid/Accounts', async(req, res) => {
const logger = req.app.locals.logger;
@@ -129,7 +130,6 @@ router.get('/:sid/ApiKeys', async(req, res) => {
}
});
/* add */
router.post('/', async(req, res) => {
const logger = req.app.locals.logger;

View File

@@ -1806,7 +1806,7 @@ paths:
summary: test a speech credential
operationId: testSpeechCredential
parameters:
- name: AccountSid
- name: ServiceProviderSid
in: path
required: true
schema:
@@ -1855,6 +1855,122 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'
/ServiceProviders/{ServiceProviderSid}/Limits:
post:
summary: create a limit for a service provider
operationId: addLimitForServiceProvider
parameters:
- name: ServiceProviderSid
in: path
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Limits'
responses:
201:
description: limit successfully created or updated
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessfulAdd'
404:
description: service provider not found
500:
description: system error
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'
get:
summary: retrieve call capacity and other limits from the service provider
operationId: getServiceProviderLimits
parameters:
- name: ServiceProviderSid
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: service provider limits
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Limits'
404:
description: service provider not found
500:
description: system error
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'
/Accounts/{AccountSid}/Limits:
post:
summary: create a limit for an account
operationId: addLimitForAccount
parameters:
- name: AccountSid
in: path
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Limits'
responses:
201:
description: limit successfully created or updated
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessfulAdd'
404:
description: account not found
500:
description: system error
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'
get:
summary: retrieve call capacity and other limits from the account
operationId: getAccountLimits
parameters:
- name: AccountSid
in: path
required: true
schema:
type: string
format: uuid
responses:
200:
description: account limits
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Limits'
404:
description: account not found
500:
description: system error
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'
/MicrosoftTeamsTenants:
post:
summary: provision a customer tenant for MS Teams
@@ -4409,6 +4525,15 @@ components:
- requires_static_ip
- e164_leading_plus
- requires_register
Limits:
type: object
properties:
category:
type: string
enum:
- voice_call_session
- api_limit
- devices
security:
- bearerAuth: []

View File

@@ -188,6 +188,60 @@ test('account tests', async(t) => {
});
t.ok(result.statusCode === 204, 'successfully assigned phone number to account');
/* query all limits for an account */
result = await request.get(`/Accounts/${sid}/Limits`, {
auth: authAdmin,
json: true,
});
t.ok(result.length === 0, 'successfully queried account limits when there is none configured');
/* add a new limit for a account */
result = await request.post(`/Accounts/${sid}/Limits`, {
auth: authAdmin,
json: true,
resolveWithFullResponse: true,
body: {
category: 'voice_call_session',
quantity: 200
}
});
t.ok(result.statusCode === 201, 'successfully added a call session limit to an account');
/* update an existing limit for a account */
result = await request.post(`/Accounts/${sid}/Limits`, {
auth: authAdmin,
json: true,
resolveWithFullResponse: true,
body: {
category: 'voice_call_session',
quantity: 205
}
});
t.ok(result.statusCode === 201, 'successfully updated a call session limit to an account');
/* query all limits for an account */
result = await request.get(`/Accounts/${sid}/Limits`, {
auth: authAdmin,
json: true,
});
//console.log(result);
t.ok(result.length === 1 && result[0].quantity === 205, 'successfully queried account limits');
/* query all limits for an account by category*/
result = await request.get(`/Accounts/${sid}/Limits?category=voice_call_session`, {
auth: authAdmin,
json: true,
});
//console.log(result);
t.ok(result.length === 1 && result[0].quantity === 205, 'successfully queried account limits by category');
/* delete call session limits for a service provider */
result = await request.delete(`/Accounts/${sid}/Limits?category=voice_call_session`, {
auth: authAdmin,
resolveWithFullResponse: true
});
t.ok(result.statusCode === 204, 'successfully deleted a call session limit for an account');
/* delete account */
result = await request.delete(`/Accounts/${sid}`, {
auth: authAdmin,

View File

@@ -140,9 +140,34 @@ test('service provider tests', async(t) => {
resolveWithFullResponse: true,
});
t.ok(result.statusCode === 201, 'successfully added predefined carrier to service provider');
await deleteObjectBySid(request, '/VoipCarriers', result.body.sid);
/* add a limit for a service provider */
result = await request.post(`/ServiceProviders/${sid}/Limits`, {
auth: authAdmin,
json: true,
resolveWithFullResponse: true,
body: {
category: 'voice_call_session',
quantity: 1000
}
});
t.ok(result.statusCode === 201, 'successfully added a call session limit to service provider');
/* query all limits for a service provider */
result = await request.get(`/ServiceProviders/${sid}/Limits`, {
auth: authAdmin,
json: true,
});
t.ok(result.length === 1 , 'successfully queried all limits');
/* delete call session limits for a service provider */
result = await request.delete(`/ServiceProviders/${sid}/Limits?category=voice_call_session`, {
auth: authAdmin,
resolveWithFullResponse: true
});
t.ok(result.statusCode === 204, 'successfully deleted a call session limit for a service provider');
/* delete service providers */
result = await request.delete(`/ServiceProviders/${sid}`, {
auth: authAdmin,