/
CorsForm.tsx
90 lines (81 loc) · 3.3 KB
/
CorsForm.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { ADMIN } from 'component/providers/AccessProvider/permissions';
import React, { useState } from 'react';
import { TextField, Box } from '@mui/material';
import { UpdateButton } from 'component/common/UpdateButton/UpdateButton';
import { useUiConfigApi } from 'hooks/api/actions/useUiConfigApi/useUiConfigApi';
import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError';
import { useId } from 'hooks/useId';
import { fontSize } from '@mui/system';
interface ICorsFormProps {
frontendApiOrigins: string[] | undefined;
}
export const CorsForm = ({ frontendApiOrigins }: ICorsFormProps) => {
const { setFrontendSettings } = useUiConfigApi();
const { setToastData, setToastApiError } = useToast();
const [value, setValue] = useState(formatInputValue(frontendApiOrigins));
const inputFieldId = useId();
const helpTextId = useId();
const onSubmit = async (event: React.FormEvent) => {
try {
const split = parseInputValue(value);
event.preventDefault();
await setFrontendSettings(split);
setValue(formatInputValue(split));
setToastData({ title: 'Settings saved', type: 'success' });
} catch (error) {
setToastApiError(formatUnknownError(error));
}
};
return (
<form onSubmit={onSubmit}>
<Box sx={{ display: 'grid', gap: 1 }}>
<label htmlFor={inputFieldId}>
Which origins should be allowed to call the Frontend API?
Add only one origin per line. The CORS specification does
not support wildcard for subdomains, it needs to be a fully
qualified domain, including the protocol.
<br />
<br />
If you specify "*" it will be the chosen origin.
<br />
<br />
Example:
</label>
<code style={{ fontSize: '0.7em' }}>
https://www.example.com
<br />
https://www.example2.com
</code>
<TextField
id={inputFieldId}
aria-describedby={helpTextId}
placeholder={textareaDomainsPlaceholder}
value={value}
onChange={event => setValue(event.target.value)}
multiline
rows={12}
variant="outlined"
fullWidth
InputProps={{
style: { fontFamily: 'monospace', fontSize: '0.8em' },
}}
/>
<UpdateButton permission={ADMIN} />
</Box>
</form>
);
};
export const parseInputValue = (value: string): string[] => {
return value
.split(/[,\n\s]+/) // Split by commas/newlines/spaces.
.map(value => value.replace(/\/$/, '')) // Remove trailing slashes.
.filter(Boolean); // Remove empty values from (e.g.) double newlines.
};
export const formatInputValue = (values: string[] | undefined): string => {
return values?.join('\n') ?? '';
};
const textareaDomainsPlaceholder = [
'https://example.com',
'https://example.org',
].join('\n');