From 11d0080488b47fab55ff6b738cf8dbb08d2b9b1b Mon Sep 17 00:00:00 2001 From: jinapurapu <65002498+jinapurapu@users.noreply.github.com> Date: Fri, 11 Jun 2021 15:24:41 -0700 Subject: [PATCH] Move change user password modal (#806) --- .../Console/Account/ChangePasswordModal.tsx | 5 + .../Account/ChangeUserPasswordModal.tsx | 14 +- .../Console/Users/DeleteUserString.tsx | 122 ++++++++++++++++++ .../src/screens/Console/Users/ListUsers.tsx | 16 --- .../src/screens/Console/Users/UserDetails.tsx | 97 +++++++++++++- 5 files changed, 232 insertions(+), 22 deletions(-) create mode 100644 portal-ui/src/screens/Console/Users/DeleteUserString.tsx diff --git a/portal-ui/src/screens/Console/Account/ChangePasswordModal.tsx b/portal-ui/src/screens/Console/Account/ChangePasswordModal.tsx index 137bbb756..65fd67965 100644 --- a/portal-ui/src/screens/Console/Account/ChangePasswordModal.tsx +++ b/portal-ui/src/screens/Console/Account/ChangePasswordModal.tsx @@ -66,6 +66,11 @@ const ChangePassword = ({ return; } + if (newPassword.length < 8) { + setModalErrorSnackMessage("Passwords must be at least 8 characters long"); + return; + } + if (loading) { return; } diff --git a/portal-ui/src/screens/Console/Account/ChangeUserPasswordModal.tsx b/portal-ui/src/screens/Console/Account/ChangeUserPasswordModal.tsx index 02a24a3ef..73840af21 100644 --- a/portal-ui/src/screens/Console/Account/ChangeUserPasswordModal.tsx +++ b/portal-ui/src/screens/Console/Account/ChangeUserPasswordModal.tsx @@ -44,7 +44,7 @@ const styles = (theme: Theme) => interface IChangeUserPasswordProps { classes: any; open: boolean; - selectedUser: User | null; + userName: string; closeModal: () => void; setModalErrorSnackMessage: typeof setModalErrorSnackMessage; } @@ -52,7 +52,7 @@ interface IChangeUserPasswordProps { const ChangeUserPassword = ({ classes, open, - selectedUser, + userName, closeModal, setModalErrorSnackMessage, }: IChangeUserPasswordProps) => { @@ -67,9 +67,15 @@ const ChangeUserPassword = ({ return; } setLoading(true); + + if (newPassword.length < 8) { + setModalErrorSnackMessage("Passwords must be at least 8 characters long"); + setLoading(false); + return; + } let request: ChangeUserPasswordRequest = { - selectedUser: String(selectedUser?.accessKey), + selectedUser: userName, newSecretKey: newPassword, }; @@ -110,7 +116,7 @@ const ChangeUserPassword = ({ > -

Change password for {selectedUser?.accessKey}

+

Change password for {userName}

. + +import React, { useState } from "react"; +import { connect } from "react-redux"; +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, + LinearProgress, +} from "@material-ui/core"; +import api from "../../../common/api"; +import { User, UsersList } from "./types"; +import { setErrorSnackMessage } from "../../../actions"; +import history from "../../../history"; + +interface IDeleteUserProps { + closeDeleteModalAndRefresh: (refresh: boolean) => void; + deleteOpen: boolean; + userName: string; + setErrorSnackMessage: typeof setErrorSnackMessage; +} + +const DeleteUserString = ({ + closeDeleteModalAndRefresh, + deleteOpen, + userName, + setErrorSnackMessage, +}: IDeleteUserProps) => { + const [deleteLoading, setDeleteLoading] = useState(false); + + const removeRecord = () => { + if (deleteLoading) { + return; + } + if (userName == null) { + return; + } + setDeleteLoading(true); + api + .invoke("DELETE", `/api/v1/users/${userName}`, { + id: userName, + }) + .then((res: UsersList) => { + setDeleteLoading(false); + closeDeleteModalAndRefresh(true); + }) + .catch((err) => { + setDeleteLoading(false); + setErrorSnackMessage(err); + }); + }; + + if (userName === null) { + return
; + } + + return ( + { + closeDeleteModalAndRefresh(false); + }} + aria-labelledby="alert-dialog-title" + aria-describedby="alert-dialog-description" + > + Delete User + + {deleteLoading && } + + Are you sure you want to delete user {userName}? + + + + + + + + ); +}; + +const mapDispatchToProps = { + setErrorSnackMessage, +}; + +const connector = connect(null, mapDispatchToProps); + +export default connector(DeleteUserString); diff --git a/portal-ui/src/screens/Console/Users/ListUsers.tsx b/portal-ui/src/screens/Console/Users/ListUsers.tsx index 59d217748..8f2136bc9 100644 --- a/portal-ui/src/screens/Console/Users/ListUsers.tsx +++ b/portal-ui/src/screens/Console/Users/ListUsers.tsx @@ -37,7 +37,6 @@ import TableWrapper from "../Common/TableWrapper/TableWrapper"; import SetPolicy from "../Policies/SetPolicy"; import PageHeader from "../Common/PageHeader/PageHeader"; import history from "../../../history"; -import ChangeUserPasswordModal from "../Account/ChangeUserPasswordModal"; const styles = (theme: Theme) => createStyles({ @@ -91,8 +90,6 @@ const ListUsers = ({ classes, setErrorSnackMessage }: IUsersProps) => { const [filter, setFilter] = useState(""); const [checkedUsers, setCheckedUsers] = useState([]); const [policyOpen, setPolicyOpen] = useState(false); - const [ChangeUserPasswordModalOpen, setChangeUserPasswordModalOpen] = - useState(false); const fetchRecords = useCallback(() => { setLoading(true); @@ -168,14 +165,8 @@ const ListUsers = ({ classes, setErrorSnackMessage }: IUsersProps) => { const userLoggedIn = atob(localStorage.getItem("userLoggedIn") || ""); - const setNewPW = (selectionElement: any): void => { - setChangeUserPasswordModalOpen(true); - setSelectedUser(selectionElement); - }; - const tableActions = [ { type: "view", onClick: viewAction }, - { type: "edit", onClick: setNewPW }, { type: "delete", onClick: deleteAction, @@ -223,13 +214,6 @@ const ListUsers = ({ classes, setErrorSnackMessage }: IUsersProps) => { }} /> )} - {ChangeUserPasswordModalOpen && ( - setChangeUserPasswordModalOpen(false)} - selectedUser={selectedUser} - /> - )} diff --git a/portal-ui/src/screens/Console/Users/UserDetails.tsx b/portal-ui/src/screens/Console/Users/UserDetails.tsx index 5c948c857..8a8fee77f 100644 --- a/portal-ui/src/screens/Console/Users/UserDetails.tsx +++ b/portal-ui/src/screens/Console/Users/UserDetails.tsx @@ -17,7 +17,7 @@ import React, { Fragment, useCallback, useEffect, useState } from "react"; import { connect } from "react-redux"; import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; -import { Button, Grid } from "@material-ui/core"; +import { Button, Grid, IconButton, Menu, MenuItem } from "@material-ui/core"; import PageHeader from "../Common/PageHeader/PageHeader"; import { CreateIcon } from "../../../icons"; import { @@ -29,7 +29,7 @@ import { containerForHeader, searchField, } from "../Common/FormComponents/common/styleLibrary"; -import { IPolicyItem } from "./types"; +import { IPolicyItem, User, UsersList } from "./types"; import Tabs from "@material-ui/core/Tabs"; import Tab from "@material-ui/core/Tab"; import { TabPanel } from "../../shared/tabs"; @@ -42,6 +42,10 @@ import SetUserPolicies from "./SetUserPolicies"; import { Bookmark } from "@material-ui/icons"; import history from "../../../history"; import UserServiceAccountsPanel from "./UserServiceAccountsPanel"; +import MoreVertIcon from "@material-ui/icons/MoreVert"; +import ChangeUserPasswordModal from "../Account/ChangeUserPasswordModal"; +import DeleteUserString from "./DeleteUserString"; +import { usersSort } from "../../../utils/sortFunctions"; const styles = (theme: Theme) => createStyles({ @@ -134,14 +138,29 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { const [addGroupOpen, setAddGroupOpen] = useState(false); const [policyOpen, setPolicyOpen] = useState(false); const [addLoading, setAddLoading] = useState(false); + const [records, setRecords] = useState([]); const [enabled, setEnabled] = useState(false); const [selectedGroups, setSelectedGroups] = useState([]); const [currentGroups, setCurrentGroups] = useState([]); const [currentPolicies, setCurrentPolicies] = useState([]); + const [changeUserPasswordModalOpen, setChangeUserPasswordModalOpen] = + useState(false); + const [deleteOpen, setDeleteOpen] = useState(false); + const [selectedUser, setSelectedUser] = useState(null); const userName = match.params["userName"]; + const changeUserPassword = () => { + setAnchorEl(null); + setChangeUserPasswordModalOpen(true); + }; + + const deleteUser = () => { + setAnchorEl(null); + setDeleteOpen(true); + }; + const getUserInformation = useCallback(() => { if (userName === "") { return null; @@ -168,6 +187,7 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { } setCurrentPolicies(currentPolicies); setEnabled(res.status === "enabled"); + setSelectedUser(res.user); setLoading(false); }) .catch((err) => { @@ -196,12 +216,41 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { }); }; + const fetchRecords = useCallback(() => { + setLoading(true); + api + .invoke("GET", `/api/v1/users`) + .then((res: UsersList) => { + const users = res.users === null ? [] : res.users; + + setLoading(false); + setRecords(users.sort(usersSort)); + }) + .catch((err) => { + setLoading(false); + setErrorSnackMessage(err); + }); + }, [setLoading, setRecords, setErrorSnackMessage]); + + const [anchorEl, setAnchorEl] = React.useState(null); + + const handleUserMenu = (event: any) => { + setAnchorEl(event.currentTarget); + }; + useEffect(() => { getUserInformation(); }, [getUserInformation]); const userLoggedIn = atob(localStorage.getItem("userLoggedIn") || ""); + const closeDeleteModalAndRefresh = (refresh: boolean) => { + setDeleteOpen(false); + if (refresh) { + fetchRecords(); + } + }; + return ( @@ -226,6 +275,23 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { }} /> )} + {deleteOpen && ( + { + closeDeleteModalAndRefresh(refresh); + }} + /> + )} + {changeUserPasswordModalOpen && ( + setChangeUserPasswordModalOpen(false)} + /> + )} + @@ -249,10 +315,37 @@ const UserDetails = ({ classes, match }: IUserDetailsProps) => { />
+ + + + + + + Change User Password + + + Delete User + + +
+

{selectedUser != null && selectedUser.id}