Compare commits

..

4 Commits

Author SHA1 Message Date
Quan HL
1b165b9692 fix: riva_server_uri 2023-02-10 20:28:29 +07:00
Quan HL
922ef9f0b7 fix: riva_server_uri 2023-02-10 20:26:18 +07:00
Quan HL
f6612f551e feat: nvidia speech credential 2023-02-10 14:51:43 +07:00
EgleH
d4f2be3dc1 Add check for users to delete function (#104)
* add check for users to delete function

* fix typo

* fix active admin check

---------

Co-authored-by: eglehelms <e.helms@cognigy.com>
2023-02-08 07:16:29 -05:00
6 changed files with 60 additions and 6 deletions

View File

@@ -12,7 +12,7 @@ const {hasServiceProviderPermissions, parseServiceProviderSid} = require('./util
const sysError = require('../error');
const decorate = require('./decorate');
const preconditions = {
'delete': noActiveAccounts
'delete': noActiveAccountsOrUsers
};
const sqlDeleteSipGateways = `DELETE from sip_gateways
WHERE voip_carrier_sid IN (
@@ -59,12 +59,20 @@ function validateUpdate(req) {
}
/* can not delete a service provider if it has any active accounts */
async function noActiveAccounts(req, sid) {
async function noActiveAccountsOrUsers(req, sid) {
if (!req.user.hasAdminAuth) {
throw new DbErrorForbidden('only admin users can delete a service provider');
}
const activeAccounts = await ServiceProvider.getForeignKeyReferences('accounts.service_provider_sid', sid);
const activeUsers = await ServiceProvider.getForeignKeyReferences('users.service_provider_sid', sid);
if (activeAccounts > 0 && activeUsers > 0) throw new DbErrorUnprocessableRequest(
'cannot delete service provider with active accounts or users'
);
if (activeAccounts > 0) throw new DbErrorUnprocessableRequest('cannot delete service provider with active accounts');
if (activeUsers > 0) throw new DbErrorUnprocessableRequest(
'cannot delete service provider with active service provider level users'
);
/* ok we can delete -- no active accounts. remove carriers and speech credentials */
await promisePool.execute('DELETE from speech_credentials WHERE service_provider_sid = ?', [sid]);

View File

@@ -51,6 +51,7 @@ const encryptCredential = (obj) => {
tts_region,
stt_api_key,
stt_region,
riva_server_uri,
instance_id
} = obj;
@@ -106,6 +107,11 @@ const encryptCredential = (obj) => {
const ibmData = JSON.stringify({tts_api_key, tts_region, stt_api_key, stt_region, instance_id});
return encrypt(ibmData);
case 'nvidia':
assert(riva_server_uri, 'invalid riva server uri: riva_server_uri is required');
const nvidiaData = JSON.stringify({ riva_server_uri });
return encrypt(nvidiaData);
default:
assert(false, `invalid or missing vendor: ${vendor}`);
}
@@ -210,6 +216,9 @@ router.get('/', async(req, res) => {
obj.stt_api_key = obscureKey(o.stt_api_key);
obj.stt_region = o.stt_region;
obj.instance_id = o.instance_id;
} else if ('nvidia' == obj.vendor) {
const o = JSON.parse(decrypt(credential));
obj.riva_server_uri = o.riva_server_uri;
}
return obj;
}));
@@ -272,6 +281,9 @@ router.get('/:sid', async(req, res) => {
obj.stt_api_key = obscureKey(o.stt_api_key);
obj.stt_region = o.stt_region;
obj.instance_id = o.instance_id;
} else if ('nvidia' == obj.vendor) {
const o = JSON.parse(decrypt(credential));
obj.riva_server_uri = o.riva_server_uri;
}
res.status(200).json(obj);
} catch (err) {
@@ -302,7 +314,7 @@ router.put('/:sid', async(req, res) => {
const sid = req.params.sid;
const logger = req.app.locals.logger;
try {
const {use_for_tts, use_for_stt, region, aws_region, stt_region, tts_region} = req.body;
const {use_for_tts, use_for_stt, region, aws_region, stt_region, tts_region, riva_server_uri} = req.body;
if (typeof use_for_tts === 'undefined' && typeof use_for_stt === 'undefined') {
throw new DbErrorUnprocessableRequest('use_for_tts and use_for_stt are the only updateable fields');
}
@@ -337,7 +349,8 @@ router.put('/:sid', async(req, res) => {
use_custom_stt,
custom_stt_endpoint,
stt_region,
tts_region
tts_region,
riva_server_uri
};
logger.info({o, newCred}, 'updating speech credential with this new credential');
obj.credential = encryptCredential(newCred);

View File

@@ -424,7 +424,8 @@ router.delete('/:user_sid', async(req, res) => {
const user = await User.retrieve(user_sid);
try {
if (decodedJwt.scope === 'admin' && activeAdminUsers.length === 1) {
if (decodedJwt.scope === 'admin' && !user.account_sid && !user.service_provider_sid &&
activeAdminUsers.length === 1) {
throw new Error('cannot delete this admin user - there are no other active admin users');
}

View File

@@ -4262,6 +4262,8 @@ components:
type: boolean
stt_tested_ok:
type: boolean
riva_server_uri:
type: string
SpeechCredentialUpdate:
properties:
use_for_tts:

View File

@@ -16,7 +16,6 @@ const testNuanceStt = async(logger, credentials) => {
return true;
};
const testGoogleTts = async(logger, credentials) => {
const client = new ttsGoogle.TextToSpeechClient({credentials});
await client.listVoices();

View File

@@ -300,6 +300,37 @@ test('speech credentials tests', async(t) => {
t.ok(result.statusCode === 204, 'successfully deleted speech credential');
}
/* add a credential for nvidia */
result = await request.post(`/Accounts/${account_sid}/SpeechCredentials`, {
resolveWithFullResponse: true,
auth: authUser,
json: true,
body: {
vendor: 'nvidia',
use_for_stt: true,
use_for_tts: true,
riva_server_uri: "192.168.1.2:5060"
}
});
t.ok(result.statusCode === 201, 'successfully added speech credential for nvidia');
const ms_sid = result.body.sid;
/* test the speech credential */
result = await request.get(`/Accounts/${account_sid}/SpeechCredentials/${ms_sid}/test`, {
resolveWithFullResponse: true,
auth: authUser,
json: true,
});
// TODO Nvidia test.
t.ok(result.statusCode === 200 && result.body.stt.status === 'not tested', 'successfully tested speech credential for nvida stt');
/* delete the credential */
result = await request.delete(`/Accounts/${account_sid}/SpeechCredentials/${ms_sid}`, {
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();