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;