您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. from flask_restx import Resource, reqparse
  2. from jwt import InvalidTokenError
  3. import services
  4. from controllers.console.auth.error import (
  5. AuthenticationFailedError,
  6. EmailCodeError,
  7. InvalidEmailError,
  8. )
  9. from controllers.console.error import AccountBannedError
  10. from controllers.console.wraps import only_edition_enterprise, setup_required
  11. from controllers.web import web_ns
  12. from libs.helper import email
  13. from libs.password import valid_password
  14. from services.account_service import AccountService
  15. from services.webapp_auth_service import WebAppAuthService
  16. @web_ns.route("/login")
  17. class LoginApi(Resource):
  18. """Resource for web app email/password login."""
  19. @setup_required
  20. @only_edition_enterprise
  21. @web_ns.doc("web_app_login")
  22. @web_ns.doc(description="Authenticate user for web application access")
  23. @web_ns.doc(
  24. responses={
  25. 200: "Authentication successful",
  26. 400: "Bad request - invalid email or password format",
  27. 401: "Authentication failed - email or password mismatch",
  28. 403: "Account banned or login disabled",
  29. 404: "Account not found",
  30. }
  31. )
  32. def post(self):
  33. """Authenticate user and login."""
  34. parser = reqparse.RequestParser()
  35. parser.add_argument("email", type=email, required=True, location="json")
  36. parser.add_argument("password", type=valid_password, required=True, location="json")
  37. args = parser.parse_args()
  38. try:
  39. account = WebAppAuthService.authenticate(args["email"], args["password"])
  40. except services.errors.account.AccountLoginError:
  41. raise AccountBannedError()
  42. except services.errors.account.AccountPasswordError:
  43. raise AuthenticationFailedError()
  44. except services.errors.account.AccountNotFoundError:
  45. raise AuthenticationFailedError()
  46. token = WebAppAuthService.login(account=account)
  47. return {"result": "success", "data": {"access_token": token}}
  48. # class LogoutApi(Resource):
  49. # @setup_required
  50. # def get(self):
  51. # account = cast(Account, flask_login.current_user)
  52. # if isinstance(account, flask_login.AnonymousUserMixin):
  53. # return {"result": "success"}
  54. # flask_login.logout_user()
  55. # return {"result": "success"}
  56. @web_ns.route("/email-code-login")
  57. class EmailCodeLoginSendEmailApi(Resource):
  58. @setup_required
  59. @only_edition_enterprise
  60. @web_ns.doc("send_email_code_login")
  61. @web_ns.doc(description="Send email verification code for login")
  62. @web_ns.doc(
  63. responses={
  64. 200: "Email code sent successfully",
  65. 400: "Bad request - invalid email format",
  66. 404: "Account not found",
  67. }
  68. )
  69. def post(self):
  70. parser = reqparse.RequestParser()
  71. parser.add_argument("email", type=email, required=True, location="json")
  72. parser.add_argument("language", type=str, required=False, location="json")
  73. args = parser.parse_args()
  74. if args["language"] is not None and args["language"] == "zh-Hans":
  75. language = "zh-Hans"
  76. else:
  77. language = "en-US"
  78. account = WebAppAuthService.get_user_through_email(args["email"])
  79. if account is None:
  80. raise AuthenticationFailedError()
  81. else:
  82. token = WebAppAuthService.send_email_code_login_email(account=account, language=language)
  83. return {"result": "success", "data": token}
  84. @web_ns.route("/email-code-login/validity")
  85. class EmailCodeLoginApi(Resource):
  86. @setup_required
  87. @only_edition_enterprise
  88. @web_ns.doc("verify_email_code_login")
  89. @web_ns.doc(description="Verify email code and complete login")
  90. @web_ns.doc(
  91. responses={
  92. 200: "Email code verified and login successful",
  93. 400: "Bad request - invalid code or token",
  94. 401: "Invalid token or expired code",
  95. 404: "Account not found",
  96. }
  97. )
  98. def post(self):
  99. parser = reqparse.RequestParser()
  100. parser.add_argument("email", type=str, required=True, location="json")
  101. parser.add_argument("code", type=str, required=True, location="json")
  102. parser.add_argument("token", type=str, required=True, location="json")
  103. args = parser.parse_args()
  104. user_email = args["email"]
  105. token_data = WebAppAuthService.get_email_code_login_data(args["token"])
  106. if token_data is None:
  107. raise InvalidTokenError()
  108. if token_data["email"] != args["email"]:
  109. raise InvalidEmailError()
  110. if token_data["code"] != args["code"]:
  111. raise EmailCodeError()
  112. WebAppAuthService.revoke_email_code_login_token(args["token"])
  113. account = WebAppAuthService.get_user_through_email(user_email)
  114. if not account:
  115. raise AuthenticationFailedError()
  116. token = WebAppAuthService.login(account=account)
  117. AccountService.reset_login_error_rate_limit(args["email"])
  118. return {"result": "success", "data": {"access_token": token}}