Feature/user photo storage (#877)

* add default assets for user profile

* add recipe avatar

* change user_id to UUID

* add profile image upload

* setup image cache keys

* cleanup tests and add image tests

* purge user data on delete

* new user repository tests

* add user_id validator for int -> UUID conversion

* delete depreciated route

* force set content type

* refactor tests to use temp directory

* validate parent exists before createing

* set user_id to correct type

* update instruction id

* reset primary key on migration
This commit is contained in:
Hayden
2021-12-18 19:04:36 -09:00
committed by GitHub
parent a2f8f27193
commit ea7c4771ee
64 changed files with 433 additions and 181 deletions

View File

@@ -23,6 +23,22 @@ def get_image_sizes(org_img: Path, min_img: Path, tiny_img: Path) -> ImageSizes:
return ImageSizes(org=sizeof_fmt(org_img), min=sizeof_fmt(min_img), tiny=sizeof_fmt(tiny_img))
def to_webp(image_file: Path, quality: int = 100) -> Path:
"""
Converts an image to the webp format in-place. The original image is not
removed By default, the quality is set to 100.
"""
if image_file.suffix == ".webp":
return image_file
img = Image.open(image_file)
dest = image_file.with_suffix(".webp")
img.save(dest, "WEBP", quality=quality)
return dest
def minify_image(image_file: Path, force=False) -> ImageSizes:
"""Minifies an image in it's original file format. Quality is lost

View File

@@ -2,6 +2,8 @@ from pathlib import Path
from typing import Tuple
from uuid import UUID
from pydantic import UUID4
from mealie.core import root_logger
from mealie.db.database import Database
from mealie.schema.recipe import Recipe
@@ -27,7 +29,7 @@ class BaseMigrator(BaseService):
report_id: int
report: ReportOut
def __init__(self, archive: Path, db: Database, session, user_id: int, group_id: UUID, add_migration_tag: bool):
def __init__(self, archive: Path, db: Database, session, user_id: UUID4, group_id: UUID, add_migration_tag: bool):
self.archive = archive
self.db = db
self.session = session

View File

@@ -51,6 +51,9 @@ class MealieAlphaMigrator(BaseMigrator):
recipe["comments"] = []
# Reset ID on migration
recipe["id"] = None
return Recipe(**recipe)
def _migrate(self) -> None:

View File

@@ -1,6 +1,6 @@
from typing import TypeVar
from pydantic import BaseModel
from pydantic import UUID4, BaseModel
from slugify import slugify
from sqlalchemy.orm import Session
@@ -13,7 +13,7 @@ T = TypeVar("T", bound=BaseModel)
class DatabaseMigrationHelpers:
def __init__(self, db: Database, session: Session, group_id: int, user_id: int) -> None:
def __init__(self, db: Database, session: Session, group_id: int, user_id: UUID4) -> None:
self.group_id = group_id
self.user_id = user_id
self.session = session

View File

@@ -60,10 +60,10 @@ class RecipeService(CrudHttpMixins[CreateRecipe, Recipe, Recipe], UserHttpServic
raise HTTPException(status.HTTP_403_FORBIDDEN)
def can_update(self) -> bool:
if self.user.id == self.item.user_id:
return True
if self.item.settings.locked and self.user.id != self.item.user_id:
raise HTTPException(status.HTTP_403_FORBIDDEN)
raise HTTPException(status.HTTP_403_FORBIDDEN)
return True
def get_all(self, start=0, limit=None, load_foods=False) -> list[RecipeSummary]:
items = self.db.recipes.summary(self.user.group_id, start=start, limit=limit, load_foods=load_foods)

View File

@@ -1,3 +1,5 @@
from pathlib import Path
from fastapi import HTTPException, status
from mealie.core.root_logger import get_logger
@@ -43,3 +45,6 @@ class UserService(UserHttpService[int, str]):
self.target_user.password = hash_password(password_change.new_password)
return self.db.users.update_password(self.target_user.id, self.target_user.password)
def set_profile_picture(self, file_path: Path) -> PrivateUser:
pass