diff --git a/api/apps/user_app.py b/api/apps/user_app.py
index fde8a7af5..53876826c 100644
--- a/api/apps/user_app.py
+++ b/api/apps/user_app.py
@@ -21,8 +21,9 @@ import re
import secrets
import time
from datetime import datetime
+import base64
-from quart import redirect, request, session
+from quart import make_response, redirect, request, session
from werkzeug.security import check_password_hash, generate_password_hash
from api.apps.auth import get_auth_client
@@ -868,12 +869,9 @@ async def forget_get_captcha():
from captcha.image import ImageCaptcha
image = ImageCaptcha(width=300, height=120, font_sizes=[50, 60, 70])
img_bytes = image.generate(captcha_text).read()
-
- import base64
- base64_img = base64.b64encode(img_bytes).decode('utf-8')
- data_uri = f"data:image/jpeg;base64,{base64_img}"
-
- return get_json_result(data=data_uri)
+ response = await make_response(img_bytes)
+ response.headers.set("Content-Type", "image/JPEG")
+ return response
@manager.route("/forget/otp", methods=["POST"]) # noqa: F821
@@ -940,19 +938,6 @@ async def forget_send_otp():
return get_json_result(data=False, code=RetCode.SERVER_ERROR, message="failed to send email")
return get_json_result(data=True, code=RetCode.SUCCESS, message="verification passed, email sent")
-
-
-@manager.route("/forget", methods=["POST"]) # noqa: F821
-async def forget():
- """
- Deprecated single-step reset endpoint.
- Use /forget/verify-otp then /forget/reset-password.
- """
- return get_json_result(
- data=False,
- code=RetCode.NOT_EFFECTIVE,
- message="Use /forget/verify-otp then /forget/reset-password",
- )
def _verified_key(email: str) -> str:
@@ -1031,39 +1016,37 @@ async def forget_reset_password():
- auto login
- clear verified flag
"""
+
req = await get_request_json()
email = req.get("email") or ""
new_pwd = req.get("new_password")
new_pwd2 = req.get("confirm_new_password")
+ new_pwd_base64 = decrypt(new_pwd)
+ new_pwd_string = base64.b64decode(new_pwd_base64).decode('utf-8')
+ new_pwd2_string = base64.b64decode(decrypt(new_pwd2)).decode('utf-8')
+
+ REDIS_CONN.get(_verified_key(email))
+ if not REDIS_CONN.get(_verified_key(email)):
+ return get_json_result(data=False, code=RetCode.AUTHENTICATION_ERROR, message="email not verified")
+
if not all([email, new_pwd, new_pwd2]):
return get_json_result(data=False, code=RetCode.ARGUMENT_ERROR, message="email and passwords are required")
- if new_pwd != new_pwd2:
+ if new_pwd_string != new_pwd2_string:
return get_json_result(data=False, code=RetCode.ARGUMENT_ERROR, message="passwords do not match")
- users = UserService.query(email=email)
+ users = UserService.query_user_by_email(email=email)
if not users:
return get_json_result(data=False, code=RetCode.DATA_ERROR, message="invalid email")
user = users[0]
try:
- UserService.update_user_password(user.id, new_pwd)
+ UserService.update_user_password(user.id, new_pwd_base64)
except Exception as e:
logging.exception(e)
return get_json_result(data=False, code=RetCode.EXCEPTION_ERROR, message="failed to reset password")
- # login
- try:
- user.access_token = get_uuid()
- login_user(user)
- user.update_time = current_timestamp()
- user.update_date = datetime_format(datetime.now())
- user.save()
- except Exception as e:
- logging.exception(e)
- return get_json_result(data=False, code=RetCode.EXCEPTION_ERROR, message="failed to login after reset")
-
# clear verified flag
try:
REDIS_CONN.delete(_verified_key(email))
diff --git a/api/utils/web_utils.py b/api/utils/web_utils.py
index cba87535f..2866e5f28 100644
--- a/api/utils/web_utils.py
+++ b/api/utils/web_utils.py
@@ -36,7 +36,7 @@ from selenium.webdriver.support.ui import WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager
-OTP_LENGTH = 8
+OTP_LENGTH = 4
OTP_TTL_SECONDS = 5 * 60 # valid for 5 minutes
ATTEMPT_LIMIT = 5 # maximum attempts
ATTEMPT_LOCK_SECONDS = 30 * 60 # lock for 30 minutes
diff --git a/web/src/pages/user-setting/data-source/component/box-token-field.tsx b/web/src/pages/user-setting/data-source/component/box-token-field.tsx
index 7151ebea8..3bb805868 100644
--- a/web/src/pages/user-setting/data-source/component/box-token-field.tsx
+++ b/web/src/pages/user-setting/data-source/component/box-token-field.tsx
@@ -346,7 +346,7 @@ const BoxTokenField = ({ value, onChange }: BoxTokenFieldProps) => {
)}