Browse Source

Add the ability to add links (badly)

Getty Ritter 4 years ago
parent
commit
6111dea680
7 changed files with 100 additions and 18 deletions
  1. 23 12
      lc/app.py
  2. 11 0
      lc/error.py
  3. 3 0
      lc/model.py
  4. 14 0
      lc/request.py
  5. 11 1
      lc/web.py
  6. 28 0
      templates/add_link.mustache
  7. 10 5
      templates/main.mustache

+ 23 - 12
lc/app.py

@@ -31,13 +31,8 @@ class Login(Endpoint):
         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"],
-            )
-        )
+        req = self.request_data(r.User)
+        u, token = m.User.login(req)
         flask.session["auth"] = token
         raise e.LCRedirect(u.base_url())
 
@@ -80,27 +75,43 @@ class GetUser(Endpoint):
 
 
 @endpoint("/u/<string:user>/l")
-class CreateLink:
+class CreateLink(Endpoint):
+    def html(self, user: str):
+        return render("main", title="login", content=render("add_link"), user=self.user)
+
     def api_post(self, user: str):
-        pass
+        u = self.require_authentication(user)
+        req = self.request_data(r.Link)
+        l = m.Link.from_request(u, req)
+        raise e.LCRedirect(l.link_url())
 
 
 @endpoint("/u/<string:user>/l/<string:link>")
-class GetLink:
+class GetLink(Endpoint):
     def api_get(self, user: str, link: str):
         pass
 
     def html(self, user: str, link: str):
+        l = m.User.by_slug(user).get_link(int(link))
+        return render(
+            "main",
+            title=f"link {l.name}",
+            content=render("linklist", links=[l]),
+            user=self.user,
+        )
         pass
 
 
 @endpoint("/u/<string:user>/t/<path:tag>")
-class GetTaggedLinks:
+class GetTaggedLinks(Endpoint):
     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,
+            "main",
+            title=f"tag {tag}",
+            content=render("linklist", links=links),
+            user=self.user,
         )

+ 11 - 0
lc/error.py

@@ -60,3 +60,14 @@ class BadPermissions(LCException):
 
     def http_code(self) -> int:
         return 400
+
+
+@dataclass
+class BadContentType(LCException):
+    content_type: str
+
+    def __str__(self):
+        return f"Bad content type for request: {self.content_type}"
+
+    def http_code(self) -> int:
+        return 500

+ 3 - 0
lc/model.py

@@ -57,6 +57,9 @@ class User(Model):
     def get_links(self, page: int) -> typing.List["Link"]:
         return Link.select().where(Link.user == self).paginate(page, c.PER_PAGE)
 
+    def get_link(self, link_id: int) -> "Link":
+        return Link.get((Link.user == self) & (Link.id == link_id))
+
     def get_tag(self, tag_name: str) -> "Tag":
         return Tag.get((Tag.user == self) & (Tag.name == tag_name))
 

+ 14 - 0
lc/request.py

@@ -9,6 +9,10 @@ class User:
     name: str
     password: str
 
+    @classmethod
+    def from_form(cls, form):
+        return cls(name=form["username"], password=form["password"],)
+
 
 @dataclass_json
 @dataclass
@@ -18,3 +22,13 @@ class Link:
     description: str
     private: bool
     tags: List[str]
+
+    @classmethod
+    def from_form(cls, form):
+        return cls(
+            url=form["url"],
+            name=form["name"],
+            description=form["description"],
+            private="private" in form,
+            tags=form["tags"].split(),
+        )

+ 11 - 1
lc/web.py

@@ -33,7 +33,15 @@ class Endpoint:
             if u.authenticate(payload["password"]):
                 self.user = u
 
-    def require_authentication(self, name: str):
+    def request_data(self, cls):
+        if flask.request.content_type == "application/json":
+            return cls.from_json(flask.request.data)
+        elif flask.request.content_type == "application/x-www-form-urlencoded":
+            return cls.from_form(flask.request.form)
+        else:
+            raise e.BadContentType(flask.request.content_type)
+
+    def require_authentication(self, name: str) -> m.User:
         """
         Check that the currently logged-in user exists and is the
         same as the user whose username is given. Raises an exception
@@ -42,6 +50,8 @@ class Endpoint:
         if not self.user or name != self.user.name:
             raise e.BadPermissions()
 
+        return m.User.by_slug(name)
+
     def route(self, *args, **kwargs):
         try:
             if flask.request.method == "POST":

+ 28 - 0
templates/add_link.mustache

@@ -0,0 +1,28 @@
+<div class="loginform">
+  <form name="login" method="POST">
+    <div class="url">
+      <input name="url" type="text" />
+      <label for="url">URL</label>
+    </div>
+    <div class="name">
+      <input name="name" type="text" />
+      <label for="name">Link Name</label>
+    </div>
+    <div class="description">
+      <input name="description" type="text" />
+      <label for="description">Description</label>
+    </div>
+    <div class="private">
+      <input name=private" type="checkbox"/>
+      <label for="private">Private?</label>
+    </div>
+    <div class="tags">
+      <input name="tags" type="text" />
+      <label for="tags">Tags</label>
+    </div>
+
+    <div class="submit">
+      <input type="submit" value="Add Link"/>
+    </div>
+  </form>
+</div>

+ 10 - 5
templates/main.mustache

@@ -17,14 +17,19 @@
       {{^user}}
         <span class="user">not logged in</span>
       {{/user}}
-      <div class="login">
-        {{#user}}
+      {{#user}}
+        <div class="addlink">
+          <a href="/u/{{name}}/l">add link</a>
+        </div>
+        <div class="login">
           <a href="/logout">log out</a>
-        {{/user}}
-        {{^user}}
+        </div>
+      {{/user}}
+      {{^user}}
+        <div class="login">
           <a href="/login">log in</a>
+        </div>
       {{/user}}
-      </div>
     </div>
     <div class="content">
       {{{ content }}}