From c2c4a28868fd20385e689f28ff04478f970536b5 Mon Sep 17 00:00:00 2001 From: eglehelms Date: Wed, 30 Nov 2022 17:32:34 +0100 Subject: [PATCH] post speech to a different path if scoped user --- src/api/index.ts | 43 +++++++++++++---- .../internal/views/carriers/form.tsx | 31 ++++++++---- .../internal/views/speech-services/edit.tsx | 18 +++++-- .../internal/views/speech-services/form.tsx | 48 ++++++++++--------- .../internal/views/speech-services/index.tsx | 20 +++++--- .../internal/views/speech-services/status.tsx | 16 +++++-- src/router/auth.tsx | 8 +++- 7 files changed, 126 insertions(+), 58 deletions(-) diff --git a/src/api/index.ts b/src/api/index.ts index 1cd2124..79e8141 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -17,6 +17,7 @@ import { API_SMPP_GATEWAY, API_SIP_GATEWAY, API_PASSWORD_SETTINGS, + USER_ACCOUNT, } from "./constants"; import { ROUTE_LOGIN } from "src/router/routes"; import { @@ -58,6 +59,7 @@ import type { LimitCategories, PasswordSettings, } from "./types"; +import { UserData } from "../store/types"; import { StatusCodes } from "./types"; /** Wrap all requests to normalize response handling */ @@ -257,13 +259,21 @@ export const postApplication = (payload: Partial) => { }; export const postSpeechService = ( + user: UserData, sid: string, payload: Partial ) => { - return postFetch>( - `${API_SERVICE_PROVIDERS}/${sid}/SpeechCredentials`, - payload - ); + if (user.scope === USER_ACCOUNT) { + return postFetch>( + `${API_ACCOUNTS}/${user.account_sid}/SpeechCredentials`, + payload + ); + } else { + return postFetch>( + `${API_SERVICE_PROVIDERS}/${sid}/SpeechCredentials`, + payload + ); + } }; export const postMsTeamsTentant = (payload: Partial) => { @@ -296,6 +306,15 @@ export const postPredefinedCarrierTemplate = ( ); }; +export const postPredefinedCarrierTemplateAccount = ( + accountSid: string, + predefinedCarrierSid: string +) => { + return postFetch( + `${API_BASE_URL}/Accounts/${accountSid}/PredefinedCarriers/${predefinedCarrierSid}` + ); +}; + export const postSipGateway = (payload: Partial) => { return postFetch>(API_SIP_GATEWAY, payload); }; @@ -364,14 +383,22 @@ export const putApplication = (sid: string, payload: Partial) => { }; export const putSpeechService = ( + user: UserData, sid1: string, sid2: string, payload: Partial ) => { - return putFetch>( - `${API_SERVICE_PROVIDERS}/${sid1}/SpeechCredentials/${sid2}`, - payload - ); + if (user.scope === USER_ACCOUNT) { + return putFetch>( + `${API_ACCOUNTS}/${user.account_sid}/SpeechCredentials/${sid2}`, + payload + ); + } else { + return putFetch>( + `${API_SERVICE_PROVIDERS}/${sid1}/SpeechCredentials/${sid2}`, + payload + ); + } }; export const putMsTeamsTenant = ( diff --git a/src/containers/internal/views/carriers/form.tsx b/src/containers/internal/views/carriers/form.tsx index 6c5c850..cba93d6 100644 --- a/src/containers/internal/views/carriers/form.tsx +++ b/src/containers/internal/views/carriers/form.tsx @@ -14,6 +14,7 @@ import { useApiData, useServiceProviderData, postPredefinedCarrierTemplate, + postPredefinedCarrierTemplateAccount, } from "src/api"; import { DEFAULT_SIP_GATEWAY, @@ -536,16 +537,26 @@ export const CarrierForm = ({ )?.predefined_carrier_sid; if (currentServiceProvider && predefinedCarrierSid) { - postPredefinedCarrierTemplate( - currentServiceProvider.service_provider_sid, - predefinedCarrierSid - ) - .then(({ json }) => { - navigate(`${ROUTE_INTERNAL_CARRIERS}/${json.sid}/edit`); - }) - .catch((error) => { - toastError(error.msg); - }); + if (user?.scope === USER_ACCOUNT) { + postPredefinedCarrierTemplateAccount(accountSid, predefinedCarrierSid) + .then(({ json }) => { + navigate(`${ROUTE_INTERNAL_CARRIERS}/${json.sid}/edit`); + }) + .catch((error) => { + toastError(error.msg); + }); + } else { + postPredefinedCarrierTemplate( + currentServiceProvider.service_provider_sid, + predefinedCarrierSid + ) + .then(({ json }) => { + navigate(`${ROUTE_INTERNAL_CARRIERS}/${json.sid}/edit`); + }) + .catch((error) => { + toastError(error.msg); + }); + } } } }, [predefinedName]); diff --git a/src/containers/internal/views/speech-services/edit.tsx b/src/containers/internal/views/speech-services/edit.tsx index f71b968..ab5f275 100644 --- a/src/containers/internal/views/speech-services/edit.tsx +++ b/src/containers/internal/views/speech-services/edit.tsx @@ -2,17 +2,25 @@ import React, { useEffect } from "react"; import { H1 } from "jambonz-ui"; import { useParams } from "react-router-dom"; -import { useServiceProviderData } from "src/api"; -import { toastError } from "src/store"; +import { useApiData, useServiceProviderData } from "src/api"; +import { toastError, useSelectState } from "src/store"; import { SpeechServiceForm } from "./form"; import type { SpeechCredential } from "src/api/types"; +import { USER_ACCOUNT } from "src/api/constants"; export const EditSpeechService = () => { const params = useParams(); - const [data, refetch, error] = useServiceProviderData( - `SpeechCredentials/${params.speech_credential_sid}` - ); + const user = useSelectState("user"); + + const [data, refetch, error] = + user && user.scope !== USER_ACCOUNT + ? useServiceProviderData( + `SpeechCredentials/${params.speech_credential_sid}` + ) + : useApiData( + `Accounts/${user?.account_sid}/SpeechCredentials/${params.speech_credential_sid}` + ); useEffect(() => { if (error) { diff --git a/src/containers/internal/views/speech-services/form.tsx b/src/containers/internal/views/speech-services/form.tsx index 244087c..81e0b7c 100644 --- a/src/containers/internal/views/speech-services/form.tsx +++ b/src/containers/internal/views/speech-services/form.tsx @@ -115,7 +115,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => { }), }; - if (credential && credential.data) { + if (credential && credential.data && user) { if (user?.scope === USER_ACCOUNT && user.account_sid !== accountSid) { toastError( "You do not have permissions to make changes to these Speech Credentials" @@ -125,6 +125,7 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => { /** The backend API returns obscured secrets now so we need to make sure we don't send them back */ /** Fields not sent back via :PUT are `service_key`, `access_key_id`, `secret_access_key` and `api_key` */ putSpeechService( + user, currentServiceProvider.service_provider_sid, credential.data.speech_credential_sid, payload @@ -139,28 +140,31 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => { toastError(error.msg); }); } else { - postSpeechService(currentServiceProvider.service_provider_sid, { - ...payload, - service_key: - vendor === VENDOR_GOOGLE ? JSON.stringify(googleServiceKey) : null, - access_key_id: vendor === VENDOR_AWS ? accessKeyId : null, - secret_access_key: vendor === VENDOR_AWS ? secretAccessKey : null, - api_key: - vendor === VENDOR_MICROSOFT || - vendor === VENDOR_WELLSAID || - vendor === VENDOR_DEEPGRAM - ? apiKey - : null, - client_id: vendor === VENDOR_NUANCE ? clientId : null, - secret: vendor === VENDOR_NUANCE ? secretKey : null, - }) - .then(({ json }) => { - toastSuccess("Speech credential created successfully"); - navigate(`${ROUTE_INTERNAL_SPEECH}/${json.sid}/edit`); + if (user) + postSpeechService(user, currentServiceProvider.service_provider_sid, { + ...payload, + service_key: + vendor === VENDOR_GOOGLE + ? JSON.stringify(googleServiceKey) + : null, + access_key_id: vendor === VENDOR_AWS ? accessKeyId : null, + secret_access_key: vendor === VENDOR_AWS ? secretAccessKey : null, + api_key: + vendor === VENDOR_MICROSOFT || + vendor === VENDOR_WELLSAID || + vendor === VENDOR_DEEPGRAM + ? apiKey + : null, + client_id: vendor === VENDOR_NUANCE ? clientId : null, + secret: vendor === VENDOR_NUANCE ? secretKey : null, }) - .catch((error) => { - toastError(error.msg); - }); + .then(({ json }) => { + toastSuccess("Speech credential created successfully"); + navigate(`${ROUTE_INTERNAL_SPEECH}/${json.sid}/edit`); + }) + .catch((error) => { + toastError(error.msg); + }); } } }; diff --git a/src/containers/internal/views/speech-services/index.tsx b/src/containers/internal/views/speech-services/index.tsx index 97d6117..238e525 100644 --- a/src/containers/internal/views/speech-services/index.tsx +++ b/src/containers/internal/views/speech-services/index.tsx @@ -49,9 +49,11 @@ export const SpeechServices = () => { credential.speech_credential_sid ) .then(() => { - if (accountSid) { + if ((user && user?.scope === USER_ACCOUNT) || accountSid) { getSpeechCredentials( - `${API_ACCOUNTS}/${accountSid}/SpeechCredentials` + `${API_ACCOUNTS}/${ + user?.account_sid || accountSid + }/SpeechCredentials` ); } else { getSpeechCredentials( @@ -72,14 +74,18 @@ export const SpeechServices = () => { }; useEffect(() => { - if (accountSid) { - getSpeechCredentials(`${API_ACCOUNTS}/${accountSid}/SpeechCredentials`); - } else if (currentServiceProvider) { + if ((user && user?.scope === USER_ACCOUNT) || accountSid) { getSpeechCredentials( - `${API_SERVICE_PROVIDERS}/${currentServiceProvider.service_provider_sid}/SpeechCredentials` + `${API_ACCOUNTS}/${user?.account_sid || accountSid}/SpeechCredentials` ); + } else { + if (currentServiceProvider) { + getSpeechCredentials( + `${API_SERVICE_PROVIDERS}/${currentServiceProvider.service_provider_sid}/SpeechCredentials` + ); + } } - }, [accountSid, currentServiceProvider]); + }, [user, accountSid, currentServiceProvider]); return ( <> diff --git a/src/containers/internal/views/speech-services/status.tsx b/src/containers/internal/views/speech-services/status.tsx index bd78dc8..359bf04 100644 --- a/src/containers/internal/views/speech-services/status.tsx +++ b/src/containers/internal/views/speech-services/status.tsx @@ -1,12 +1,13 @@ import React, { useState } from "react"; import { MS } from "jambonz-ui"; -import { CRED_NOT_TESTED, CRED_OK } from "src/api/constants"; +import { CRED_NOT_TESTED, CRED_OK, USER_ACCOUNT } from "src/api/constants"; import { Icons, Spinner } from "src/components"; -import { useServiceProviderData } from "src/api"; +import { useApiData, useServiceProviderData } from "src/api"; import { getStatus, getReason } from "./utils"; import type { SpeechCredential, CredentialTestResult } from "src/api/types"; +import { useSelectState } from "src/store"; type CredentialStatusProps = { cred: SpeechCredential; @@ -17,10 +18,15 @@ export const CredentialStatus = ({ cred, showSummary = false, }: CredentialStatusProps) => { + const user = useSelectState("user"); const [testResult, testRefetch, testError] = - useServiceProviderData( - `SpeechCredentials/${cred.speech_credential_sid}/test` - ); + user && user.scope !== USER_ACCOUNT + ? useServiceProviderData( + `SpeechCredentials/${cred.speech_credential_sid}/test` + ) + : useApiData( + `Accounts/${user?.account_sid}/SpeechCredentials/${cred.speech_credential_sid}/test` + ); const notTestedTxt = "In order to test your credentials you need to enable TTS/STT."; diff --git a/src/router/auth.tsx b/src/router/auth.tsx index 6321c2c..92aacf1 100644 --- a/src/router/auth.tsx +++ b/src/router/auth.tsx @@ -10,6 +10,7 @@ import { ROUTE_LOGIN, ROUTE_CREATE_PASSWORD, ROUTE_INTERNAL_ACCOUNTS, + ROUTE_INTERNAL_APPLICATIONS, } from "./routes"; import { SESS_OLD_PASSWORD, @@ -20,6 +21,7 @@ import { } from "src/constants"; import type { UserLogin } from "src/api/types"; +import { USER_ACCOUNT } from "src/api/constants"; interface SignIn { (username: string, password: string): Promise; @@ -101,7 +103,11 @@ export const useProvideAuth = (): AuthStateContext => { sessionStorage.setItem(SESS_OLD_PASSWORD, password); navigate(ROUTE_CREATE_PASSWORD); } else { - navigate(ROUTE_INTERNAL_ACCOUNTS); + navigate( + parseJwt(token).scope !== USER_ACCOUNT + ? ROUTE_INTERNAL_ACCOUNTS + : ROUTE_INTERNAL_APPLICATIONS + ); } resolve(response.json);