11import {
2+ Alert ,
23 Badge ,
34 Button ,
45 Center ,
56 Checkbox ,
67 Code ,
78 CopyButton ,
89 Group ,
10+ JsonInput ,
911 List ,
1012 Modal ,
1113 MultiSelect ,
@@ -18,6 +20,7 @@ import { DateTimePicker } from "@mantine/dates";
1820import {
1921 IconAlertCircle ,
2022 IconEye ,
23+ IconHandStop ,
2124 IconPlus ,
2225 IconTrash ,
2326} from "@tabler/icons-react" ;
@@ -26,13 +29,15 @@ import {
2629 apiKeyAllowedRoles ,
2730 ApiKeyMaskedEntry ,
2831 ApiKeyPostBody ,
32+ policyUnion ,
2933} from "@common/types/apiKey" ;
3034import { useAuth } from "@ui/components/AuthContext" ;
3135import { notifications } from "@mantine/notifications" ;
3236import pluralize from "pluralize" ;
3337import dayjs from "dayjs" ;
3438import { AppRoles } from "@common/roles" ;
3539import { BlurredTextDisplay } from "../../components/BlurredTextDisplay" ;
40+ import { z } from "zod" ;
3641
3742const HumanFriendlyDate = ( { date } : { date : number } ) => {
3843 return (
@@ -131,8 +136,8 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
131136 await fetchKeys ( ) ;
132137 } catch ( e ) {
133138 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 ." ,
136141 color : "red" ,
137142 } ) ;
138143 }
@@ -188,6 +193,7 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
188193 const [ roles , setRoles ] = useState < AppRoles [ ] > ( [ ] ) ;
189194 const [ description , setDescription ] = useState ( "" ) ;
190195 const [ expiresAt , setExpiresAt ] = useState < Date | null > ( null ) ;
196+ const [ policyDocument , setPolicyDocument ] = useState ( "" ) ;
191197
192198 return (
193199 < >
@@ -309,17 +315,62 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
309315 clearable
310316 mt = "md"
311317 />
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+ />
312347 < Group justify = "flex-end" mt = "lg" >
313348 < 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+ } }
323374 disabled = { roles . length === 0 || description . trim ( ) === "" }
324375 >
325376 Create
0 commit comments