diff --git a/db/jambones-sql.sql b/db/jambones-sql.sql index e450a4a..e502bd1 100644 --- a/db/jambones-sql.sql +++ b/db/jambones-sql.sql @@ -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); diff --git a/db/jambones.sqs b/db/jambones.sqs index f931aa3..af71528 100644 --- a/db/jambones.sqs +++ b/db/jambones.sqs @@ -95,8 +95,8 @@ - 1791.00 - 608.00 + 1823.00 + 738.00 294.00 @@ -233,8 +233,8 @@ - 1334.00 - 1169.00 + 1333.00 + 1267.00 298.00 @@ -287,8 +287,8 @@ - 1745.00 - 19.00 + 1769.00 + 16.00 316.00 @@ -757,12 +757,63 @@ + + + + + 1334.00 + 325.00 + + + 352.00 + 100.00 + + 30 + + + + 1 + + + + + + + + account_sid + accounts + 1 + + + 4 + 1 + + + + + + + + + + + + + + + + + + + + + - 1354.00 - 821.00 + 1328.00 + 958.00 368.00 @@ -909,8 +960,8 @@ - 1386.00 - 333.00 + 1330.00 + 514.00 276.00 @@ -966,6 +1017,57 @@ + + + + + 1327.00 + 205.00 + + + 352.00 + 100.00 + + 29 + + + + 1 + + + + + + + + service_provider_sid + service_providers + 1 + + + 4 + 1 + + + + + + + + + + + + + + + + + + + + + @@ -1226,8 +1328,8 @@ - 1796.00 - 780.00 + 1860.00 + 897.00 232.00 @@ -1599,8 +1701,8 @@ - 1779.00 - 427.00 + 1842.00 + 550.00 352.00 @@ -2146,8 +2248,8 @@ - 1367.00 - 477.00 + 1324.00 + 637.00 322.00 @@ -2455,7 +2557,7 @@ - + diff --git a/db/upgrade-jambonz-db.js b/db/upgrade-jambonz-db.js index 8101aaa..28b62de 100644 --- a/db/upgrade-jambonz-db.js +++ b/db/upgrade-jambonz-db.js @@ -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..'); diff --git a/lib/models/account-limits.js b/lib/models/account-limits.js new file mode 100644 index 0000000..34bd13a --- /dev/null +++ b/lib/models/account-limits.js @@ -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; diff --git a/lib/models/service-provider-limits.js b/lib/models/service-provider-limits.js new file mode 100644 index 0000000..8db6830 --- /dev/null +++ b/lib/models/service-provider-limits.js @@ -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; diff --git a/lib/routes/api/accounts.js b/lib/routes/api/accounts.js index 62ffb37..b430281 100644 --- a/lib/routes/api/accounts.js +++ b/lib/routes/api/accounts.js @@ -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 { diff --git a/lib/routes/api/limits.js b/lib/routes/api/limits.js new file mode 100644 index 0000000..7f07e9e --- /dev/null +++ b/lib/routes/api/limits.js @@ -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; diff --git a/lib/routes/api/service-providers.js b/lib/routes/api/service-providers.js index 240743d..dc4df52 100644 --- a/lib/routes/api/service-providers.js +++ b/lib/routes/api/service-providers.js @@ -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; diff --git a/lib/swagger/swagger.yaml b/lib/swagger/swagger.yaml index 990c2b3..bad0ebe 100644 --- a/lib/swagger/swagger.yaml +++ b/lib/swagger/swagger.yaml @@ -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: [] \ No newline at end of file diff --git a/test/accounts.js b/test/accounts.js index cf46279..ae66d4d 100644 --- a/test/accounts.js +++ b/test/accounts.js @@ -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, diff --git a/test/service-providers.js b/test/service-providers.js index bf874f0..29bc632 100644 --- a/test/service-providers.js +++ b/test/service-providers.js @@ -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,