1
0
mirror of https://github.com/enpaul/kodak.git synced 2024-11-14 10:36:55 +00:00
kodak/dehance/resources/image.py

114 lines
3.0 KiB
Python

import hashlib
import shutil
import uuid
import flask
from dehance import constants
from dehance import database
from dehance import exceptions
from dehance.resources._shared import DehanceResource
class ImageUpload(DehanceResource):
routes = ("/image/",)
def post(self):
if "image" not in flask.request.files:
raise
uploaded = flask.request.files["image"]
if not uploaded.filename:
raise
format = uploaded.filename.rpartition(".")[-1].lower()
if format not in flask.current_app.appconfig.upload.formats:
raise
image = database.ImageRecord(format=format, width=0, height=0, owner="foobar")
imagedir = flask.current_app.appconfig.storage_path / str(image.uuid)
imagedir.mkdir()
uploaded.save(imagedir / f"base.{format}")
with (imagedir / f"base.{format}").open() as infile:
image.sha256 = hashlib.sha256(infile.read()).hexdigest()
with database.interface.atomic():
image.save()
return None, 201
class Image(DehanceResource):
routes = ("/image/<string:image_id>.jpeg",)
def get(self, image_id: str):
image = database.ImageRecord.get(
database.ImageRecord.uuid == uuid.UUID(image_id)
)
if image.deleted:
raise exceptions.ImageResourceDeletedError(
f"Image with ID '{image_id}' was deleted"
)
filepath = (
flask.current_app.appconfig.storage_path
/ str(image.uuid)
/ f"base.{image.format}"
)
if not filepath.exists():
with database.interface.atomic():
image.deleted = True
image.save()
raise exceptions.ImageFileRemovedError(
f"Image file with ID '{image_id}' removed from the server"
)
flask.send_file(
filepath,
mimetype=f"image/{'jpeg' if image.format == 'jpg' else image.format}",
# images are indexed by UUID with no ability to update, y'all should cache
# this thing 'till the sun explodes
cache_timeout=(60 * 60 * 24 * 365),
)
return (
None,
200,
{constants.HTTP_HEADER_RESPONSE_DIGEST: f"sha-256={image.sha256}"},
)
def delete(self, image_id: str, format: str):
image = database.ImageRecord.get(
database.ImageRecord.uuid
== uuid.UUID(image_id) & database.ImageRecord.format
== format
)
if image.deleted:
raise exceptions.ImageResourceDeletedError(
f"Image with ID '{image_id}' was deleted"
)
filepath = flask.current_app.appconfig.storage_path / str(image.uuid)
with database.interface.atomic():
image.deleted = True
image.save()
if filepath.exists():
shutil.rmtree(filepath)
return None, 204