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);