fix: close library upload flow and harden image storage
This commit is contained in:
@@ -30,7 +30,13 @@ from pigway_frame_flow.storage.database import encode
|
||||
class PhotoSourceInput(StrictModel):
|
||||
name: str = Field(min_length=1, max_length=120)
|
||||
kind: Literal[
|
||||
"local", "synology-photos", "webdav", "google-drive", "alipan", "baidu"
|
||||
"local",
|
||||
"synology-photos",
|
||||
"webdav",
|
||||
"google-drive",
|
||||
"alipan",
|
||||
"baidu",
|
||||
"uploads",
|
||||
]
|
||||
location: str = Field(min_length=1, max_length=2048)
|
||||
nas_root_path: str | None = Field(default=None, max_length=2048, pattern=r"^/")
|
||||
@@ -132,6 +138,12 @@ class PhotoSources:
|
||||
|
||||
def save(self, source_id, source):
|
||||
self.require_api_source(source)
|
||||
if source.kind == "uploads" and (
|
||||
source_id != "manual-uploads" or source.location != "."
|
||||
):
|
||||
raise FlowError(E.INVALID_REQUEST, "Invalid manual upload source")
|
||||
if source_id == "manual-uploads" and source.kind != "uploads":
|
||||
raise FlowError(E.CONFLICT, "Reserved manual upload source")
|
||||
if source.minimum_brightness > source.maximum_brightness:
|
||||
raise FlowError(E.INVALID_REQUEST, "Brightness range is reversed")
|
||||
if source.kind not in ("local", "synology-photos") and (
|
||||
@@ -310,6 +322,20 @@ class PhotoSources:
|
||||
self.require_api_source(source)
|
||||
if not source.enabled:
|
||||
raise FlowError(E.CONFLICT, "Photo source is disabled", 409)
|
||||
if source.kind == "uploads":
|
||||
return [
|
||||
{
|
||||
"id": row["item_id"],
|
||||
"name": row["name"],
|
||||
"caption": json.loads(row["caption"]),
|
||||
"starred": bool(row["starred"]),
|
||||
"excluded": bool(row["excluded"]),
|
||||
}
|
||||
for row in self.db.all(
|
||||
"SELECT s.item_id,s.caption,a.name,COALESCE(p.starred,0) AS starred,COALESCE(p.excluded,0) AS excluded FROM source_images s JOIN assets a ON a.id=s.id LEFT JOIN photo_preferences p ON p.source_id=s.source_id AND p.item_id=s.item_id WHERE s.source_id=? ORDER BY s.created_at DESC,s.id DESC",
|
||||
(source_id,),
|
||||
)
|
||||
]
|
||||
session_identity = (
|
||||
self.synology.sid() if source.kind == "synology-photos" else None
|
||||
)
|
||||
@@ -610,6 +636,18 @@ class PhotoSources:
|
||||
)
|
||||
if item is None:
|
||||
raise FlowError(E.NOT_FOUND, "Photo is not in this source", 404)
|
||||
if source.kind == "uploads":
|
||||
row = self.db.one(
|
||||
"SELECT id,caption FROM source_images WHERE source_id=? AND item_id=?",
|
||||
(source_id, item["id"]),
|
||||
)
|
||||
if not row:
|
||||
raise FlowError(E.NOT_FOUND, "Uploaded source picture not found", 404)
|
||||
return (
|
||||
self.assets.path(row["id"]).read_bytes(),
|
||||
item["name"],
|
||||
json.loads(row["caption"]),
|
||||
)
|
||||
if source.kind == "local":
|
||||
root = self.settings.photo_root.resolve()
|
||||
path = root / item["id"]
|
||||
@@ -688,7 +726,7 @@ class PhotoSources:
|
||||
|
||||
from PIL import Image
|
||||
|
||||
with Image.open(BytesIO(data)) as image:
|
||||
with Image.open(BytesIO(data), formats=("JPEG", "PNG", "WEBP")) as image:
|
||||
width, height = image.size
|
||||
if image.getexif().get(274, 1) in (5, 6, 7, 8):
|
||||
width, height = height, width
|
||||
|
||||
Reference in New Issue
Block a user