added API for retrieving queues

This commit is contained in:
Dave Horton
2021-06-17 09:01:58 -04:00
parent 1f4b175fc8
commit af79d92e71
7 changed files with 143 additions and 3 deletions
+4
View File
@@ -24,6 +24,8 @@ const {
retrieveCall,
deleteCall,
listCalls,
pushBack,
listQueues,
purgeCalls,
retrieveSet
} = require('@jambonz/realtimedb-helpers')({
@@ -53,6 +55,8 @@ Object.assign(app.locals, {
retrieveCall,
deleteCall,
listCalls,
pushBack,
listQueues,
purgeCalls,
retrieveSet,
lookupAppBySid,
+3
View File
@@ -9,8 +9,11 @@ const uuidv4 = require('uuid/v4');
const snakeCase = require('../../utils/snake-case');
const sysError = require('./error');
const {promisePool} = require('../../db');
const {hasAccountPermissions} = require('./utils');
let idx = 0;
router.use('/:sid/Queues', hasAccountPermissions, require('./queues'));
function coerceNumbers(callInfo) {
if (Array.isArray(callInfo)) {
return callInfo.map((ci) => {
+20
View File
@@ -0,0 +1,20 @@
const router = require('express').Router();
const sysError = require('./error');
const {parseAccountSid} = require('./utils');
/**
* retrieve queues for an account
*/
router.get('/', async(req, res) => {
const account_sid = parseAccountSid(req);
const {logger, listQueues} = req.app.locals;
try {
const queues = await listQueues(account_sid, req.query.name);
res.status(200).json(queues);
} catch (err) {
sysError(logger, res, err);
}
});
module.exports = router;
+40
View File
@@ -0,0 +1,40 @@
const parseServiceProviderSid = (req) => {
const arr = /ServiceProviders\/([^\/]*)/.exec(req.originalUrl);
if (arr) return arr[1];
};
const parseAccountSid = (req) => {
const arr = /Accounts\/([^\/]*)/.exec(req.originalUrl);
if (arr) return arr[1];
};
const hasAccountPermissions = (req, res, next) => {
if (req.user.hasScope('admin')) return next();
if (req.user.hasScope('account')) {
const account_sid = parseAccountSid(req);
if (account_sid === req.user.account_sid) return next();
}
res.status(403).json({
status: 'fail',
message: 'insufficient privileges'
});
};
const hasServiceProviderPermissions = (req, res, next) => {
if (req.user.hasScope('admin')) return next();
if (req.user.hasScope('service_provider')) {
const service_provider_sid = parseServiceProviderSid(req);
if (service_provider_sid === req.user.service_provider_sid) return next();
}
res.status(403).json({
status: 'fail',
message: 'insufficient privileges'
});
};
module.exports = {
parseAccountSid,
parseServiceProviderSid,
hasAccountPermissions,
hasServiceProviderPermissions
};
+44 -2
View File
@@ -1402,7 +1402,37 @@ paths:
schema:
$ref: '#/components/schemas/GeneralError'
/Accounts/{AccountSid}/Queues:
get:
summary: list queues for an Account
parameters:
- name: AccountSid
in: path
required: true
schema:
type: string
- name:
- in: query
name: name
required: false
schema:
type: string
description: a queue name or glob-style pattern matching one or more queues to return
responses:
200:
description: list of queues for this account matching the name query param, if provided
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Queue'
500:
description: system error
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'
/Accounts/{AccountSid}/Calls:
post:
summary: create a call
@@ -1989,6 +2019,18 @@ components:
- from
- to
example: {"from": "13394445678", "to": "16173333456", "text": "please call when you can"}
Queue:
properties:
name:
type: string
example: support
length:
type: number
format: integer
example: 5
required:
- name
- length
example: {"name": "new-orders", length: 12}
security:
- bearerAuth: []
+1 -1
View File
@@ -17,7 +17,7 @@
},
"dependencies": {
"@jambonz/db-helpers": "^0.6.11",
"@jambonz/realtimedb-helpers": "^0.4.1",
"@jambonz/realtimedb-helpers": "^0.4.3",
"cors": "^2.8.5",
"express": "^4.17.1",
"mysql2": "^2.2.5",
+31
View File
@@ -16,6 +16,7 @@ process.on('unhandledRejection', (reason, p) => {
test('account tests', async(t) => {
const app = require('../app');
const {pushBack} = app.locals;
let sid;
try {
let result;
@@ -122,6 +123,36 @@ test('account tests', async(t) => {
});
t.ok(result.statusCode === 204, 'successfully assigned phone number to account');
/* retrieve queues for account */
result = await request.get(`/Accounts/${sid}/Queues`, {
auth: {bearer: accountLevelToken},
json: true,
resolveWithFullResponse: true,
});
t.ok(result.statusCode === 200 && 0 === result.body.length,
'successfully retrieved an empty array when no queues exist');
await pushBack(`queue:${sid}:customer-support`, 'https://ip:300/v1/enqueue/foobar');
await pushBack(`queue:${sid}:customer-support`, 'https://ip:300/v1/enqueue/bazzle');
await pushBack(`queue:${sid}:sales-new-orders`, 'https://ip:300/v1/enqueue/bazzle');
await pushBack(`queue:${sid}:sales-returns`, 'https://ip:300/v1/enqueue/bazzle');
result = await request.get(`/Accounts/${sid}/Queues`, {
auth: {bearer: accountLevelToken},
json: true,
resolveWithFullResponse: true,
});
console.log(`retrieved queues: ${result.statusCode}: ${JSON.stringify(result.body)}`);
//t.ok(result.statusCode === 200 && 0 === result.body.length,
// 'successfully retrieved an empty array when no queues exist');
result = await request.get(`/Accounts/${sid}/Queues?name=sales-*`, {
auth: {bearer: accountLevelToken},
json: true,
resolveWithFullResponse: true,
});
console.log(`retrieved queues: ${result.statusCode}: ${JSON.stringify(result.body)}`);
/* cannot delete account that has phone numbers assigned */
result = await request.delete(`/Accounts/${sid}`, {
auth: authAdmin,