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.
 
 
 
 
 

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