github.com/argoproj/argo-cd@v1.8.7/ui/src/app/settings/components/project-role-jwt-tokens/project-role-jwt-tokens.tsx (about) 1 import {FormField, Tooltip} from 'argo-ui'; 2 import * as React from 'react'; 3 import {Form, FormApi, Text} from 'react-form'; 4 5 import {Consumer, ContextApis} from '../../../shared/context'; 6 import {JwtToken} from '../../../shared/models'; 7 import {CreateJWTTokenParams, DeleteJWTTokenParams} from '../../../shared/services'; 8 import {convertExpiresInToSeconds, validExpiresIn} from '../utils'; 9 10 interface ProjectRoleJWTTokensProps { 11 projName: string; 12 roleName: string; 13 tokens: JwtToken[]; 14 token: string; 15 createJWTToken: (params: CreateJWTTokenParams) => void; 16 deleteJWTToken: (params: DeleteJWTTokenParams) => void; 17 hideJWTToken: () => void; 18 getApi?: (formApi: FormApi) => void; 19 } 20 21 require('./project-role-jwt-tokens.scss'); 22 23 export const ProjectRoleJWTTokens = (props: ProjectRoleJWTTokensProps) => { 24 return ( 25 <Consumer> 26 {ctx => ( 27 <React.Fragment> 28 <h4>JWT Tokens</h4> 29 <div>Generate JWT tokens to bind to this role</div> 30 {props.tokens && props.tokens.length > 0 && ( 31 <div className='argo-table-list'> 32 <div className='argo-table-list__head'> 33 <div className='row'> 34 <div className='columns small-3'>ID</div> 35 <div className='columns small-4'>ISSUED AT</div> 36 <div className='columns small-4'>EXPIRES AT</div> 37 </div> 38 </div> 39 {props.tokens.map(jwToken => renderJWTRow(props, ctx, jwToken))} 40 </div> 41 )} 42 <Form 43 getApi={props.getApi} 44 defaultValues={{expiresIn: ''}} 45 validateError={(params: any) => ({ 46 expiresIn: !validExpiresIn(params.expiresIn) && 'Must be in the "[0-9]+[smhd]" format. For example, "12h", "7d".' 47 })}> 48 {api => ( 49 <form onSubmit={api.submitForm} role='form' className='width-control'> 50 <div className='white-box'> 51 <div className='argo-table-list'> 52 <div className='argo-form-row'> 53 <FormField formApi={api} label='Token ID' field='id' component={Text} /> 54 </div> 55 <div className='argo-form-row'> 56 <FormField formApi={api} label='Expires In' field='expiresIn' component={Text} /> 57 </div> 58 59 <div> 60 <button className='argo-button argo-button--base' onClick={() => createJWTToken(props, api, ctx)}> 61 Create 62 </button> 63 </div> 64 </div> 65 </div> 66 67 {props.token && ( 68 <div className='argo-table-list'> 69 <div className='argo-table-list__head'> 70 <div className='row'> 71 <div className='columns small-3'>NEW TOKEN</div> 72 </div> 73 </div> 74 <div className='argo-table-list__row'> 75 <div className='white-box'> 76 <p style={{overflowWrap: 'break-word'}}> 77 {props.token} 78 <i className='fa fa-times project-role-jwt-tokens__hide-token' onClick={() => props.hideJWTToken()} /> 79 </p> 80 </div> 81 </div> 82 </div> 83 )} 84 </form> 85 )} 86 </Form> 87 </React.Fragment> 88 )} 89 </Consumer> 90 ); 91 }; 92 93 async function createJWTToken(props: ProjectRoleJWTTokensProps, api: FormApi, ctx: any) { 94 if (api.errors.expiresIn) { 95 return; 96 } 97 const project = props.projName; 98 const role = props.roleName; 99 const expiresIn = convertExpiresInToSeconds(api.values.expiresIn); 100 let expiresInPrompt = 'has no expiration'; 101 if (expiresIn !== 0) { 102 expiresInPrompt = 'expires in ' + api.values.expiresIn; 103 } 104 const id = api.values.id; 105 const nameContext = id === undefined || id === '' ? ` has no token ID and ` : ` has token ID '${id}' and `; 106 const confirmed = await ctx.popup.confirm( 107 'Create JWT Token', 108 `Are you sure you want to create a JWT token that ${nameContext}${expiresInPrompt} for role '${role}' in project '${project}'?` 109 ); 110 if (confirmed) { 111 props.createJWTToken({project, role, expiresIn, id} as CreateJWTTokenParams); 112 api.values.expiresIn = ''; 113 api.values.id = ''; 114 } 115 } 116 117 async function deleteJWTToken(props: ProjectRoleJWTTokensProps, iat: number, ctx: any, id: string) { 118 const confirmed = await ctx.popup.confirm('Delete JWT Token', `Are you sure you want to delete token ID '${id}' for role '${props.roleName}' in project '${props.projName}'?`); 119 if (confirmed) { 120 props.deleteJWTToken({project: props.projName, role: props.roleName, iat} as DeleteJWTTokenParams); 121 } 122 } 123 124 function renderJWTRow(props: ProjectRoleJWTTokensProps, ctx: ContextApis, jwToken: JwtToken): React.ReactFragment { 125 const issuedAt = new Date(jwToken.iat * 1000).toISOString(); 126 const expiresAt = jwToken.exp == null ? 'Never' : new Date(jwToken.exp * 1000).toISOString(); 127 128 return ( 129 <React.Fragment> 130 <div className='argo-table-list__row' key={`${jwToken.iat}`}> 131 <div className='row'> 132 <Tooltip content={jwToken.id}> 133 <div className='columns small-3'>{jwToken.id}</div> 134 </Tooltip> 135 <Tooltip content={issuedAt}> 136 <div className='columns small-4'>{issuedAt}</div> 137 </Tooltip> 138 <Tooltip content={expiresAt}> 139 <div className='columns small-4'>{expiresAt}</div> 140 </Tooltip> 141 <Tooltip content='Delete Token'> 142 <div className='columns small-1'> 143 <i className='fa fa-times' onClick={() => deleteJWTToken(props, jwToken.iat, ctx, jwToken.id)} style={{cursor: 'pointer'}} /> 144 </div> 145 </Tooltip> 146 </div> 147 </div> 148 </React.Fragment> 149 ); 150 }