123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- import flask
- import lc.config as c
- import lc.error as e
- import lc.model as m
- import lc.request as r
- import lc.view as v
- from lc.web import Endpoint, endpoint, render
- app = c.app.app
- @endpoint("/")
- class Index(Endpoint):
- def html(self):
- pg = int(flask.request.args.get("page", 1))
- links, pages = m.Link.get_all(as_user=self.user, page=pg)
- linklist = v.LinkList(links=links, pages=pages, user="", tags=[])
- return render(
- "main",
- v.Page(
- title="main",
- content=render("linklist", linklist),
- user=self.user,
- ),
- )
- @endpoint("/auth")
- class Auth(Endpoint):
- def api_post(self):
- u, token = m.User.login(self.request_data(r.User))
- flask.session["auth"] = token
- return self.api_ok(u.base_url(), {"token": token})
- @endpoint("/login")
- class Login(Endpoint):
- def html(self):
- return render(
- "main",
- v.Page(
- title="login",
- content=render("login"),
- user=self.user,
- ),
- )
- @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"]
- return self.api_ok("/")
- @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("/")
- add_user = v.AddUser(token=token)
- return render(
- "main",
- v.Page(
- title="add user",
- user=self.user,
- content=render("add_user", add_user),
- ),
- )
- def api_post(self):
- token = flask.request.args["token"]
- req = self.request_data(r.NewUser).to_user_request()
- u = m.User.from_invite(req, token)
- flask.session["auth"] = req.to_token()
- return self.api_ok(u.base_url(), u.to_dict())
- @endpoint("/u/<string:slug>")
- class GetUser(Endpoint):
- def html(self, slug: str):
- u = m.User.by_slug(slug)
- pg = int(flask.request.args.get("page", 1))
- tags = u.get_tags()
- links, pages = u.get_links(as_user=self.user, page=pg)
- linklist = v.LinkList(links=links, user=slug, pages=pages, tags=tags)
- return render(
- "main",
- v.Page(
- title=f"user {u.name}",
- content=render("linklist", linklist),
- user=self.user,
- ),
- )
- def api_get(self, slug: str):
- return m.User.by_slug(slug).to_dict()
- @endpoint("/u/<string:user>/config")
- class GetUserConfig(Endpoint):
- def html(self, user: str):
- u = self.require_authentication(user)
- status_msg = flask.request.args.get("m", None)
- if status_msg is not None:
- status_msg = int(status_msg)
- return render(
- "main",
- v.Page(
- title="configuration",
- content=render("config", u.get_config(status_msg)),
- user=self.user,
- ),
- )
- @endpoint("/u/<string:user>/invite")
- class CreateInvite(Endpoint):
- def api_post(self, user: str):
- u = self.require_authentication(user)
- invite = m.UserInvite.manufacture(u)
- return self.api_ok(f"/u/{user}/config", {"invite": invite.token})
- @endpoint("/u/<string:user>/password")
- class ChangePassword(Endpoint):
- def api_post(self, user: str):
- u = self.require_authentication(user)
- config_url = u.config_url()
- req = self.request_data(r.PasswordChange)
- try:
- req.require_match()
- except e.MismatchedPassword:
- raise e.LCRedirect(f"{config_url}?m=2")
- try:
- u.change_password(req)
- except e.BadPassword:
- raise e.LCRedirect(f"{config_url}?m=3")
- return self.api_ok(f"{config_url}?m=1")
- @endpoint("/u/<string:user>/l")
- class CreateLink(Endpoint):
- def html(self, user: str):
- u = self.require_authentication(user)
- url = flask.request.args.get("url", "")
- name = flask.request.args.get("name", "")
- tags = u.get_tags()
- defaults = v.AddLinkDefaults(
- user=user,
- name=name,
- url=url,
- all_tags=tags,
- )
- return render(
- "main",
- v.Page(
- title="login",
- content=render("add_link", defaults),
- user=self.user,
- ),
- )
- def api_post(self, user: str):
- u = self.require_authentication(user)
- req = self.request_data(r.Link)
- link = m.Link.from_request(u, req)
- return self.api_ok(link.link_url(), link.to_dict())
- @endpoint("/u/<string:user>/l/<string:link_id>")
- class GetLink(Endpoint):
- def api_get(self, user: str, link_id: str):
- u = self.require_authentication(user)
- link = u.get_link(int(link_id))
- return self.api_ok(link.link_url(), link.to_dict())
- def api_post(self, user: str, link_id: str):
- u = self.require_authentication(user)
- link = u.get_link(int(link_id))
- req = self.request_data(r.Link)
- link.update_from_request(u, req)
- raise e.LCRedirect(link.link_url())
- def api_delete(self, user: str, link_id: str):
- u = self.require_authentication(user)
- u.get_link(int(link_id)).full_delete()
- return self.api_ok(u.base_url())
- def html(self, user: str, link_id: str):
- link = m.User.by_slug(user).get_link(int(link_id))
- return render(
- "main",
- v.Page(
- title=f"link {link.name}",
- content=render(
- "linklist", v.LinkList([link.to_view(self.user)], [], user=user)
- ),
- user=self.user,
- ),
- )
- @endpoint("/u/<string:slug>/l/<string:link_id>/edit")
- class EditLink(Endpoint):
- def html(self, slug: str, link_id: str):
- u = self.require_authentication(slug)
- all_tags = u.get_tags()
- link = u.get_link(int(link_id))
- return render(
- "main",
- v.Page(
- title="login",
- content=render("edit_link", v.SingleLink(link, all_tags)),
- user=self.user,
- ),
- )
- @endpoint("/u/<string:user>/t/<path:tag>")
- class GetTaggedLinks(Endpoint):
- def html(self, user: str, tag: str):
- u = m.User.by_slug(user)
- pg = int(flask.request.args.get("page", 1))
- t = u.get_tag(tag)
- links, pages = t.get_links(as_user=self.user, page=pg)
- tags = u.get_related_tags(t)
- linklist = v.LinkList(links=links, pages=pages, tags=tags, user=user)
- return render(
- "main",
- v.Page(
- title=f"tag {tag}",
- content=render("linklist", linklist),
- user=self.user,
- ),
- )
- @endpoint("/u/<string:user>/search/<string:needle>")
- class GetStringSearch(Endpoint):
- def html(self, user: str, needle: str):
- u = m.User.by_slug(user)
- pg = int(flask.request.args.get("page", 1))
- links, pages = u.get_string_search(needle=needle, as_user=self.user, page=pg)
- tags = u.get_tags()
- linklist = v.LinkList(links=links, pages=pages, tags=tags, user=user)
- return render(
- "main",
- v.Page(
- title=f"search for '{needle}'",
- content=render("linklist", linklist),
- user=self.user,
- ),
- )
- @endpoint("/u/<string:user>/import")
- class PinboardImport(Endpoint):
- def html(self, user: str):
- _ = self.require_authentication(user)
- return render(
- "main",
- v.Page(
- title="import pinboard data",
- content=render("import"),
- user=self.user,
- ),
- )
- def api_post(self, user: str):
- u = self.require_authentication(user)
- if "file" not in flask.request.files:
- raise e.BadFileUpload("could not find attached file")
- file = flask.request.files["file"]
- if file.filename == "":
- raise e.BadFileUpload("no file selected")
- u.import_pinboard_data(file.stream)
- return self.api_ok(u.base_url())
- @endpoint("/service-worker.js")
- class ServiceWorker(Endpoint):
- def route(self, *args, **kwargs):
- return flask.send_file("../js/serviceWorker.js", mimetype="text/javascript")
- @endpoint("/add-link")
- class AddLink(Endpoint):
- def html(self):
- if not self.user:
- raise e.LCRedirect("/login")
- url = flask.request.args.get("text", None)
- name = flask.request.args.get("name", None)
- text = flask.request.args.get("text", None)
- # Android sets the text field to the url only
- if url is None and name is None and text is not None:
- args = f"url={text}"
- else:
- args = "&".join(f"{key}={value}" for key, value in flask.request.args.items())
- raise e.LCRedirect(f"/u/{self.user.name}/l?{args}")
|