You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

login.py 2.4KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from collections.abc import Callable
  2. from functools import wraps
  3. from typing import Union, cast
  4. from flask import current_app, g, has_request_context, request
  5. from flask_login.config import EXEMPT_METHODS # type: ignore
  6. from werkzeug.local import LocalProxy
  7. from configs import dify_config
  8. from models.account import Account
  9. from models.model import EndUser
  10. #: A proxy for the current user. If no user is logged in, this will be an
  11. #: anonymous user
  12. current_user = cast(Union[Account, EndUser, None], LocalProxy(lambda: _get_user()))
  13. from typing import ParamSpec, TypeVar
  14. P = ParamSpec("P")
  15. R = TypeVar("R")
  16. def login_required(func: Callable[P, R]):
  17. """
  18. If you decorate a view with this, it will ensure that the current user is
  19. logged in and authenticated before calling the actual view. (If they are
  20. not, it calls the :attr:`LoginManager.unauthorized` callback.) For
  21. example::
  22. @app.route('/post')
  23. @login_required
  24. def post():
  25. pass
  26. If there are only certain times you need to require that your user is
  27. logged in, you can do so with::
  28. if not current_user.is_authenticated:
  29. return current_app.login_manager.unauthorized()
  30. ...which is essentially the code that this function adds to your views.
  31. It can be convenient to globally turn off authentication when unit testing.
  32. To enable this, if the application configuration variable `LOGIN_DISABLED`
  33. is set to `True`, this decorator will be ignored.
  34. .. Note ::
  35. Per `W3 guidelines for CORS preflight requests
  36. <http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0>`_,
  37. HTTP ``OPTIONS`` requests are exempt from login checks.
  38. :param func: The view function to decorate.
  39. :type func: function
  40. """
  41. @wraps(func)
  42. def decorated_view(*args: P.args, **kwargs: P.kwargs):
  43. if request.method in EXEMPT_METHODS or dify_config.LOGIN_DISABLED:
  44. pass
  45. elif current_user is not None and not current_user.is_authenticated:
  46. return current_app.login_manager.unauthorized() # type: ignore
  47. return current_app.ensure_sync(func)(*args, **kwargs)
  48. return decorated_view
  49. def _get_user() -> EndUser | Account | None:
  50. if has_request_context():
  51. if "_login_user" not in g:
  52. current_app.login_manager._load_user() # type: ignore
  53. return g._login_user # type: ignore
  54. return None