github.com/minio/console@v1.4.1/web-app/src/screens/Console/Account/ChangePasswordModal.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 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 { 19 Button, 20 ChangePasswordIcon, 21 InputBox, 22 Grid, 23 FormLayout, 24 ProgressBar, 25 InformativeMessage, 26 } from "mds"; 27 import ModalWrapper from "../Common/ModalWrapper/ModalWrapper"; 28 29 import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary"; 30 import { 31 setErrorSnackMessage, 32 setModalErrorSnackMessage, 33 setSnackBarMessage, 34 } from "../../../systemSlice"; 35 import { useAppDispatch } from "../../../store"; 36 import { api } from "api"; 37 import { AccountChangePasswordRequest, ApiError } from "api/consoleApi"; 38 import { errorToHandler } from "api/errors"; 39 40 interface IChangePasswordProps { 41 open: boolean; 42 closeModal: () => void; 43 } 44 45 const ChangePassword = ({ open, closeModal }: IChangePasswordProps) => { 46 const dispatch = useAppDispatch(); 47 const [currentPassword, setCurrentPassword] = useState<string>(""); 48 const [newPassword, setNewPassword] = useState<string>(""); 49 const [reNewPassword, setReNewPassword] = useState<string>(""); 50 const [loading, setLoading] = useState<boolean>(false); 51 52 const userLoggedIn = localStorage.getItem("userLoggedIn") || ""; 53 54 const changePassword = (event: React.FormEvent) => { 55 event.preventDefault(); 56 57 if (newPassword !== reNewPassword) { 58 dispatch( 59 setModalErrorSnackMessage({ 60 errorMessage: "New passwords don't match", 61 detailedError: "", 62 }), 63 ); 64 return; 65 } 66 67 if (newPassword.length < 8) { 68 dispatch( 69 setModalErrorSnackMessage({ 70 errorMessage: "Passwords must be at least 8 characters long", 71 detailedError: "", 72 }), 73 ); 74 return; 75 } 76 77 if (loading) { 78 return; 79 } 80 setLoading(true); 81 82 let request: AccountChangePasswordRequest = { 83 current_secret_key: currentPassword, 84 new_secret_key: newPassword, 85 }; 86 87 api.account 88 .accountChangePassword(request) 89 .then(() => { 90 setLoading(false); 91 setNewPassword(""); 92 setReNewPassword(""); 93 setCurrentPassword(""); 94 dispatch(setSnackBarMessage("Successfully updated the password.")); 95 closeModal(); 96 }) 97 .catch(async (res) => { 98 setLoading(false); 99 setNewPassword(""); 100 setReNewPassword(""); 101 setCurrentPassword(""); 102 const err = (await res.json()) as ApiError; 103 dispatch(setErrorSnackMessage(errorToHandler(err))); 104 }); 105 }; 106 107 return open ? ( 108 <ModalWrapper 109 title={`Change Password for ${userLoggedIn}`} 110 modalOpen={open} 111 onClose={() => { 112 setNewPassword(""); 113 setReNewPassword(""); 114 setCurrentPassword(""); 115 closeModal(); 116 }} 117 titleIcon={<ChangePasswordIcon />} 118 > 119 <div> 120 This will change your Console password. Please note your new password 121 down, as it will be required to log into Console after this session. 122 </div> 123 <InformativeMessage 124 variant={"warning"} 125 title={"Warning"} 126 message={ 127 <Fragment> 128 If you are looking to change MINIO_ROOT_USER credentials, <br /> 129 Please refer to{" "} 130 <a 131 target="_blank" 132 rel="noopener" 133 href="https://min.io/docs/minio/linux/administration/identity-access-management/minio-user-management.html#id4?ref=con" 134 > 135 rotating 136 </a>{" "} 137 credentials. 138 </Fragment> 139 } 140 sx={{ margin: "15px 0" }} 141 /> 142 <form 143 noValidate 144 autoComplete="off" 145 onSubmit={(e: React.FormEvent<HTMLFormElement>) => { 146 changePassword(e); 147 }} 148 > 149 <Grid container> 150 <Grid item xs={12} sx={{ ...modalStyleUtils.modalFormScrollable }}> 151 <FormLayout withBorders={false} containerPadding={false}> 152 <InputBox 153 id="current-password" 154 name="current-password" 155 onChange={(event: React.ChangeEvent<HTMLInputElement>) => { 156 setCurrentPassword(event.target.value); 157 }} 158 label="Current Password" 159 type={"password"} 160 value={currentPassword} 161 /> 162 <InputBox 163 id="new-password" 164 name="new-password" 165 onChange={(event: React.ChangeEvent<HTMLInputElement>) => { 166 setNewPassword(event.target.value); 167 }} 168 label="New Password" 169 type={"password"} 170 value={newPassword} 171 /> 172 <InputBox 173 id="re-new-password" 174 name="re-new-password" 175 onChange={(event: React.ChangeEvent<HTMLInputElement>) => { 176 setReNewPassword(event.target.value); 177 }} 178 label="Type New Password Again" 179 type={"password"} 180 value={reNewPassword} 181 /> 182 </FormLayout> 183 </Grid> 184 <Grid item xs={12} sx={{ ...modalStyleUtils.modalButtonBar }}> 185 <Button 186 id={"save-password-modal"} 187 type="submit" 188 variant="callAction" 189 color="primary" 190 disabled={ 191 loading || 192 !( 193 currentPassword.length > 0 && 194 newPassword.length > 0 && 195 reNewPassword.length > 0 196 ) 197 } 198 label="Save" 199 /> 200 </Grid> 201 {loading && ( 202 <Grid item xs={12}> 203 <ProgressBar /> 204 </Grid> 205 )} 206 </Grid> 207 </form> 208 </ModalWrapper> 209 ) : null; 210 }; 211 212 export default ChangePassword;