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