github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/lib/components/policy.jsx (about)

     1  import React, {useEffect, useRef, useState} from "react";
     2  
     3  import Table from "react-bootstrap/Table";
     4  import Modal from "react-bootstrap/Modal";
     5  import Form from "react-bootstrap/Form";
     6  import {FormControl} from "react-bootstrap";
     7  import Button from "react-bootstrap/Button";
     8  import {AlertError, FormattedDate} from "./controls";
     9  
    10  export const PolicyEditor = ({ show, onHide, onSubmit, policy = null, noID = false, isCreate = false, validationFunction = null, externalError = null }) => {
    11      const [error, setError] = useState(null);
    12      const idField = useRef(null);
    13      const bodyField = useRef(null);
    14  
    15      useEffect(() => {
    16          if (policy === null && !!idField.current && idField.current.value === "")
    17              idField.current.focus();
    18      });
    19  
    20      const [body, setBody] = useState('')
    21      useEffect(() => {
    22          if (policy !== null) {
    23          const newBody = JSON.stringify(policy, null, 4);
    24              setBody(newBody);
    25          setSavedBody(newBody);
    26          }
    27      }, [policy]);
    28  
    29      const [savedBody, setSavedBody] = useState(null);
    30  
    31      const submit = () => {
    32          if (validationFunction) {
    33              const validationResult = validationFunction(idField.current.value);
    34              if (!validationResult.isValid) {
    35                  setError(validationResult.errorMessage);
    36                  return;
    37              }
    38          }
    39          const statement = bodyField.current.value;
    40          try {
    41              JSON.parse(statement);
    42          } catch (error) {
    43              setError(error);
    44          return false;
    45          }
    46          const promise = (policy === null) ? onSubmit(idField.current.value, statement) : onSubmit(statement)
    47          return promise
    48          .then((res) => {
    49          setSavedBody(statement);
    50          setError(null);
    51          return res;
    52          })
    53          .catch((err) => {
    54          setError(err);
    55          return null;
    56          });
    57      };
    58  
    59      const hide = () => {
    60          setError(null);
    61      if (savedBody !== null) {
    62          setBody(savedBody);
    63      }
    64          onHide();
    65      };
    66      const actionName = policy === null || isCreate ? 'Create' : 'Edit'
    67      return (
    68          <Modal show={show} onHide={hide}>
    69              <Modal.Header closeButton>
    70                  <Modal.Title>{actionName} Policy</Modal.Title>
    71              </Modal.Header>
    72  
    73              <Modal.Body>
    74                  <Form onSubmit={e => {
    75                      e.preventDefault();
    76                      submit();
    77                  }}>
    78                      {(policy === null) && !noID && (
    79                          <Form.Group className="mb-3">
    80                              <FormControl ref={idField} autoFocus placeholder="Policy ID (e.g. 'MyRepoReadWrite')" type="text"/>
    81                          </Form.Group>
    82                      )}
    83                      <Form.Group className="mb-3">
    84                          <FormControl
    85                              className="policy-document"
    86                              ref={bodyField}
    87                              placeholder="Policy JSON Document"
    88                              rows={15}
    89                              as="textarea"
    90                              type="text"
    91                              onChange={e => setBody(e.target.value)}
    92                              value={body}/>
    93                      </Form.Group>
    94                  </Form>
    95  
    96                  {(!!error) && <AlertError className="mt-3" error={error}/>}
    97                  {(!!externalError) && <AlertError className="mt-3" error={externalError}/>}
    98  
    99              </Modal.Body>
   100  
   101              <Modal.Footer>
   102                  <Button onClick={submit} variant="success">Save</Button>
   103                  <Button onClick={hide} variant="secondary">Cancel</Button>
   104              </Modal.Footer>
   105          </Modal>
   106      );
   107  };
   108  
   109  export const PolicyDisplay = ({ policy, asJSON }) => {
   110      let childComponent;
   111      if (asJSON) {
   112          childComponent = (<pre className={"policy-body"}>{JSON.stringify({statement: policy.statement}, null, 4)}</pre>);
   113      } else {
   114          childComponent = (
   115              <Table>
   116                  <thead>
   117                  <tr>
   118                      <th>Actions</th>
   119                      <th>Resource</th>
   120                      <th>Effect</th>
   121                  </tr>
   122                  </thead>
   123                  <tbody>
   124                  {policy.statement.map((statement, i) => {
   125                      return (
   126                          <tr key={`statement-${i}`}>
   127                              <td><code>{statement.action.join(", ")}</code></td>
   128                              <td><code>{statement.resource}</code></td>
   129                              <td><strong style={{'color': (statement.effect === "allow") ? 'green':'red'}}>{statement.effect}</strong></td>
   130                          </tr>
   131                      );
   132                  })}
   133                  </tbody>
   134              </Table>
   135  
   136          );
   137      }
   138  
   139      return (
   140          <div>
   141              <p>
   142                  <strong>Created At: </strong>
   143                  <FormattedDate dateValue={policy.creation_date}/>
   144              </p>
   145              {childComponent}
   146          </div>
   147      );
   148  };