Browse Source

Add routes and models for using invites

Getty Ritter 4 years ago
parent
commit
908bd814d2
4 changed files with 83 additions and 2 deletions
  1. 38 2
      lc/app.py
  2. 9 0
      lc/error.py
  3. 17 0
      lc/model.py
  4. 19 0
      lc/request.py

+ 38 - 2
lc/app.py

@@ -61,9 +61,25 @@ class Logout(Endpoint):
 
 @endpoint("/u")
 class CreateUser(Endpoint):
+    def html(self):
+        if self.user:
+            raise e.LCRedirect(f"/u/{self.user.name}")
+
+        token = flask.request.args.get("token")
+        if not token:
+            raise e.LCRedirect("/")
+
+        return render(
+            "main",
+            title="add user",
+            user=self.user,
+            content=render("add_user", token=token),
+        )
+
     def api_post(self):
-        u = m.User.from_request(self.request_data(r.User))
-        return flask.redirect(u.base_url())
+        token = flask.request.args["token"]
+        u = m.User.from_invite(self.request_data(r.NewUser).to_user_request(), token)
+        raise e.LCRedirect(u.base_url())
 
 
 @endpoint("/u/<string:slug>")
@@ -83,6 +99,26 @@ class GetUser(Endpoint):
         return m.User.by_slug(slug).to_dict()
 
 
+@endpoint("/u/<string:user>/config")
+class UserConfig(Endpoint):
+    def html(self, user: str):
+        u = self.require_authentication(user)
+        return render(
+            "main",
+            title="configuration",
+            content=render("config", **u.get_config()),
+            user=self.user,
+        )
+
+
+@endpoint("/u/<string:user>/invite")
+class CreateInvite(Endpoint):
+    def api_post(self, user: str):
+        u = self.require_authentication(user)
+        m.UserInvite.manufacture(u)
+        raise e.LCRedirect(f"/u/{user}/config")
+
+
 @endpoint("/u/<string:user>/l")
 class CreateLink(Endpoint):
     def html(self, user: str):

+ 9 - 0
lc/error.py

@@ -96,3 +96,12 @@ class AlreadyUsedInvite(LCException):
 
     def http_code(self) -> int:
         return 403
+
+
+@dataclass
+class MismatchedPassword(LCException):
+    def __str__(self):
+        return f"Provided passwords do not match. Please check your passwords."
+
+    def http_code(self) -> int:
+        return 400

+ 17 - 0
lc/model.py

@@ -110,6 +110,23 @@ class User(Model):
     def to_dict(self) -> dict:
         return {"id": self.id, "name": self.name}
 
+    def get_config(self) -> dict:
+        admin_pane = None
+        if self.is_admin:
+            user_invites = [
+                {"claimed": ui.claimed_by is not None,
+                 "claimant": ui.claimed_by and ui.claimed_by.name,
+                 "token": ui.token}
+                for ui in UserInvite.select().where(UserInvite.created_by == self)
+            ]
+            admin_pane = {
+                "invites": user_invites
+            }
+        return {
+            "username": self.name,
+            "admin_pane": admin_pane,
+        }
+
 
 class Link(Model):
     """

+ 19 - 0
lc/request.py

@@ -5,6 +5,7 @@ from datetime import datetime
 from typing import List, Mapping, Optional, TypeVar, Type
 
 import lc.config as c
+import lc.error as e
 
 T = TypeVar("T")
 
@@ -37,6 +38,24 @@ class User(Request):
         return c.serializer.dumps({"name": self.name, "password": self.password,})
 
 
+@dataclass_json
+@dataclass
+class NewUser(Request):
+    name: str
+    n1: str
+    n2: str
+
+    @classmethod
+    def from_form(cls, form: Mapping[str, str]):
+        return cls(name=form["username"], n1=form["n1"], n2=form["n2"],)
+
+    def to_user_request(self) -> User:
+        if self.n1 != self.n2:
+            raise e.MismatchedPassword()
+
+        return User(name=self.name, password=self.n1)
+
+
 @dataclass_json
 @dataclass
 class Link(Request):