mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-01-25 02:08:24 +00:00
Compare commits
9 Commits
subspace
...
v0.7.2-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4119d766d5 | ||
|
|
936a9da887 | ||
|
|
77098f273d | ||
|
|
e27b5a39a6 | ||
|
|
66872494f9 | ||
|
|
4557b32804 | ||
|
|
e55fe77171 | ||
|
|
0fd87a732f | ||
|
|
f6d358d3df |
51
.github/workflows/docker-publish-dbcreate.yml
vendored
Normal file
51
.github/workflows/docker-publish-dbcreate.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
# Publish `main` as Docker `latest` image.
|
||||
branches:
|
||||
- main
|
||||
|
||||
# Publish `v1.2.3` tags as releases.
|
||||
tags:
|
||||
- v*
|
||||
|
||||
env:
|
||||
IMAGE_NAME: db-create
|
||||
|
||||
jobs:
|
||||
push:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build image
|
||||
run: docker build . --file Dockerfile.db-create --tag $IMAGE_NAME
|
||||
|
||||
- name: Log into registry
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Push image
|
||||
run: |
|
||||
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
|
||||
|
||||
# Change all uppercase to lowercase
|
||||
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
|
||||
|
||||
# Strip git ref prefix from version
|
||||
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
|
||||
|
||||
# Strip "v" prefix from tag name
|
||||
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
|
||||
|
||||
# Use Docker `latest` tag convention
|
||||
[ "$VERSION" == "main" ] && VERSION=latest
|
||||
|
||||
echo IMAGE_ID=$IMAGE_ID
|
||||
echo VERSION=$VERSION
|
||||
|
||||
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
|
||||
docker push $IMAGE_ID:$VERSION
|
||||
51
.github/workflows/docker-publish.yml
vendored
Normal file
51
.github/workflows/docker-publish.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
# Publish `main` as Docker `latest` image.
|
||||
branches:
|
||||
- main
|
||||
|
||||
# Publish `v1.2.3` tags as releases.
|
||||
tags:
|
||||
- v*
|
||||
|
||||
env:
|
||||
IMAGE_NAME: api-server
|
||||
|
||||
jobs:
|
||||
push:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build image
|
||||
run: docker build . --file Dockerfile --tag $IMAGE_NAME
|
||||
|
||||
- name: Log into registry
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Push image
|
||||
run: |
|
||||
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
|
||||
|
||||
# Change all uppercase to lowercase
|
||||
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
|
||||
|
||||
# Strip git ref prefix from version
|
||||
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
|
||||
|
||||
# Strip "v" prefix from tag name
|
||||
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
|
||||
|
||||
# Use Docker `latest` tag convention
|
||||
[ "$VERSION" == "main" ] && VERSION=latest
|
||||
|
||||
echo IMAGE_ID=$IMAGE_ID
|
||||
echo VERSION=$VERSION
|
||||
|
||||
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
|
||||
docker push $IMAGE_ID:$VERSION
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:16
|
||||
FROM node:17
|
||||
WORKDIR /opt/app/
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:16
|
||||
FROM node:17
|
||||
WORKDIR /opt/app/
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
|
||||
@@ -418,6 +418,10 @@ disable_cdrs BOOLEAN NOT NULL DEFAULT 0,
|
||||
trial_end_date DATETIME,
|
||||
deactivated_reason VARCHAR(255),
|
||||
device_to_call_ratio INTEGER NOT NULL DEFAULT 5,
|
||||
subspace_client_id VARCHAR(255),
|
||||
subspace_client_secret VARCHAR(255),
|
||||
subspace_sip_teleport_id VARCHAR(255),
|
||||
subspace_sip_teleport_destinations VARCHAR(255),
|
||||
PRIMARY KEY (account_sid)
|
||||
) COMMENT='An enterprise that uses the platform for comm services';
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -296,7 +296,23 @@ Account.fields = [
|
||||
{
|
||||
name: 'disable_cdrs',
|
||||
type: 'number',
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'subspace_client_id',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
name: 'subspace_client_secret',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
name: 'subspace_sip_teleport_id',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
name: 'subspace_sip_teleport_destinations',
|
||||
type: 'string',
|
||||
},
|
||||
];
|
||||
|
||||
module.exports = Account;
|
||||
|
||||
@@ -12,7 +12,7 @@ const uuidv4 = require('uuid/v4');
|
||||
const snakeCase = require('../../utils/snake-case');
|
||||
const sysError = require('../error');
|
||||
const {promisePool} = require('../../db');
|
||||
const {hasAccountPermissions, parseAccountSid} = require('./utils');
|
||||
const {hasAccountPermissions, parseAccountSid, enableSubspace, disableSubspace} = require('./utils');
|
||||
const short = require('short-uuid');
|
||||
const VoipCarrier = require('../../models/voip-carrier');
|
||||
const translator = short();
|
||||
@@ -371,6 +371,58 @@ router.get('/:sid/WebhookSecret', async(req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/:sid/SubspaceTeleport', async(req, res) => {
|
||||
const logger = req.app.locals.logger;
|
||||
try {
|
||||
const service_provider_sid = req.user.hasServiceProviderAuth ? req.user.service_provider_sid : null;
|
||||
const results = await Account.retrieve(req.params.sid, service_provider_sid);
|
||||
if (results.length === 0) return res.status(404).end();
|
||||
const {subspace_client_id, subspace_client_secret} = results[0];
|
||||
const {destination} = req.body;
|
||||
const arr = /^(.*):\d+$/.exec(destination);
|
||||
const dest = arr ? `sip:${arr[1]}` : `sip:${destination}`;
|
||||
|
||||
const teleport = await enableSubspace({
|
||||
subspace_client_id,
|
||||
subspace_client_secret,
|
||||
destination: dest
|
||||
});
|
||||
logger.info({destination, teleport}, 'SubspaceTeleport - create teleport');
|
||||
await Account.update(req.params.sid, {
|
||||
subspace_sip_teleport_id: teleport.id,
|
||||
subspace_sip_teleport_destinations: JSON.stringify(teleport.teleport_entry_points)//hacky
|
||||
});
|
||||
|
||||
return res.status(200).json({
|
||||
subspace_sip_teleport_id: teleport.id,
|
||||
subspace_sip_teleport_destinations: teleport.teleport_entry_points
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
sysError(logger, res, err);
|
||||
}
|
||||
});
|
||||
|
||||
router.delete('/:sid/SubspaceTeleport', async(req, res) => {
|
||||
const logger = req.app.locals.logger;
|
||||
try {
|
||||
const service_provider_sid = req.user.hasServiceProviderAuth ? req.user.service_provider_sid : null;
|
||||
const results = await Account.retrieve(req.params.sid, service_provider_sid);
|
||||
if (results.length === 0) return res.status(404).end();
|
||||
const {subspace_client_id, subspace_client_secret, subspace_sip_teleport_id} = results[0];
|
||||
|
||||
await disableSubspace({subspace_client_id, subspace_client_secret, subspace_sip_teleport_id});
|
||||
await Account.update(req.params.sid, {
|
||||
subspace_sip_teleport_id: null,
|
||||
subspace_sip_teleport_destinations: null
|
||||
});
|
||||
return res.sendStatus(204);
|
||||
}
|
||||
catch (err) {
|
||||
sysError(logger, res, err);
|
||||
}
|
||||
});
|
||||
|
||||
/* update */
|
||||
router.put('/:sid', async(req, res) => {
|
||||
const sid = req.params.sid;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const uuid = require('uuid').v4;
|
||||
const bent = require('bent');
|
||||
const Account = require('../../models/account');
|
||||
const {promisePool} = require('../../db');
|
||||
const {cancelSubscription, detachPaymentMethod} = require('../../utils/stripe-utils');
|
||||
@@ -9,6 +10,8 @@ values (?, ?)`;
|
||||
const replaceOldSubscriptionSql = `UPDATE account_subscriptions
|
||||
SET effective_end_date = CURRENT_TIMESTAMP, change_reason = ?
|
||||
WHERE account_subscription_sid = ?`;
|
||||
//const request = require('request');
|
||||
//require('request-debug')(request);
|
||||
|
||||
const setupFreeTrial = async(logger, account_sid, isReturningUser) => {
|
||||
const sid = uuid();
|
||||
@@ -224,6 +227,52 @@ const checkLimits = async(req, res, next) => {
|
||||
next();
|
||||
};
|
||||
|
||||
const getSubspaceJWT = async(id, secret) => {
|
||||
const postJwt = bent('https://id.subspace.com', 'POST', 'json', 200);
|
||||
const jwt = await postJwt('/oauth/token',
|
||||
{
|
||||
client_id: id,
|
||||
client_secret: secret,
|
||||
audience: 'https://api.subspace.com/',
|
||||
grant_type: 'client_credentials',
|
||||
}
|
||||
);
|
||||
return jwt.access_token;
|
||||
};
|
||||
|
||||
const enableSubspace = async(opts) => {
|
||||
const {subspace_client_id, subspace_client_secret, destination} = opts;
|
||||
const accessToken = await getSubspaceJWT(subspace_client_id, subspace_client_secret);
|
||||
const postTeleport = bent('https://api.subspace.com', 'POST', 'json', 200);
|
||||
|
||||
const teleport = await postTeleport('/v1/sipteleport',
|
||||
{
|
||||
name: 'Jambonz',
|
||||
destination,
|
||||
status: 'ENABLED'
|
||||
},
|
||||
{
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
);
|
||||
|
||||
return teleport;
|
||||
};
|
||||
|
||||
const disableSubspace = async(opts) => {
|
||||
const {subspace_client_id, subspace_client_secret, subspace_sip_teleport_id} = opts;
|
||||
const accessToken = await getSubspaceJWT(subspace_client_id, subspace_client_secret);
|
||||
const relativeUrl = `/v1/sipteleport/${subspace_sip_teleport_id}`;
|
||||
const deleteTeleport = bent('https://api.subspace.com', 'DELETE', 'json', 200);
|
||||
await deleteTeleport(relativeUrl, {},
|
||||
{
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
setupFreeTrial,
|
||||
createTestCdrs,
|
||||
@@ -232,5 +281,7 @@ module.exports = {
|
||||
parseServiceProviderSid,
|
||||
hasAccountPermissions,
|
||||
hasServiceProviderPermissions,
|
||||
checkLimits
|
||||
checkLimits,
|
||||
enableSubspace,
|
||||
disableSubspace
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jambonz-api-server",
|
||||
"version": "v0.6.7-rc8",
|
||||
"version": "v0.7.1",
|
||||
"description": "",
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
@@ -19,7 +19,6 @@
|
||||
"dependencies": {
|
||||
"@google-cloud/speech": "^4.2.0",
|
||||
"@google-cloud/text-to-speech": "^3.1.3",
|
||||
"microsoft-cognitiveservices-speech-sdk": "^1.19.0",
|
||||
"@jambonz/db-helpers": "^0.6.12",
|
||||
"@jambonz/realtimedb-helpers": "^0.4.3",
|
||||
"@jambonz/time-series": "^0.1.5",
|
||||
@@ -33,10 +32,12 @@
|
||||
"form-urlencoded": "^6.0.4",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mailgun.js": "^3.3.0",
|
||||
"microsoft-cognitiveservices-speech-sdk": "^1.19.0",
|
||||
"mysql2": "^2.2.5",
|
||||
"passport": "^0.5.0",
|
||||
"passport-http-bearer": "^1.0.1",
|
||||
"pino": "^5.17.0",
|
||||
"request-debug": "^0.2.0",
|
||||
"short-uuid": "^4.1.0",
|
||||
"stripe": "^8.138.0",
|
||||
"swagger-ui-express": "^4.1.6",
|
||||
|
||||
@@ -10,6 +10,7 @@ networks:
|
||||
|
||||
services:
|
||||
mysql:
|
||||
platform: linux/x86_64
|
||||
image: mysql:5.7
|
||||
ports:
|
||||
- "3360:3306"
|
||||
@@ -35,6 +36,7 @@ services:
|
||||
ipv4_address: 172.58.0.3
|
||||
|
||||
influxdb:
|
||||
platform: linux/x86_64
|
||||
image: influxdb:1.8-alpine
|
||||
ports:
|
||||
- "8086:8086"
|
||||
|
||||
Reference in New Issue
Block a user