From 227eac79c8e6ba913cd9ab0b88053c9b060ce93b Mon Sep 17 00:00:00 2001 From: Yansong Zhang <916125788@qq.com> Date: Fri, 11 Jul 2025 11:17:33 +0800 Subject: [PATCH] ran reformat --- api/controllers/console/auth/error.py | 6 +++++- api/controllers/console/workspace/account.py | 20 +++++++++++++------- api/controllers/console/wraps.py | 2 ++ api/services/account_service.py | 8 +++----- api/tasks/mail_change_mail_task.py | 4 ++-- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/api/controllers/console/auth/error.py b/api/controllers/console/auth/error.py index e1cf7a67e6..7076c850a8 100644 --- a/api/controllers/console/auth/error.py +++ b/api/controllers/console/auth/error.py @@ -30,11 +30,13 @@ class PasswordResetRateLimitExceededError(BaseHTTPException): description = "Too many password reset emails have been sent. Please try again in 1 minutes." code = 429 + class EmailChangeRateLimitExceededError(BaseHTTPException): error_code = "email_change_rate_limit_exceeded" description = "Too many email change emails have been sent. Please try again in 1 minutes." code = 429 + class EmailCodeError(BaseHTTPException): error_code = "email_code_error" description = "Email code is invalid or expired." @@ -70,12 +72,14 @@ class EmailPasswordResetLimitError(BaseHTTPException): description = "Too many failed password reset attempts. Please try again in 24 hours." code = 429 + class EmailChangeLimitError(BaseHTTPException): error_code = "email_change_limit" description = "Too many failed email change attempts. Please try again in 24 hours." code = 429 + class EmailAlreadyInUseError(BaseHTTPException): error_code = "email_already_in_use" description = "A user with this email already exists." - code = 400 \ No newline at end of file + code = 400 diff --git a/api/controllers/console/workspace/account.py b/api/controllers/console/workspace/account.py index 4779c69e7d..7f17d968c3 100644 --- a/api/controllers/console/workspace/account.py +++ b/api/controllers/console/workspace/account.py @@ -11,11 +11,11 @@ from configs import dify_config from constants.languages import supported_language from controllers.console import api from controllers.console.auth.error import ( + EmailAlreadyInUseError, EmailChangeLimitError, EmailCodeError, InvalidEmailError, InvalidTokenError, - EmailAlreadyInUseError, ) from controllers.console.error import AccountNotFound, EmailSendIpLimitError from controllers.console.workspace.error import ( @@ -380,6 +380,7 @@ class EducationAutoCompleteApi(Resource): return BillingService.EducationIdentity.autocomplete(args["keywords"], args["page"], args["limit"]) + class ChangeEmailSendEmailApi(Resource): @enable_change_email @setup_required @@ -405,12 +406,12 @@ class ChangeEmailSendEmailApi(Resource): user_email = args["email"] if args["phase"] is not None and args["phase"] == "new_email": if args["token"] is None: - raise InvalidTokenError() + raise InvalidTokenError() reset_data = AccountService.get_change_email_data(args["token"]) if reset_data is None: raise InvalidTokenError() - user_email = reset_data.get("email","") + user_email = reset_data.get("email", "") if user_email == current_user.email: raise InvalidEmailError() @@ -418,9 +419,11 @@ class ChangeEmailSendEmailApi(Resource): with Session(db.engine) as session: account = session.execute(select(Account).filter_by(email=args["email"])).scalar_one_or_none() if account is None: - raise AccountNotFound() + raise AccountNotFound() - token = AccountService.send_change_email_email(account=account, email=args["email"], old_email=user_email, language=language, phase=args["phase"]) # noqa: E501 + token = AccountService.send_change_email_email( + account=account, email=args["email"], old_email=user_email, language=language, phase=args["phase"] + ) # noqa: E501 return {"result": "success", "data": token} @@ -458,12 +461,13 @@ class ChangeEmailCheckApi(Resource): # Refresh token data by generating a new token _, new_token = AccountService.generate_change_email_token( - user_email, code=args["code"],old_email=token_data.get("old_email"), additional_data={} + user_email, code=args["code"], old_email=token_data.get("old_email"), additional_data={} ) AccountService.reset_change_email_error_rate_limit(args["email"]) return {"is_valid": True, "email": token_data.get("email"), "token": new_token} + class ChangeEmailResetApi(Resource): @enable_change_email @setup_required @@ -488,11 +492,12 @@ class ChangeEmailResetApi(Resource): old_email = reset_data.get("old_email", "") if current_user.email != old_email: raise AccountNotFound() - + updated_account = AccountService.update_account(current_user, email=args["new_email"]) return updated_account + class CheckEmailUnique(Resource): @setup_required def post(self): @@ -506,6 +511,7 @@ class CheckEmailUnique(Resource): raise EmailAlreadyInUseError() return {"result": "success"} + # Register API resources api.add_resource(AccountInitApi, "/account/init") api.add_resource(AccountProfileApi, "/account/profile") diff --git a/api/controllers/console/wraps.py b/api/controllers/console/wraps.py index 56c0ba2326..feb4b2ec39 100644 --- a/api/controllers/console/wraps.py +++ b/api/controllers/console/wraps.py @@ -236,6 +236,7 @@ def email_password_login_enabled(view): return decorated + def enable_change_email(view): @wraps(view) def decorated(*args, **kwargs): @@ -245,4 +246,5 @@ def enable_change_email(view): # otherwise, return 403 abort(403) + return decorated diff --git a/api/services/account_service.py b/api/services/account_service.py index ba4c325372..02c313ebba 100644 --- a/api/services/account_service.py +++ b/api/services/account_service.py @@ -76,9 +76,7 @@ class AccountService: email_code_account_deletion_rate_limiter = RateLimiter( prefix="email_code_account_deletion_rate_limit", max_attempts=1, time_window=60 * 1 ) - change_email_rate_limiter = RateLimiter( - prefix="change_email_rate_limit", max_attempts=2, time_window=60 * 1 - ) + change_email_rate_limiter = RateLimiter(prefix="change_email_rate_limit", max_attempts=1, time_window=60 * 1) LOGIN_MAX_ERROR_LIMITS = 5 FORGOT_PASSWORD_MAX_ERROR_LIMITS = 5 CHANGE_EMAIL_MAX_ERROR_LIMITS = 5 @@ -498,7 +496,7 @@ class AccountService: @classmethod def get_reset_password_data(cls, token: str) -> Optional[dict[str, Any]]: return TokenManager.get_token_data(token, "reset_password") - + @classmethod def get_change_email_data(cls, token: str) -> Optional[dict[str, Any]]: return TokenManager.get_token_data(token, "change_email") @@ -600,7 +598,7 @@ class AccountService: if count > AccountService.FORGOT_PASSWORD_MAX_ERROR_LIMITS: return True return False - + @staticmethod def reset_forgot_password_error_rate_limit(email: str): key = f"forgot_password_error_rate_limit:{email}" diff --git a/api/tasks/mail_change_mail_task.py b/api/tasks/mail_change_mail_task.py index d64b50c60d..08e55ecef3 100644 --- a/api/tasks/mail_change_mail_task.py +++ b/api/tasks/mail_change_mail_task.py @@ -25,13 +25,13 @@ def send_change_mail_task(language: str, to: str, code: str, phase: str): # send change email mail using different languages try: - if phase == "old_email" : + if phase == "old_email": template = "change_mail_confirm_old_template_en-US.html" elif phase == "new_email": template = "change_mail_confirm_new_template_en-US.html" else: raise ValueError("Invalid phase") - + if language == "zh-Hans": html_content = render_template(template, to=to, code=code) mail.send(to=to, subject="检测您现在的邮箱", html=html_content)