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