github.com/minio/console@v1.4.1/web-app/src/screens/Console/Policies/PolicyView.tsx (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2022 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  import React, { Fragment, useState } from "react";
    18  import { DisabledIcon, EnabledIcon, Box, Grid, HelpTip } from "mds";
    19  import SearchBox from "../Common/SearchBox";
    20  import { STATUS_COLORS } from "../Dashboard/BasicDashboard/Utils";
    21  import { IAMStatement } from "./types";
    22  
    23  const rowGridStyle = {
    24    display: "grid",
    25    gridTemplateColumns: "70px 1fr",
    26    gap: 15,
    27  };
    28  
    29  const escapeRegExp = (str = "") =>
    30    str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
    31  
    32  const Highlight = ({ search = "", children = "" }): any => {
    33    const txtParts = new RegExp(`(${escapeRegExp(search)})`, "i");
    34    const parts = String(children).split(txtParts);
    35  
    36    if (search) {
    37      return parts.map((part, index) =>
    38        txtParts.test(part) ? <mark key={index}>{part}</mark> : part,
    39      );
    40    } else {
    41      return children;
    42    }
    43  };
    44  
    45  const PolicyView = ({
    46    policyStatements,
    47  }: {
    48    policyStatements: IAMStatement[];
    49  }) => {
    50    const [filter, setFilter] = useState<string>("");
    51  
    52    return (
    53      <Grid container>
    54        <Grid item xs={12}>
    55          <Grid container sx={{ display: "flex", alignItems: "center" }}>
    56            <HelpTip
    57              content={
    58                <Fragment>
    59                  Define which actions are permitted on a specified resource.
    60                  Learn more about{" "}
    61                  <a
    62                    target="blank"
    63                    href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html"
    64                  >
    65                    IAM conditional statements
    66                  </a>
    67                  .
    68                </Fragment>
    69              }
    70              placement="right"
    71            >
    72              <Grid item xs={12} sm={6} sx={{ fontWeight: "bold" }}>
    73                Statements
    74              </Grid>
    75            </HelpTip>
    76            <Grid
    77              item
    78              xs={12}
    79              sm={6}
    80              sx={{ display: "flex", justifyContent: "flex-end" }}
    81            >
    82              <SearchBox
    83                placeholder={"Search"}
    84                onChange={setFilter}
    85                value={filter}
    86                sx={{
    87                  maxWidth: 380,
    88                }}
    89              />
    90            </Grid>
    91          </Grid>
    92        </Grid>
    93        {!policyStatements && <Fragment>Policy has no statements</Fragment>}
    94        {policyStatements && (
    95          <Grid
    96            item
    97            xs={12}
    98            sx={{
    99              "& .policy-row": {
   100                borderBottom: "1px solid #eaeaea",
   101              },
   102              "& .policy-row:first-child": {
   103                borderTop: "1px solid #eaeaea",
   104              },
   105              "& .policy-row:last-child": {
   106                borderBottom: "0px",
   107              },
   108              paddingTop: "15px",
   109              "& mark": {
   110                color: "#000000",
   111                fontWeight: 500,
   112              },
   113            }}
   114          >
   115            {policyStatements.map((stmt, i) => {
   116              const effect = stmt.Effect;
   117              const isAllow = effect === "Allow";
   118              return (
   119                <Box
   120                  className="policy-row"
   121                  key={`${i}`}
   122                  sx={{
   123                    display: "grid",
   124                    gridTemplateColumns: "1fr",
   125                    gap: "15px",
   126                    fontSize: "14px",
   127                    padding: "10px 0 10px 0",
   128                    "& .label": {
   129                      fontWeight: 600,
   130                    },
   131                  }}
   132                >
   133                  <Box sx={rowGridStyle}>
   134                    <Box className="label">Effect:</Box>
   135                    <Box
   136                      sx={{
   137                        display: "flex",
   138  
   139                        alignItems: "center",
   140                        "& .min-icon": {
   141                          marginRight: "5px",
   142                          fill: isAllow ? STATUS_COLORS.GREEN : STATUS_COLORS.RED,
   143                          height: "14px",
   144                          width: "14px",
   145                        },
   146                      }}
   147                    >
   148                      {isAllow ? <EnabledIcon /> : <DisabledIcon />}
   149                      {effect}
   150                    </Box>
   151                  </Box>
   152                  <Grid container sx={{ gap: 15 }}>
   153                    <Grid item xs={12} sm={6} sx={rowGridStyle}>
   154                      <Box className="label">Actions:</Box>
   155                      <Box>
   156                        {stmt.Action &&
   157                          stmt.Action.map((act, actIndex) => (
   158                            <div key={`${i}-r-${actIndex}`}>
   159                              <Highlight search={filter}>{act}</Highlight>
   160                            </div>
   161                          ))}
   162                      </Box>
   163                    </Grid>
   164                    <Grid item xs={12} sm={6} sx={rowGridStyle}>
   165                      <Box className="label">Resources:</Box>
   166                      <Box>
   167                        {stmt.Resource &&
   168                          stmt.Resource.map((res, resIndex) => (
   169                            <div key={`${i}-r-${resIndex}`}>
   170                              {" "}
   171                              <Highlight search={filter}>{res}</Highlight>
   172                            </div>
   173                          ))}
   174                      </Box>
   175                    </Grid>
   176                  </Grid>
   177                </Box>
   178              );
   179            })}
   180          </Grid>
   181        )}
   182      </Grid>
   183    );
   184  };
   185  
   186  export default PolicyView;