diff --git a/src/containers/internal/navi/index.tsx b/src/containers/internal/navi/index.tsx index e16445c..b8f0431 100644 --- a/src/containers/internal/navi/index.tsx +++ b/src/containers/internal/navi/index.tsx @@ -17,6 +17,8 @@ import type { NaviItem } from "./items"; import "./styles.scss"; import { ScopedAccess } from "src/components/scoped-access"; import { Scope } from "src/store/types"; +import { USER_ACCOUNT } from "src/api/constants"; +import { ROUTE_INTERNAL_ACCOUNTS } from "src/router/routes"; type CommonProps = { handleMenu: () => void; @@ -172,9 +174,47 @@ export const Navi = ({
diff --git a/src/containers/internal/views/alerts/index.tsx b/src/containers/internal/views/alerts/index.tsx index 66af58d..f665f10 100644 --- a/src/containers/internal/views/alerts/index.tsx +++ b/src/containers/internal/views/alerts/index.tsx @@ -3,8 +3,12 @@ import { ButtonGroup, H1, M, MS } from "jambonz-ui"; import dayjs from "dayjs"; import { getAlerts, useServiceProviderData } from "src/api"; -import { DATE_SELECTION, PER_PAGE_SELECTION } from "src/api/constants"; -import { toastError } from "src/store"; +import { + DATE_SELECTION, + PER_PAGE_SELECTION, + USER_ACCOUNT, +} from "src/api/constants"; +import { toastError, useSelectState } from "src/store"; import { hasLength, hasValue } from "src/utils"; import { AccountFilter, @@ -18,6 +22,7 @@ import { import type { Account, Alert, PageQuery } from "src/api/types"; export const Alerts = () => { + const user = useSelectState("user"); const [accounts] = useServiceProviderData("Accounts"); const [accountSid, setAccountSid] = useState(""); const [dateFilter, setDateFilter] = useState("today"); @@ -69,7 +74,13 @@ export const Alerts = () => {
acct.account_sid === user.account_sid + ) + : accounts + } /> { const navigate = useNavigate(); + const user = useSelectState("user"); const currentServiceProvider = useSelectState("currentServiceProvider"); const refSipIp = useRef([]); @@ -437,6 +439,11 @@ export const CarrierForm = ({ const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); + if (user?.scope === USER_ACCOUNT && user.account_sid !== accountSid) { + toastError("You do not have permissions to make changes to this Carrier"); + return; + } + setSipMessage(""); setSmppInboundMessage(""); setSmppOutboundMessage(""); @@ -677,11 +684,17 @@ export const CarrierForm = ({ Prepend a leading + on origination attempts. user.account_sid === acct.account_sid + ) + : accounts + } account={[accountSid, setAccountSid]} label="Used By" required={false} - defaultOption + defaultOption={user?.scope !== USER_ACCOUNT} /> {accountSid && hasLength(applications) && ( <> diff --git a/src/containers/internal/views/carriers/index.tsx b/src/containers/internal/views/carriers/index.tsx index e77f3c8..d1ef48a 100644 --- a/src/containers/internal/views/carriers/index.tsx +++ b/src/containers/internal/views/carriers/index.tsx @@ -8,7 +8,7 @@ import { getFetch, useServiceProviderData, } from "src/api"; -import { toastSuccess, toastError } from "src/store"; +import { toastSuccess, toastError, useSelectState } from "src/store"; import { ROUTE_INTERNAL_CARRIERS } from "src/router/routes"; import { AccountFilter, @@ -18,13 +18,18 @@ import { SearchFilter, } from "src/components"; import { hasLength, hasValue, useFilteredResults } from "src/utils"; -import { API_SIP_GATEWAY, API_SMPP_GATEWAY } from "src/api/constants"; +import { + API_SIP_GATEWAY, + API_SMPP_GATEWAY, + USER_ACCOUNT, +} from "src/api/constants"; import { DeleteCarrier } from "./delete"; import type { Account, Carrier, SipGateway, SmppGateway } from "src/api/types"; import { Gateways } from "./gateways"; export const Carriers = () => { + const user = useSelectState("user"); const [carrier, setCarrier] = useState(null); const [carriers, refetch] = useServiceProviderData("VoipCarriers"); const [accounts] = useServiceProviderData("Accounts"); @@ -48,6 +53,11 @@ export const Carriers = () => { const handleDelete = () => { if (carrier) { + if (user?.scope === USER_ACCOUNT && user.account_sid !== accountSid) { + toastError("You do not have permissions to delete this Carrier"); + return; + } + deleteCarrier(carrier.voip_carrier_sid) .then(() => { Promise.all([ @@ -109,7 +119,13 @@ export const Carriers = () => { /> acct.account_sid === user.account_sid + ) + : accounts + } label="Used by" defaultOption /> diff --git a/src/containers/internal/views/settings/index.tsx b/src/containers/internal/views/settings/index.tsx index 794147d..91cbc13 100644 --- a/src/containers/internal/views/settings/index.tsx +++ b/src/containers/internal/views/settings/index.tsx @@ -8,12 +8,16 @@ import AdminSettings from "./admin-settings"; import type { ServiceProvider } from "src/api/types"; import { Section } from "src/components"; import { MSG_REQUIRED_FIELDS } from "src/constants"; +import { ScopedAccess } from "src/components/scoped-access"; +import { Scope } from "src/store/types"; +import { useSelectState } from "src/store"; type SettingsProps = { currentServiceProvider: ServiceProvider; }; export const Settings = ({ currentServiceProvider }: SettingsProps) => { + const user = useSelectState("user"); const [activeTab, setActiveTab] = useState(""); return ( @@ -24,14 +28,19 @@ export const Settings = ({ currentServiceProvider }: SettingsProps) => {
{MSG_REQUIRED_FIELDS}
- - - - - - - - + + + + + + + + + + + + +
diff --git a/src/containers/internal/views/speech-services/form.tsx b/src/containers/internal/views/speech-services/form.tsx index 92215b5..244087c 100644 --- a/src/containers/internal/views/speech-services/form.tsx +++ b/src/containers/internal/views/speech-services/form.tsx @@ -33,6 +33,7 @@ import { CredentialStatus } from "./status"; import type { RegionVendors, GoogleServiceKey, Vendor } from "src/vendor/types"; import type { Account, SpeechCredential, UseApiDataMap } from "src/api/types"; +import { USER_ACCOUNT } from "src/api/constants"; type SpeechServiceFormProps = { credential?: UseApiDataMap; @@ -40,6 +41,7 @@ type SpeechServiceFormProps = { export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => { const navigate = useNavigate(); + const user = useSelectState("user"); const currentServiceProvider = useSelectState("currentServiceProvider"); const regions = useRegionVendors(); const [accounts] = useServiceProviderData("Accounts"); @@ -114,6 +116,12 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => { }; if (credential && credential.data) { + if (user?.scope === USER_ACCOUNT && user.account_sid !== accountSid) { + toastError( + "You do not have permissions to make changes to these Speech Credentials" + ); + return; + } /** 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( @@ -258,10 +266,16 @@ export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
acct.account_sid === user.account_sid + ) + : accounts + } account={[accountSid, setAccountSid]} required={false} - defaultOption + defaultOption={user?.scope !== USER_ACCOUNT} disabled={credential ? true : false} />
diff --git a/src/containers/internal/views/speech-services/index.tsx b/src/containers/internal/views/speech-services/index.tsx index 628cbb6..97d6117 100644 --- a/src/containers/internal/views/speech-services/index.tsx +++ b/src/containers/internal/views/speech-services/index.tsx @@ -2,7 +2,11 @@ import React, { useEffect, useState } from "react"; import { Button, H1, Icon, M } from "jambonz-ui"; import { Link } from "react-router-dom"; -import { API_ACCOUNTS, API_SERVICE_PROVIDERS } from "src/api/constants"; +import { + API_ACCOUNTS, + API_SERVICE_PROVIDERS, + USER_ACCOUNT, +} from "src/api/constants"; import { AccountFilter, Icons, Section, Spinner } from "src/components"; import { useSelectState, toastError, toastSuccess } from "src/store"; import { getFetch, deleteSpeechService, useServiceProviderData } from "src/api"; @@ -15,6 +19,7 @@ import { CredentialStatus } from "./status"; import type { SpeechCredential, Account } from "src/api/types"; export const SpeechServices = () => { + const user = useSelectState("user"); const currentServiceProvider = useSelectState("currentServiceProvider"); const [accounts] = useServiceProviderData("Accounts"); const [accountSid, setAccountSid] = useState(""); @@ -33,6 +38,12 @@ export const SpeechServices = () => { const handleDelete = () => { if (credential && currentServiceProvider) { + if (user?.scope === USER_ACCOUNT && user.account_sid !== accountSid) { + toastError( + "You do not have permissions to delete these Speech Credentials" + ); + return; + } deleteSpeechService( currentServiceProvider.service_provider_sid, credential.speech_credential_sid diff --git a/src/containers/login/create-password.tsx b/src/containers/login/create-password.tsx index b50c017..de3266d 100644 --- a/src/containers/login/create-password.tsx +++ b/src/containers/login/create-password.tsx @@ -6,7 +6,11 @@ import { isValidPasswd } from "src/utils"; import { putUser, useApiData } from "src/api"; import { PasswordSettings, StatusCodes } from "src/api/types"; import { Passwd, Message } from "src/components/forms"; -import { ROUTE_LOGIN, ROUTE_INTERNAL_ACCOUNTS } from "src/router/routes"; +import { + ROUTE_LOGIN, + ROUTE_INTERNAL_ACCOUNTS, + ROUTE_INTERNAL_APPLICATIONS, +} from "src/router/routes"; import { SESS_OLD_PASSWORD, SESS_USER_SID, @@ -17,8 +21,11 @@ import { } from "src/constants"; import type { IMessage } from "src/store/types"; +import { useSelectState } from "src/store"; +import { USER_ACCOUNT } from "src/api/constants"; export const CreatePassword = () => { + const user = useSelectState("user"); const [passwdSettings] = useApiData("PasswordSettings"); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); @@ -65,7 +72,11 @@ export const CreatePassword = () => { if (response.status === StatusCodes.NO_CONTENT) { sessionStorage.clear(); - navigate(ROUTE_INTERNAL_ACCOUNTS); + navigate( + user?.scope !== USER_ACCOUNT + ? ROUTE_INTERNAL_ACCOUNTS + : ROUTE_INTERNAL_APPLICATIONS + ); } else { setMessage(MSG_SOMETHING_WRONG); }