base.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import logging
  2. from typing import Any, Callable
  3. import unicodedata
  4. from urllib.parse import urlparse
  5. from flask import current_app, request
  6. from flask_babel import gettext
  7. from flask_babel.speaklater import LazyString
  8. log = logging.getLogger(__name__)
  9. def is_safe_redirect_url(url: str) -> bool:
  10. if url.startswith("///"):
  11. return False
  12. try:
  13. url_info = urlparse(url)
  14. except ValueError:
  15. return False
  16. if not url_info.netloc and url_info.scheme:
  17. return False
  18. if unicodedata.category(url[0])[0] == "C":
  19. return False
  20. scheme = url_info.scheme
  21. # Consider URLs without a scheme (e.g. //example.com/p) to be http.
  22. if not url_info.scheme and url_info.netloc:
  23. scheme = "http"
  24. valid_schemes = ["http", "https"]
  25. host_url = urlparse(request.host_url)
  26. return (not url_info.netloc or url_info.netloc == host_url.netloc) and (
  27. not scheme or scheme in valid_schemes
  28. )
  29. def get_safe_redirect(url):
  30. if url and is_safe_redirect_url(url):
  31. return url
  32. log.warning("Invalid redirect detected, falling back to index")
  33. return current_app.appbuilder.get_url_for_index
  34. def get_column_root_relation(column: str) -> str:
  35. if "." in column:
  36. return column.split(".")[0]
  37. return column
  38. def get_column_leaf(column: str) -> str:
  39. if "." in column:
  40. return column.split(".")[1]
  41. return column
  42. def is_column_dotted(column: str) -> bool:
  43. return "." in column
  44. def _wrap_lazy_formatter_gettext(
  45. string: str, lazy_formater: Callable[[str], str], **variables: Any
  46. ) -> str:
  47. return gettext(lazy_formater(string), **variables)
  48. def lazy_formatter_gettext(
  49. string: str, lazy_formatter: Callable[[str], str], **variables: Any
  50. ) -> LazyString:
  51. """Formats a lazy_gettext string with a custom function
  52. Example::
  53. def custom_formatter(string: str) -> str:
  54. if current_app.config["CONDITIONAL_KEY"]:
  55. string += " . Condition key is on"
  56. return string
  57. hello = lazy_formatter_gettext(u'Hello World', custom_formatter)
  58. @app.route('/')
  59. def index():
  60. return unicode(hello)
  61. """
  62. return LazyString(_wrap_lazy_formatter_gettext, string, lazy_formatter, **variables)