Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import json
  2. import flask_login # type: ignore
  3. from flask import Response, request
  4. from flask_login import user_loaded_from_request, user_logged_in
  5. from werkzeug.exceptions import NotFound, Unauthorized
  6. from configs import dify_config
  7. from dify_app import DifyApp
  8. from extensions.ext_database import db
  9. from libs.passport import PassportService
  10. from models.account import Account, Tenant, TenantAccountJoin
  11. from models.model import AppMCPServer, EndUser
  12. from services.account_service import AccountService
  13. login_manager = flask_login.LoginManager()
  14. # Flask-Login configuration
  15. @login_manager.request_loader
  16. def load_user_from_request(request_from_flask_login):
  17. """Load user based on the request."""
  18. # Skip authentication for documentation endpoints
  19. if dify_config.SWAGGER_UI_ENABLED and request.path.endswith((dify_config.SWAGGER_UI_PATH, "/swagger.json")):
  20. return None
  21. auth_header = request.headers.get("Authorization", "")
  22. auth_token: str | None = None
  23. if auth_header:
  24. if " " not in auth_header:
  25. raise Unauthorized("Invalid Authorization header format. Expected 'Bearer <api-key>' format.")
  26. auth_scheme, auth_token = auth_header.split(maxsplit=1)
  27. auth_scheme = auth_scheme.lower()
  28. if auth_scheme != "bearer":
  29. raise Unauthorized("Invalid Authorization header format. Expected 'Bearer <api-key>' format.")
  30. else:
  31. auth_token = request.args.get("_token")
  32. # Check for admin API key authentication first
  33. if dify_config.ADMIN_API_KEY_ENABLE and auth_header:
  34. admin_api_key = dify_config.ADMIN_API_KEY
  35. if admin_api_key and admin_api_key == auth_token:
  36. workspace_id = request.headers.get("X-WORKSPACE-ID")
  37. if workspace_id:
  38. tenant_account_join = (
  39. db.session.query(Tenant, TenantAccountJoin)
  40. .where(Tenant.id == workspace_id)
  41. .where(TenantAccountJoin.tenant_id == Tenant.id)
  42. .where(TenantAccountJoin.role == "owner")
  43. .one_or_none()
  44. )
  45. if tenant_account_join:
  46. tenant, ta = tenant_account_join
  47. account = db.session.query(Account).filter_by(id=ta.account_id).first()
  48. if account:
  49. account.current_tenant = tenant
  50. return account
  51. if request.blueprint in {"console", "inner_api"}:
  52. if not auth_token:
  53. raise Unauthorized("Invalid Authorization token.")
  54. decoded = PassportService().verify(auth_token)
  55. user_id = decoded.get("user_id")
  56. source = decoded.get("token_source")
  57. if source:
  58. raise Unauthorized("Invalid Authorization token.")
  59. if not user_id:
  60. raise Unauthorized("Invalid Authorization token.")
  61. logged_in_account = AccountService.load_logged_in_account(account_id=user_id)
  62. return logged_in_account
  63. elif request.blueprint == "web":
  64. decoded = PassportService().verify(auth_token)
  65. end_user_id = decoded.get("end_user_id")
  66. if not end_user_id:
  67. raise Unauthorized("Invalid Authorization token.")
  68. end_user = db.session.query(EndUser).where(EndUser.id == decoded["end_user_id"]).first()
  69. if not end_user:
  70. raise NotFound("End user not found.")
  71. return end_user
  72. elif request.blueprint == "mcp":
  73. server_code = request.view_args.get("server_code") if request.view_args else None
  74. if not server_code:
  75. raise Unauthorized("Invalid Authorization token.")
  76. app_mcp_server = db.session.query(AppMCPServer).where(AppMCPServer.server_code == server_code).first()
  77. if not app_mcp_server:
  78. raise NotFound("App MCP server not found.")
  79. end_user = (
  80. db.session.query(EndUser)
  81. .where(EndUser.external_user_id == app_mcp_server.id, EndUser.type == "mcp")
  82. .first()
  83. )
  84. if not end_user:
  85. raise NotFound("End user not found.")
  86. return end_user
  87. @user_logged_in.connect
  88. @user_loaded_from_request.connect
  89. def on_user_logged_in(_sender, user):
  90. """Called when a user logged in.
  91. Note: AccountService.load_logged_in_account will populate user.current_tenant_id
  92. through the load_user method, which calls account.set_tenant_id().
  93. """
  94. # tenant_id context variable removed - using current_user.current_tenant_id directly
  95. pass
  96. @login_manager.unauthorized_handler
  97. def unauthorized_handler():
  98. """Handle unauthorized requests."""
  99. return Response(
  100. json.dumps({"code": "unauthorized", "message": "Unauthorized."}),
  101. status=401,
  102. content_type="application/json",
  103. )
  104. def init_app(app: DifyApp):
  105. login_manager.init_app(app)