github.com/argoproj/argo-cd/v3@v3.2.1/ui/src/app/settings/components/project-role-policies-edit/project-role-policies-edit.tsx (about) 1 import * as React from 'react'; 2 import * as ReactForm from 'react-form'; 3 4 import {DataLoader} from '../../../shared/components'; 5 import {Application} from '../../../shared/models'; 6 import {services} from '../../../shared/services'; 7 8 require('./project-role-policies-edit.scss'); 9 10 interface ProjectRolePoliciesProps { 11 projName: string; 12 roleName: string; 13 policies: string[]; 14 formApi: ReactForm.FormApi; 15 newRole: boolean; 16 } 17 18 function generatePolicy(project: string, role: string, resource?: string, action?: string, object?: string, permission?: string): string { 19 return `p, proj:${project}:${role}, ${resource || ''}, ${action || ''}, ${object ? project + '/' + object : ''}, ${permission || ''}`; 20 } 21 22 const actions = ['get', 'create', 'update', 'delete', 'sync', 'override']; 23 24 export const ProjectRolePoliciesEdit = (props: ProjectRolePoliciesProps) => ( 25 <DataLoader load={() => services.applications.list([props.projName], {fields: ['items.metadata.name']}).then(list => list.items)}> 26 {applications => ( 27 <React.Fragment> 28 <p>POLICY RULES</p> 29 <div>Manage this role's permissions to applications, appsets, repositories, clusters, exec and logs</div> 30 <div className='argo-table-list'> 31 <div className='argo-table-list__head'> 32 <div className='row'> 33 <div className='columns small-3'>RESOURCE</div> 34 <div className='columns small-3'>ACTION</div> 35 <div className='columns small-3'>OBJECT</div> 36 <div className='columns small-3'>PERMISSION</div> 37 </div> 38 </div> 39 <div className='argo-table-list__row'> 40 {props.policies.map((policy, i) => ( 41 <Policy 42 key={i} 43 field={['policies', i]} 44 formApi={props.formApi} 45 policy={policy} 46 projName={props.projName} 47 roleName={props.roleName} 48 deletePolicy={() => props.formApi.setValue('policies', removeEl(props.policies, i))} 49 availableApps={applications} 50 actions={actions} 51 /> 52 ))} 53 <div className='row'> 54 <div className='columns small-4'> 55 <a 56 className='argo-button argo-button--base' 57 onClick={() => { 58 const newPolicy = generatePolicy(props.projName, props.roleName); 59 props.formApi.setValue('policies', (props.formApi.values.policies || []).concat(newPolicy)); 60 }}> 61 Add policy 62 </a> 63 </div> 64 </div> 65 </div> 66 </div> 67 </React.Fragment> 68 )} 69 </DataLoader> 70 ); 71 72 interface PolicyProps { 73 projName: string; 74 roleName: string; 75 policy: string; 76 fieldApi: ReactForm.FieldApi; 77 actions: string[]; 78 availableApps: Application[]; 79 deletePolicy: () => void; 80 } 81 82 function removeEl(items: any[], index: number) { 83 items.splice(index, 1); 84 return items; 85 } 86 87 function PolicyWrapper(props: PolicyProps) { 88 const getResource = (): string => { 89 const fields = (props.fieldApi.getValue() as string).split(','); 90 if (fields.length !== 6) { 91 return ''; 92 } 93 return fields[2].trim(); 94 }; 95 96 const setResource = (resource: string) => { 97 const fields = (props.fieldApi.getValue() as string).split(','); 98 if (fields.length !== 6) { 99 props.fieldApi.setValue(generatePolicy(props.projName, props.roleName, resource, '', '', '')); 100 return; 101 } 102 fields[2] = ` ${resource}`; 103 props.fieldApi.setValue(fields.join()); 104 }; 105 106 const getAction = (): string => { 107 const fields = (props.fieldApi.getValue() as string).split(','); 108 if (fields.length !== 6) { 109 return ''; 110 } 111 return fields[3].trim(); 112 }; 113 114 const setAction = (action: string) => { 115 const fields = (props.fieldApi.getValue() as string).split(','); 116 if (fields.length !== 6) { 117 props.fieldApi.setValue(generatePolicy(props.projName, props.roleName, '', action, '', '')); 118 return; 119 } 120 fields[3] = ` ${action}`; 121 props.fieldApi.setValue(fields.join()); 122 }; 123 124 const getObject = (): string => { 125 const fields = (props.fieldApi.getValue() as string).split(','); 126 if (fields.length !== 6) { 127 return ''; 128 } 129 return fields[4].trim(); 130 }; 131 132 const setObject = (object: string) => { 133 const fields = (props.fieldApi.getValue() as string).split(','); 134 if (fields.length !== 6) { 135 props.fieldApi.setValue(generatePolicy(props.projName, props.roleName, '', '', object, '')); 136 return; 137 } 138 fields[4] = ` ${object}`; 139 props.fieldApi.setValue(fields.join()); 140 }; 141 142 const getPermission = (): string => { 143 const fields = (props.fieldApi.getValue() as string).split(','); 144 if (fields.length !== 6) { 145 return ''; 146 } 147 return fields[5].trim(); 148 }; 149 const setPermission = (permission: string) => { 150 const fields = (props.fieldApi.getValue() as string).split(','); 151 if (fields.length !== 6) { 152 props.fieldApi.setValue(generatePolicy(props.projName, props.roleName, '', '', '', permission)); 153 return; 154 } 155 fields[5] = ` ${permission}`; 156 props.fieldApi.setValue(fields.join()); 157 }; 158 159 return ( 160 <div className='row project-role-policies-edit__wrapper-row'> 161 <div className='columns small-3'> 162 <datalist id='resource'> 163 <option>applications</option> 164 <option>applicationsets</option> 165 <option>clusters</option> 166 <option>repositories</option> 167 <option>logs</option> 168 <option>exec</option> 169 </datalist> 170 <input 171 className='argo-field' 172 list='resource' 173 value={getResource()} 174 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 175 setResource(e.target.value); 176 }} 177 /> 178 </div> 179 <div className='columns small-3'> 180 <datalist id='action'> 181 {props.actions !== undefined && props.actions.length > 0 && props.actions.map(action => <option key={action}>{action}</option>)} 182 <option key='wildcard'>*</option> 183 </datalist> 184 <input 185 className='argo-field' 186 list='action' 187 value={getAction()} 188 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 189 setAction(e.target.value); 190 }} 191 /> 192 </div> 193 <div className='columns small-3'> 194 <datalist id='object'> 195 {props.availableApps !== undefined && 196 props.availableApps.length > 0 && 197 props.availableApps.map(app => ( 198 <option key={app.metadata.name}> 199 {props.projName}/{app.metadata.name} 200 </option> 201 ))} 202 <option key='wildcard'>{`${props.projName}/*`}</option> 203 </datalist> 204 <input 205 className='argo-field' 206 list='object' 207 value={getObject()} 208 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 209 setObject(e.target.value); 210 }} 211 /> 212 </div> 213 <div className='columns small-3'> 214 <datalist id='permission'> 215 <option>allow</option> 216 <option>deny</option> 217 </datalist> 218 <input 219 className='argo-field' 220 list='permission' 221 value={getPermission()} 222 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 223 setPermission(e.target.value); 224 }} 225 /> 226 </div> 227 <div style={{position: 'absolute', right: '0.5em'}}> 228 <i className='fa fa-times' onClick={() => props.deletePolicy()} style={{cursor: 'pointer'}} /> 229 </div> 230 </div> 231 ); 232 } 233 234 const Policy = ReactForm.FormField(PolicyWrapper);