1
1
import {
2
+ Alert ,
2
3
Badge ,
3
4
Button ,
4
5
Center ,
5
6
Checkbox ,
6
7
Code ,
7
8
CopyButton ,
8
9
Group ,
10
+ JsonInput ,
9
11
List ,
10
12
Modal ,
11
13
MultiSelect ,
@@ -18,6 +20,7 @@ import { DateTimePicker } from "@mantine/dates";
18
20
import {
19
21
IconAlertCircle ,
20
22
IconEye ,
23
+ IconHandStop ,
21
24
IconPlus ,
22
25
IconTrash ,
23
26
} from "@tabler/icons-react" ;
@@ -26,13 +29,15 @@ import {
26
29
apiKeyAllowedRoles ,
27
30
ApiKeyMaskedEntry ,
28
31
ApiKeyPostBody ,
32
+ policyUnion ,
29
33
} from "@common/types/apiKey" ;
30
34
import { useAuth } from "@ui/components/AuthContext" ;
31
35
import { notifications } from "@mantine/notifications" ;
32
36
import pluralize from "pluralize" ;
33
37
import dayjs from "dayjs" ;
34
38
import { AppRoles } from "@common/roles" ;
35
39
import { BlurredTextDisplay } from "../../components/BlurredTextDisplay" ;
40
+ import { z } from "zod" ;
36
41
37
42
const HumanFriendlyDate = ( { date } : { date : number } ) => {
38
43
return (
@@ -131,8 +136,8 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
131
136
await fetchKeys ( ) ;
132
137
} catch ( e ) {
133
138
notifications . show ( {
134
- title : "Create failed " ,
135
- message : "Unable to create API key ." ,
139
+ title : "Unable to create API key. " ,
140
+ message : "Please try again or contact support ." ,
136
141
color : "red" ,
137
142
} ) ;
138
143
}
@@ -188,6 +193,7 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
188
193
const [ roles , setRoles ] = useState < AppRoles [ ] > ( [ ] ) ;
189
194
const [ description , setDescription ] = useState ( "" ) ;
190
195
const [ expiresAt , setExpiresAt ] = useState < Date | null > ( null ) ;
196
+ const [ policyDocument , setPolicyDocument ] = useState ( "" ) ;
191
197
192
198
return (
193
199
< >
@@ -309,17 +315,62 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
309
315
clearable
310
316
mt = "md"
311
317
/>
318
+ < JsonInput
319
+ label = "Policy Document (optional)"
320
+ description = {
321
+ < Alert
322
+ icon = { < IconHandStop /> }
323
+ title = "Advanced Feature"
324
+ color = "orange"
325
+ >
326
+ Errors in this field will prevent your API key from working!
327
+ Please consult the API documentation for instructions.
328
+ </ Alert >
329
+ }
330
+ value = { policyDocument }
331
+ onChange = { setPolicyDocument }
332
+ placeholder = { `[
333
+ {
334
+ "name": "EventsHostRestrictionPolicy",
335
+ "params": {
336
+ "host": [
337
+ "ACM"
338
+ ]
339
+ }
340
+ }
341
+ ]` }
342
+ validationError = "Invalid JSON"
343
+ formatOnBlur
344
+ autosize
345
+ minRows = { 6 }
346
+ />
312
347
< Group justify = "flex-end" mt = "lg" >
313
348
< Button
314
- onClick = { ( ) =>
315
- handleCreate ( {
316
- roles,
317
- description,
318
- expiresAt : expiresAt
319
- ? Math . floor ( expiresAt . getTime ( ) / 1000 )
320
- : undefined ,
321
- } )
322
- }
349
+ onClick = { ( ) => {
350
+ let parsedPolicyDocument = undefined ;
351
+ try {
352
+ if ( policyDocument && policyDocument . trim ( ) !== "" ) {
353
+ parsedPolicyDocument = z
354
+ . array ( policyUnion )
355
+ . parse ( JSON . parse ( policyDocument ) ) ;
356
+ }
357
+ handleCreate ( {
358
+ roles,
359
+ description,
360
+ expiresAt : expiresAt
361
+ ? Math . floor ( expiresAt . getTime ( ) / 1000 )
362
+ : undefined ,
363
+ restrictions : parsedPolicyDocument ,
364
+ } ) ;
365
+ } catch ( e ) {
366
+ console . error ( e ) ;
367
+ notifications . show ( {
368
+ title : "Invalid policy document!" ,
369
+ message : "Please correct the policy document and try again." ,
370
+ color : "red" ,
371
+ } ) ;
372
+ }
373
+ } }
323
374
disabled = { roles . length === 0 || description . trim ( ) === "" }
324
375
>
325
376
Create
0 commit comments