github.com/minio/console@v1.4.1/web-app/src/screens/Console/KMS/ListKeys.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, { useEffect, useState } from "react";
    18  import {
    19    AddIcon,
    20    Button,
    21    DataTable,
    22    Grid,
    23    PageLayout,
    24    RefreshIcon,
    25    UploadIcon,
    26  } from "mds";
    27  import { useNavigate } from "react-router-dom";
    28  import api from "../../../common/api";
    29  import {
    30    hasPermission,
    31    SecureComponent,
    32  } from "../../../common/SecureComponent";
    33  import {
    34    CONSOLE_UI_RESOURCE,
    35    IAM_PAGES,
    36    IAM_SCOPES,
    37  } from "../../../common/SecureComponent/permissions";
    38  import { ErrorResponseHandler } from "../../../common/types";
    39  import { useAppDispatch } from "../../../store";
    40  import { setErrorSnackMessage, setHelpName } from "../../../systemSlice";
    41  import withSuspense from "../Common/Components/withSuspense";
    42  import SearchBox from "../Common/SearchBox";
    43  import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
    44  import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
    45  import HelpMenu from "../HelpMenu";
    46  
    47  const DeleteKMSModal = withSuspense(
    48    React.lazy(() => import("./DeleteKMSModal")),
    49  );
    50  
    51  const ListKeys = () => {
    52    const dispatch = useAppDispatch();
    53    const navigate = useNavigate();
    54  
    55    const [filter, setFilter] = useState<string>("");
    56    const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
    57    const [selectedKey, setSelectedKey] = useState<string>("");
    58    const [loading, setLoading] = useState<boolean>(false);
    59    const [records, setRecords] = useState<[]>([]);
    60  
    61    const deleteKey = hasPermission(CONSOLE_UI_RESOURCE, [
    62      IAM_SCOPES.KMS_DELETE_KEY,
    63    ]);
    64    const createKey = hasPermission(CONSOLE_UI_RESOURCE, [
    65      IAM_SCOPES.KMS_CREATE_KEY,
    66    ]);
    67  
    68    const importKey = hasPermission(CONSOLE_UI_RESOURCE, [
    69      IAM_SCOPES.KMS_IMPORT_KEY,
    70    ]);
    71  
    72    const displayKeys = hasPermission(CONSOLE_UI_RESOURCE, [
    73      IAM_SCOPES.KMS_LIST_KEYS,
    74    ]);
    75  
    76    useEffect(() => {
    77      fetchRecords();
    78    }, []);
    79  
    80    useEffect(() => {
    81      setLoading(true);
    82    }, [filter]);
    83  
    84    useEffect(() => {
    85      if (loading) {
    86        if (displayKeys) {
    87          let pattern = filter.trim() === "" ? "*" : filter.trim();
    88          api
    89            .invoke("GET", `/api/v1/kms/keys?pattern=${pattern}`)
    90            .then((res) => {
    91              setLoading(false);
    92              setRecords(res.results);
    93            })
    94            .catch((err: ErrorResponseHandler) => {
    95              setLoading(false);
    96              dispatch(setErrorSnackMessage(err));
    97            });
    98        } else {
    99          setLoading(false);
   100        }
   101      }
   102    }, [loading, setLoading, setRecords, dispatch, displayKeys, filter]);
   103  
   104    const fetchRecords = () => {
   105      setLoading(true);
   106    };
   107  
   108    const confirmDeleteKey = (key: string) => {
   109      setDeleteOpen(true);
   110      setSelectedKey(key);
   111    };
   112  
   113    const closeDeleteModalAndRefresh = (refresh: boolean) => {
   114      setDeleteOpen(false);
   115  
   116      if (refresh) {
   117        fetchRecords();
   118      }
   119    };
   120  
   121    const tableActions: any[] = [];
   122    if (deleteKey) {
   123      tableActions.push({
   124        type: "delete",
   125        onClick: confirmDeleteKey,
   126        sendOnlyId: true,
   127        disableButtonFunction: () => !deleteKey,
   128      });
   129    }
   130  
   131    useEffect(() => {
   132      dispatch(setHelpName("list_keys"));
   133    }, [dispatch]);
   134  
   135    return (
   136      <React.Fragment>
   137        {deleteOpen && (
   138          <DeleteKMSModal
   139            deleteOpen={deleteOpen}
   140            selectedItem={selectedKey}
   141            closeDeleteModalAndRefresh={closeDeleteModalAndRefresh}
   142          />
   143        )}
   144        <PageHeaderWrapper
   145          label="Key Management Service Keys"
   146          actions={<HelpMenu />}
   147        />
   148  
   149        <PageLayout>
   150          <Grid container>
   151            <Grid
   152              item
   153              xs={12}
   154              sx={{
   155                display: "flex",
   156                alignItems: "center",
   157                justifyContent: "flex-end",
   158                "& button": {
   159                  marginLeft: "8px",
   160                },
   161              }}
   162            >
   163              <SecureComponent
   164                scopes={[IAM_SCOPES.KMS_LIST_KEYS]}
   165                resource={CONSOLE_UI_RESOURCE}
   166                errorProps={{ disabled: true }}
   167              >
   168                <SearchBox
   169                  onChange={setFilter}
   170                  placeholder="Search Keys with pattern"
   171                  value={filter}
   172                />
   173              </SecureComponent>
   174  
   175              <SecureComponent
   176                scopes={[IAM_SCOPES.KMS_LIST_KEYS]}
   177                resource={CONSOLE_UI_RESOURCE}
   178                errorProps={{ disabled: true }}
   179              >
   180                <TooltipWrapper tooltip={"Refresh"}>
   181                  <Button
   182                    id={"refresh-keys"}
   183                    variant="regular"
   184                    icon={<RefreshIcon />}
   185                    onClick={() => setLoading(true)}
   186                  />
   187                </TooltipWrapper>
   188              </SecureComponent>
   189              {importKey ? (
   190                <SecureComponent
   191                  scopes={[IAM_SCOPES.KMS_IMPORT_KEY]}
   192                  resource={CONSOLE_UI_RESOURCE}
   193                  errorProps={{ disabled: true }}
   194                >
   195                  <TooltipWrapper tooltip={"Import Key"}>
   196                    <Button
   197                      id={"import-key"}
   198                      variant={"regular"}
   199                      icon={<UploadIcon />}
   200                      onClick={() => {
   201                        navigate(IAM_PAGES.KMS_KEYS_IMPORT);
   202                      }}
   203                    />
   204                  </TooltipWrapper>
   205                </SecureComponent>
   206              ) : null}
   207              {createKey ? (
   208                <SecureComponent
   209                  scopes={[IAM_SCOPES.KMS_CREATE_KEY]}
   210                  resource={CONSOLE_UI_RESOURCE}
   211                  errorProps={{ disabled: true }}
   212                >
   213                  <TooltipWrapper tooltip={"Create Key"}>
   214                    <Button
   215                      id={"create-key"}
   216                      label={"Create Key"}
   217                      variant={"callAction"}
   218                      icon={<AddIcon />}
   219                      onClick={() => navigate(IAM_PAGES.KMS_KEYS_ADD)}
   220                    />
   221                  </TooltipWrapper>
   222                </SecureComponent>
   223              ) : null}
   224            </Grid>
   225            <Grid item xs={12} sx={{ marginTop: "5px" }}>
   226              <SecureComponent
   227                scopes={[IAM_SCOPES.KMS_LIST_KEYS]}
   228                resource={CONSOLE_UI_RESOURCE}
   229                errorProps={{ disabled: true }}
   230              >
   231                <DataTable
   232                  itemActions={tableActions}
   233                  columns={[
   234                    { label: "Name", elementKey: "name" },
   235                    { label: "Created By", elementKey: "createdBy" },
   236                    { label: "Created At", elementKey: "createdAt" },
   237                  ]}
   238                  isLoading={loading}
   239                  records={records}
   240                  entityName="Keys"
   241                  idField="name"
   242                />
   243              </SecureComponent>
   244            </Grid>
   245          </Grid>
   246        </PageLayout>
   247      </React.Fragment>
   248    );
   249  };
   250  
   251  export default ListKeys;