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) => {
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
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) => {
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);
}