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;