ui refactoring for change password (#148)

This commit is contained in:
Michael Quigley 2024-02-16 15:19:32 -05:00
parent fa91d091bb
commit 9949a55c1f
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
3 changed files with 102 additions and 78 deletions

View File

@ -16,7 +16,7 @@ const ActionsTab = (props) => {
<div className={"actions-tab"}> <div className={"actions-tab"}>
<div id={"change-password"} style={{"padding-top": "10px"}}> <div id={"change-password"} style={{"padding-top": "10px"}}>
<h3>Change Password?</h3> <h3>Change Password?</h3>
<p>Note that this will <strong>not</strong> log out of any already logged in sessions.</p> <p>Change your password here. Note that this will <strong>not</strong> log you out of any already logged in sessions.</p>
<Button variant={"danger"} onClick={openChangePasswordModal}>Change Password</Button> <Button variant={"danger"} onClick={openChangePasswordModal}>Change Password</Button>
<ChangePassword show={showChangePasswordModal} onHide={closeChangePasswordModal} user={props.user}/> <ChangePassword show={showChangePasswordModal} onHide={closeChangePasswordModal} user={props.user}/>
</div> </div>

View File

@ -1,23 +1,43 @@
import React, { useEffect, useState } from "react"; import React, {useEffect, useState} from "react";
import * as account from "../../../../api/account"; import * as account from "../../../../api/account";
import * as metadata from "../../../../api/metadata"; import {Button, Container, Form, Row} from "react-bootstrap";
import { Button, Container, Form, Row } from "react-bootstrap";
import PasswordForm from "../../../../components/password";
import Modal from "react-bootstrap/Modal"; import Modal from "react-bootstrap/Modal";
import * as metadata from "../../../../api/metadata";
const validatePassword = (password, l, rc, rn, rs, spc, cb) => {
if(password.length < l) {
cb(false, "Entered password is too short! (" + l + " characters minimum)!");
return;
}
if(rc && !/[A-Z]/.test(password)) {
cb(false, "Entered password requires a capital letter!");
return;
}
if(rn && !/\d/.test(password)) {
cb(false, "Entered password requires a digit!");
return;
}
if(rs) {
if(!spc.split("").some(v => password.includes(v))) {
cb(false, "Entered password requires a special character!");
return;
}
}
return cb(true, "");
}
const ChangePassword = (props) => { const ChangePassword = (props) => {
const [oldPassword, setOldPassword] = useState(''); const [oldPassword, setOldPassword] = useState('');
const [newPassword, setNewPassword] = useState(''); const [newPassword, setNewPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const [complete, setComplete] = useState(false);
const [passwordLength, setPasswordLength] = useState(10); const [passwordLength, setPasswordLength] = useState(8);
const [passwordRequireCapital, setPasswordRequireCapital] = useState(true); const [passwordRequireCapital, setPasswordRequireCapital] = useState(true);
const [passwordRequireNumeric, setPasswordRequireNumeric] = useState(true); const [passwordRequireNumeric, setPasswordRequireNumeric] = useState(true);
const [passwordRequireSpecial, setPasswordRequireSpecial] = useState(true); const [passwordRequireSpecial, setPasswordRequireSpecial] = useState(true);
const [passwordValidSpecialCharacters, setPasswordValidSpecialCharacters] = useState(""); const [passwordValidSpecialCharacters, setPasswordValidSpecialCharacters] = useState("");
const errorMessage = <h2 className={"errorMessage"}>Change Password Failed!</h2>;
useEffect(() => { useEffect(() => {
metadata.configuration().then(resp => { metadata.configuration().then(resp => {
if (!resp.error) { if (!resp.error) {
@ -28,90 +48,95 @@ const ChangePassword = (props) => {
setPasswordValidSpecialCharacters(resp.data.passwordRequirements.validSpecialCharacters) setPasswordValidSpecialCharacters(resp.data.passwordRequirements.validSpecialCharacters)
} }
}).catch(err => { }).catch(err => {
console.log("err", err); console.log("error getting configuration", err);
}); });
}, []) }, [])
const handleSubmit = async e => { const handleSubmit = async e => {
e.preventDefault(); e.preventDefault();
if (newPassword !== undefined && newPassword !== "" && oldPassword !== undefined && oldPassword !== "") {
account.changePassword({ body: { "email": props.user.email, "oldPassword": oldPassword, "newPassword": newPassword } }) let ok = false;
validatePassword(newPassword,
passwordLength,
passwordRequireCapital,
passwordRequireNumeric,
passwordRequireSpecial,
passwordValidSpecialCharacters, (isOk, msg) => { ok = isOk; setMessage(msg); })
if(!ok) {
return;
}
if(confirmPassword !== newPassword) {
setMessage("New password and confirmation do not match!");
return;
}
account.changePassword({ body: { oldPassword: oldPassword, newPassword: newPassword, email: props.user.email } })
.then(resp => { .then(resp => {
if (!resp.error) { if (!resp.error) {
console.log("resp", resp) console.log("resp", resp)
setMessage(undefined); setMessage("Password successfully changed!");
setComplete(true)
} else { } else {
setMessage(errorMessage); setMessage("Failure changing password! Is old password correct?");
} }
}).catch(resp => { }).catch(resp => {
console.log("resp", resp) console.log("resp", resp)
setMessage(errorMessage) setMessage("Failure changing password! Is old password correct?")
}) })
}
} }
let hide = () => { let hide = () => {
props.onHide(); props.onHide();
setMessage(""); setMessage("");
setComplete(false);
setOldPassword(""); setOldPassword("");
setNewPassword(""); setNewPassword("");
setConfirmPassword("");
} }
if (!complete) {
return ( return (
<Modal show={props.show} onHide={hide} centered> <Modal show={props.show} onHide={hide} size={"md"} centered>
<Modal.Header closeButton>Change Password</Modal.Header> <Modal.Header closeButton>Change Password</Modal.Header>
<Modal.Body> <Modal.Body>
<Form onSubmit={handleSubmit}> <Form onSubmit={handleSubmit}>
<div className="container" style={{ marginBottom: "1em" }}> <Container>
<Form.Group controlId={"oldPassword"}> <Form.Group controlId={"oldPassword"}>
<Form.Control <Form.Control
type={"password"} type={"password"}
placeholder={"Old Password"} placeholder={"Old Password"}
onChange={t => { setOldPassword(t.target.value); }} onChange={t => { setMessage(''); setOldPassword(t.target.value); }}
value={oldPassword} value={oldPassword}
style={{ marginBottom: "1em" }}
/>
</Form.Group>
<Form.Group controlId={"newPassword"}>
<Form.Control
type={"password"}
placeholder={"New Password"}
onChange={t => { setMessage(''); setNewPassword(t.target.value); }}
value={newPassword}
style={{ marginBottom: "1em" }}
/>
</Form.Group>
<Form.Group controlId={"confirmPassword"}>
<Form.Control
type={"password"}
placeholder={"Confirm Password"}
onChange={t => { setMessage(''); setConfirmPassword(t.target.value); }}
value={confirmPassword}
/> />
</Form.Group> </Form.Group>
</div>
<PasswordForm
setMessage={setMessage}
passwordLength={passwordLength}
passwordRequireCapital={passwordRequireCapital}
passwordRequireNumeric={passwordRequireNumeric}
passwordRequireSpecial={passwordRequireSpecial}
passwordValidSpecialCharacters={passwordValidSpecialCharacters}
setParentPassword={setNewPassword} />
<Row style={{ justifyContent: "center", marginTop: "1em" }}> <Row style={{ justifyContent: "center", marginTop: "1em" }}>
<Button variant={"light"} type={"submit"}>Reset Password</Button> <p style={{ color: "red" }}>{message}</p>
</Row> </Row>
</Form> <Row style={{ justifyContent: "right", marginTop: "1em" }}>
{message} <Button variant={"danger"} type={"submit"}>Change Password</Button>
</Modal.Body>
</Modal>
)
}
else {
return (
<Modal show={props.show} onHide={hide} centered>
<Modal.Header closeButton>Change Password</Modal.Header>
<Modal.Body>
<Container fluid>
<Row>
<h1>Change Password</h1>
</Row>
<Row>
Password reset successful! You can now return to the actions page.
</Row>
<Row>
<Button variant={"light"} onClick={hide}>Back</Button>
</Row> </Row>
</Container> </Container>
</Form>
</Modal.Body> </Modal.Body>
</Modal> </Modal>
) );
}
} }
export default ChangePassword; export default ChangePassword;

View File

@ -64,7 +64,6 @@ const ResetToken = (props) => {
<p>Did you read the warning on the previous screen? This action will reset all of your active environments and shares!</p> <p>Did you read the warning on the previous screen? This action will reset all of your active environments and shares!</p>
<p>You will need to update each of your <code> &#36;&#123;HOME&#125;/.zrok/environments.yml</code> files with your new token!</p> <p>You will need to update each of your <code> &#36;&#123;HOME&#125;/.zrok/environments.yml</code> files with your new token!</p>
<p align={"right"}> <p align={"right"}>
<Button onClick={props.onHide}>Cancel</Button>
<Button variant={"danger"} onClick={resetToken}>Regenerate Token</Button> <Button variant={"danger"} onClick={resetToken}>Regenerate Token</Button>
</p> </p>
</div> </div>
@ -75,7 +74,7 @@ const ResetToken = (props) => {
return ( return (
<div> <div>
<Modal show={props.show} onHide={hide} centered> <Modal show={props.show} onHide={hide} size={"lg"} centered>
<Modal.Header closeButton>{modalHeader}</Modal.Header> <Modal.Header closeButton>{modalHeader}</Modal.Header>
<Modal.Body> <Modal.Body>
{modalBody} {modalBody}