app.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import contextlib
  2. import os
  3. import flask
  4. import pystache
  5. import sys
  6. import lc.config as c
  7. import lc.error as e
  8. import lc.model as m
  9. import lc.request as r
  10. app = flask.Flask(__name__)
  11. loader = pystache.loader.Loader(extension="mustache", search_dirs=["templates"])
  12. def render(name, **kwargs):
  13. """Load and use a Mustache template from the project root"""
  14. template = loader.load_name(name)
  15. renderer = pystache.Renderer(missing_tags="strict", search_dirs=["templates"])
  16. return renderer.render(template, kwargs)
  17. class Endpoint:
  18. def __init__(self):
  19. self.user = None
  20. # try finding the token
  21. token = None
  22. if (auth := flask.request.headers["Authorization"]) :
  23. token = auth.split()[1]
  24. elif flask.session["auth"]:
  25. token = flask.session["auth"]
  26. if token and (payload := c.SERIALIZER.loads(token)):
  27. if "name" not in payload or "password" not in payload:
  28. return
  29. try:
  30. u = m.User.by_slug(payload["name"])
  31. except e.LCException:
  32. return
  33. if u.authenticate(payload["password"]):
  34. self.user = u
  35. def require_authentication(self, name: user):
  36. if name != self.user.name:
  37. raise e.BadPermissions()
  38. def api_post(self, *args, **kwargs) -> dict:
  39. raise e.NotImplemented()
  40. def api_get(self, *args, **kwargs) -> dict:
  41. raise e.NotImplemented()
  42. def html(self, *args, **kwargs):
  43. raise e.NotImplemented()
  44. def route(self, *args, **kwargs):
  45. try:
  46. if flask.request.method == "POST":
  47. require_authentication()
  48. return flask.jsonify(self.api_post(*args, **kwargs))
  49. elif (
  50. flask.request.method in ["GET", "HEAD"]
  51. and flask.request.content_type == "application/json"
  52. ):
  53. return flask.jsonify(self.api_get(*args, **kwargs))
  54. except e.LCException as exn:
  55. return ({"status": exn.http_code(), "error": str(exn)}, exn.http_code())
  56. try:
  57. return self.html(*args, **kwargs)
  58. except e.LCException as exn:
  59. page = render(
  60. "main", title="error", content=f"shit's fucked yo: {exn}", user=None,
  61. )
  62. return (page, exn.http_code())
  63. def endpoint(cls):
  64. def func(*args, **kwargs):
  65. return cls().route(*args, **kwargs)
  66. func.__name__ = cls.__name__
  67. return func
  68. @app.route("/")
  69. @endpoint
  70. class Index(Endpoint):
  71. def html(self):
  72. return render("main", title="main", content="whoo", user=self.user)
  73. @app.route("/auth", methods=["GET", "POST"])
  74. @endpoint
  75. class Auth(Endpoint):
  76. def api_post(self):
  77. return m.User.login(r.User.from_json(flask.request.data))
  78. @app.route("/u", methods=["GET", "POST"])
  79. @endpoint
  80. class CreateUser(Endpoint):
  81. def api_post(self):
  82. u = m.User.from_request(r.User.from_json(flask.request.data))
  83. return flask.redirect(u.base_url())
  84. @app.route("/u/<string:slug>")
  85. @endpoint
  86. class GetUser(Endpoint):
  87. def html(self, slug: str):
  88. u = m.User.by_slug(slug)
  89. pg = int(flask.request.args.get("page", 0))
  90. links = u.get_links(page=pg)
  91. return render(
  92. "main",
  93. title=f"user {u.name}",
  94. content=render("linklist", links=links),
  95. user=self.user,
  96. )
  97. def api_get(self, current_user, slug: str):
  98. return m.User.by_slug(slug).to_dict()
  99. @app.route("/u/<string:user>/l")
  100. def create_link(user: str):
  101. pass
  102. @app.route("/u/<string:user>/l/<string:link>")
  103. def link(user: str, link: str):
  104. pass
  105. @app.route("/u/<string:user>/t/<path:tag>")
  106. def get_tagged_links(user: str, tag: str):
  107. u = m.User.by_slug(user)
  108. pg = int(flask.request.args.get("page", 0))
  109. t = u.get_tag(tag)
  110. links = t.get_links(page=pg)
  111. return render(
  112. "main", title=f"tag {tag}", content=render("linklist", links=links), user=u,
  113. )