#!/usr/bin/env python3 # TODO maxlength on folder name # TODO maxlength on file name # TODO maxlength on file contents import json import falcon from slugify import slugify from wolkje_files import img_store def get_slug(folder: dict): if "name" in folder: return slugify(folder["name"]) else: return "untitled" def ensure_slug(folder: dict, folder_slug_in_url: str): expected_slug = get_slug(folder) if folder_slug_in_url != expected_slug: raise falcon.HTTPPermanentRedirect(f"/folder/{folder['folder_id']}/{expected_slug}") def redirect_to_folder(folder: dict): assert folder raise falcon.HTTPFound(f"/folder/{folder['folder_id']}/{get_slug(folder)}") class FolderIndex: def on_post(self, req: falcon.Request, resp: falcon.Response): try: data = json.load(req.bounded_stream) except Exception as exc: raise falcon.HTTPBadRequest(description="Could not read body as JSON") from exc if "folder_name" not in data: raise falcon.HTTPBadRequest(description="folder_name not given in body") folder = img_store.new_folder(data["folder_name"]) if not folder: raise falcon.HTTPInternalServerError(description="Failed to create a new folder") redirect_to_folder(folder) class FolderResource: def on_get(self, req: falcon.Request, resp: falcon.Response, folder_id: str, folder_slug=None): folder = img_store.get_folder(folder_id) if not folder: raise falcon.HTTPNotFound() ensure_slug(folder, folder_slug) resp.media = { "name": folder.get("name"), "created": folder.get("created"), "files": img_store.ls(folder_id), } def on_post(self, req: falcon.Request, resp: falcon.Response, folder_id: str, folder_slug: str): # TODO check authorization form = req.get_media() for part in form: if part.filename is None: pass try: img_store.save_file(folder_id, part.filename, part.stream, part.content_type) except img_store.NoSuchFolderError: raise falcon.HTTPNotFound(description="Folder does not exist") folder = img_store.get_folder(folder_id) redirect_to_folder(folder) class FileResource: def on_get( self, req: falcon.Request, resp: falcon.Response, folder_id: str, folder_slug: str, file_name: str ): try: resp.stream, resp.content_length, resp.content_type = img_store.open_file(folder_id, file_name) except img_store.NoSuchFolderError: raise falcon.HTTPNotFound(description="Folder does not exist") except img_store.NoSuchFileError: raise falcon.HTTPNotFound(description="File does not exist") app = falcon.App() app.add_route("/", FolderIndex()) app.add_route("/{folder_id}/{folder_slug}", FolderResource()) app.add_route("/{folder_id}/{folder_slug}/{file_name}", FileResource())