A corporation manager and dashboard for EVE Online
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.
 
 
 
 
 

97 lines
3.3 KiB

  1. # -*- coding: utf-8 -*-
  2. from functools import wraps
  3. from hashlib import md5
  4. from os import path
  5. from traceback import format_exc
  6. from flask import flash, request, url_for
  7. from flask_mako import render_template, TemplateError
  8. from werkzeug.exceptions import HTTPException
  9. from .exceptions import AccessDeniedError, EVEAPIError
  10. from .messages import Messages
  11. __all__ = [
  12. "try_func", "make_error_catcher", "make_route_restricter",
  13. "set_up_asset_versioning"]
  14. def try_func(inner):
  15. """Evaluate inner(), catching subclasses of CalefactionError.
  16. If nothing was caught, return (inner(), False). Otherwise, flash an
  17. appropriate error message and return (False, True).
  18. """
  19. try:
  20. result = inner()
  21. return (result, False)
  22. except EVEAPIError:
  23. flash(Messages.EVE_API_ERROR, "error")
  24. return (False, True)
  25. except AccessDeniedError:
  26. flash(Messages.ACCESS_DENIED, "error")
  27. return (False, True)
  28. def make_error_catcher(app, error_template):
  29. """Wrap a route to display and log any uncaught exceptions."""
  30. def callback(func):
  31. @wraps(func)
  32. def inner(*args, **kwargs):
  33. try:
  34. return func(*args, **kwargs)
  35. except HTTPException:
  36. raise
  37. except TemplateError as exc:
  38. app.logger.error("Caught exception:\n{0}".format(exc.text))
  39. return render_template(error_template, traceback=exc.text)
  40. except Exception:
  41. app.logger.exception("Caught exception:")
  42. return render_template(error_template, traceback=format_exc())
  43. return inner
  44. return callback
  45. def make_route_restricter(auth, on_failure):
  46. """Wrap a route to ensure the user is authenticated."""
  47. def callback(func):
  48. @wraps(func)
  49. def inner(*args, **kwargs):
  50. success, caught = try_func(auth.is_authenticated)
  51. if success:
  52. return func(*args, **kwargs)
  53. if not caught:
  54. flash(Messages.LOG_IN_FIRST, "error")
  55. return on_failure()
  56. return inner
  57. return callback
  58. def set_up_asset_versioning(app):
  59. """Add a staticv endpoint that adds hash versioning to static assets."""
  60. def callback(app, error, endpoint, values):
  61. if endpoint == "staticv":
  62. filename = values["filename"]
  63. fpath = path.join(app.static_folder, filename)
  64. try:
  65. mtime = path.getmtime(fpath)
  66. except OSError:
  67. return url_for("static", filename=filename)
  68. cache = app._hash_cache.get(fpath)
  69. if cache and cache[0] == mtime:
  70. hashstr = cache[1]
  71. else:
  72. with open(fpath, "rb") as fp:
  73. hashstr = md5(fp.read()).hexdigest()
  74. app._hash_cache[fpath] = (mtime, hashstr)
  75. return url_for("static", filename=filename, v=hashstr)
  76. raise error
  77. old_get_max_age = app.get_send_file_max_age
  78. def extend_max_age(filename):
  79. if "v" in request.args:
  80. return 60 * 60 * 24 * 365 # 1 year
  81. return old_get_max_age(filename)
  82. app._hash_cache = {}
  83. app.url_build_error_handlers.append(lambda a, b, c: callback(app, a, b, c))
  84. app.get_send_file_max_age = extend_max_age