web.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import flask
  2. import pystache
  3. import lc.config as c
  4. import lc.model as m
  5. class Endpoint:
  6. def __init__(self):
  7. self.user = None
  8. # try finding the token
  9. token = None
  10. # first check the HTTP headers
  11. if (auth := flask.request.headers.get("Authorization", None)):
  12. token = auth.split()[1]
  13. # if that fails, check the session
  14. elif flask.session.get("auth", None):
  15. token = flask.session["auth"]
  16. # if that exists and we can deserialize it, then make sure
  17. # it contains a valid user password, too
  18. if token and (payload := c.SERIALIZER.loads(token)):
  19. if "name" not in payload or "password" not in payload:
  20. return
  21. try:
  22. u = m.User.by_slug(payload["name"])
  23. except e.LCException:
  24. return
  25. if u.authenticate(payload["password"]):
  26. self.user = u
  27. def require_authentication(self, name: str):
  28. '''
  29. Check that the currently logged-in user exists and is the
  30. same as the user whose username is given. Raises an exception
  31. otherwise.
  32. '''
  33. if not self.user or name != self.user.name:
  34. raise e.BadPermissions()
  35. def api_post(self, *args, **kwargs) -> dict:
  36. raise e.NotImplemented()
  37. def api_get(self, *args, **kwargs) -> dict:
  38. raise e.NotImplemented()
  39. def html(self, *args, **kwargs):
  40. raise e.NotImplemented()
  41. def route(self, *args, **kwargs):
  42. try:
  43. if flask.request.method == "POST":
  44. require_authentication()
  45. return flask.jsonify(self.api_post(*args, **kwargs))
  46. elif (
  47. flask.request.method in ["GET", "HEAD"]
  48. and flask.request.content_type == "application/json"
  49. ):
  50. return flask.jsonify(self.api_get(*args, **kwargs))
  51. except e.LCException as exn:
  52. return ({"status": exn.http_code(), "error": str(exn)}, exn.http_code())
  53. try:
  54. return self.html(*args, **kwargs)
  55. except e.LCException as exn:
  56. page = render(
  57. "main", title="error", content=f"shit's fucked yo: {exn}", user=None,
  58. )
  59. return (page, exn.http_code())
  60. def endpoint(cls):
  61. def func(*args, **kwargs):
  62. return cls().route(*args, **kwargs)
  63. func.__name__ = cls.__name__
  64. return func
  65. LOADER = pystache.loader.Loader(extension="mustache", search_dirs=["templates"])
  66. def render(name, **kwargs):
  67. """Load and use a Mustache template from the project root"""
  68. template = LOADER.load_name(name)
  69. renderer = pystache.Renderer(missing_tags="strict", search_dirs=["templates"])
  70. return renderer.render(template, kwargs)