Browse Source

Add endpoint decorator and add login/logout

Getty Ritter 4 years ago
parent
commit
133b6bbd80
7 changed files with 100 additions and 32 deletions
  1. 55 25
      lc/app.py
  2. 3 0
      lc/config.py
  3. 8 0
      lc/error.py
  4. 4 1
      lc/model.py
  5. 15 6
      lc/web.py
  6. 7 0
      templates/login.mustache
  7. 8 0
      templates/main.mustache

+ 55 - 25
lc/app.py

@@ -9,32 +9,56 @@ import lc.model as m
 import lc.request as r
 from lc.web import Endpoint, endpoint, render
 
-app = flask.Flask(__name__)
+app = c.app
 
-@app.route("/")
-@endpoint
+@endpoint("/")
 class Index(Endpoint):
     def html(self):
         return render("main", title="main", content="whoo", user=self.user)
 
 
-@app.route("/auth", methods=["GET", "POST"])
-@endpoint
+@endpoint("/auth")
 class Auth(Endpoint):
     def api_post(self):
-        return m.User.login(r.User.from_json(flask.request.data))
+        _, token = m.User.login(r.User.from_json(flask.request.data))
+        return token
 
 
-@app.route("/u", methods=["GET", "POST"])
-@endpoint
+@endpoint("/login")
+class Login(Endpoint):
+    def html(self):
+        return render("main", title="login", content=render("login"), user=self.user)
+
+    def api_post(self):
+        print(flask.request.form)
+        u, token = m.User.login(r.User(
+            name=flask.request.form["username"],
+            password=flask.request.form["password"],
+        ))
+        flask.session["auth"] = token
+        raise e.LCRedirect(u.base_url())
+
+@endpoint("/logout")
+class Logout(Endpoint):
+    def html(self):
+        if "auth" in flask.session:
+            del flask.session["auth"]
+        raise e.LCRedirect("/")
+
+    def api_post(self):
+        if "auth" in flask.session:
+            del flask.session["auth"]
+        raise e.LCRedirect("/")
+
+
+@endpoint("/u")
 class CreateUser(Endpoint):
     def api_post(self):
         u = m.User.from_request(r.User.from_json(flask.request.data))
         return flask.redirect(u.base_url())
 
 
-@app.route("/u/<string:slug>")
-@endpoint
+@endpoint("/u/<string:slug>")
 class GetUser(Endpoint):
     def html(self, slug: str):
         u = m.User.by_slug(slug)
@@ -51,22 +75,28 @@ class GetUser(Endpoint):
         return m.User.by_slug(slug).to_dict()
 
 
-@app.route("/u/<string:user>/l")
-def create_link(user: str):
-    pass
+@endpoint("/u/<string:user>/l")
+class CreateLink:
+    def api_post(self, user: str):
+        pass
+
 
+@endpoint("/u/<string:user>/l/<string:link>")
+class GetLink:
+    def api_get(self, user: str, link: str):
+        pass
 
-@app.route("/u/<string:user>/l/<string:link>")
-def link(user: str, link: str):
-    pass
+    def html(self, user: str, link: str):
+        pass
 
 
-@app.route("/u/<string:user>/t/<path:tag>")
-def get_tagged_links(user: str, tag: str):
-    u = m.User.by_slug(user)
-    pg = int(flask.request.args.get("page", 0))
-    t = u.get_tag(tag)
-    links = t.get_links(page=pg)
-    return render(
-        "main", title=f"tag {tag}", content=render("linklist", links=links), user=u,
-    )
+@endpoint("/u/<string:user>/t/<path:tag>")
+class GetTaggedLinks:
+    def html(self, user: str, tag: str):
+        u = m.User.by_slug(user)
+        pg = int(flask.request.args.get("page", 0))
+        t = u.get_tag(tag)
+        links = t.get_links(page=pg)
+        return render(
+            "main", title=f"tag {tag}", content=render("linklist", links=links), user=u,
+        )

+ 3 - 0
lc/config.py

@@ -1,12 +1,15 @@
 import os
 import sys
 
+import flask
 import itsdangerous
 import playhouse.sqlite_ext
 
 DB = playhouse.sqlite_ext.SqliteExtDatabase(None)
 PER_PAGE = 50
 SERIALIZER = itsdangerous.URLSafeSerializer("TEMP KEY")
+app = flask.Flask(__name__)
+app.secret_key = "ARGLBARGL"
 
 if sys.stderr.isatty():
 

+ 8 - 0
lc/error.py

@@ -1,6 +1,14 @@
 from dataclasses import dataclass
 
 
+@dataclass
+class LCRedirect(Exception):
+    path: str
+
+    def to_path(self) -> str:
+        return self.path
+
+
 class LCException(Exception):
     def to_json(self) -> dict:
         return {"error": str(self)}

+ 4 - 1
lc/model.py

@@ -42,7 +42,7 @@ class User(Model):
         u = User.by_slug(user.name)
         if not u.authenticate(user.password):
             raise e.BadPassword(name=user.name)
-        return c.SERIALIZER.dumps(user.to_dict())
+        return u, c.SERIALIZER.dumps(user.to_dict())
 
     @staticmethod
     def by_slug(slug: str) -> "User":
@@ -142,6 +142,9 @@ class HasTag(Model):
     tag = peewee.ForeignKeyField(Tag, backref="models")
 
 
+class UserInvite(Model):
+    token: str
+
 MODELS = [
     User,
     Link,

+ 15 - 6
lc/web.py

@@ -45,7 +45,6 @@ class Endpoint:
     def route(self, *args, **kwargs):
         try:
             if flask.request.method == "POST":
-                require_authentication()
                 return flask.jsonify(self.api_post(*args, **kwargs))
             elif (
                 flask.request.method in ["GET", "HEAD"]
@@ -54,6 +53,8 @@ class Endpoint:
                 return flask.jsonify(self.api_get(*args, **kwargs))
         except e.LCException as exn:
             return ({"status": exn.http_code(), "error": str(exn)}, exn.http_code())
+        except e.LCRedirect as exn:
+            return flask.redirect(exn.to_path())
 
         try:
             return self.html(*args, **kwargs)
@@ -62,14 +63,22 @@ class Endpoint:
                 "main", title="error", content=f"shit's fucked yo: {exn}", user=None,
             )
             return (page, exn.http_code())
+        except e.LCRedirect as exn:
+            return flask.redirect(exn.to_path())
 
 
-def endpoint(cls):
-    def func(*args, **kwargs):
-        return cls().route(*args, **kwargs)
+def endpoint(route):
+    def do_endpoint(cls):
+        def func(*args, **kwargs):
+            return cls().route(*args, **kwargs)
 
-    func.__name__ = cls.__name__
-    return func
+        methods = ["GET"]
+        if 'api_post' in dir(cls):
+            methods.append("POST")
+
+        func.__name__ = cls.__name__
+        return c.app.route(route, methods=methods)(func)
+    return do_endpoint
 
 
 LOADER = pystache.loader.Loader(extension="mustache", search_dirs=["templates"])

+ 7 - 0
templates/login.mustache

@@ -0,0 +1,7 @@
+<div class="loginform">
+  <form name="login" method="POST">
+    <div class="user"><input name="username" type="text" /></div>
+    <div class="password"><input name="password" type="password" /></div>
+    <div class="submit"><input type="submit" value="Login" /></div>
+  </form>
+</div>

+ 8 - 0
templates/main.mustache

@@ -17,6 +17,14 @@
       {{^user}}
         <span class="user">not logged in</span>
       {{/user}}
+      <div class="login">
+        {{#user}}
+          <a href="/logout">log out</a>
+        {{/user}}
+        {{^user}}
+          <a href="/login">log in</a>
+      {{/user}}
+      </div>
     </div>
     <div class="content">
       {{{ content }}}