97 lines
2.8 KiB
Python
97 lines
2.8 KiB
Python
#!/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)
|
|
except img_store.NoSuchFolderError:
|
|
raise falcon.HTTPNotFound(description="Folder does not exist")
|
|
except img_store.UnknownExtensionError:
|
|
raise falcon.HTTPNotFound(description="Unknown extension in file name")
|
|
except img_store.IllegalFileNameError:
|
|
raise falcon.HTTPNotFound(description="Invalid file name")
|
|
|
|
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())
|