Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow users to reset password #59

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion backend/routes/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
)
from werkzeug.urls import url_parse

from backend import app, jwt, redis_client
from backend import app, db, jwt, redis_client
from backend.models import User

from . import auth
Expand Down Expand Up @@ -110,3 +110,42 @@ def logout():
jti = get_raw_jwt()["jti"]
redis_client.set(jti, "true", app.config["JWT_ACCESS_TOKEN_EXPIRES"] * 1.2)
return jsonify(message="User logged out", type="LOGGED_OUT"), 200


@auth.route("/reset", methods=["PATCH"])
@jwt_required
def reset_password():
identity = get_jwt_identity()
request_user = User.query.filter_by(username=identity["username"]).first()

if not request.is_json:
return jsonify(message="Missing JSON in request"), 400

old_password = request.json.get("oldpassword", None)
new_password = request.json.get("newpassword", None)

if request_user is None or not request_user.check_password(old_password):
return (
jsonify(
message="Incorrect password!", type="INCORRECT_CREDENTIALS"
),
401,
)

if new_password is None or new_password is "":
return (
jsonify(
message="New password field is blank!"
),
400,
)

try:
request_user.set_password(new_password)
db.session.commit()
except Exception as e:
app.logger.error("Error resetting the user password")
app.logger.error(e)
return jsonify(message="Error resetting the user password!"), 500

return jsonify(user_id=request_user.id, message="User password has been reset!"), 200
126 changes: 126 additions & 0 deletions frontend/src/containers/forms/resetPasswordForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React from "react";
import axios from "axios";
import { withRouter } from "react-router";
import { withStore } from "@spyna/react-store";

import Alert from "../../components/alert";
import { Button } from "../../components/button";

import { setAuthorizationToken } from "../../utils";

class ResetPassword extends React.Component {
constructor(props) {
super(props);

this.initialState = {
newpassword: "",
oldpassword: "",
isResetIn: false,
errorMessage: "",
successMessage: "",
};

this.state = Object.assign({}, this.initialState);
}

resetState() {
this.setState(this.initialState);
}

handlePasswordChange(e) {
console.log();
const passType = e.target.id;
if (passType == "old-password") {
this.setState({ oldpassword: e.target.value });
} else {
this.setState({ newpassword: e.target.value });
}
}

handleResetPass(e) {
const { oldpassword, newpassword } = this.state;

axios({
method: "patch",
url: "auth/reset",
data: {
oldpassword,
newpassword,
},
})
.then((response) => {
this.setState({
errorMessage: null,
successMessage: "Password Succesfully reset!",
});
})
.catch((error) => {
this.setState({
isResetIn: false,
successMessage: "",
errorMessage: error.response.data.message,
});
});
}

handleAlertDismiss(e) {
e.preventDefault();
this.setState({
successMessage: "",
errorMessage: "",
});
}

render() {
const { isResetIn, successMessage, errorMessage } = this.state;
return (
<form className="col-10" name="reset-password">
{errorMessage ? (
<Alert
type="danger"
message={errorMessage}
onClose={(e) => this.handleAlertDismiss(e)}
/>
) : null}
{successMessage ? (
<Alert
type="success"
message={successMessage}
onClose={(e) => this.handleAlertDismiss(e)}
/>
) : null}
<div className="form-group">
<input
type="password"
className="form-control"
id="old-password"
placeholder="Enter Current password"
required={true}
onChange={(e) => this.handlePasswordChange(e)}
/>
</div>
<div className="form-group">
<input
type="password"
className="form-control"
id="new-password"
placeholder="Enter New Password"
required={true}
onChange={(e) => this.handlePasswordChange(e)}
/>
</div>
<div className="form-group">
<Button
size="lg"
type="primary"
disabled={isResetIn ? true : false}
onClick={(e) => this.handleResetPass(e)}
isSubmitting={isResetIn}
text="Reset Password"
/>
</div>
</form>
);
}
}
export default withStore(withRouter(ResetPassword));
2 changes: 2 additions & 0 deletions frontend/src/containers/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import EditLabelForm from "./forms/editLabelForm";
import ManageUsersProjectForm from "./forms/manageUsersProjectForm";
import CreateLabelValueForm from "./forms/createLabelValuelForm";
import EditLabelValueForm from "./forms/editLabelValueForm";
import ResetPassword from "./forms/resetPasswordForm";

const FormModal = (props) => {
return (
Expand All @@ -27,6 +28,7 @@ const FormModal = (props) => {
</Modal.Header>
<Modal.Body>
{props.formType === "NEW_USER" ? <CreateUserForm /> : null}
{props.formType === "RESET_USER" ? <ResetPassword /> : null}
{props.formType === "NEW_PROJECT" ? <CreateProjectForm /> : null}
{props.formType === "EDIT_USER" ? (
<EditUserForm userId={props.userId} />
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/containers/navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ import { withStore } from "@spyna/react-store";

import { setAuthorizationToken } from "../utils";

import FormModal from "./modal";

class NavBar extends React.Component {
constructor(props) {
super(props);
this.state = { modalShow: false };
}

handleLogout(e) {
const { history } = this.props;

Expand All @@ -30,6 +37,14 @@ class NavBar extends React.Component {
});
}

setModalShow(modalShow) {
this.setState({ modalShow });
}

handleResetPassword(e) {
this.setModalShow(true);
}

render() {
const isUserLoggedIn = this.props.store.get("isUserLoggedIn");
const isAdmin = this.props.store.get("isAdmin");
Expand Down Expand Up @@ -66,6 +81,23 @@ class NavBar extends React.Component {
Logout
</button>
</li>
<li className="nav-item">
<button
type="button"
className="nav-link btn btn-link text-decoration-none"
onClick={(e) => this.handleResetPassword(e)}
>
Reset Password
</button>
</li>
{this.state.modalShow ? (
<FormModal
formType="RESET_USER"
title="Reset Password"
show={this.state.modalShow}
onHide={() => this.setModalShow(false)}
/>
) : null}
</ul>
</div>
</div>
Expand Down