From 37195fefa8361771959e5e106d3206f6d216b25f Mon Sep 17 00:00:00 2001 From: Daniel Valdivia Date: Fri, 22 May 2020 08:48:55 -0700 Subject: [PATCH] Set Policy UI (#138) --- .../Common/TableWrapper/TableActionButton.tsx | 6 +- .../Common/TableWrapper/TableWrapper.tsx | 2 +- .../screens/Console/Policies/SetPolicy.tsx | 201 ++++++++++++++++++ portal-ui/src/screens/Console/Users/Users.tsx | 23 ++ portal-ui/src/utils/sortFunctions.ts | 15 ++ 5 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 portal-ui/src/screens/Console/Policies/SetPolicy.tsx diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionButton.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionButton.tsx index d07034ec6..2ef25bf6b 100644 --- a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionButton.tsx +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionButton.tsx @@ -20,6 +20,7 @@ import ViewIcon from "./TableActionIcons/ViewIcon"; import PencilIcon from "./TableActionIcons/PencilIcon"; import DeleteIcon from "./TableActionIcons/DeleteIcon"; import { Link } from "react-router-dom"; +import DescriptionIcon from "@material-ui/icons/Description"; interface IActionButton { type: string; @@ -39,6 +40,8 @@ const defineIcon = (type: string, selected: boolean) => { return ; case "delete": return ; + case "description": + return ; } return null; @@ -51,13 +54,14 @@ const TableActionButton = ({ idField, selected, to, - sendOnlyId = false + sendOnlyId = false, }: IActionButton) => { const valueClick = sendOnlyId ? valueToSend[idField] : valueToSend; const buttonElement = ( { diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx index a9e1aea58..85fb6e799 100644 --- a/portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx @@ -130,7 +130,7 @@ const styles = (theme: Theme) => }, }, actionsContainer: { - width: 120, + width: 150, borderColor: borderColor, }, paginatorComponent: { diff --git a/portal-ui/src/screens/Console/Policies/SetPolicy.tsx b/portal-ui/src/screens/Console/Policies/SetPolicy.tsx new file mode 100644 index 000000000..ea99aca99 --- /dev/null +++ b/portal-ui/src/screens/Console/Policies/SetPolicy.tsx @@ -0,0 +1,201 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import React, { useCallback, useEffect, useState } from "react"; +import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; +import { + Button, + FormControlLabel, + LinearProgress, + Paper, + Switch, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, +} from "@material-ui/core"; +import Grid from "@material-ui/core/Grid"; +import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import { RadioGroupSelector } from "../Common/FormComponents/RadioGroupSelector/RadioGroupSelector"; +import { modalBasic } from "../Common/FormComponents/common/styleLibrary"; +import { IElementValue } from "../Configurations/types"; +import { User } from "../Users/types"; +import ModalWrapper from "../Common/ModalWrapper/ModalWrapper"; +import { Policy, PolicyList } from "./types"; +import api from "../../../common/api"; +import { policySort } from "../../../utils/sortFunctions"; + +interface ISetPolicyProps { + classes: any; + closeModalAndRefresh: () => void; + selectedUser: User | null; + open: boolean; +} + +const styles = (theme: Theme) => + createStyles({ + ...modalBasic, + }); + +const SetPolicy = ({ + classes, + closeModalAndRefresh, + selectedUser, + open, +}: ISetPolicyProps) => { + //Local States + const [useConnectionString, setUseConnectionString] = useState( + false + ); + const [connectionString, setConnectionString] = useState(""); + const [host, setHostname] = useState(""); + const [dbName, setDbName] = useState(""); + const [port, setPort] = useState(""); + const [user, setUser] = useState(""); + const [password, setPassword] = useState(""); + const [sslMode, setSslMode] = useState("require"); + + const [table, setTable] = useState(""); + const [format, setFormat] = useState("namespace"); + const [queueDir, setQueueDir] = useState(""); + const [queueLimit, setQueueLimit] = useState(""); + const [comment, setComment] = useState(""); + + const [records, setRecords] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + + const fetchRecords = () => { + setLoading(true); + + api + .invoke("GET", `/api/v1/policies?limit=1000`) + .then((res: PolicyList) => { + const policies = res.policies === null ? [] : res.policies; + setLoading(false); + setRecords(policies.sort(policySort)); + setError(""); + }) + .catch((err) => { + setLoading(false); + setError(err); + }); + }; + + const setPolicyAction = (policyName: string) => { + if (selectedUser === null) { + return; + } + setLoading(true); + + api + .invoke("PUT", `/api/v1/set-policy/${policyName}`, { + entityName: selectedUser!.accessKey, + entityType: "user", + }) + .then((res: any) => { + setLoading(false); + setError(""); + closeModalAndRefresh(); + }) + .catch((err) => { + setLoading(false); + setError(err); + }); + }; + + useEffect(() => { + if (open) { + console.log("im open"); + console.log(selectedUser); + fetchRecords(); + } + }, []); + + return ( + { + closeModalAndRefresh(); + }} + modalOpen={open} + title={ + selectedUser !== null ? "Set Policy to User" : "Set Policy to Group" + } + > + + + + + + + Policy + + + + + {records.map((row) => ( + + + {row.name} + + + + + + ))} + +
+
+
+ + + + {loading && ( + + + + )} +
+
+ ); +}; + +export default withStyles(styles)(SetPolicy); diff --git a/portal-ui/src/screens/Console/Users/Users.tsx b/portal-ui/src/screens/Console/Users/Users.tsx index 113d0df83..aefbb7032 100644 --- a/portal-ui/src/screens/Console/Users/Users.tsx +++ b/portal-ui/src/screens/Console/Users/Users.tsx @@ -34,6 +34,8 @@ import AddUser from "./AddUser"; import DeleteUser from "./DeleteUser"; import AddToGroup from "./AddToGroup"; import TableWrapper from "../Common/TableWrapper/TableWrapper"; +import DescriptionIcon from "@material-ui/icons/Description"; +import SetPolicy from "../Policies/SetPolicy"; const styles = (theme: Theme) => createStyles({ @@ -102,6 +104,7 @@ interface IUsersState { addGroupOpen: boolean; filter: string; checkedUsers: string[]; + setPolicyOpen: boolean; } class Users extends React.Component { @@ -119,6 +122,7 @@ class Users extends React.Component { addGroupOpen: false, filter: "", checkedUsers: [], + setPolicyOpen: false, }; fetchRecords() { @@ -192,6 +196,7 @@ class Users extends React.Component { filter, checkedUsers, addGroupOpen, + setPolicyOpen, } = this.state; const handleChangePage = (event: unknown, newPage: number) => { @@ -243,6 +248,14 @@ class Users extends React.Component { }); }; + const setPolicyAction = (selectionElement: any): void => { + console.log("click"); + this.setState({ + setPolicyOpen: true, + selectedUser: selectionElement, + }); + }; + const deleteAction = (selectionElement: any): void => { this.setState({ deleteOpen: true, @@ -251,6 +264,7 @@ class Users extends React.Component { }; const tableActions = [ + { type: "description", onClick: setPolicyAction }, { type: "view", onClick: viewAction }, { type: "delete", onClick: deleteAction }, ]; @@ -266,6 +280,15 @@ class Users extends React.Component { }} /> )} + {setPolicyOpen && ( + { + this.setState({ setPolicyOpen: false }); + }} + /> + )} {deleteOpen && ( { if (a.accessKey > b.accessKey) { return 1; @@ -29,6 +33,17 @@ export const usersSort = (a: userInterface, b: userInterface) => { return 0; }; +export const policySort = (a: policyInterface, b: policyInterface) => { + if (a.name > b.name) { + return 1; + } + if (a.name < b.name) { + return -1; + } + // a must be equal to b + return 0; +}; + export const stringSort = (a: string, b: string) => { if (a > b) { return 1;