mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2025-12-19 05:47:46 +00:00
feat support multi speech credential with diff labels and same vendor (#218)
* feat support multi speech credential with diff labels and same vendor * fix review comment * wip * fix review comments * update verb spec version
This commit is contained in:
@@ -334,6 +334,7 @@ last_tested DATETIME,
|
||||
tts_tested_ok BOOLEAN,
|
||||
stt_tested_ok BOOLEAN,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
label VARCHAR(64),
|
||||
PRIMARY KEY (speech_credential_sid)
|
||||
);
|
||||
|
||||
@@ -478,8 +479,10 @@ app_json TEXT,
|
||||
speech_synthesis_vendor VARCHAR(64) NOT NULL DEFAULT 'google',
|
||||
speech_synthesis_language VARCHAR(12) NOT NULL DEFAULT 'en-US',
|
||||
speech_synthesis_voice VARCHAR(64),
|
||||
speech_synthesis_label VARCHAR(64),
|
||||
speech_recognizer_vendor VARCHAR(64) NOT NULL DEFAULT 'google',
|
||||
speech_recognizer_language VARCHAR(64) NOT NULL DEFAULT 'en-US',
|
||||
speech_recognizer_label VARCHAR(64),
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
record_all_calls BOOLEAN NOT NULL DEFAULT false,
|
||||
PRIMARY KEY (application_sid)
|
||||
@@ -609,8 +612,6 @@ CREATE INDEX smpp_address_sid_idx ON smpp_addresses (smpp_address_sid);
|
||||
CREATE INDEX service_provider_sid_idx ON smpp_addresses (service_provider_sid);
|
||||
ALTER TABLE smpp_addresses ADD FOREIGN KEY service_provider_sid_idxfk_4 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
|
||||
|
||||
CREATE UNIQUE INDEX speech_credentials_idx_1 ON speech_credentials (vendor,account_sid);
|
||||
|
||||
CREATE INDEX speech_credential_sid_idx ON speech_credentials (speech_credential_sid);
|
||||
CREATE INDEX service_provider_sid_idx ON speech_credentials (service_provider_sid);
|
||||
ALTER TABLE speech_credentials ADD FOREIGN KEY service_provider_sid_idxfk_5 (service_provider_sid) REFERENCES service_providers (service_provider_sid);
|
||||
|
||||
@@ -884,7 +884,7 @@
|
||||
<y>958.00</y>
|
||||
</location>
|
||||
<size>
|
||||
<width>368.00</width>
|
||||
<width>302.00</width>
|
||||
<height>280.00</height>
|
||||
</size>
|
||||
<zorder>14</zorder>
|
||||
@@ -981,24 +981,11 @@
|
||||
<notNull><![CDATA[1]]></notNull>
|
||||
<uid><![CDATA[8860648C-4790-4A01-9E2E-60DC52A287FA]]></uid>
|
||||
</SQLField>
|
||||
<SQLIndex>
|
||||
<name><![CDATA[speech_credentials_idx_1]]></name>
|
||||
<fieldName><![CDATA[vendor]]></fieldName>
|
||||
<fieldName><![CDATA[account_sid]]></fieldName>
|
||||
<SQLIndexEntry>
|
||||
<name><![CDATA[vendor]]></name>
|
||||
<prefixSize><![CDATA[]]></prefixSize>
|
||||
<fieldUid><![CDATA[9D8FCF55-D68E-44D3-90DF-27B5ABD1D0BE]]></fieldUid>
|
||||
</SQLIndexEntry>
|
||||
<SQLIndexEntry>
|
||||
<name><![CDATA[account_sid]]></name>
|
||||
<prefixSize><![CDATA[]]></prefixSize>
|
||||
<fieldUid><![CDATA[7E964ED2-EC2E-4BCB-8DEC-C455B87FAC07]]></fieldUid>
|
||||
</SQLIndexEntry>
|
||||
<indexNamePrefix><![CDATA[speech_credentials]]></indexNamePrefix>
|
||||
<indexType><![CDATA[UNIQUE]]></indexType>
|
||||
<uid><![CDATA[554ABEC2-3E1B-41B1-BF07-25F403D5E3B4]]></uid>
|
||||
</SQLIndex>
|
||||
<SQLField>
|
||||
<name><![CDATA[label]]></name>
|
||||
<type><![CDATA[VARCHAR(64)]]></type>
|
||||
<uid><![CDATA[0D42A22C-DF14-42A1-BDE2-A53AC8B0D8D6]]></uid>
|
||||
</SQLField>
|
||||
<labelWindowIndex><![CDATA[21]]></labelWindowIndex>
|
||||
<ui.treeExpanded><![CDATA[1]]></ui.treeExpanded>
|
||||
<uid><![CDATA[49A68E1C-DEE2-446C-A4EB-9850E16155CC]]></uid>
|
||||
@@ -2368,7 +2355,7 @@
|
||||
</location>
|
||||
<size>
|
||||
<width>345.00</width>
|
||||
<height>340.00</height>
|
||||
<height>380.00</height>
|
||||
</size>
|
||||
<zorder>0</zorder>
|
||||
<SQLField>
|
||||
@@ -2487,6 +2474,12 @@
|
||||
<notNull><![CDATA[0]]></notNull>
|
||||
<uid><![CDATA[929D66F0-64B9-4D7C-AB4B-24F131E1178F]]></uid>
|
||||
</SQLField>
|
||||
<SQLField>
|
||||
<name><![CDATA[speech_synthesis_label]]></name>
|
||||
<type><![CDATA[VARCHAR(64)]]></type>
|
||||
<notNull><![CDATA[0]]></notNull>
|
||||
<uid><![CDATA[BFA24DF2-9CF5-47B0-848D-8B685B7C6750]]></uid>
|
||||
</SQLField>
|
||||
<SQLField>
|
||||
<name><![CDATA[speech_recognizer_vendor]]></name>
|
||||
<type><![CDATA[VARCHAR(64)]]></type>
|
||||
@@ -2501,6 +2494,12 @@
|
||||
<notNull><![CDATA[1]]></notNull>
|
||||
<uid><![CDATA[A03AFB7B-492F-48E3-AE3C-B1416D5B6B12]]></uid>
|
||||
</SQLField>
|
||||
<SQLField>
|
||||
<name><![CDATA[speech_recognizer_label]]></name>
|
||||
<type><![CDATA[VARCHAR(64)]]></type>
|
||||
<notNull><![CDATA[0]]></notNull>
|
||||
<uid><![CDATA[A247A784-CCD6-40B4-9D0A-2F0EF8F8AFD2]]></uid>
|
||||
</SQLField>
|
||||
<SQLField>
|
||||
<name><![CDATA[created_at]]></name>
|
||||
<type><![CDATA[DATETIME]]></type>
|
||||
@@ -2966,9 +2965,9 @@
|
||||
<SQLEditorFileFormatVersion><![CDATA[4]]></SQLEditorFileFormatVersion>
|
||||
<uid><![CDATA[58C99A00-06C9-478C-A667-C63842E088F3]]></uid>
|
||||
<windowHeight><![CDATA[1055.000000]]></windowHeight>
|
||||
<windowLocationX><![CDATA[0.000000]]></windowLocationX>
|
||||
<windowLocationY><![CDATA[24.000000]]></windowLocationY>
|
||||
<windowScrollOrigin><![CDATA[{157, 832}]]></windowScrollOrigin>
|
||||
<windowLocationX><![CDATA[1728.000000]]></windowLocationX>
|
||||
<windowLocationY><![CDATA[37.000000]]></windowLocationY>
|
||||
<windowScrollOrigin><![CDATA[{157, 830}]]></windowScrollOrigin>
|
||||
<windowWidth><![CDATA[1682.000000]]></windowWidth>
|
||||
</SQLDocumentInfo>
|
||||
<AllowsIndexRenamingOnInsert><![CDATA[1]]></AllowsIndexRenamingOnInsert>
|
||||
|
||||
@@ -159,6 +159,12 @@ const sql = {
|
||||
'CREATE INDEX client_sid_idx ON clients (client_sid)',
|
||||
'ALTER TABLE clients ADD CONSTRAINT account_sid_idxfk_13 FOREIGN KEY account_sid_idxfk_13 (account_sid) REFERENCES accounts (account_sid)',
|
||||
'ALTER TABLE sip_gateways ADD COLUMN protocol ENUM(\'udp\',\'tcp\',\'tls\', \'tls/srtp\') DEFAULT \'udp\''
|
||||
],
|
||||
8005: [
|
||||
'DROP INDEX speech_credentials_idx_1 ON speech_credentials',
|
||||
'ALTER TABLE speech_credentials ADD COLUMN label VARCHAR(64)',
|
||||
'ALTER TABLE applications ADD COLUMN speech_synthesis_label VARCHAR(64)',
|
||||
'ALTER TABLE applications ADD COLUMN speech_recognizer_label VARCHAR(64)'
|
||||
]
|
||||
};
|
||||
|
||||
@@ -190,6 +196,7 @@ const doIt = async() => {
|
||||
if (val < 8000) upgrades.push(...sql['8000']);
|
||||
if (val < 8003) upgrades.push(...sql['8003']);
|
||||
if (val < 8004) upgrades.push(...sql['8004']);
|
||||
if (val < 8005) upgrades.push(...sql['8005']);
|
||||
|
||||
// perform all upgrades
|
||||
logger.info({upgrades}, 'applying schema upgrades..');
|
||||
|
||||
@@ -20,6 +20,17 @@ class SpeechCredential extends Model {
|
||||
return rows;
|
||||
}
|
||||
|
||||
static async isAvailableVendorAndLabel(service_provider_sid, account_sid, vendor, label) {
|
||||
let sql;
|
||||
if (account_sid) {
|
||||
sql = 'SELECT * FROM speech_credentials WHERE account_sid = ? AND vendor = ? AND label = ?';
|
||||
} else {
|
||||
sql = 'SELECT * FROM speech_credentials WHERE service_provider_sid = ? AND vendor = ? AND label = ?';
|
||||
}
|
||||
const [rows] = await promisePool.query(sql, [account_sid ? account_sid : service_provider_sid, vendor, label]);
|
||||
return rows;
|
||||
}
|
||||
|
||||
static async disableStt(account_sid) {
|
||||
await promisePool.execute('UPDATE speech_credentials SET use_for_stt = 0 WHERE account_sid = ?', [account_sid]);
|
||||
}
|
||||
@@ -86,6 +97,10 @@ SpeechCredential.fields = [
|
||||
{
|
||||
name: 'last_tested',
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
name: 'label',
|
||||
type: 'string'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -207,6 +207,7 @@ router.post('/', async(req, res) => {
|
||||
use_for_stt,
|
||||
use_for_tts,
|
||||
vendor,
|
||||
label
|
||||
} = req.body;
|
||||
const account_sid = req.user.account_sid || req.body.account_sid;
|
||||
const service_provider_sid = req.user.service_provider_sid ||
|
||||
@@ -221,11 +222,21 @@ router.post('/', async(req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if vendor and label is already used for account or SP
|
||||
if (label) {
|
||||
const existingSpeech = await SpeechCredential.isAvailableVendorAndLabel(
|
||||
service_provider_sid, account_sid, vendor, label);
|
||||
if (existingSpeech.length > 0) {
|
||||
throw new DbErrorUnprocessableRequest(`Label ${label} is already in use for another speech credential`);
|
||||
}
|
||||
}
|
||||
|
||||
const encrypted_credential = encryptCredential(req.body);
|
||||
const uuid = await SpeechCredential.make({
|
||||
account_sid,
|
||||
service_provider_sid,
|
||||
vendor,
|
||||
label,
|
||||
use_for_tts,
|
||||
use_for_stt,
|
||||
credential: encrypted_credential
|
||||
|
||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -19,7 +19,7 @@
|
||||
"@jambonz/realtimedb-helpers": "^0.8.6",
|
||||
"@jambonz/speech-utils": "^0.0.15",
|
||||
"@jambonz/time-series": "^0.2.8",
|
||||
"@jambonz/verb-specifications": "^0.0.26",
|
||||
"@jambonz/verb-specifications": "^0.0.27",
|
||||
"@soniox/soniox-node": "^1.1.1",
|
||||
"argon2": "^0.30.3",
|
||||
"bent": "^7.3.12",
|
||||
@@ -1906,9 +1906,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@jambonz/verb-specifications": {
|
||||
"version": "0.0.26",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.26.tgz",
|
||||
"integrity": "sha512-C/2KpX7dLPrEOFbcpyjJ3FkR8EEp+QbNmJoWbCcfYoZEyLiOcawWVwPRvz8hNPVa/Hf2Scth9OvjKeGuny33gQ==",
|
||||
"version": "0.0.27",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.27.tgz",
|
||||
"integrity": "sha512-DIcxhCNrgr2RTE3YrGNP15RqKyV+P8f97SPBlKd2zTM5aN2oV5xv+pRDx5gLzmrUZ5TIEaBXQN3vTmM2Zx5Q6g==",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.4",
|
||||
"pino": "^8.8.0"
|
||||
@@ -11017,9 +11017,9 @@
|
||||
}
|
||||
},
|
||||
"@jambonz/verb-specifications": {
|
||||
"version": "0.0.26",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.26.tgz",
|
||||
"integrity": "sha512-C/2KpX7dLPrEOFbcpyjJ3FkR8EEp+QbNmJoWbCcfYoZEyLiOcawWVwPRvz8hNPVa/Hf2Scth9OvjKeGuny33gQ==",
|
||||
"version": "0.0.27",
|
||||
"resolved": "https://registry.npmjs.org/@jambonz/verb-specifications/-/verb-specifications-0.0.27.tgz",
|
||||
"integrity": "sha512-DIcxhCNrgr2RTE3YrGNP15RqKyV+P8f97SPBlKd2zTM5aN2oV5xv+pRDx5gLzmrUZ5TIEaBXQN3vTmM2Zx5Q6g==",
|
||||
"requires": {
|
||||
"debug": "^4.3.4",
|
||||
"pino": "^8.8.0"
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"@jambonz/realtimedb-helpers": "^0.8.6",
|
||||
"@jambonz/speech-utils": "^0.0.15",
|
||||
"@jambonz/time-series": "^0.2.8",
|
||||
"@jambonz/verb-specifications": "^0.0.26",
|
||||
"@jambonz/verb-specifications": "^0.0.27",
|
||||
"@jambonz/lamejs": "^1.2.2",
|
||||
"@soniox/soniox-node": "^1.1.1",
|
||||
"argon2": "^0.30.3",
|
||||
|
||||
@@ -84,6 +84,7 @@ test('speech credentials tests', async(t) => {
|
||||
json: true,
|
||||
body: {
|
||||
vendor: 'google',
|
||||
label: 'label1',
|
||||
service_key: jsonKey,
|
||||
use_for_tts: true,
|
||||
use_for_stt: true
|
||||
@@ -111,6 +112,7 @@ test('speech credentials tests', async(t) => {
|
||||
json: true,
|
||||
});
|
||||
t.ok(result.vendor === 'google' , 'successfully retrieved speech credential by sid');
|
||||
t.ok(result.label === 'label1' , 'label is successfully created');
|
||||
|
||||
/* query all credentials */
|
||||
result = await request.get(`/Accounts/${account_sid}/SpeechCredentials`, {
|
||||
|
||||
Reference in New Issue
Block a user