mirror of
https://github.com/jambonz/jambonz-webapp.git
synced 2026-02-09 02:29:45 +00:00
Compare commits
14 Commits
v0.7.5-rc1
...
v0.7.7-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b97d5e538f | ||
|
|
2704e97a96 | ||
|
|
4cfdfc3b49 | ||
|
|
47d73a7edd | ||
|
|
c14fa5db34 | ||
|
|
668d7f05f6 | ||
|
|
5ae88ff13e | ||
|
|
06c21f2545 | ||
|
|
663aabc80c | ||
|
|
a7de0a494e | ||
|
|
b742e67715 | ||
|
|
013681e7eb | ||
|
|
4912758120 | ||
|
|
bb335d0838 |
@@ -1,4 +1,4 @@
|
||||
FROM node:alpine as builder
|
||||
FROM node:18.8.0-alpine as builder
|
||||
RUN apk update && apk add --no-cache python3 make g++
|
||||
COPY . /opt/app
|
||||
WORKDIR /opt/app/
|
||||
@@ -7,7 +7,7 @@ RUN npm install
|
||||
RUN npm run build
|
||||
RUN npm prune
|
||||
|
||||
FROM node:alpine as webapp
|
||||
FROM node:18.6.0-alpine as webapp
|
||||
RUN apk add curl
|
||||
WORKDIR /opt/app
|
||||
COPY . /opt/app
|
||||
|
||||
1502
package-lock.json
generated
1502
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "jambonz-webapp",
|
||||
"version": "v0.7.5",
|
||||
"version": "v0.7.6",
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^5.16.1",
|
||||
"@testing-library/react": "^12.1.2",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^12.1.5",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"antd": "^4.15.4",
|
||||
"antd": "^4.21.0",
|
||||
"axios": "^0.21.1",
|
||||
"moment": "^2.29.1",
|
||||
"moment": "^2.29.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
|
||||
@@ -21,6 +21,7 @@ const StyledLink = styled(FilteredLink)`
|
||||
border-radius: 50%;
|
||||
text-decoration: none;
|
||||
color: #565656;
|
||||
z-index: 1;
|
||||
|
||||
& > span:first-child {
|
||||
display: flex;
|
||||
|
||||
@@ -73,6 +73,7 @@ const AccountForm = props => {
|
||||
const [ name, setName ] = useState('');
|
||||
const [ sipRealm, setSipRealm ] = useState('');
|
||||
const [ deviceCallingApplication, setDeviceCallingApplication ] = useState('');
|
||||
const [ siprecCallingApplication, setSiprecCallingApplication ] = useState('');
|
||||
const [ regWebhook, setRegWebhook ] = useState('');
|
||||
const [ regMethod, setRegMethod ] = useState('POST');
|
||||
const [ regUser, setRegUser ] = useState('');
|
||||
@@ -376,6 +377,7 @@ const AccountForm = props => {
|
||||
setName(acc.name || '');
|
||||
setSipRealm(acc.sip_realm || '');
|
||||
setDeviceCallingApplication(acc.device_calling_application_sid || '');
|
||||
setSiprecCallingApplication(acc.siprec_hook_sid || '');
|
||||
setRegWebhook((acc.registration_hook && acc.registration_hook.url ) || '');
|
||||
setRegMethod((acc.registration_hook && acc.registration_hook.method ) || 'post');
|
||||
setRegUser((acc.registration_hook && acc.registration_hook.username) || '');
|
||||
@@ -549,6 +551,7 @@ const AccountForm = props => {
|
||||
|
||||
if (props.type === 'edit') {
|
||||
axiosData.device_calling_application_sid = deviceCallingApplication || null;
|
||||
axiosData.siprec_hook_sid = siprecCallingApplication || null;
|
||||
}
|
||||
|
||||
const url = props.type === 'add'
|
||||
@@ -695,33 +698,61 @@ const AccountForm = props => {
|
||||
</StyledInputGroup>
|
||||
|
||||
{props.type === 'edit' && (
|
||||
<React.Fragment>
|
||||
<Label tooltip htmlFor="deviceCallingApplication">
|
||||
<span style={{ position: 'relative' }}>
|
||||
Application for SIP Device Calls
|
||||
<Tooltip large>
|
||||
This application is used to handle incoming calls from SIP users who have registered to the Account’s SIP Realm.
|
||||
</Tooltip>
|
||||
</span>
|
||||
</Label>
|
||||
<Select
|
||||
large={props.type === 'setup'}
|
||||
name="deviceCallingApplication"
|
||||
id="deviceCallingApplication"
|
||||
value={deviceCallingApplication}
|
||||
onChange={e => setDeviceCallingApplication(e.target.value)}
|
||||
>
|
||||
<option value="">-- NONE --</option>
|
||||
{accountApplications && accountApplications.map(app => (
|
||||
<option
|
||||
key={app.application_sid}
|
||||
value={app.application_sid}
|
||||
>
|
||||
{app.name}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</React.Fragment>
|
||||
<>
|
||||
<React.Fragment>
|
||||
<Label tooltip htmlFor="deviceCallingApplication">
|
||||
<span style={{ position: 'relative' }}>
|
||||
Application for SIP Device Calls
|
||||
<Tooltip large>
|
||||
This application is used to handle incoming calls from SIP users who have registered to the Account’s SIP Realm.
|
||||
</Tooltip>
|
||||
</span>
|
||||
</Label>
|
||||
<Select
|
||||
large={props.type === 'setup'}
|
||||
name="deviceCallingApplication"
|
||||
id="deviceCallingApplication"
|
||||
value={deviceCallingApplication}
|
||||
onChange={e => setDeviceCallingApplication(e.target.value)}
|
||||
>
|
||||
<option value="">-- NONE --</option>
|
||||
{accountApplications && accountApplications.map(app => (
|
||||
<option
|
||||
key={app.application_sid}
|
||||
value={app.application_sid}
|
||||
>
|
||||
{app.name}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</React.Fragment>
|
||||
|
||||
<React.Fragment>
|
||||
<Label tooltip htmlFor="siprecCallingApplication">
|
||||
<span style={{ position: 'relative' }}>
|
||||
Application for SIPREC Calls
|
||||
</span>
|
||||
</Label>
|
||||
<Select
|
||||
large={props.type === 'setup'}
|
||||
name="siprecCallingApplication"
|
||||
id="siprecCallingApplication"
|
||||
value={siprecCallingApplication}
|
||||
onChange={e => setSiprecCallingApplication(e.target.value)}
|
||||
right
|
||||
>
|
||||
<option value="">-- NONE --</option>
|
||||
{accountApplications && accountApplications.map(app => (
|
||||
<option
|
||||
key={app.application_sid}
|
||||
value={app.application_sid}
|
||||
>
|
||||
{app.name}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</React.Fragment>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Label htmlFor="regWebhook">Registration Webhook</Label>
|
||||
|
||||
@@ -63,7 +63,7 @@ const PhoneNumberForm = props => {
|
||||
const sipTrunksPromise = axios({
|
||||
method: 'get',
|
||||
baseURL: APP_API_BASE_URL,
|
||||
url: '/VoipCarriers',
|
||||
url: `ServiceProviders/${currentServiceProvider}/VoipCarriers`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
@@ -71,7 +71,7 @@ const PhoneNumberForm = props => {
|
||||
const accountsPromise = axios({
|
||||
method: 'get',
|
||||
baseURL: APP_API_BASE_URL,
|
||||
url: '/Accounts',
|
||||
url: `ServiceProviders/${currentServiceProvider}/Accounts`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
@@ -79,7 +79,7 @@ const PhoneNumberForm = props => {
|
||||
const applicationsPromise = axios({
|
||||
method: 'get',
|
||||
baseURL: APP_API_BASE_URL,
|
||||
url: '/Applications',
|
||||
url: `ServiceProviders/${currentServiceProvider}/Applications`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
@@ -87,7 +87,7 @@ const PhoneNumberForm = props => {
|
||||
const phoneNumbersPromise = axios({
|
||||
method: 'get',
|
||||
baseURL: APP_API_BASE_URL,
|
||||
url: '/PhoneNumbers',
|
||||
url: `ServiceProviders/${currentServiceProvider}/PhoneNumbers`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
|
||||
@@ -43,23 +43,23 @@ const SettingsForm = () => {
|
||||
const refServiceProviderName = useRef(null);
|
||||
|
||||
// Form inputs
|
||||
const [ enableMsTeams, setEnableMsTeams ] = useState(false);
|
||||
const [ sbcDomainName, setSbcDomainName ] = useState('');
|
||||
const [enableMsTeams, setEnableMsTeams] = useState(false);
|
||||
const [sbcDomainName, setSbcDomainName] = useState('');
|
||||
const [serviceProviderName, setServiceProviderName] = useState('');
|
||||
|
||||
// For when user has data in sbcDomainName and then taps the checkbox to disable MsTeams
|
||||
const [ savedSbcDomainName, setSavedSbcDomainName ] = useState('');
|
||||
const [savedSbcDomainName, setSavedSbcDomainName] = useState('');
|
||||
|
||||
// Invalid form inputs
|
||||
const [ invalidEnableMsTeams, setInvalidEnableMsTeams ] = useState(false);
|
||||
const [ invalidSbcDomainName, setInvalidSbcDomainName ] = useState(false);
|
||||
const [invalidEnableMsTeams, setInvalidEnableMsTeams] = useState(false);
|
||||
const [invalidSbcDomainName, setInvalidSbcDomainName] = useState(false);
|
||||
const [invalidServiceProviderName, setInvalidServiceProviderName] = useState(false);
|
||||
|
||||
const [ showLoader, setShowLoader ] = useState(true);
|
||||
const [ errorMessage, setErrorMessage ] = useState('');
|
||||
const [ serviceProviderSid, setServiceProviderSid ] = useState('');
|
||||
const [ serviceProviders, setServiceProviders ] = useState([]);
|
||||
const [ confirmDelete, setConfirmDelete ] = useState(false);
|
||||
const [showLoader, setShowLoader] = useState(true);
|
||||
const [errorMessage, setErrorMessage] = useState('');
|
||||
const [serviceProviderSid, setServiceProviderSid] = useState('');
|
||||
const [serviceProviders, setServiceProviders] = useState([]);
|
||||
const [confirmDelete, setConfirmDelete] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const getSettingsData = async () => {
|
||||
@@ -127,19 +127,19 @@ const SettingsForm = () => {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
setConfirmDelete(false);
|
||||
setErrorMessage('');
|
||||
history.push('/internal/accounts');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'success',
|
||||
message: 'Service Provider Deleted'
|
||||
.then(() => {
|
||||
setConfirmDelete(false);
|
||||
setErrorMessage('');
|
||||
history.push('/internal/accounts');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'success',
|
||||
message: 'Service Provider Deleted'
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
setErrorMessage(error.response.data.msg);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
setErrorMessage(error.response.data.msg);
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
@@ -255,115 +255,115 @@ const SettingsForm = () => {
|
||||
|
||||
return (
|
||||
showLoader
|
||||
? <Loader height="365px" />
|
||||
: (
|
||||
<>
|
||||
<Form
|
||||
large
|
||||
wideLabel
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Label htmlFor="serviceProviderName">Service Provider Name</Label>
|
||||
<Input
|
||||
name="serviceProviderName"
|
||||
id="serviceProviderName"
|
||||
value={serviceProviderName}
|
||||
onChange={e => setServiceProviderName(e.target.value)}
|
||||
invalid={invalidServiceProviderName}
|
||||
ref={refServiceProviderName}
|
||||
/>
|
||||
<div>{/* needed for CSS grid layout */}</div>
|
||||
<Checkbox
|
||||
noLeftMargin
|
||||
id="enableMsTeams"
|
||||
label="Enable Microsoft Teams Direct Routing"
|
||||
checked={enableMsTeams}
|
||||
onChange={toggleMsTeams}
|
||||
invalid={invalidEnableMsTeams}
|
||||
ref={refEnableMsTeams}
|
||||
/>
|
||||
? <Loader height="365px" />
|
||||
: (
|
||||
<>
|
||||
<Form
|
||||
large
|
||||
wideLabel
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Label htmlFor="serviceProviderName">Service Provider Name</Label>
|
||||
<Input
|
||||
name="serviceProviderName"
|
||||
id="serviceProviderName"
|
||||
value={serviceProviderName}
|
||||
onChange={e => setServiceProviderName(e.target.value)}
|
||||
invalid={invalidServiceProviderName}
|
||||
ref={refServiceProviderName}
|
||||
/>
|
||||
<div>{/* needed for CSS grid layout */}</div>
|
||||
<Checkbox
|
||||
noLeftMargin
|
||||
id="enableMsTeams"
|
||||
label="Enable Microsoft Teams Direct Routing"
|
||||
checked={enableMsTeams}
|
||||
onChange={toggleMsTeams}
|
||||
invalid={invalidEnableMsTeams}
|
||||
ref={refEnableMsTeams}
|
||||
/>
|
||||
|
||||
<Label htmlFor="sbcDomainName">SBC Domain Name</Label>
|
||||
<Input
|
||||
name="sbcDomainName"
|
||||
id="sbcDomainName"
|
||||
value={sbcDomainName}
|
||||
onChange={e => setSbcDomainName(e.target.value)}
|
||||
placeholder="Fully qualified domain name used for Microsoft Teams"
|
||||
invalid={invalidSbcDomainName}
|
||||
autoFocus={enableMsTeams}
|
||||
ref={refSbcDomainName}
|
||||
disabled={!enableMsTeams}
|
||||
title={(!enableMsTeams && "You must enable Microsoft Teams Direct Routing in order to provide an SBC Domain Name") || ""}
|
||||
/>
|
||||
<Label htmlFor="sbcDomainName">SBC Domain Name</Label>
|
||||
<Input
|
||||
name="sbcDomainName"
|
||||
id="sbcDomainName"
|
||||
value={sbcDomainName}
|
||||
onChange={e => setSbcDomainName(e.target.value)}
|
||||
placeholder="Fully qualified domain name used for Microsoft Teams"
|
||||
invalid={invalidSbcDomainName}
|
||||
autoFocus={enableMsTeams}
|
||||
ref={refSbcDomainName}
|
||||
disabled={!enableMsTeams}
|
||||
title={(!enableMsTeams && "You must enable Microsoft Teams Direct Routing in order to provide an SBC Domain Name") || ""}
|
||||
/>
|
||||
|
||||
{errorMessage && !confirmDelete && (
|
||||
<FormError grid message={errorMessage} />
|
||||
)}
|
||||
{errorMessage && !confirmDelete && (
|
||||
<FormError grid message={errorMessage} />
|
||||
)}
|
||||
|
||||
<InputGroup flexEnd spaced>
|
||||
<Button
|
||||
grid
|
||||
gray
|
||||
type="button"
|
||||
onClick={() => {
|
||||
history.push('/internal/accounts');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'info',
|
||||
message: 'Changes canceled',
|
||||
});
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
{serviceProviders.length > 1 && (
|
||||
<InputGroup flexEnd spaced>
|
||||
<Button
|
||||
grid
|
||||
gray
|
||||
type="button"
|
||||
onClick={() => setConfirmDelete(true)}
|
||||
onClick={() => {
|
||||
history.push('/internal/accounts');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'info',
|
||||
message: 'Changes canceled',
|
||||
});
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
Cancel
|
||||
</Button>
|
||||
)}
|
||||
<Button grid>Save</Button>
|
||||
</InputGroup>
|
||||
</Form>
|
||||
{serviceProviders.length > 1 && (
|
||||
<Button
|
||||
grid
|
||||
gray
|
||||
type="button"
|
||||
onClick={() => setConfirmDelete(true)}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
<Button grid>Save</Button>
|
||||
</InputGroup>
|
||||
</Form>
|
||||
|
||||
{confirmDelete && serviceProviders.length > 1 && (
|
||||
<Modal
|
||||
title="Are you sure you want to delete the Service Provider?"
|
||||
loader={false}
|
||||
content={
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<Td>Service Provider Name:</Td>
|
||||
<Td>{serviceProviderName}</Td>
|
||||
</tr>
|
||||
<tr>
|
||||
<Td>SBC Domain Name:</Td>
|
||||
<Td>{sbcDomainName || '[none]'}</Td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{errorMessage && (
|
||||
<FormError message={errorMessage} />
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
handleCancel={() => {
|
||||
setConfirmDelete(false);
|
||||
setErrorMessage('');
|
||||
}}
|
||||
handleSubmit={handleDelete}
|
||||
actionText="Delete"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
{confirmDelete && serviceProviders.length > 1 && (
|
||||
<Modal
|
||||
title="Are you sure you want to delete the Service Provider?"
|
||||
loader={false}
|
||||
content={
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<Td>Service Provider Name:</Td>
|
||||
<Td>{serviceProviderName}</Td>
|
||||
</tr>
|
||||
<tr>
|
||||
<Td>SBC Domain Name:</Td>
|
||||
<Td>{sbcDomainName || '[none]'}</Td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{errorMessage && (
|
||||
<FormError message={errorMessage} />
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
handleCancel={() => {
|
||||
setConfirmDelete(false);
|
||||
setErrorMessage('');
|
||||
}}
|
||||
handleSubmit={handleDelete}
|
||||
actionText="Delete"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -489,7 +489,7 @@ const SpeechServicesAddEdit = (props) => {
|
||||
id="vendor"
|
||||
value={vendor}
|
||||
onChange={e => setVendor(e.target.value)}
|
||||
ref={[refVendorGoogle, refVendorAws, refVendorMs, refVendorWellSaid]}
|
||||
{...[refVendorGoogle, refVendorAws, refVendorMs, refVendorWellSaid]}
|
||||
invalid={[invalidVendorGoogle, invalidVendorAws, invalidVendorMs, invalidVendorWellSaid].includes(true)}
|
||||
>
|
||||
<option value="">
|
||||
|
||||
@@ -209,7 +209,7 @@ const AccountsAddEdit = () => {
|
||||
name="API key"
|
||||
getContent={getApiKeys}
|
||||
columns={[
|
||||
{ header: 'API Key', key: 'token', width: '27rem', fontWeight: 'normal' },
|
||||
{ header: 'Account API Keys', key: 'token', width: '27rem', fontWeight: 'normal' },
|
||||
{ header: 'Last Used', key: 'last_used', width: '10rem' },
|
||||
]}
|
||||
addContent={createApiKey}
|
||||
|
||||
@@ -104,7 +104,6 @@ const CarriersList = () => {
|
||||
return;
|
||||
}
|
||||
if(!currentServiceProvider) return [];
|
||||
if (!accountList.length) return [];
|
||||
// Get all SIP trunks
|
||||
const trunkResults = await axios({
|
||||
method: 'get',
|
||||
|
||||
@@ -1,16 +1,221 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useContext } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { NotificationDispatchContext } from '../../../contexts/NotificationContext';
|
||||
import InternalTemplate from '../../templates/InternalTemplate';
|
||||
import SettingsForm from '../../forms/SettingsForm';
|
||||
import TableContent from '../../blocks/TableContent.js';
|
||||
import axios from 'axios';
|
||||
import { APP_API_BASE_URL } from "../../../constants";
|
||||
import { ServiceProviderValueContext } from '../../../contexts/ServiceProviderContext';
|
||||
|
||||
|
||||
const Settings = () => {
|
||||
let history = useHistory();
|
||||
const dispatch = useContext(NotificationDispatchContext);
|
||||
let service_provider_sid = useContext(ServiceProviderValueContext);
|
||||
const pageTitle = 'Settings';
|
||||
useEffect(() => {
|
||||
document.title = `${pageTitle} | Jambonz | Open Source CPAAS`;
|
||||
});
|
||||
|
||||
//=============================================================================
|
||||
// Get API keys
|
||||
//=============================================================================
|
||||
const getApiKeys = async () => {
|
||||
try {
|
||||
if (!localStorage.getItem('token')) {
|
||||
history.push('/');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: 'You must log in to view that page.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const results = await axios({
|
||||
method: 'get',
|
||||
baseURL: APP_API_BASE_URL,
|
||||
url: `/ServiceProviders/${service_provider_sid}/ApiKeys`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
});
|
||||
const simplifiedApiKeys = results.data.map(a => {
|
||||
const { token } = a;
|
||||
const maskLength = token.length - 4;
|
||||
const maskedPortion = token.substring(0, maskLength).replace(/[a-zA-Z0-9]/g, '*');
|
||||
const revealedPortion = token.substring(maskLength);
|
||||
const maskedToken = `${maskedPortion}${revealedPortion}`;
|
||||
|
||||
const { last_used } = a;
|
||||
let lastUsedString = 'Never used';
|
||||
if (last_used) {
|
||||
const currentDate = new Date();
|
||||
const lastUsedDate = new Date(last_used);
|
||||
currentDate.setHours(0, 0, 0, 0);
|
||||
lastUsedDate.setHours(0, 0, 0, 0);
|
||||
const daysDifference = Math.round((currentDate - lastUsedDate) / 1000 / 60 / 60 / 24);
|
||||
lastUsedString = daysDifference > 1
|
||||
? `${daysDifference} days ago`
|
||||
: daysDifference === 1
|
||||
? 'Yesterday'
|
||||
: daysDifference === 0
|
||||
? 'Today'
|
||||
: 'Never used';
|
||||
}
|
||||
|
||||
return {
|
||||
sid: a.api_key_sid,
|
||||
token: {
|
||||
type: 'masked',
|
||||
masked: maskedToken,
|
||||
revealed: token,
|
||||
},
|
||||
last_used: {
|
||||
type: 'normal',
|
||||
content: lastUsedString,
|
||||
},
|
||||
};
|
||||
});
|
||||
return (simplifiedApiKeys);
|
||||
} catch (err) {
|
||||
if (err.response && err.response.status === 401) {
|
||||
localStorage.removeItem('token');
|
||||
sessionStorage.clear();
|
||||
history.push('/');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: 'Your session has expired. Please log in and try again.',
|
||||
});
|
||||
} else {
|
||||
console.log(err.response || err);
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: (err.response && err.response.data && err.response.data.msg) || 'Unable to get API key data',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// Create API key
|
||||
//=============================================================================
|
||||
const createApiKey = async () => {
|
||||
try {
|
||||
if (!localStorage.getItem('token')) {
|
||||
history.push('/');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: 'You must log in to view that page.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const result = await axios({
|
||||
method: 'post',
|
||||
baseURL: APP_API_BASE_URL,
|
||||
url: '/ApiKeys',
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
data: {
|
||||
"service_provider_sid": service_provider_sid,
|
||||
}
|
||||
});
|
||||
return result.data.token;
|
||||
} catch (err) {
|
||||
if (err.response && err.response.status === 401) {
|
||||
localStorage.removeItem('token');
|
||||
sessionStorage.clear();
|
||||
history.push('/');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: 'Your session has expired. Please log in and try again.',
|
||||
});
|
||||
} else {
|
||||
console.log(err.response || err);
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: (err.response && err.response.data && err.response.data.msg) || 'Unable to create API key',
|
||||
});
|
||||
return 'error';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// Delete API key
|
||||
//=============================================================================
|
||||
const formatApiKeyToDelete = apiKey => {
|
||||
const items = [
|
||||
{ name: 'API Key:', content: apiKey.token.masked || '[none]' },
|
||||
{ name: 'Last Used:', content: apiKey.last_used.content || 'Never used' },
|
||||
];
|
||||
return items;
|
||||
};
|
||||
const deleteApiKey = async apiKeyToDelete => {
|
||||
try {
|
||||
if (!localStorage.getItem('token')) {
|
||||
history.push('/');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: 'You must log in to view that page.',
|
||||
});
|
||||
return;
|
||||
}
|
||||
await axios({
|
||||
method: 'delete',
|
||||
baseURL: APP_API_BASE_URL,
|
||||
url: `/Apikeys/${apiKeyToDelete.sid}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
});
|
||||
return 'success';
|
||||
} catch (err) {
|
||||
if (err.response && err.response.status === 401) {
|
||||
localStorage.removeItem('token');
|
||||
sessionStorage.clear();
|
||||
history.push('/');
|
||||
dispatch({
|
||||
type: 'ADD',
|
||||
level: 'error',
|
||||
message: 'Your session has expired. Please log in and try again.',
|
||||
});
|
||||
} else {
|
||||
console.log(err.response || err);
|
||||
return ((err.response && err.response.data && err.response.data.msg) || 'Unable to delete API key');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<InternalTemplate
|
||||
type="form"
|
||||
title={pageTitle}
|
||||
breadcrumbs={[
|
||||
{ name: 'Service Provider', url: '/internal/settings' },
|
||||
{ name: pageTitle },
|
||||
]}
|
||||
additionalTable={service_provider_sid && (
|
||||
<TableContent
|
||||
name="API key"
|
||||
getContent={getApiKeys}
|
||||
columns={[
|
||||
{ header: 'Service Provider API Keys', key: 'token', width: '27rem', fontWeight: 'normal' },
|
||||
{ header: 'Last Used', key: 'last_used', width: '10rem' },
|
||||
]}
|
||||
addContent={createApiKey}
|
||||
formatContentToDelete={formatApiKeyToDelete}
|
||||
deleteContent={deleteApiKey}
|
||||
rowsHaveDeleteButtons
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<SettingsForm />
|
||||
</InternalTemplate>
|
||||
|
||||
@@ -54,6 +54,38 @@ const regions = [
|
||||
{
|
||||
name: 'Canada (Central)',
|
||||
value: 'ca-central-1'
|
||||
},
|
||||
{
|
||||
name: 'Europe (Frankfurt)',
|
||||
value: 'eu-central-1'
|
||||
},
|
||||
{
|
||||
name: 'Europe (Ireland)',
|
||||
value: 'eu-west-1'
|
||||
},
|
||||
{
|
||||
name: 'Europe (London)',
|
||||
value: 'eu-west-2'
|
||||
},
|
||||
{
|
||||
name: 'Europe (Milan)',
|
||||
value: 'eu-south-1'
|
||||
},
|
||||
{
|
||||
name: 'Europe (Paris)',
|
||||
value: 'eu-west-3'
|
||||
},
|
||||
{
|
||||
name: 'Europe (Stockholm)',
|
||||
value: 'eu-north-1'
|
||||
},
|
||||
{
|
||||
name: 'Middle East (Bahrain)',
|
||||
value: 'me-south-1'
|
||||
},
|
||||
{
|
||||
name: 'South America (São Paulo)',
|
||||
value: 'sa-east-1'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -1,96 +1,124 @@
|
||||
const regions = [
|
||||
{
|
||||
name: 'Asia (East)',
|
||||
value: 'eastasia'
|
||||
{
|
||||
name: 'Australia - East (australiaeast)',
|
||||
value: 'australiaeast'
|
||||
},
|
||||
{
|
||||
name: 'Asia (Southeast)',
|
||||
value: 'southeastasia'
|
||||
{
|
||||
name: 'Brazil - South (brazilsouth)',
|
||||
value: 'brazilsouth'
|
||||
},
|
||||
{
|
||||
name: 'Australia (East)',
|
||||
value: 'australiaeast'
|
||||
{
|
||||
name: 'Canada - Central (canadacentral)',
|
||||
value: 'canadacentral'
|
||||
},
|
||||
{
|
||||
name: 'Brazil (South)',
|
||||
value: 'brazilsouth'
|
||||
{
|
||||
name: 'East Asia (eastasia)',
|
||||
value: 'eastasia'
|
||||
},
|
||||
{
|
||||
name: 'Canada (Central)',
|
||||
value: 'canadacentral'
|
||||
{
|
||||
name: 'Europe - North (northeurope)',
|
||||
value: 'northeurope'
|
||||
},
|
||||
{
|
||||
name: 'Europe (North)',
|
||||
value: 'northeurope'
|
||||
{
|
||||
name: 'Europe - West (westeurope)',
|
||||
value: 'westeurope'
|
||||
},
|
||||
{
|
||||
name: 'Europe (West)',
|
||||
value: 'westeurope'
|
||||
{
|
||||
name: 'France - Central (francecentral)',
|
||||
value: 'francecentral'
|
||||
},
|
||||
{
|
||||
name: 'France (Central)',
|
||||
value: 'francecentral'
|
||||
{
|
||||
name: 'Germany - West Central (germanywestcentral)',
|
||||
value: 'germanywestcentral'
|
||||
},
|
||||
{
|
||||
name: 'Switzerland (North)',
|
||||
value: 'switzerlandnorth'
|
||||
{
|
||||
name: 'India - Central (centralindia)',
|
||||
value: 'centralindia'
|
||||
},
|
||||
{
|
||||
name: 'India (Central)',
|
||||
value: 'centralindia'
|
||||
{
|
||||
name: 'Japan - East (japaneast)',
|
||||
value: 'japaneast'
|
||||
},
|
||||
{
|
||||
name: 'Japan (West)',
|
||||
value: 'japanwest'
|
||||
{
|
||||
name: 'Japan - West (japanwest)',
|
||||
value: 'japanwest'
|
||||
},
|
||||
{
|
||||
name: 'Japan (East)',
|
||||
value: 'japaneast'
|
||||
{
|
||||
name: 'Korea - Central (koreacentral)',
|
||||
value: 'koreacentral'
|
||||
},
|
||||
{
|
||||
name: 'Korea (Central)',
|
||||
value: 'koreacentral'
|
||||
{
|
||||
name: 'Norway - East (norwayeast)',
|
||||
value: 'norwayeast'
|
||||
},
|
||||
{
|
||||
name: 'South Africa (North)',
|
||||
value: 'southafricanorth'
|
||||
{
|
||||
name: 'South Africa - North (southafricanorth)',
|
||||
value: 'southafricanorth'
|
||||
},
|
||||
{
|
||||
name: 'UK (South)',
|
||||
value: 'uksouth'
|
||||
{
|
||||
name: 'Southeast Asia (southeastasia)',
|
||||
value: 'southeastasia'
|
||||
},
|
||||
{
|
||||
name: 'US (Cental)',
|
||||
value: 'centralus'
|
||||
{
|
||||
name: 'Switzerland - North (switzerlandnorth)',
|
||||
value: 'switzerlandnorth'
|
||||
},
|
||||
{
|
||||
name: 'US (West Central)',
|
||||
value: 'westcentralus'
|
||||
{
|
||||
name: 'Switzerland - West (switzerlandwest)',
|
||||
value: 'switzerlandwest'
|
||||
},
|
||||
{
|
||||
name: 'US (East)',
|
||||
value: 'eastus'
|
||||
{
|
||||
name: 'UAE - North (uaenorth)',
|
||||
value: 'uaenorth'
|
||||
},
|
||||
{
|
||||
name: 'US (East 2)',
|
||||
value: 'eastus2'
|
||||
{
|
||||
name: 'UK - South (uksouth)',
|
||||
value: 'uksouth'
|
||||
},
|
||||
{
|
||||
name: 'US (North Central)',
|
||||
value: 'northcentralus'
|
||||
{
|
||||
name: 'US - Central (centralus)',
|
||||
value: 'centralus'
|
||||
},
|
||||
{
|
||||
name: 'US (South Central)',
|
||||
value: 'southcentralus'
|
||||
{
|
||||
name: 'US - East (eastus)',
|
||||
value: 'eastus'
|
||||
},
|
||||
{
|
||||
name: 'US (West)',
|
||||
value: 'westus'
|
||||
{
|
||||
name: 'US - East 2 (eastus2)',
|
||||
value: 'eastus2'
|
||||
},
|
||||
{
|
||||
name: 'US (West 2)',
|
||||
value: 'westus2'
|
||||
{
|
||||
name: 'US - Gov Arizona (usgovarizona)',
|
||||
value: 'usgovarizona'
|
||||
},
|
||||
{
|
||||
name: 'US - Gov Virginia (usgovvirginia)',
|
||||
value: 'usgovvirginia'
|
||||
},
|
||||
{
|
||||
name: 'US - North Central (northcentralus)',
|
||||
value: 'northcentralus'
|
||||
},
|
||||
{
|
||||
name: 'US - South Central (southcentralus)',
|
||||
value: 'southcentralus'
|
||||
},
|
||||
{
|
||||
name: 'US - West Central (westcentralus)',
|
||||
value: 'westcentralus'
|
||||
},
|
||||
{
|
||||
name: 'US - West (westus)',
|
||||
value: 'westus'
|
||||
},
|
||||
{
|
||||
name: 'US - West 2 (westus2)',
|
||||
value: 'westus2'
|
||||
},
|
||||
{
|
||||
name: 'US - West 3 (westus3)',
|
||||
value: 'westus3'
|
||||
}
|
||||
];
|
||||
|
||||
export default regions;
|
||||
Reference in New Issue
Block a user