prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Implement User Emails
  Parent Issue: #4196 
  
  Requires #4210 to be merged
  
  - [x] Email verification email - To the user who registered
  - [x] A welcome email - After registration. Before email verification. - To the user who registered
  - [x] Forgot password reset email - To the user who registered
  - [x] Email change notification (#4210) - To both the old email address and the new email address
  - [ ] Password change notification - To the user
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `app/api/auth.py`
  Content:
  ```
  1 import base64
  2 
  3 from flask import Blueprint, abort, make_response
  4 from flask import request, jsonify
  5 
  6 from app.api.helpers.db import save_to_db
  7 
  8 from app.api.helpers.utilities import get_serializer
  9 from app.models.user import User
  10 
  11 auth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')
  12 
  13 
  14 @auth_routes.route('/verify-email', methods=['POST'])
  15 def verify_email():
  16     token = base64.b64decode(request.json['data']['token'])
  17     s = get_serializer()
  18 
  19     try:
  20         data = s.loads(token)
  21     except Exception:
  22         return abort(
  23             make_response(jsonify(error="Invalid Token"), 400)
  24         )
  25 
  26     try:
  27         user = User.query.filter_by(email=data[0]).one()
  28     except Exception:
  29         return abort(
  30             make_response(jsonify(error="Invalid Token"), 400)
  31         )
  32     else:
  33         user.is_verified = True
  34         save_to_db(user)
  35 
  36     return jsonify({
  37         "id": user.id,
  38         "email": user.email,
  39         "name": user.name if user.get('name') else None
  40     })
  41
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/app/api/auth.py b/app/api/auth.py
  --- a/app/api/auth.py
  +++ b/app/api/auth.py
  @@ -1,11 +1,14 @@
   import base64
  +from flask import request, jsonify, abort, make_response, Blueprint
  +from sqlalchemy.orm.exc import NoResultFound
   
  -from flask import Blueprint, abort, make_response
  -from flask import request, jsonify
  -
  +from app import get_settings
   from app.api.helpers.db import save_to_db
  +from app.api.helpers.files import make_frontend_url
  +from app.api.helpers.mail import send_email_with_action
   
   from app.api.helpers.utilities import get_serializer
  +from app.models.mail import PASSWORD_RESET
   from app.models.user import User
   
   auth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')
  @@ -31,6 +34,38 @@
           )
       else:
           user.is_verified = True
  +
  +
  +@auth_routes.route('/reset-password', methods=['POST'])
  +def reset_password_post():
  +    email = request.json['data']['email']
  +
  +    try:
  +        user = User.query.filter_by(email=email).one()
  +    except NoResultFound:
  +        return abort(
  +            make_response(jsonify(error="User not found"), 404)
  +        )
  +    else:
  +        link = make_frontend_url('/reset-password', {'token': user.reset_password})
  +        send_email_with_action(user, PASSWORD_RESET, app_name=get_settings()['app_name'], link=link)
  +
  +    return make_response(jsonify(message="Email Sent"), 200)
  +
  +
  +@auth_routes.route('/reset-password', methods=['PATCH'])
  +def reset_password_patch():
  +    token = request.json['data']['token']
  +    password = request.json['data']['password']
  +
  +    try:
  +        user = User.query.filter_by(reset_password=token).one()
  +    except NoResultFound:
  +        return abort(
  +            make_response(jsonify(error="User not found"), 404)
  +        )
  +    else:
  +        user.password = password
           save_to_db(user)
   
       return jsonify({
  
verification_info: {"golden_diff": "diff --git a/app/api/auth.py b/app/api/auth.py\n--- a/app/api/auth.py\n+++ b/app/api/auth.py\n@@ -1,11 +1,14 @@\n import base64\n+from flask import request, jsonify, abort, make_response, Blueprint\n+from sqlalchemy.orm.exc import NoResultFound\n \n-from flask import Blueprint, abort, make_response\n-from flask import request, jsonify\n-\n+from app import get_settings\n from app.api.helpers.db import save_to_db\n+from app.api.helpers.files import make_frontend_url\n+from app.api.helpers.mail import send_email_with_action\n \n from app.api.helpers.utilities import get_serializer\n+from app.models.mail import PASSWORD_RESET\n from app.models.user import User\n \n auth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')\n@@ -31,6 +34,38 @@\n         )\n     else:\n         user.is_verified = True\n+\n+\n+@auth_routes.route('/reset-password', methods=['POST'])\n+def reset_password_post():\n+    email = request.json['data']['email']\n+\n+    try:\n+        user = User.query.filter_by(email=email).one()\n+    except NoResultFound:\n+        return abort(\n+            make_response(jsonify(error=\"User not found\"), 404)\n+        )\n+    else:\n+        link = make_frontend_url('/reset-password', {'token': user.reset_password})\n+        send_email_with_action(user, PASSWORD_RESET, app_name=get_settings()['app_name'], link=link)\n+\n+    return make_response(jsonify(message=\"Email Sent\"), 200)\n+\n+\n+@auth_routes.route('/reset-password', methods=['PATCH'])\n+def reset_password_patch():\n+    token = request.json['data']['token']\n+    password = request.json['data']['password']\n+\n+    try:\n+        user = User.query.filter_by(reset_password=token).one()\n+    except NoResultFound:\n+        return abort(\n+            make_response(jsonify(error=\"User not found\"), 404)\n+        )\n+    else:\n+        user.password = password\n         save_to_db(user)\n \n     return jsonify({\n", "issue": "Implement User Emails\nParent Issue: #4196 \r\n\r\nRequires #4210 to be merged\r\n\r\n- [x] Email verification email - To the user who registered\r\n- [x] A welcome email - After registration. Before email verification. - To the user who registered\r\n- [x] Forgot password reset email - To the user who registered\r\n- [x] Email change notification (#4210) - To both the old email address and the new email address\r\n- [ ] Password change notification - To the user\n", "before_files": [{"content": "import base64\n\nfrom flask import Blueprint, abort, make_response\nfrom flask import request, jsonify\n\nfrom app.api.helpers.db import save_to_db\n\nfrom app.api.helpers.utilities import get_serializer\nfrom app.models.user import User\n\nauth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')\n\n\n@auth_routes.route('/verify-email', methods=['POST'])\ndef verify_email():\n    token = base64.b64decode(request.json['data']['token'])\n    s = get_serializer()\n\n    try:\n        data = s.loads(token)\n    except Exception:\n        return abort(\n            make_response(jsonify(error=\"Invalid Token\"), 400)\n        )\n\n    try:\n        user = User.query.filter_by(email=data[0]).one()\n    except Exception:\n        return abort(\n            make_response(jsonify(error=\"Invalid Token\"), 400)\n        )\n    else:\n        user.is_verified = True\n        save_to_db(user)\n\n    return jsonify({\n        \"id\": user.id,\n        \"email\": user.email,\n        \"name\": user.name if user.get('name') else None\n    })\n", "path": "app/api/auth.py"}], "after_files": [{"content": "import base64\nfrom flask import request, jsonify, abort, make_response, Blueprint\nfrom sqlalchemy.orm.exc import NoResultFound\n\nfrom app import get_settings\nfrom app.api.helpers.db import save_to_db\nfrom app.api.helpers.files import make_frontend_url\nfrom app.api.helpers.mail import send_email_with_action\n\nfrom app.api.helpers.utilities import get_serializer\nfrom app.models.mail import PASSWORD_RESET\nfrom app.models.user import User\n\nauth_routes = Blueprint('auth', __name__, url_prefix='/v1/auth')\n\n\n@auth_routes.route('/verify-email', methods=['POST'])\ndef verify_email():\n    token = base64.b64decode(request.json['data']['token'])\n    s = get_serializer()\n\n    try:\n        data = s.loads(token)\n    except Exception:\n        return abort(\n            make_response(jsonify(error=\"Invalid Token\"), 400)\n        )\n\n    try:\n        user = User.query.filter_by(email=data[0]).one()\n    except Exception:\n        return abort(\n            make_response(jsonify(error=\"Invalid Token\"), 400)\n        )\n    else:\n        user.is_verified = True\n\n\n@auth_routes.route('/reset-password', methods=['POST'])\ndef reset_password_post():\n    email = request.json['data']['email']\n\n    try:\n        user = User.query.filter_by(email=email).one()\n    except NoResultFound:\n        return abort(\n            make_response(jsonify(error=\"User not found\"), 404)\n        )\n    else:\n        link = make_frontend_url('/reset-password', {'token': user.reset_password})\n        send_email_with_action(user, PASSWORD_RESET, app_name=get_settings()['app_name'], link=link)\n\n    return make_response(jsonify(message=\"Email Sent\"), 200)\n\n\n@auth_routes.route('/reset-password', methods=['PATCH'])\ndef reset_password_patch():\n    token = request.json['data']['token']\n    password = request.json['data']['password']\n\n    try:\n        user = User.query.filter_by(reset_password=token).one()\n    except NoResultFound:\n        return abort(\n            make_response(jsonify(error=\"User not found\"), 404)\n        )\n    else:\n        user.password = password\n        save_to_db(user)\n\n    return jsonify({\n        \"id\": user.id,\n        \"email\": user.email,\n        \"name\": user.name if user.get('name') else None\n    })\n", "path": "app/api/auth.py"}]}