mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-07-24 13:02:16 +00:00
merge of features from hosted branch (#7)
major merge of features from the hosted branch that was created temporarily during the initial launch of jambonz.org
This commit is contained in:
+69
-14
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
@@ -16,6 +16,7 @@ process.on('unhandledRejection', (reason, p) => {
|
||||
|
||||
test('account tests', async(t) => {
|
||||
const app = require('../app');
|
||||
const logger = app.locals.logger;
|
||||
let sid;
|
||||
try {
|
||||
let result;
|
||||
@@ -25,6 +26,61 @@ test('account tests', async(t) => {
|
||||
const service_provider_sid = await createServiceProvider(request);
|
||||
const phone_number_sid = await createPhoneNumber(request, voip_carrier_sid);
|
||||
|
||||
/* add invite codes */
|
||||
result = await request.post('/BetaInviteCodes', {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authAdmin,
|
||||
body: {
|
||||
count: 2
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 200 && 2 === parseInt(result.body.added), 'successfully added 2 beta codes');
|
||||
//console.log(result.body.codes);
|
||||
|
||||
/* claim an invite code */
|
||||
/*
|
||||
const mycodes = result.body.codes;
|
||||
result = await request.post('/InviteCodes', {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authAdmin,
|
||||
body: {
|
||||
test: true,
|
||||
code: mycodes[0]
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully tested a beta codes');
|
||||
result = await request.post('/InviteCodes', {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authAdmin,
|
||||
body: {
|
||||
code: mycodes[0]
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully claimed a beta codes');
|
||||
*/
|
||||
|
||||
result = await request.post('/BetaInviteCodes', {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authAdmin,
|
||||
body: {
|
||||
count: 50
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 200 && 50 === parseInt(result.body.added), 'successfully added 50 beta codes');
|
||||
|
||||
result = await request.post('/BetaInviteCodes', {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authAdmin,
|
||||
body: {
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 200 && 1 === parseInt(result.body.added), 'successfully added 1 beta codes');
|
||||
|
||||
/* add an account */
|
||||
result = await request.post('/Accounts', {
|
||||
resolveWithFullResponse: true,
|
||||
@@ -36,12 +92,22 @@ test('account tests', async(t) => {
|
||||
registration_hook: {
|
||||
url: 'http://example.com/reg',
|
||||
method: 'get'
|
||||
}
|
||||
},
|
||||
webhook_secret: 'foobar'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created account');
|
||||
const sid = result.body.sid;
|
||||
|
||||
/* query accounts for service providers */
|
||||
result = await request.get(`/ServiceProviders/${service_provider_sid}/Accounts`, {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
resolveWithFullResponse: true,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200, 'successfully queried accounts for service provider');
|
||||
|
||||
/* add an account level api key */
|
||||
result = await request.post(`/ApiKeys`, {
|
||||
auth: authAdmin,
|
||||
@@ -118,23 +184,12 @@ test('account tests', async(t) => {
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully assigned phone number to account');
|
||||
|
||||
/* cannot delete account that has phone numbers assigned */
|
||||
result = await request.delete(`/Accounts/${sid}`, {
|
||||
auth: authAdmin,
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
json: true
|
||||
});
|
||||
t.ok(result.statusCode === 422 && result.body.msg === 'cannot delete account with phone numbers', 'cannot delete account with phone numbers');
|
||||
|
||||
/* delete account */
|
||||
await request.delete(`ApiKeys/${apiKeySid}`, {auth: {bearer: accountLevelToken}});
|
||||
await request.delete(`/PhoneNumbers/${phone_number_sid}`, {auth: authAdmin});
|
||||
result = await request.delete(`/Accounts/${sid}`, {
|
||||
auth: authAdmin,
|
||||
resolveWithFullResponse: true,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully deleted account after removing phone number');
|
||||
t.ok(result.statusCode === 204, 'successfully deleted account');
|
||||
|
||||
await deleteObjectBySid(request, '/VoipCarriers', voip_carrier_sid);
|
||||
await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
|
||||
+7
-29
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
@@ -56,6 +56,7 @@ test('authentication tests', async(t) => {
|
||||
json: true,
|
||||
body: {
|
||||
name: 'accountA1',
|
||||
webhook_secret: 'foobar',
|
||||
registration_hook: {
|
||||
url: 'http://example.com'
|
||||
}
|
||||
@@ -69,6 +70,7 @@ test('authentication tests', async(t) => {
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
webhook_secret: 'foobar',
|
||||
name: 'accountA2'
|
||||
}
|
||||
});
|
||||
@@ -80,6 +82,7 @@ test('authentication tests', async(t) => {
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
webhook_secret: 'foobar',
|
||||
name: 'accountB1'
|
||||
}
|
||||
});
|
||||
@@ -91,6 +94,7 @@ test('authentication tests', async(t) => {
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
webhook_secret: 'foobar',
|
||||
name: 'accountB2'
|
||||
}
|
||||
});
|
||||
@@ -170,6 +174,7 @@ test('authentication tests', async(t) => {
|
||||
json: true,
|
||||
body: {
|
||||
name: 'accountC',
|
||||
webhook_secret: 'foobar',
|
||||
service_provider_sid: spA_sid
|
||||
}
|
||||
});
|
||||
@@ -206,7 +211,7 @@ test('authentication tests', async(t) => {
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
sip_realm: 'sip.foo.bar'
|
||||
name: 'joe knife'
|
||||
}
|
||||
});
|
||||
//console.log(`result: ${JSON.stringify(result)}`);
|
||||
@@ -324,33 +329,6 @@ test('authentication tests', async(t) => {
|
||||
});
|
||||
t.ok(result.statusCode === 404, 'using account token A1 we are not able to retrieve application A2s');
|
||||
|
||||
|
||||
/* service provider token can not be used to add phone number */
|
||||
result = await request.post('/PhoneNumbers', {
|
||||
auth: {bearer: spA_token},
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
number: '16173333456',
|
||||
voip_carrier_sid
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 403, 'service provider token can not be used to add phone number');
|
||||
|
||||
/* account token can not be used to add phone number */
|
||||
result = await request.post('/PhoneNumbers', {
|
||||
auth: {bearer: accA1_token},
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
number: '16173333456',
|
||||
voip_carrier_sid
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 403, 'account level token can not be used to add phone number');
|
||||
|
||||
/* account level token can not create token for another account */
|
||||
result = await request.post('/ApiKeys', {
|
||||
resolveWithFullResponse: true,
|
||||
|
||||
+11
-3
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const exec = require('child_process').exec ;
|
||||
|
||||
test('creating jambones_test database', (t) => {
|
||||
@@ -10,7 +10,7 @@ test('creating jambones_test database', (t) => {
|
||||
});
|
||||
|
||||
test('creating schema', (t) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/jambones-sql.sql`, (err, stdout, stderr) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/jambones-sql.sql`, (err, stdout, stderr) => {
|
||||
if (err) return t.end(err);
|
||||
t.pass('schema successfully created');
|
||||
t.end();
|
||||
@@ -18,9 +18,17 @@ test('creating schema', (t) => {
|
||||
});
|
||||
|
||||
test('creating auth token', (t) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/create-admin-token.sql`, (err, stdout, stderr) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/create-admin-token.sql`, (err, stdout, stderr) => {
|
||||
if (err) return t.end(err);
|
||||
t.pass('auth token successfully created');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('add predefined carriers', (t) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/add-predefined-carriers.sql`, (err, stdout, stderr) => {
|
||||
if (err) return t.end(err);
|
||||
t.pass('predefined carriers added');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,908 @@
|
||||
{
|
||||
"id": "sub_J5d3C56ZGMDZFA",
|
||||
"object": "subscription",
|
||||
"application_fee_percent": null,
|
||||
"billing_cycle_anchor": 1615381795,
|
||||
"billing_thresholds": null,
|
||||
"cancel_at": null,
|
||||
"cancel_at_period_end": false,
|
||||
"canceled_at": null,
|
||||
"collection_method": "charge_automatically",
|
||||
"created": 1615381795,
|
||||
"current_period_end": 1618060195,
|
||||
"current_period_start": 1615381795,
|
||||
"customer": "cus_J5coVe5AQ5UR6h",
|
||||
"days_until_due": null,
|
||||
"default_payment_method": null,
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"discount": null,
|
||||
"ended_at": null,
|
||||
"items": {
|
||||
"object": "list",
|
||||
"data": [{
|
||||
"id": "si_J5d3M9tUQgrnPa",
|
||||
"object": "subscription_item",
|
||||
"billing_thresholds": null,
|
||||
"created": 1615381796,
|
||||
"metadata": {
|
||||
"product_sid": "c4403cdb-8e75-4b27-9726-7d8315e3216d"
|
||||
},
|
||||
"plan": {
|
||||
"id": "price_1ISRinAxTxXxh2fmnZmorCm2",
|
||||
"object": "plan",
|
||||
"active": true,
|
||||
"aggregate_usage": null,
|
||||
"amount": null,
|
||||
"amount_decimal": null,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143177,
|
||||
"currency": "usd",
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4au1au9F2Ysa0",
|
||||
"tiers": [{
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 1000,
|
||||
"unit_amount_decimal": "1000",
|
||||
"up_to": 99
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 900,
|
||||
"unit_amount_decimal": "900",
|
||||
"up_to": 250
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 800,
|
||||
"unit_amount_decimal": "800",
|
||||
"up_to": 499
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 700,
|
||||
"unit_amount_decimal": "700",
|
||||
"up_to": 999
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 500,
|
||||
"unit_amount_decimal": "500",
|
||||
"up_to": null
|
||||
}],
|
||||
"tiers_mode": "volume",
|
||||
"transform_usage": null,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"price": {
|
||||
"id": "price_1ISRinAxTxXxh2fmnZmorCm2",
|
||||
"object": "price",
|
||||
"active": true,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143177,
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4au1au9F2Ysa0",
|
||||
"recurring": {
|
||||
"aggregate_usage": null,
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"tiers_mode": "volume",
|
||||
"transform_quantity": null,
|
||||
"type": "recurring",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null
|
||||
},
|
||||
"quantity": 100,
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"tax_rates": []
|
||||
}, {
|
||||
"id": "si_J5d3F3SkebrH4S",
|
||||
"object": "subscription_item",
|
||||
"billing_thresholds": null,
|
||||
"created": 1615381796,
|
||||
"metadata": {
|
||||
"product_sid": "2c815913-5c26-4004-b748-183b459329df"
|
||||
},
|
||||
"plan": {
|
||||
"id": "price_1ISRhKAxTxXxh2fmhsYLgyLM",
|
||||
"object": "plan",
|
||||
"active": true,
|
||||
"aggregate_usage": null,
|
||||
"amount": 100,
|
||||
"amount_decimal": "100",
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1615143086,
|
||||
"currency": "usd",
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4at3poNkI5OSA",
|
||||
"tiers": null,
|
||||
"tiers_mode": null,
|
||||
"transform_usage": null,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"price": {
|
||||
"id": "price_1ISRhKAxTxXxh2fmhsYLgyLM",
|
||||
"object": "price",
|
||||
"active": true,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1615143086,
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4at3poNkI5OSA",
|
||||
"recurring": {
|
||||
"aggregate_usage": null,
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "recurring",
|
||||
"unit_amount": 100,
|
||||
"unit_amount_decimal": "100"
|
||||
},
|
||||
"quantity": 50,
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"tax_rates": []
|
||||
}, {
|
||||
"id": "si_J5d3bcURInlK5Y",
|
||||
"object": "subscription_item",
|
||||
"billing_thresholds": null,
|
||||
"created": 1615381796,
|
||||
"metadata": {
|
||||
"product_sid": "35a9fb10-233d-4eb9-aada-78de5814d680"
|
||||
},
|
||||
"plan": {
|
||||
"id": "price_1ISRgHAxTxXxh2fmUg80e3mw",
|
||||
"object": "plan",
|
||||
"active": true,
|
||||
"aggregate_usage": null,
|
||||
"amount": null,
|
||||
"amount_decimal": null,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143021,
|
||||
"currency": "usd",
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4asDaODFXDjui",
|
||||
"tiers": [{
|
||||
"flat_amount": 0,
|
||||
"flat_amount_decimal": "0",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 10
|
||||
}, {
|
||||
"flat_amount": 500,
|
||||
"flat_amount_decimal": "500",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 30
|
||||
}, {
|
||||
"flat_amount": 1000,
|
||||
"flat_amount_decimal": "1000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 60
|
||||
}, {
|
||||
"flat_amount": 2000,
|
||||
"flat_amount_decimal": "2000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 120
|
||||
}, {
|
||||
"flat_amount": 4000,
|
||||
"flat_amount_decimal": "4000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 300
|
||||
}, {
|
||||
"flat_amount": 5000,
|
||||
"flat_amount_decimal": "5000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": null
|
||||
}],
|
||||
"tiers_mode": "volume",
|
||||
"transform_usage": null,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"price": {
|
||||
"id": "price_1ISRgHAxTxXxh2fmUg80e3mw",
|
||||
"object": "price",
|
||||
"active": true,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143021,
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4asDaODFXDjui",
|
||||
"recurring": {
|
||||
"aggregate_usage": null,
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"tiers_mode": "volume",
|
||||
"transform_quantity": null,
|
||||
"type": "recurring",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null
|
||||
},
|
||||
"quantity": 60,
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"tax_rates": []
|
||||
}],
|
||||
"has_more": false,
|
||||
"total_count": 3,
|
||||
"url": "/v1/subscription_items?subscription=sub_J5d3C56ZGMDZFA"
|
||||
},
|
||||
"latest_invoice": {
|
||||
"id": "in_1ITRnUAxTxXxh2fmmch7bUlr",
|
||||
"object": "invoice",
|
||||
"account_country": "US",
|
||||
"account_name": "drachtio.org",
|
||||
"account_tax_ids": null,
|
||||
"amount_due": 96000,
|
||||
"amount_paid": 96000,
|
||||
"amount_remaining": 0,
|
||||
"application_fee_amount": null,
|
||||
"attempt_count": 1,
|
||||
"attempted": true,
|
||||
"auto_advance": false,
|
||||
"billing_reason": "subscription_create",
|
||||
"charge": "ch_1ITRnUAxTxXxh2fmvtLpMbNr",
|
||||
"collection_method": "charge_automatically",
|
||||
"created": 1615381796,
|
||||
"currency": "usd",
|
||||
"custom_fields": null,
|
||||
"customer": "cus_J5coVe5AQ5UR6h",
|
||||
"customer_address": null,
|
||||
"customer_email": "daveh@drachtio.org",
|
||||
"customer_name": "Dave Horton",
|
||||
"customer_phone": null,
|
||||
"customer_shipping": null,
|
||||
"customer_tax_exempt": "none",
|
||||
"customer_tax_ids": [],
|
||||
"default_payment_method": null,
|
||||
"default_source": null,
|
||||
"default_tax_rates": [],
|
||||
"description": null,
|
||||
"discount": null,
|
||||
"discounts": [],
|
||||
"due_date": null,
|
||||
"ending_balance": 0,
|
||||
"footer": null,
|
||||
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_1GjPVFAxTxXxh2fm/invst_J5d3z2L367YU08uV3ZStblw4QzWzN4b",
|
||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_1GjPVFAxTxXxh2fm/invst_J5d3z2L367YU08uV3ZStblw4QzWzN4b/pdf",
|
||||
"last_finalization_error": null,
|
||||
"lines": {
|
||||
"object": "list",
|
||||
"data": [{
|
||||
"id": "il_1ITRnUAxTxXxh2fmApdPmIJQ",
|
||||
"object": "line_item",
|
||||
"amount": 90000,
|
||||
"currency": "usd",
|
||||
"description": "100 session × concurrent call session (Tier 2 at $9.00 / month)",
|
||||
"discount_amounts": [],
|
||||
"discountable": true,
|
||||
"discounts": [],
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"period": {
|
||||
"end": 1618060195,
|
||||
"start": 1615381795
|
||||
},
|
||||
"plan": {
|
||||
"id": "price_1ISRinAxTxXxh2fmnZmorCm2",
|
||||
"object": "plan",
|
||||
"active": true,
|
||||
"aggregate_usage": null,
|
||||
"amount": null,
|
||||
"amount_decimal": null,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143177,
|
||||
"currency": "usd",
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4au1au9F2Ysa0",
|
||||
"tiers": [{
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 1000,
|
||||
"unit_amount_decimal": "1000",
|
||||
"up_to": 99
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 900,
|
||||
"unit_amount_decimal": "900",
|
||||
"up_to": 250
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 800,
|
||||
"unit_amount_decimal": "800",
|
||||
"up_to": 499
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 700,
|
||||
"unit_amount_decimal": "700",
|
||||
"up_to": 999
|
||||
}, {
|
||||
"flat_amount": null,
|
||||
"flat_amount_decimal": null,
|
||||
"unit_amount": 500,
|
||||
"unit_amount_decimal": "500",
|
||||
"up_to": null
|
||||
}],
|
||||
"tiers_mode": "volume",
|
||||
"transform_usage": null,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"price": {
|
||||
"id": "price_1ISRinAxTxXxh2fmnZmorCm2",
|
||||
"object": "price",
|
||||
"active": true,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143177,
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4au1au9F2Ysa0",
|
||||
"recurring": {
|
||||
"aggregate_usage": null,
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"tiers_mode": "volume",
|
||||
"transform_quantity": null,
|
||||
"type": "recurring",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 100,
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"subscription_item": "si_J5d3M9tUQgrnPa",
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "subscription"
|
||||
}, {
|
||||
"id": "il_1ITRnUAxTxXxh2fmGn4D2s9W",
|
||||
"object": "line_item",
|
||||
"amount": 5000,
|
||||
"currency": "usd",
|
||||
"description": "50 sip device × registered device (at $1.00 / month)",
|
||||
"discount_amounts": [],
|
||||
"discountable": true,
|
||||
"discounts": [],
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"period": {
|
||||
"end": 1618060195,
|
||||
"start": 1615381795
|
||||
},
|
||||
"plan": {
|
||||
"id": "price_1ISRhKAxTxXxh2fmhsYLgyLM",
|
||||
"object": "plan",
|
||||
"active": true,
|
||||
"aggregate_usage": null,
|
||||
"amount": 100,
|
||||
"amount_decimal": "100",
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1615143086,
|
||||
"currency": "usd",
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4at3poNkI5OSA",
|
||||
"tiers": null,
|
||||
"tiers_mode": null,
|
||||
"transform_usage": null,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"price": {
|
||||
"id": "price_1ISRhKAxTxXxh2fmhsYLgyLM",
|
||||
"object": "price",
|
||||
"active": true,
|
||||
"billing_scheme": "per_unit",
|
||||
"created": 1615143086,
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4at3poNkI5OSA",
|
||||
"recurring": {
|
||||
"aggregate_usage": null,
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"tiers_mode": null,
|
||||
"transform_quantity": null,
|
||||
"type": "recurring",
|
||||
"unit_amount": 100,
|
||||
"unit_amount_decimal": "100"
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 50,
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"subscription_item": "si_J5d3F3SkebrH4S",
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "subscription"
|
||||
}, {
|
||||
"id": "il_1ITRnUAxTxXxh2fmmUTvs8b0",
|
||||
"object": "line_item",
|
||||
"amount": 0,
|
||||
"currency": "usd",
|
||||
"description": "60 per min × api rate limit (Tier 3 at $0.00 / month)",
|
||||
"discount_amounts": [],
|
||||
"discountable": true,
|
||||
"discounts": [],
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"period": {
|
||||
"end": 1618060195,
|
||||
"start": 1615381795
|
||||
},
|
||||
"plan": {
|
||||
"id": "price_1ISRgHAxTxXxh2fmUg80e3mw",
|
||||
"object": "plan",
|
||||
"active": true,
|
||||
"aggregate_usage": null,
|
||||
"amount": null,
|
||||
"amount_decimal": null,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143021,
|
||||
"currency": "usd",
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4asDaODFXDjui",
|
||||
"tiers": [{
|
||||
"flat_amount": 0,
|
||||
"flat_amount_decimal": "0",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 10
|
||||
}, {
|
||||
"flat_amount": 500,
|
||||
"flat_amount_decimal": "500",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 30
|
||||
}, {
|
||||
"flat_amount": 1000,
|
||||
"flat_amount_decimal": "1000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 60
|
||||
}, {
|
||||
"flat_amount": 2000,
|
||||
"flat_amount_decimal": "2000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 120
|
||||
}, {
|
||||
"flat_amount": 4000,
|
||||
"flat_amount_decimal": "4000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 300
|
||||
}, {
|
||||
"flat_amount": 5000,
|
||||
"flat_amount_decimal": "5000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": null
|
||||
}],
|
||||
"tiers_mode": "volume",
|
||||
"transform_usage": null,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"price": {
|
||||
"id": "price_1ISRgHAxTxXxh2fmUg80e3mw",
|
||||
"object": "price",
|
||||
"active": true,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143021,
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4asDaODFXDjui",
|
||||
"recurring": {
|
||||
"aggregate_usage": null,
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"tiers_mode": "volume",
|
||||
"transform_quantity": null,
|
||||
"type": "recurring",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 60,
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"subscription_item": "si_J5d3bcURInlK5Y",
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "subscription"
|
||||
}, {
|
||||
"id": "il_1ITRnVAxTxXxh2fm6VDudRAm",
|
||||
"object": "line_item",
|
||||
"amount": 1000,
|
||||
"currency": "usd",
|
||||
"description": "api rate limit (Tier 3 at $10.00 / month)",
|
||||
"discount_amounts": [],
|
||||
"discountable": true,
|
||||
"discounts": [],
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"period": {
|
||||
"end": 1618060195,
|
||||
"start": 1615381795
|
||||
},
|
||||
"plan": {
|
||||
"id": "price_1ISRgHAxTxXxh2fmUg80e3mw",
|
||||
"object": "plan",
|
||||
"active": true,
|
||||
"aggregate_usage": null,
|
||||
"amount": null,
|
||||
"amount_decimal": null,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143021,
|
||||
"currency": "usd",
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4asDaODFXDjui",
|
||||
"tiers": [{
|
||||
"flat_amount": 0,
|
||||
"flat_amount_decimal": "0",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 10
|
||||
}, {
|
||||
"flat_amount": 500,
|
||||
"flat_amount_decimal": "500",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 30
|
||||
}, {
|
||||
"flat_amount": 1000,
|
||||
"flat_amount_decimal": "1000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 60
|
||||
}, {
|
||||
"flat_amount": 2000,
|
||||
"flat_amount_decimal": "2000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 120
|
||||
}, {
|
||||
"flat_amount": 4000,
|
||||
"flat_amount_decimal": "4000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": 300
|
||||
}, {
|
||||
"flat_amount": 5000,
|
||||
"flat_amount_decimal": "5000",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null,
|
||||
"up_to": null
|
||||
}],
|
||||
"tiers_mode": "volume",
|
||||
"transform_usage": null,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"price": {
|
||||
"id": "price_1ISRgHAxTxXxh2fmUg80e3mw",
|
||||
"object": "price",
|
||||
"active": true,
|
||||
"billing_scheme": "tiered",
|
||||
"created": 1615143021,
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"lookup_key": null,
|
||||
"metadata": {},
|
||||
"nickname": null,
|
||||
"product": "prod_J4asDaODFXDjui",
|
||||
"recurring": {
|
||||
"aggregate_usage": null,
|
||||
"interval": "month",
|
||||
"interval_count": 1,
|
||||
"trial_period_days": null,
|
||||
"usage_type": "licensed"
|
||||
},
|
||||
"tiers_mode": "volume",
|
||||
"transform_quantity": null,
|
||||
"type": "recurring",
|
||||
"unit_amount": null,
|
||||
"unit_amount_decimal": null
|
||||
},
|
||||
"proration": false,
|
||||
"quantity": 0,
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"subscription_item": "si_J5d3bcURInlK5Y",
|
||||
"tax_amounts": [],
|
||||
"tax_rates": [],
|
||||
"type": "subscription"
|
||||
}],
|
||||
"has_more": false,
|
||||
"total_count": 4,
|
||||
"url": "/v1/invoices/in_1ITRnUAxTxXxh2fmmch7bUlr/lines"
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_payment_attempt": null,
|
||||
"number": "0A22219A-0001",
|
||||
"on_behalf_of": null,
|
||||
"paid": true,
|
||||
"payment_intent": {
|
||||
"id": "pi_1ITRnUAxTxXxh2fmmyjspFCb",
|
||||
"object": "payment_intent",
|
||||
"amount": 96000,
|
||||
"amount_capturable": 0,
|
||||
"amount_received": 96000,
|
||||
"application": null,
|
||||
"application_fee_amount": null,
|
||||
"canceled_at": null,
|
||||
"cancellation_reason": null,
|
||||
"capture_method": "automatic",
|
||||
"charges": {
|
||||
"object": "list",
|
||||
"data": [{
|
||||
"id": "ch_1ITRnUAxTxXxh2fmvtLpMbNr",
|
||||
"object": "charge",
|
||||
"amount": 96000,
|
||||
"amount_captured": 96000,
|
||||
"amount_refunded": 0,
|
||||
"application": null,
|
||||
"application_fee": null,
|
||||
"application_fee_amount": null,
|
||||
"balance_transaction": "txn_1ITRnVAxTxXxh2fmTGIuTAaB",
|
||||
"billing_details": {
|
||||
"address": {
|
||||
"city": null,
|
||||
"country": null,
|
||||
"line1": null,
|
||||
"line2": null,
|
||||
"postal_code": null,
|
||||
"state": null
|
||||
},
|
||||
"email": null,
|
||||
"name": null,
|
||||
"phone": null
|
||||
},
|
||||
"calculated_statement_descriptor": "DRACHTIO COMM SVCS LLC",
|
||||
"captured": true,
|
||||
"created": 1615381796,
|
||||
"currency": "usd",
|
||||
"customer": "cus_J5coVe5AQ5UR6h",
|
||||
"description": "Subscription creation",
|
||||
"destination": null,
|
||||
"dispute": null,
|
||||
"disputed": false,
|
||||
"failure_code": null,
|
||||
"failure_message": null,
|
||||
"fraud_details": {},
|
||||
"invoice": "in_1ITRnUAxTxXxh2fmmch7bUlr",
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"on_behalf_of": null,
|
||||
"order": null,
|
||||
"outcome": {
|
||||
"network_status": "approved_by_network",
|
||||
"reason": null,
|
||||
"risk_level": "normal",
|
||||
"risk_score": 16,
|
||||
"seller_message": "Payment complete.",
|
||||
"type": "authorized"
|
||||
},
|
||||
"paid": true,
|
||||
"payment_intent": "pi_1ITRnUAxTxXxh2fmmyjspFCb",
|
||||
"payment_method": "card_1ITRZIAxTxXxh2fmgZWoCsPx",
|
||||
"payment_method_details": {
|
||||
"card": {
|
||||
"brand": "visa",
|
||||
"checks": {
|
||||
"address_line1_check": null,
|
||||
"address_postal_code_check": null,
|
||||
"cvc_check": null
|
||||
},
|
||||
"country": "US",
|
||||
"exp_month": 9,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "KDQxr00TBv7zH8Sg",
|
||||
"funding": "credit",
|
||||
"installments": null,
|
||||
"last4": "4242",
|
||||
"network": "visa",
|
||||
"three_d_secure": null,
|
||||
"wallet": null
|
||||
},
|
||||
"type": "card"
|
||||
},
|
||||
"receipt_email": null,
|
||||
"receipt_number": null,
|
||||
"receipt_url": "https://pay.stripe.com/receipts/acct_1GjPVFAxTxXxh2fm/ch_1ITRnUAxTxXxh2fmvtLpMbNr/rcpt_J5d3fiWQsaYt9Pmkw0SEV34LbxYJyGl",
|
||||
"refunded": false,
|
||||
"refunds": {
|
||||
"object": "list",
|
||||
"data": [],
|
||||
"has_more": false,
|
||||
"total_count": 0,
|
||||
"url": "/v1/charges/ch_1ITRnUAxTxXxh2fmvtLpMbNr/refunds"
|
||||
},
|
||||
"review": null,
|
||||
"shipping": null,
|
||||
"source": {
|
||||
"id": "card_1ITRZIAxTxXxh2fmgZWoCsPx",
|
||||
"object": "card",
|
||||
"address_city": null,
|
||||
"address_country": null,
|
||||
"address_line1": null,
|
||||
"address_line1_check": null,
|
||||
"address_line2": null,
|
||||
"address_state": null,
|
||||
"address_zip": null,
|
||||
"address_zip_check": null,
|
||||
"brand": "Visa",
|
||||
"country": "US",
|
||||
"customer": "cus_J5coVe5AQ5UR6h",
|
||||
"cvc_check": null,
|
||||
"dynamic_last4": null,
|
||||
"exp_month": 9,
|
||||
"exp_year": 2024,
|
||||
"fingerprint": "KDQxr00TBv7zH8Sg",
|
||||
"funding": "credit",
|
||||
"last4": "4242",
|
||||
"metadata": {},
|
||||
"name": null,
|
||||
"tokenization_method": null
|
||||
},
|
||||
"source_transfer": null,
|
||||
"statement_descriptor": "Drachtio Comm Svcs LLC",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
}],
|
||||
"has_more": false,
|
||||
"total_count": 1,
|
||||
"url": "/v1/charges?payment_intent=pi_1ITRnUAxTxXxh2fmmyjspFCb"
|
||||
},
|
||||
"client_secret": "pi_1ITRnUAxTxXxh2fmmyjspFCb_secret_6FB5iXrTQ3w1f7ckUWeycmYoc",
|
||||
"confirmation_method": "automatic",
|
||||
"created": 1615381796,
|
||||
"currency": "usd",
|
||||
"customer": "cus_J5coVe5AQ5UR6h",
|
||||
"description": "Subscription creation",
|
||||
"invoice": "in_1ITRnUAxTxXxh2fmmch7bUlr",
|
||||
"last_payment_error": null,
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_action": null,
|
||||
"on_behalf_of": null,
|
||||
"payment_method": null,
|
||||
"payment_method_options": {
|
||||
"card": {
|
||||
"installments": null,
|
||||
"network": null,
|
||||
"request_three_d_secure": "automatic"
|
||||
}
|
||||
},
|
||||
"payment_method_types": ["card"],
|
||||
"receipt_email": null,
|
||||
"review": null,
|
||||
"setup_future_usage": "off_session",
|
||||
"shipping": null,
|
||||
"source": "card_1ITRZIAxTxXxh2fmgZWoCsPx",
|
||||
"statement_descriptor": "Drachtio Comm Svcs LLC",
|
||||
"statement_descriptor_suffix": null,
|
||||
"status": "succeeded",
|
||||
"transfer_data": null,
|
||||
"transfer_group": null
|
||||
},
|
||||
"payment_settings": {
|
||||
"payment_method_options": null,
|
||||
"payment_method_types": null
|
||||
},
|
||||
"period_end": 1615381795,
|
||||
"period_start": 1615381795,
|
||||
"post_payment_credit_notes_amount": 0,
|
||||
"pre_payment_credit_notes_amount": 0,
|
||||
"receipt_number": null,
|
||||
"starting_balance": 0,
|
||||
"statement_descriptor": null,
|
||||
"status": "paid",
|
||||
"status_transitions": {
|
||||
"finalized_at": 1615381795,
|
||||
"marked_uncollectible_at": null,
|
||||
"paid_at": 1615381795,
|
||||
"voided_at": null
|
||||
},
|
||||
"subscription": "sub_J5d3C56ZGMDZFA",
|
||||
"subtotal": 96000,
|
||||
"tax": null,
|
||||
"tax_percent": null,
|
||||
"total": 96000,
|
||||
"total_discount_amounts": [],
|
||||
"total_tax_amounts": [],
|
||||
"transfer_data": null,
|
||||
"webhooks_delivered_at": null
|
||||
},
|
||||
"livemode": false,
|
||||
"metadata": {},
|
||||
"next_pending_invoice_item_invoice": null,
|
||||
"pause_collection": null,
|
||||
"pending_invoice_item_interval": null,
|
||||
"pending_setup_intent": null,
|
||||
"pending_update": null,
|
||||
"plan": null,
|
||||
"quantity": null,
|
||||
"schedule": null,
|
||||
"start_date": 1615381795,
|
||||
"status": "active",
|
||||
"tax_percent": null,
|
||||
"transfer_data": null,
|
||||
"trial_end": null,
|
||||
"trial_start": null
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"type": "service_account",
|
||||
"project_id": "foobar",
|
||||
"private_key_id": "17a374747574b98284367f1fd2197401c8",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\nkdkdkdkdkdkdkdkdkdkdkdkdkddjdjdjdjjEVtS\n8cZeK4w128sbogusVmVARsj5/\nw6Ou08xBX+e1rsKkiaGnzuKhuZczwWMuAwfnBtNQhw2ZUJCDkQfk7tT1100CAi4h\nLAWX/sufHNi9h2z7yCAeRDGqmIM89lRguycKexy8MM4NZRxAIrLs7LIGhTczMFUC\n6TxaFWlXAgMBAAECggEAMHFgrcUn0ATiQcxkeplWom9Ki7gTuhO1wQeOqRtTIZ+d\nCQOigARklx0YTQlsqoG/acLSfeAcfyLWEklULaqJbeghl9KPE4FwPX13VPlZHCMj\nyXUycrjlxw4tHpcy9egDjj5c4XSiUQ/3nNrn0q0EMxFleM3Mhhj1408HifBLH3KY\nKCA+fq+tqmS/daCUgs7jEZCo4z8qFmz0npHUcQ5P7SrsYf00Di9RH8m1Tc9aXU6H\nkMSCfM8/UpPvt+lOQktWjDKP2APowuPyfl4RgX+9jNUm8h2y9jYKeyTelQC0CAUM\nW4ZB6tiDbXOVeP9miXgVwv3WUh4Mrwufar5e0DeqvQKBgQDKZ6Vk7CEVfGQgBoUU\neWo203Tmc2W5qnXRh0pa1VwUtgte+D7l8Lwfc0gCfjbkk7EXKQrQ19jtTwZAzvHz\nsgziQ8H1IDLQBBtknWxuOJbNuronZE6NMWNp+ULu2Y4XN6MnD75sPgtxFMPUUuWI\n5CdXPKweyC+BKC99ukIposGWcwKBgQDGVCYik8nh3fX+BkC1xrFGZ4z3jIqZs8bk\nLFDCiDGwAJTXee2/L5wUJIv4UGoO822OOg+8ftMCtDmdrIkOjsXUPrhbnrGyqZgM\nEC4T3CNDiQXHqxw4tjg4eM5Vcwi6KkuhSAcClz/aaZ1T5jk0QGdF7UpqKcbsURx8\n5hGcscVEjQKBgBXPcV0crLv5+XgR+8knBDEAPDqQ+Mc2/Rck8vgywYdhznvfWDfC\n5yKkc4ABRbz/xTdvrsCuYavAtjXJlvzhlM3U61OUsqUDrEf9Rq/h3S4yDtkrz+Mb\nDVFgELxYKR2LW0NcSPK1BNqcmDWK8Tz9CNg3q3xtqeDLCcMMjRCbfyzNAoGAWlLC\nl2bFP6eNu6XvXJnj7JOGYMtR6BQ3FX2VPjM2pdht8QBnpXWyWH4YfPtqgeqdT3Pj\n7M25nfakcsm8FbQyJqp13cwVU6/nPj80LPlJ2h0SU8/6510dl6J1Hfdo1xgiH46l\nGqn1e6wz6ZzlGoXmQrOB+32RSdja54sEJF/V3pUCgYAoGFZAGVBuWqipbBLdQqNl\n1ppdEliEBhDPq4cZAnNx1lvnmFn8D5bqi+rB8bkqvGcR921AMLDadasHX4BJAJw+\nQoSx1wqy9Zsiaz9EzWUxHtnKFOzMVeVz/RJqH8hNu4xb6Lv50BgTztoO+bGIOAJ/\nVaY6N4gOkiAihhQzsSnLvQ==\n-----END PRIVATE KEY-----\n",
|
||||
"client_email": "cloud-speech-testing@foobar.iam.gserviceaccount.com",
|
||||
"client_id": "109945388890626427918",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/cloud-speech-testing%40foobarg.iam.gserviceaccount.com"
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
const test = require('blue-tape');
|
||||
//const test = require('tape').test ;
|
||||
const test = require('tape');
|
||||
const exec = require('child_process').exec ;
|
||||
|
||||
test('starting docker network..', (t) => {
|
||||
t.plan(1);
|
||||
exec(`docker-compose -f ${__dirname}/docker-compose-testbed.yaml up -d`, (err, stdout, stderr) => {
|
||||
setTimeout(() => {
|
||||
t.pass('docker started');
|
||||
t.end(err);
|
||||
}, 15000);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape');
|
||||
const test = require('tape');
|
||||
const exec = require('child_process').exec ;
|
||||
|
||||
test('stopping docker network..', (t) => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
require('./docker_start');
|
||||
require('./create-test-db');
|
||||
require('./sip-gateways');
|
||||
require('./smpp-gateways');
|
||||
require('./service-providers');
|
||||
require('./voip-carriers');
|
||||
require('./accounts');
|
||||
@@ -9,4 +10,7 @@ require('./applications');
|
||||
require('./auth');
|
||||
require('./sbcs');
|
||||
require('./ms-teams');
|
||||
require('./speech-credentials');
|
||||
require('./recent-calls');
|
||||
require('./webapp_tests');
|
||||
require('./docker_stop');
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
const bent = require('bent');
|
||||
const getJSON = bent('GET', 200);
|
||||
const request = require('request');
|
||||
require('request-debug')(request);
|
||||
|
||||
const test = async() => {
|
||||
request.get('https://api.github.com/user', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${process.env.GH_CODE}`,
|
||||
Accept: 'application/json',
|
||||
'User-Agent': 'jambonz.us'
|
||||
}
|
||||
}, (err, response, body) => {
|
||||
if (err) console.log(error);
|
||||
else console.log(body);
|
||||
})
|
||||
};
|
||||
|
||||
test();
|
||||
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Test oauth signup</title>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a href="https://github.com/login/oauth/authorize?client_id=a075a5889264b8fbc831&state=foobar&allow_signup=false">Github</a>
|
||||
</body>
|
||||
</html>
|
||||
+11
-48
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
@@ -19,19 +19,6 @@ test('phone number tests', async(t) => {
|
||||
/* add service provider, phone number, and voip carrier */
|
||||
const voip_carrier_sid = await createVoipCarrier(request);
|
||||
|
||||
/* provision phone number - failure case: voip_carrier_sid is required */
|
||||
result = await request.post('/PhoneNumbers', {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
number: '15083084809'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 400 && result.body.msg === 'voip_carrier_sid is required',
|
||||
'voip_carrier_sid is required when provisioning a phone number');
|
||||
|
||||
/* provision phone number - failure case: digits only */
|
||||
result = await request.post('/PhoneNumbers', {
|
||||
resolveWithFullResponse: true,
|
||||
@@ -43,37 +30,9 @@ test('phone number tests', async(t) => {
|
||||
voip_carrier_sid
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 400 && result.body.msg === 'phone number must only include digits',
|
||||
'service_provider_sid is required when provisioning a phone number');
|
||||
|
||||
/* provision phone number - failure case: insufficient digits */
|
||||
result = await request.post('/PhoneNumbers', {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
number: '1508308',
|
||||
voip_carrier_sid
|
||||
}
|
||||
});
|
||||
//console.log(`result: ${JSON.stringify(result)}`);
|
||||
t.ok(result.statusCode === 400 && result.body.msg === 'invalid phone number: insufficient digits',
|
||||
'invalid phone number: insufficient digits');
|
||||
|
||||
/* provision phone number - failure case: invalid US number */
|
||||
result = await request.post('/PhoneNumbers', {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
number: '150830848091',
|
||||
voip_carrier_sid
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 400 && result.body.msg === 'invalid US phone number',
|
||||
'invalid US phone number');
|
||||
t.ok(result.statusCode === 201,
|
||||
'accepts E.164 format');
|
||||
const sid = result.body.sid;
|
||||
|
||||
/* add a phone number */
|
||||
result = await request.post('/PhoneNumbers', {
|
||||
@@ -86,17 +45,17 @@ test('phone number tests', async(t) => {
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created phone number');
|
||||
const sid = result.body.sid;
|
||||
const sid2 = result.body.sid;
|
||||
|
||||
/* query all phone numbers */
|
||||
result = await request.get('/PhoneNumbers', {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.length === 1 , 'successfully queried all phone numbers');
|
||||
t.ok(result.length === 2, 'successfully queried all phone numbers');
|
||||
|
||||
/* query one phone numbers */
|
||||
result = await request.get(`/PhoneNumbers/${sid}`, {
|
||||
result = await request.get(`/PhoneNumbers/${sid2}`, {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
@@ -108,6 +67,10 @@ test('phone number tests', async(t) => {
|
||||
resolveWithFullResponse: true,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully deleted phone number');
|
||||
result = await request.delete(`/PhoneNumbers/${sid2}`, {
|
||||
auth: authAdmin,
|
||||
resolveWithFullResponse: true,
|
||||
});
|
||||
|
||||
await deleteObjectBySid(request, '/VoipCarriers', voip_carrier_sid);
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
const test = require('tape') ;
|
||||
const fs = require('fs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
baseUrl: 'http://127.0.0.1:3000/v1'
|
||||
});
|
||||
const consoleLogger = {debug: console.log, info: console.log, error: console.error}
|
||||
const {writeCdrs} = require('@jambonz/time-series')(consoleLogger, '127.0.0.1');
|
||||
const {createServiceProvider, createAccount, deleteObjectBySid} = require('./utils');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
test('recent calls tests', async(t) => {
|
||||
const app = require('../app');
|
||||
const jsonKey = fs.readFileSync(`${__dirname}/data/test.json`, {encoding: 'utf8'});
|
||||
let sid;
|
||||
try {
|
||||
let result;
|
||||
const service_provider_sid = await createServiceProvider(request);
|
||||
const account_sid = await createAccount(request, service_provider_sid);
|
||||
|
||||
const token = jwt.sign({
|
||||
account_sid
|
||||
}, process.env.JWT_SECRET, { expiresIn: '1h' });
|
||||
const authUser = {bearer: token};
|
||||
|
||||
/* write sample cdr data */
|
||||
const points = 500;
|
||||
const data = [];
|
||||
const start = new Date(Date.now() - (30 * 24 * 60 * 60 * 1000));
|
||||
const now = new Date();
|
||||
const increment = (now.getTime() - start.getTime()) / points;
|
||||
for (let i =0 ; i < 500; i++) {
|
||||
const attempted_at = new Date(start.getTime() + (i * increment));
|
||||
const failed = 0 === i % 5;
|
||||
data.push({
|
||||
call_sid: 'b6f48929-8e86-4d62-ae3b-64fb574d91f6',
|
||||
from: '15083084809',
|
||||
to: '18882349999',
|
||||
answered: !failed,
|
||||
sip_callid: '685cd008-0a66-4974-b37a-bdd6d9a3c4aa@192.168.1.100',
|
||||
sip_status: 200,
|
||||
duration: failed ? 0 : 45,
|
||||
attempted_at: attempted_at.getTime(),
|
||||
answered_at: attempted_at.getTime() + 3000,
|
||||
terminated_at: attempted_at.getTime() + 45000,
|
||||
termination_reason: 'caller hungup',
|
||||
host: "192.168.1.100",
|
||||
remote_host: '3.55.24.34',
|
||||
account_sid: account_sid,
|
||||
direction: 0 === i % 2 ? 'inbound' : 'outbound',
|
||||
trunk: 0 === i % 2 ? 'twilio' : 'user'
|
||||
});
|
||||
}
|
||||
|
||||
await writeCdrs(data);
|
||||
t.pass('seeded cdr data');
|
||||
|
||||
/* query last 7 days */
|
||||
result = await request.get(`/Accounts/${account_sid}/RecentCalls?page=1&count=25`, {
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
|
||||
await deleteObjectBySid(request, '/Accounts', account_sid);
|
||||
await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid);
|
||||
|
||||
//t.end();
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
t.end(err);
|
||||
}
|
||||
});
|
||||
|
||||
+4
-23
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
@@ -17,18 +17,6 @@ test('sbc_addresses tests', async(t) => {
|
||||
let result;
|
||||
const service_provider_sid = await createServiceProvider(request);
|
||||
|
||||
/* add a community sbc */
|
||||
result = await request.post('/Sbcs', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
ipv4: '192.168.1.1'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created community sbc ');
|
||||
const sid1 = result.body.sid;
|
||||
|
||||
/* add a service provider sbc */
|
||||
result = await request.post('/Sbcs', {
|
||||
resolveWithFullResponse: true,
|
||||
@@ -40,24 +28,17 @@ test('sbc_addresses tests', async(t) => {
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created service provider sbc ');
|
||||
const sid2 = result.body.sid;
|
||||
|
||||
result = await request.get('/Sbcs', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authAdmin,
|
||||
json: true
|
||||
});
|
||||
t.ok(result.body.length === 1 && result.body[0].ipv4 === '192.168.1.1', 'successfully retrieved community sbc');
|
||||
const sid = result.body.sid;
|
||||
|
||||
result = await request.get(`/Sbcs?service_provider_sid=${service_provider_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authAdmin,
|
||||
json: true
|
||||
});
|
||||
//console.log(result.body)
|
||||
t.ok(result.body.length === 1 && result.body[0].ipv4 === '192.168.1.4', 'successfully retrieved service provider sbc');
|
||||
|
||||
await deleteObjectBySid(request, '/Sbcs', sid1);
|
||||
await deleteObjectBySid(request, '/Sbcs', sid2);
|
||||
await deleteObjectBySid(request, '/Sbcs', sid);
|
||||
await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid);
|
||||
|
||||
//t.end();
|
||||
|
||||
@@ -45,15 +45,23 @@ const createSchema = () => {
|
||||
const seedDb = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log('seeding database..')
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/create-default-service-provider-and-account.sql`, (err) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/seed-integration-test.sql`, (err) => {
|
||||
if (err) return reject(err);
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/create-admin-token.sql`, (err) => {
|
||||
if (err) return reject(err);
|
||||
exec(`node ${__dirname}/../db/reset_admin_password.js`, (err) => {
|
||||
if (err) return reject(err);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const resetAdminPassword = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
/* not needed when running jambonz hosting mode */
|
||||
if (process.env.STRIPE_API_KEY) return resolve();
|
||||
console.log('creating admin user..')
|
||||
exec(`node ${__dirname}/../db/reset_admin_password.js`, (err, stdout, stderr) => {
|
||||
console.log(stdout);
|
||||
console.log(stderr);
|
||||
if (err) return reject(err);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -72,6 +80,7 @@ startDocker()
|
||||
.then(createDb)
|
||||
.then(createSchema)
|
||||
.then(seedDb)
|
||||
.then(resetAdminPassword)
|
||||
.then(() => {
|
||||
console.log('ready for testing!');
|
||||
require('..');
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
baseUrl: 'http://127.0.0.1:3000/v1'
|
||||
});
|
||||
const {deleteObjectBySid} = require('./utils');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
@@ -94,7 +95,6 @@ test('service provider tests', async(t) => {
|
||||
});
|
||||
t.ok(result.name === 'johndoe' && result.root_domain === 'example.com', 'successfully retrieved service provider by sid');
|
||||
|
||||
|
||||
/* update service providers */
|
||||
result = await request.put(`/ServiceProviders/${sid}`, {
|
||||
auth: authAdmin,
|
||||
@@ -106,6 +106,16 @@ test('service provider tests', async(t) => {
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully updated service provider');
|
||||
|
||||
/* add a predefined carrier for a service provider */
|
||||
result = await request.post(`/ServiceProviders/${sid}/PredefinedCarriers/7d509a18-bbff-4c5d-b21e-b99bf8f8c49a`, {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
resolveWithFullResponse: true,
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully added predefined carrier to service provider');
|
||||
|
||||
await deleteObjectBySid(request, '/VoipCarriers', result.body.sid);
|
||||
|
||||
/* delete service providers */
|
||||
result = await request.delete(`/ServiceProviders/${sid}`, {
|
||||
auth: authAdmin,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
@@ -25,6 +25,7 @@ test('sip gateway tests', async(t) => {
|
||||
body: {
|
||||
voip_carrier_sid,
|
||||
ipv4: '192.168.1.1',
|
||||
netmask: 32,
|
||||
inbound: true,
|
||||
outbound: true
|
||||
}
|
||||
@@ -34,6 +35,7 @@ test('sip gateway tests', async(t) => {
|
||||
|
||||
/* query all sip gateways */
|
||||
result = await request.get('/SipGateways', {
|
||||
qs: {voip_carrier_sid},
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
@@ -55,12 +57,13 @@ test('sip gateway tests', async(t) => {
|
||||
resolveWithFullResponse: true,
|
||||
body: {
|
||||
port: 5061,
|
||||
netmask:24,
|
||||
outbound: false
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully updated voip carrier');
|
||||
|
||||
/* delete sip gatewas */
|
||||
/* delete sip gateways */
|
||||
result = await request.delete(`/SipGateways/${sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
baseUrl: 'http://127.0.0.1:3000/v1'
|
||||
});
|
||||
const {createVoipCarrier, deleteObjectBySid} = require('./utils');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
test('smpp gateway tests', async(t) => {
|
||||
const app = require('../app');
|
||||
let sid;
|
||||
try {
|
||||
let result;
|
||||
const voip_carrier_sid = await createVoipCarrier(request);
|
||||
|
||||
/* add a smpp gateway */
|
||||
result = await request.post('/SmppGateways', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
voip_carrier_sid,
|
||||
ipv4: '192.168.1.1',
|
||||
netmask: 32,
|
||||
inbound: true,
|
||||
outbound: true,
|
||||
use_tls: true,
|
||||
is_primary: true
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created smpp gateway ');
|
||||
const sid = result.body.sid;
|
||||
|
||||
/* query all smpp gateways */
|
||||
console.log('querying with ')
|
||||
result = await request.get('/SmppGateways', {
|
||||
qs: {voip_carrier_sid},
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.length === 1 , 'successfully queried all smpp gateways');
|
||||
|
||||
/* query one smpp gateway */
|
||||
result = await request.get(`/SmppGateways/${sid}`, {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
//console.log(`result: ${JSON.stringify(result)}`);
|
||||
t.ok(result.ipv4 === '192.168.1.1' , 'successfully retrieved voip carrier by sid');
|
||||
|
||||
|
||||
/* update smpp gateway */
|
||||
result = await request.put(`/SmppGateways/${sid}`, {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
resolveWithFullResponse: true,
|
||||
body: {
|
||||
port: 5061,
|
||||
netmask:24,
|
||||
outbound: false
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully updated voip carrier');
|
||||
|
||||
/* delete smpp gatewas */
|
||||
result = await request.delete(`/SmppGateways/${sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
json: true,
|
||||
auth: authAdmin
|
||||
});
|
||||
//console.log(`result: ${JSON.stringify(result)}`);
|
||||
t.ok(result.statusCode === 204, 'successfully deleted smpp gateway');
|
||||
|
||||
await deleteObjectBySid(request, '/VoipCarriers', voip_carrier_sid);
|
||||
|
||||
//t.end();
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
t.end(err);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
const test = require('tape') ;
|
||||
const fs = require('fs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
baseUrl: 'http://127.0.0.1:3000/v1'
|
||||
});
|
||||
const {createServiceProvider, createAccount, deleteObjectBySid} = require('./utils');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
test('speech credentials tests', async(t) => {
|
||||
const app = require('../app');
|
||||
const jsonKey = fs.readFileSync(`${__dirname}/data/test.json`, {encoding: 'utf8'});
|
||||
let sid;
|
||||
try {
|
||||
let result;
|
||||
const service_provider_sid = await createServiceProvider(request);
|
||||
const account_sid = await createAccount(request, service_provider_sid);
|
||||
|
||||
/* add a speech credential to a service provider */
|
||||
result = await request.post(`/ServiceProviders/${service_provider_sid}/SpeechCredentials`, {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
vendor: 'google',
|
||||
service_key: jsonKey
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully added a speech credential to service provider');
|
||||
//console.log(result.body)
|
||||
const speech_credential_sid = result.body.sid;
|
||||
|
||||
/* query speech credentials for a service provider */
|
||||
result = await request.get(`/ServiceProviders/${service_provider_sid}/SpeechCredentials`, {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
//console.log(result.body)
|
||||
t.ok(result.statusCode === 200, 'successfully queried speech credential to service provider');
|
||||
|
||||
await deleteObjectBySid(request, `/ServiceProviders/${service_provider_sid}/SpeechCredentials`, speech_credential_sid);
|
||||
|
||||
const token = jwt.sign({
|
||||
account_sid
|
||||
}, process.env.JWT_SECRET, { expiresIn: '1h' });
|
||||
const authUser = {bearer: token};
|
||||
|
||||
/* add a credential */
|
||||
result = await request.post(`/Accounts/${account_sid}/SpeechCredentials`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
vendor: 'google',
|
||||
service_key: jsonKey
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully added speech credential');
|
||||
const sid1 = result.body.sid;
|
||||
|
||||
/* return 403 if invalid account is used */
|
||||
result = await request.post(`/Accounts/foobarbaz/SpeechCredentials`, {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
vendor: 'google',
|
||||
service_key: jsonKey
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 403, 'returns 403 Forbidden if Account does not match jwt');
|
||||
|
||||
/* query one credential */
|
||||
result = await request.get(`/Accounts/${account_sid}/SpeechCredentials/${sid1}`, {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.vendor === 'google' , 'successfully retrieved speech credential by sid');
|
||||
|
||||
/* query all credentials */
|
||||
result = await request.get(`/Accounts/${account_sid}/SpeechCredentials`, {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result[0].vendor === 'google' && result.length === 1, 'successfully retrieved all speech credentials');
|
||||
|
||||
|
||||
/* return 404 when deleting unknown credentials */
|
||||
result = await request.delete(`/Accounts/${account_sid}/SpeechCredentials/foobarbaz`, {
|
||||
auth: authUser,
|
||||
resolveWithFullResponse: true,
|
||||
simple: false
|
||||
});
|
||||
t.ok(result.statusCode === 404, 'return 404 when attempting to delete unknown credential');
|
||||
|
||||
/* delete the credential */
|
||||
result = await request.delete(`/Accounts/${account_sid}/SpeechCredentials/${sid1}`, {
|
||||
auth: authUser,
|
||||
resolveWithFullResponse: true,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully deleted speech credential');
|
||||
|
||||
|
||||
await deleteObjectBySid(request, '/Accounts', account_sid);
|
||||
await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid);
|
||||
|
||||
//t.end();
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
t.end(err);
|
||||
}
|
||||
});
|
||||
|
||||
+17
-1
@@ -1,3 +1,5 @@
|
||||
const bytesToUuid = require("uuid/lib/bytesToUuid");
|
||||
const uuid = require('uuid').v4;
|
||||
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
@@ -42,7 +44,8 @@ async function createAccount(request, service_provider_sid, name = 'daveh') {
|
||||
json: true,
|
||||
body: {
|
||||
name,
|
||||
service_provider_sid
|
||||
service_provider_sid,
|
||||
webhook_secret: 'foobar'
|
||||
}
|
||||
});
|
||||
return result.sid;
|
||||
@@ -66,6 +69,18 @@ async function createApplication(request, account_sid, name = 'daveh') {
|
||||
return result.sid;
|
||||
}
|
||||
|
||||
async function createApiKey(request, account_sid) {
|
||||
const result = await request.post('/ApiKeys', {
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
account_sid,
|
||||
token: uuid()
|
||||
}
|
||||
});
|
||||
return result.sid;
|
||||
}
|
||||
|
||||
async function deleteObjectBySid(request, path, sid) {
|
||||
const result = await request.delete(`${path}/${sid}`, {
|
||||
auth: authAdmin,
|
||||
@@ -79,5 +94,6 @@ module.exports = {
|
||||
createPhoneNumber,
|
||||
createAccount,
|
||||
createApplication,
|
||||
createApiKey,
|
||||
deleteObjectBySid
|
||||
};
|
||||
|
||||
+26
-2
@@ -1,4 +1,4 @@
|
||||
const test = require('blue-tape').test ;
|
||||
const test = require('tape') ;
|
||||
const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de';
|
||||
const authAdmin = {bearer: ADMIN_TOKEN};
|
||||
const request = require('request-promise-native').defaults({
|
||||
@@ -105,7 +105,7 @@ test('voip carrier tests', async(t) => {
|
||||
//console.log(`result: ${JSON.stringify(result)}`);
|
||||
t.ok(result.statusCode === 204, 'successfully deleted voip carrier');
|
||||
|
||||
/* create voipd carrier that is a customer PBX */
|
||||
/* create voip carrier that is a customer PBX */
|
||||
const service_provider_sid = await createServiceProvider(request);
|
||||
const account_sid = await createAccount(request, service_provider_sid);
|
||||
const account_sid2 = await createAccount(request, service_provider_sid, 'another');
|
||||
@@ -189,6 +189,30 @@ test('voip carrier tests', async(t) => {
|
||||
sid = result.body.sid;
|
||||
await deleteObjectBySid(request, '/VoipCarriers', sid);
|
||||
|
||||
/* add a voip carrier for a service provider */
|
||||
result = await request.post(`/ServiceProviders/${service_provider_sid}/VoipCarriers`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
body: {
|
||||
name: 'twilio',
|
||||
e164_leading_plus: true
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created voip carrier for a service provider');
|
||||
sid = result.body.sid;
|
||||
|
||||
/* list voip carriers for a service provider */
|
||||
result = await request.get(`/ServiceProviders/${service_provider_sid}/VoipCarriers`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authAdmin,
|
||||
json: true,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200, 'successfully retrieved voip carrier for a service provider');
|
||||
sid = result.body[0].voip_carrier_sid;
|
||||
|
||||
await deleteObjectBySid(request, '/VoipCarriers', sid);
|
||||
await deleteObjectBySid(request, '/Applications', application_sid);
|
||||
await deleteObjectBySid(request, '/Accounts', account_sid);
|
||||
await deleteObjectBySid(request, '/Accounts', account_sid2);
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
const test = require('tape') ;
|
||||
const exec = require('child_process').exec ;
|
||||
const Account = require('../lib/models/account');
|
||||
const request = require('request-promise-native').defaults({
|
||||
baseUrl: 'http://127.0.0.1:3000/v1'
|
||||
});
|
||||
const theOneAndOnlyServiceProviderSid = '2708b1b3-2736-40ea-b502-c53d8396247f';
|
||||
const {createApiKey} = require('./utils');
|
||||
|
||||
const sleepFor = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
test('re-creating schema', (t) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/jambones-sql.sql`, (err, stdout, stderr) => {
|
||||
if (err) return t.end(err);
|
||||
t.pass('schema successfully created');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('seeding database for webapp tests', (t) => {
|
||||
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${__dirname}/../db/webapp-tests.sql`, (err, stdout, stderr) => {
|
||||
if (err) return t.end(err);
|
||||
t.pass('successfully re-seeded database');
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('webapp tests', async(t) => {
|
||||
const app = require('../app');
|
||||
let sid;
|
||||
try {
|
||||
let result;
|
||||
|
||||
/* create a new user/account using email/password */
|
||||
const code = '123456';
|
||||
result = await request.post('/register', {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
body: {
|
||||
service_provider_sid: theOneAndOnlyServiceProviderSid,
|
||||
provider: 'local',
|
||||
name: 'Joe User',
|
||||
email: 'joe@user.com',
|
||||
password: 'fiddlesticks',
|
||||
email_activation_code: code
|
||||
}
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200 && result.body.pristine === true &&
|
||||
!result.body.is_active && result.body.root_domain === 'sip.yakeeda.com',
|
||||
'successfully created a user and account and got jwt using email validation');
|
||||
|
||||
const {user_sid, account_sid, jwt} = result.body;
|
||||
let authUser = {bearer: jwt};
|
||||
|
||||
/* invalid code */
|
||||
result = await request.put('/ActivationCode/38383', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
user_sid,
|
||||
type: 'email'
|
||||
}
|
||||
});
|
||||
|
||||
t.ok(result.statusCode === 400, 'fails to validate email with invalid code');
|
||||
|
||||
/* invalid user */
|
||||
result = await request.put(`/ActivationCode/${code}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
simple: false,
|
||||
json: true,
|
||||
body: {
|
||||
user_sid: 'foobar',
|
||||
type: 'email'
|
||||
}
|
||||
});
|
||||
|
||||
t.ok(result.statusCode === 400, 'fails to validate email with invalid user');
|
||||
|
||||
/* successfully validate the password */
|
||||
result = await request.put(`/ActivationCode/${code}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
user_sid,
|
||||
type: 'email'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully validated email and activated account');
|
||||
|
||||
/* create a phone validation code */
|
||||
result = await request.post('/ActivationCode', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
simple: false,
|
||||
body: {
|
||||
user_sid: 'foobar',
|
||||
type: 'phone',
|
||||
value: '16173333456',
|
||||
code: '12389'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 400, 'returns 400 bad request creating activation code with invalid user_sid');
|
||||
|
||||
result = await request.post('/ActivationCode', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
simple: false,
|
||||
body: {
|
||||
user_sid,
|
||||
type: 'foobar',
|
||||
value: '16173333456',
|
||||
code: '12389'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 400, 'returns 400 bad request creating activation code with invalid type');
|
||||
|
||||
result = await request.post('/ActivationCode', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
simple: false,
|
||||
body: {
|
||||
user_sid,
|
||||
type: 'email',
|
||||
value: 'notanemail',
|
||||
code: '12389'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 400, 'returns 400 bad request creating activation code with invalid email');
|
||||
|
||||
/* create a phone validation code */
|
||||
result = await request.post('/ActivationCode', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
user_sid,
|
||||
type: 'phone',
|
||||
value: '16173333456',
|
||||
code: '12389'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully added a phone validation code');
|
||||
|
||||
/* successfully validate the code */
|
||||
result = await request.put('/ActivationCode/12389', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
user_sid,
|
||||
type: 'phone'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully validated phone number');
|
||||
|
||||
/* check availability of a phone numbers and email */
|
||||
result = await request.get('/Availability?type=phone&value=16173333456', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.statusCode === 200 && result.body.available === false, 'indicates when phone number is not available');
|
||||
|
||||
result = await request.get('/Availability?type=phone&value=15083084809', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.statusCode === 200 && result.body.available === true, 'indicates when phone number is available');
|
||||
|
||||
result = await request.get('/Availability?type=email&value=joe@user.com', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.statusCode === 200 && result.body.available === false, 'indicates when email is not available');
|
||||
|
||||
result = await request.get('/Availability?type=email&value=jim@user.com', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.statusCode === 200 && result.body.available === true, 'indicates when email is available');
|
||||
|
||||
/* check if a subdomain is available */
|
||||
result = await request.get('/Availability?type=subdomain&value=mycompany.sip.jambonz.us', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.statusCode === 200 && result.body.available === true, 'indicates when subdomain is available');
|
||||
|
||||
/* these hit the DNS provider (dnsmadeeasy) so only do as needed */
|
||||
if (process.env.DME_API_KEY) {
|
||||
/* add a subdomain to the account */
|
||||
result = await request.post(`Accounts/${account_sid}/SipRealms/test.yakeeda.com`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'added subdomain');
|
||||
|
||||
/* change the subdomain */
|
||||
result = await request.post(`Accounts/${account_sid}/SipRealms/myco.yakeeda.com`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'added subdomain');
|
||||
|
||||
/* retrieve account and verify sip_realm */
|
||||
result = await request.get(`Accounts/${account_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200 && result.body.sip_realm === 'myco.yakeeda.com' && result.body.is_active,
|
||||
'sip_realm successfully added to account');
|
||||
|
||||
/* check if a subdomain is available */
|
||||
result = await request.get('/Availability?type=subdomain&value=myco.yakeeda.com', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.statusCode === 200 && result.body.available === false, 'indicates when subdomain is not available');
|
||||
}
|
||||
|
||||
/* retrieve test number and app for a service provider */
|
||||
result = await request.get(`/AccountTest/${theOneAndOnlyServiceProviderSid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
});
|
||||
//console.log(JSON.stringify(result.body));
|
||||
t.ok(result.statusCode === 200 &&
|
||||
result.body.phonenumbers.length === 1 && result.body.applications.length === 1, 'retrieves test number and application');
|
||||
|
||||
/* update user name */
|
||||
result = await request.put(`/Users/foobar`, {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
simple: false,
|
||||
auth: authUser,
|
||||
body: {
|
||||
name: 'Jane Doe'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 403, 'rejects attempt to update different user');
|
||||
|
||||
/* update user name */
|
||||
result = await request.put(`/Users/${user_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authUser,
|
||||
body: {
|
||||
name: 'Jane Doe'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'updates user name');
|
||||
|
||||
/* update password */
|
||||
result = await request.put(`/Users/${user_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authUser,
|
||||
body: {
|
||||
old_password: 'fiddlesticks',
|
||||
new_password: 'foobarbazzle'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'updates user password');
|
||||
|
||||
/* update email */
|
||||
result = await request.put(`/Users/${user_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authUser,
|
||||
body: {
|
||||
email: 'janedoe@gmail.com',
|
||||
email_activation_code: '39877'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'updates email address');
|
||||
|
||||
/* successfully validate the new email */
|
||||
result = await request.put('/ActivationCode/39877', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
user_sid,
|
||||
type: 'email'
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully validated the new email address');
|
||||
|
||||
/* add api keys */
|
||||
await createApiKey(request, account_sid);
|
||||
await createApiKey(request, account_sid);
|
||||
|
||||
/* retrieve my own user info */
|
||||
result = await request.get(`/Users/me`, {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authUser,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200, 'successfully retrieved my own user details');
|
||||
|
||||
/* sign in with new email and password */
|
||||
result = await request.post('/signin', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
email: 'janedoe@gmail.com',
|
||||
password: 'foobarbazzle'
|
||||
}
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200 && result.body.user_sid === user_sid, 'successfully signed in with changed email and password');
|
||||
|
||||
/* logout */
|
||||
result = await request.post('/logout', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
email: 'janedoe@gmail.com',
|
||||
password: 'foobarbazzle'
|
||||
}
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 204, 'successfully logged out');
|
||||
await sleepFor(1200);
|
||||
|
||||
/* using old jwt fails */
|
||||
result = await request.get(`/Users/me`, {
|
||||
resolveWithFullResponse: true,
|
||||
simple: false,
|
||||
auth: authUser,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 401, 'fails using jwt after logout');
|
||||
|
||||
/* sign in again */
|
||||
result = await request.post('/signin', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
email: 'janedoe@gmail.com',
|
||||
password: 'foobarbazzle'
|
||||
}
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200 && result.body.user_sid === user_sid, 'successfully signed in again');
|
||||
authUser = {bearer: result.body.jwt};
|
||||
|
||||
/* new jwt works */
|
||||
result = await request.get(`/Users/me`, {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
auth: authUser,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200, 'new jwt works');
|
||||
|
||||
/* can not delete a voip_carrier that is not associated to my account */
|
||||
result = await request.delete('/VoipCarriers/5145b436-2f38-4029-8d4c-fd8c67831c7a', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
simple: false
|
||||
});
|
||||
t.ok(result.statusCode === 422, 'fails to delete a voip_carrier not associated with users account');
|
||||
|
||||
/* add a BYOC carrier
|
||||
Note: no need to supply account_sid, it will be assigned based on the jwt
|
||||
*/
|
||||
result = await request.post('/VoipCarriers', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
name: 'BYCO1',
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201 && result.body.sid, 'succesfully created BYOC carrier');
|
||||
const carrier_sid = result.body.sid;
|
||||
|
||||
/* add a sip gateway to the carrier */
|
||||
result = await request.post('/SipGateways', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
voip_carrier_sid: carrier_sid,
|
||||
ipv4: '192.168.1.1',
|
||||
inbound: true,
|
||||
outbound: true
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created sip gateway for BYOC carrier');
|
||||
let gateway_sid = result.body.sid;
|
||||
|
||||
/* update sip gateway */
|
||||
result = await request.put(`/SipGateways/${gateway_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
port: 5080
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully updated sip gateway for BYOC carrier');
|
||||
|
||||
/* delete sip gateway */
|
||||
result = await request.delete(`/SipGateways/${gateway_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully deleted sip gateway for BYOC carrier');
|
||||
|
||||
/* add a smpp gateway to the carrier */
|
||||
result = await request.post('/SmppGateways', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
voip_carrier_sid: carrier_sid,
|
||||
ipv4: '192.168.1.1',
|
||||
inbound: true,
|
||||
outbound: true
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 201, 'successfully created smpp gateway for BYOC carrier');
|
||||
gateway_sid = result.body.sid;
|
||||
|
||||
/* update smpp gateway */
|
||||
result = await request.put(`/SmppGateways/${gateway_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
body: {
|
||||
port: 5080
|
||||
}
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully updated smpp gateway for BYOC carrier');
|
||||
|
||||
/* delete smpp gateway */
|
||||
result = await request.delete(`/SmppGateways/${gateway_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully deleted smpp gateway for BYOC carrier');
|
||||
|
||||
result = await request.get('/Sbcs', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200 && result.body.length === 1, 'retrieve Sbcs');
|
||||
|
||||
result = await request.get('/Smpps', {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
json: true,
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200 && result.body.length === 2, 'retrieve Smpps');
|
||||
|
||||
/* delete account */
|
||||
result = await request.delete(`/Accounts/${account_sid}`, {
|
||||
resolveWithFullResponse: true,
|
||||
auth: authUser,
|
||||
});
|
||||
t.ok(result.statusCode === 204, 'successfully deleted account');
|
||||
|
||||
/* create a new user/account using same email/password */
|
||||
result = await request.post('/register', {
|
||||
resolveWithFullResponse: true,
|
||||
json: true,
|
||||
body: {
|
||||
service_provider_sid: theOneAndOnlyServiceProviderSid,
|
||||
provider: 'local',
|
||||
name: 'Joe User',
|
||||
email: 'joe@user.com',
|
||||
password: 'fiddlesticks',
|
||||
email_activation_code: code
|
||||
}
|
||||
});
|
||||
//console.log(result.body);
|
||||
t.ok(result.statusCode === 200 && result.body.pristine === true &&
|
||||
!result.body.is_active && result.body.root_domain === 'sip.yakeeda.com',
|
||||
'successfully created a user and account and got jwt using email validation');
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
t.end(err);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user