diff --git a/dtbase/backend/api/user/routes.py b/dtbase/backend/api/user/routes.py index ee75efc2..44fceb47 100644 --- a/dtbase/backend/api/user/routes.py +++ b/dtbase/backend/api/user/routes.py @@ -87,27 +87,51 @@ def delete_user() -> Tuple[Response, int]: @jwt_required() def change_password() -> Tuple[Response, int]: """ - Change a users password + Change a user's password. - POST request should have json data (mimetype "application/json") containing + POST request should have JSON data (mimetype "application/json") containing { "email": , - "password": , + "current_password": , + "new_password": , + "confirm_new_password": , } - where `password` is the new password. + where `new_password` is the new password and `confirm_new_password` + must match `new_password`. - Returns 400 if user doesn't exist, otherwise 200. + Returns 400 if user doesn't exist, if current password is incorrect, + or if passwords do not match. Otherwise, returns 200. """ payload = request.get_json() - required_keys = ["email", "password"] + required_keys = [ + "email", + "current_password", + "new_password", + "confirm_new_password", + ] error_response = check_keys(payload, required_keys, "/change-password") if error_response: return error_response + email = payload.get("email") - password = payload.get("password") + current_password = payload.get("current_password") + new_password = payload.get("new_password") + confirm_new_password = payload.get("confirm_new_password") + + if new_password != confirm_new_password: + return ( + jsonify({"message": "New password and confirm new password do not match"}), + 400, + ) + try: - users.change_password(email, password, session=db.session) + # Assuming `verify_password` checks the current password is correct + if not users.verify_password(email, current_password, session=db.session): + return jsonify({"message": "Current password is incorrect"}), 400 + + users.change_password(email, new_password, session=db.session) except NoResultFound: return jsonify({"message": "User doesn't exist"}), 400 + db.session.commit() - return jsonify({"message": "Password changed"}), 200 + return jsonify({"message": "Password changed successfully"}), 200 diff --git a/dtbase/webapp/app/base/templates/security/password_reset.html b/dtbase/webapp/app/base/templates/security/password_reset.html new file mode 100644 index 00000000..c98517a4 --- /dev/null +++ b/dtbase/webapp/app/base/templates/security/password_reset.html @@ -0,0 +1,47 @@ +{% extends "base_site.html" %} + +{% block title %} Password Reset {% endblock title %} + +{% block stylesheets %} + {{ super() }} + +{% endblock stylesheets %} + +{% block body_class %}password-reset{% endblock body_class %} + +{% block body %} +
+ +
+ + {% block javascripts %} + {{ super() }} + + + {% endblock javascripts %} +{% endblock body %} diff --git a/scripts/setup_dev.sh b/scripts/setup_dev.sh new file mode 100755 index 00000000..08357860 --- /dev/null +++ b/scripts/setup_dev.sh @@ -0,0 +1,56 @@ +#!/bin/zsh + +ENV_NAME="dt_env" +# Function to check and activate Conda environment +check_activate_conda() { + if conda env list | grep "${ENV_NAME}" > /dev/null 2>&1; then + source ~/miniconda3/etc/profile.d/conda.sh + echo "Activating Conda environment: ${ENV_NAME}" + conda activate "${ENV_NAME}" + return 0 + else + return 1 + fi +} + +# Function to check for Poetry environment +check_activate_poetry() { + if poetry env list | grep "${ENV_NAME}" > /dev/null 2>&1; then + echo "Activating Poetry environment: ${ENV_NAME}" + poetry shell + return 0 + else + return 1 + fi +} + +# Function to check and activate PyEnv environment +check_activate_pyenv() { + if pyenv versions | grep "${ENV_NAME}" > /dev/null 2>&1; then + echo "Activating PyEnv environment: ${ENV_NAME}" + pyenv activate "${ENV_NAME}" + return 0 + else + return 1 + fi +} + +# Check for environment management systems in the order of preference +if ! { conda --version &>/dev/null && check_activate_conda; } && + ! { type poetry &>/dev/null && check_activate_poetry; } && + ! { type pyenv &>/dev/null && check_activate_pyenv; } && + [[ -z "$VIRTUAL_ENV" ]]; then + echo "No suitable Python environment management system is installed or the ${ENV_NAME} environment does not exist." +fi + + +# Make sure everything is installed +pip install '.[dev]' + +# Start the backend API +(cd dtbase/backend && DT_CONFIG_MODE=Debug ./run_localdb.sh) & + +# Start the frontend +(cd dtbase/webapp && npm install && FLASK_DEBUG=true DT_CONFIG_MODE=Auto-login ./run.sh) & + +echo "DTBase setup complete. Backend running on http://localhost:5000, frontend on http://localhost:8000."