mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
refactor(backend): ♻️ align variable names, eliminate dead-code, and finalize recipe services
This commit is contained in:
parent
985ad8017d
commit
8e9280efaf
@ -10,7 +10,7 @@ from mealie.routes.mealplans import meal_plan_router
|
|||||||
from mealie.routes.media import media_router
|
from mealie.routes.media import media_router
|
||||||
from mealie.routes.site_settings import settings_router
|
from mealie.routes.site_settings import settings_router
|
||||||
from mealie.services.events import create_general_event
|
from mealie.services.events import create_general_event
|
||||||
from mealie.services.recipe.all_recipes import subscripte_to_recipe_events
|
from mealie.services.recipe.all_recipe_service import subscripte_to_recipe_events
|
||||||
|
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from fastapi import APIRouter, Depends, HTTPException, status
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import is_logged_in
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import is_logged_in
|
|
||||||
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
||||||
from mealie.schema.recipe import CategoryIn, RecipeCategoryResponse
|
from mealie.schema.recipe import CategoryIn, RecipeCategoryResponse
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from fastapi import BackgroundTasks, Depends, HTTPException, status
|
from fastapi import BackgroundTasks, Depends, HTTPException, status
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
||||||
from mealie.schema.user import GroupBase, GroupInDB, UpdateGroup, UserInDB
|
from mealie.schema.user import GroupBase, GroupInDB, UpdateGroup, UserInDB
|
||||||
from mealie.services.events import create_group_event
|
from mealie.services.events import create_group_event
|
||||||
|
@ -2,9 +2,9 @@ from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status
|
|||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
from starlette.responses import FileResponse
|
from starlette.responses import FileResponse
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.schema.meal_plan import MealPlanIn, MealPlanOut
|
from mealie.schema.meal_plan import MealPlanIn, MealPlanOut
|
||||||
from mealie.schema.user import GroupInDB, UserInDB
|
from mealie.schema.user import GroupInDB, UserInDB
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.core.root_logger import get_logger
|
from mealie.core.root_logger import get_logger
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.schema.meal_plan import ListItem, MealPlanOut, ShoppingListIn, ShoppingListOut
|
from mealie.schema.meal_plan import ListItem, MealPlanOut, ShoppingListIn, ShoppingListOut
|
||||||
from mealie.schema.recipe import Recipe
|
from mealie.schema.recipe import Recipe
|
||||||
|
@ -19,11 +19,11 @@ class ImageType(str, Enum):
|
|||||||
tiny = "tiny-original.webp"
|
tiny = "tiny-original.webp"
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{recipe_slug}/images/{file_name}")
|
@router.get("/{slug}/images/{file_name}")
|
||||||
async def get_recipe_img(recipe_slug: str, file_name: ImageType = ImageType.original):
|
async def get_recipe_img(slug: str, file_name: ImageType = ImageType.original):
|
||||||
"""Takes in a recipe slug, returns the static image. This route is proxied in the docker image
|
"""Takes in a recipe slug, returns the static image. This route is proxied in the docker image
|
||||||
and should not hit the API in production"""
|
and should not hit the API in production"""
|
||||||
recipe_image = Recipe(slug=recipe_slug).image_dir.joinpath(file_name.value)
|
recipe_image = Recipe(slug=slug).image_dir.joinpath(file_name.value)
|
||||||
|
|
||||||
if recipe_image:
|
if recipe_image:
|
||||||
return FileResponse(recipe_image)
|
return FileResponse(recipe_image)
|
||||||
@ -31,10 +31,10 @@ async def get_recipe_img(recipe_slug: str, file_name: ImageType = ImageType.orig
|
|||||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{recipe_slug}/assets/{file_name}")
|
@router.get("/{slug}/assets/{file_name}")
|
||||||
async def get_recipe_asset(recipe_slug: str, file_name: str):
|
async def get_recipe_asset(slug: str, file_name: str):
|
||||||
""" Returns a recipe asset """
|
""" Returns a recipe asset """
|
||||||
file = Recipe(slug=recipe_slug).asset_dir.joinpath(file_name)
|
file = Recipe(slug=slug).asset_dir.joinpath(file_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return FileResponse(file)
|
return FileResponse(file)
|
||||||
|
@ -4,7 +4,7 @@ from sqlalchemy.orm.session import Session
|
|||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.schema.recipe import RecipeSummary
|
from mealie.schema.recipe import RecipeSummary
|
||||||
from mealie.services.recipe.all_recipes import AllRecipesService
|
from mealie.services.recipe.all_recipe_service import AllRecipesService
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@ from http.client import HTTPException
|
|||||||
from fastapi import Depends, status
|
from fastapi import Depends, status
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.schema.recipe import CommentOut, CreateComment, SaveComment
|
from mealie.schema.recipe import CommentOut, CreateComment, SaveComment
|
||||||
from mealie.schema.user import UserInDB
|
from mealie.schema.user import UserInDB
|
||||||
|
@ -14,33 +14,33 @@ from mealie.services.image.image import scrape_image, write_image
|
|||||||
user_router = UserAPIRouter()
|
user_router = UserAPIRouter()
|
||||||
|
|
||||||
|
|
||||||
@user_router.post("/{recipe_slug}/image")
|
@user_router.post("/{slug}/image")
|
||||||
def scrape_image_url(
|
def scrape_image_url(
|
||||||
recipe_slug: str,
|
slug: str,
|
||||||
url: CreateRecipeByURL,
|
url: CreateRecipeByURL,
|
||||||
):
|
):
|
||||||
""" Removes an existing image and replaces it with the incoming file. """
|
""" Removes an existing image and replaces it with the incoming file. """
|
||||||
|
|
||||||
scrape_image(url.url, recipe_slug)
|
scrape_image(url.url, slug)
|
||||||
|
|
||||||
|
|
||||||
@user_router.put("/{recipe_slug}/image")
|
@user_router.put("/{slug}/image")
|
||||||
def update_recipe_image(
|
def update_recipe_image(
|
||||||
recipe_slug: str,
|
slug: str,
|
||||||
image: bytes = File(...),
|
image: bytes = File(...),
|
||||||
extension: str = Form(...),
|
extension: str = Form(...),
|
||||||
session: Session = Depends(generate_session),
|
session: Session = Depends(generate_session),
|
||||||
):
|
):
|
||||||
""" Removes an existing image and replaces it with the incoming file. """
|
""" Removes an existing image and replaces it with the incoming file. """
|
||||||
write_image(recipe_slug, image, extension)
|
write_image(slug, image, extension)
|
||||||
new_version = db.recipes.update_image(session, recipe_slug, extension)
|
new_version = db.recipes.update_image(session, slug, extension)
|
||||||
|
|
||||||
return {"image": new_version}
|
return {"image": new_version}
|
||||||
|
|
||||||
|
|
||||||
@user_router.post("/{recipe_slug}/assets", response_model=RecipeAsset)
|
@user_router.post("/{slug}/assets", response_model=RecipeAsset)
|
||||||
def upload_recipe_asset(
|
def upload_recipe_asset(
|
||||||
recipe_slug: str,
|
slug: str,
|
||||||
name: str = Form(...),
|
name: str = Form(...),
|
||||||
icon: str = Form(...),
|
icon: str = Form(...),
|
||||||
extension: str = Form(...),
|
extension: str = Form(...),
|
||||||
@ -50,7 +50,7 @@ def upload_recipe_asset(
|
|||||||
""" Upload a file to store as a recipe asset """
|
""" Upload a file to store as a recipe asset """
|
||||||
file_name = slugify(name) + "." + extension
|
file_name = slugify(name) + "." + extension
|
||||||
asset_in = RecipeAsset(name=name, icon=icon, file_name=file_name)
|
asset_in = RecipeAsset(name=name, icon=icon, file_name=file_name)
|
||||||
dest = Recipe(slug=recipe_slug).asset_dir.joinpath(file_name)
|
dest = Recipe(slug=slug).asset_dir.joinpath(file_name)
|
||||||
|
|
||||||
with dest.open("wb") as buffer:
|
with dest.open("wb") as buffer:
|
||||||
copyfileobj(file.file, buffer)
|
copyfileobj(file.file, buffer)
|
||||||
@ -58,7 +58,7 @@ def upload_recipe_asset(
|
|||||||
if not dest.is_file():
|
if not dest.is_file():
|
||||||
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)
|
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||||
|
|
||||||
recipe: Recipe = db.recipes.get(session, recipe_slug)
|
recipe: Recipe = db.recipes.get(session, slug)
|
||||||
recipe.assets.append(asset_in)
|
recipe.assets.append(asset_in)
|
||||||
db.recipes.update(session, recipe_slug, recipe.dict())
|
db.recipes.update(session, slug, recipe.dict())
|
||||||
return asset_in
|
return asset_in
|
||||||
|
@ -2,24 +2,20 @@ import json
|
|||||||
import shutil
|
import shutil
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from fastapi import APIRouter, BackgroundTasks, Depends, File
|
from fastapi import APIRouter, Depends, File
|
||||||
from fastapi.datastructures import UploadFile
|
from fastapi.datastructures import UploadFile
|
||||||
from scrape_schema_recipe import scrape_url
|
from scrape_schema_recipe import scrape_url
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
from starlette.responses import FileResponse
|
from starlette.responses import FileResponse
|
||||||
|
|
||||||
from mealie.core.config import settings
|
from mealie.core.dependencies import temporary_zip_path
|
||||||
from mealie.core.root_logger import get_logger
|
from mealie.core.root_logger import get_logger
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user, temporary_zip_path
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.schema.recipe import CreateRecipeByURL, Recipe, RecipeImageTypes
|
from mealie.schema.recipe import CreateRecipeByURL, Recipe, RecipeImageTypes
|
||||||
from mealie.schema.recipe.recipe import CreateRecipe
|
from mealie.schema.recipe.recipe import CreateRecipe
|
||||||
from mealie.schema.user import UserInDB
|
|
||||||
from mealie.services.events import create_recipe_event
|
|
||||||
from mealie.services.image.image import write_image
|
from mealie.services.image.image import write_image
|
||||||
from mealie.services.recipe.media import check_assets
|
|
||||||
from mealie.services.recipe.recipe_service import RecipeService
|
from mealie.services.recipe.recipe_service import RecipeService
|
||||||
from mealie.services.scraper.scraper import create_from_url
|
from mealie.services.scraper.scraper import create_from_url
|
||||||
|
|
||||||
@ -28,44 +24,30 @@ public_router = APIRouter()
|
|||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
|
|
||||||
|
@public_router.get("/{slug}", response_model=Recipe)
|
||||||
|
def get_recipe(recipe_service: RecipeService = Depends(RecipeService.read_existing)):
|
||||||
|
""" Takes in a recipe slug, returns all data for a recipe """
|
||||||
|
return recipe_service.recipe
|
||||||
|
|
||||||
|
|
||||||
@user_router.post("", status_code=201, response_model=str)
|
@user_router.post("", status_code=201, response_model=str)
|
||||||
def create_from_name(data: CreateRecipe, recipe_service: RecipeService = Depends(RecipeService.base)) -> str:
|
def create_from_name(data: CreateRecipe, recipe_service: RecipeService = Depends(RecipeService.base)) -> str:
|
||||||
""" Takes in a JSON string and loads data into the database as a new entry"""
|
""" Takes in a JSON string and loads data into the database as a new entry"""
|
||||||
return recipe_service.create_recipe(data).slug
|
return recipe_service.create_recipe(data).slug
|
||||||
|
|
||||||
|
|
||||||
@user_router.post("/test-scrape-url")
|
|
||||||
def test_parse_recipe_url(url: CreateRecipeByURL):
|
|
||||||
return scrape_url(url.url)
|
|
||||||
|
|
||||||
|
|
||||||
@user_router.post("/create-url", status_code=201, response_model=str)
|
@user_router.post("/create-url", status_code=201, response_model=str)
|
||||||
def parse_recipe_url(
|
def parse_recipe_url(url: CreateRecipeByURL, recipe_service: RecipeService = Depends(RecipeService.base)):
|
||||||
background_tasks: BackgroundTasks,
|
|
||||||
url: CreateRecipeByURL,
|
|
||||||
session: Session = Depends(generate_session),
|
|
||||||
current_user: UserInDB = Depends(get_current_user),
|
|
||||||
):
|
|
||||||
""" Takes in a URL and attempts to scrape data and load it into the database """
|
""" Takes in a URL and attempts to scrape data and load it into the database """
|
||||||
|
|
||||||
recipe = create_from_url(url.url)
|
recipe = create_from_url(url.url)
|
||||||
recipe: Recipe = db.recipes.create(session, recipe.dict())
|
return recipe_service.create_recipe(recipe).slug
|
||||||
|
|
||||||
background_tasks.add_task(
|
|
||||||
create_recipe_event,
|
|
||||||
"Recipe Created (URL)",
|
|
||||||
f"'{recipe.name}' by {current_user.full_name} \n {settings.BASE_URL}/recipe/{recipe.slug}",
|
|
||||||
session=session,
|
|
||||||
attachment=recipe.image_dir.joinpath("min-original.webp"),
|
|
||||||
)
|
|
||||||
|
|
||||||
return recipe.slug
|
|
||||||
|
|
||||||
|
|
||||||
@public_router.get("/{slug}", response_model=Recipe)
|
@user_router.post("/test-scrape-url")
|
||||||
def get_recipe(recipe_service: RecipeService = Depends(RecipeService.read_existing)):
|
def test_parse_recipe_url(url: CreateRecipeByURL):
|
||||||
""" Takes in a recipe slug, returns all data for a recipe """
|
# TODO: Replace with more current implementation of testing schema
|
||||||
return recipe_service.recipe
|
return scrape_url(url.url)
|
||||||
|
|
||||||
|
|
||||||
@user_router.post("/create-from-zip")
|
@user_router.post("/create-from-zip")
|
||||||
@ -98,54 +80,36 @@ async def create_recipe_from_zip(
|
|||||||
return recipe
|
return recipe
|
||||||
|
|
||||||
|
|
||||||
@public_router.get("/{recipe_slug}/zip")
|
@public_router.get("/{slug}/zip")
|
||||||
async def get_recipe_as_zip(
|
async def get_recipe_as_zip(
|
||||||
recipe_slug: str, session: Session = Depends(generate_session), temp_path=Depends(temporary_zip_path)
|
slug: str, session: Session = Depends(generate_session), temp_path=Depends(temporary_zip_path)
|
||||||
):
|
):
|
||||||
""" Get a Recipe and It's Original Image as a Zip File """
|
""" Get a Recipe and It's Original Image as a Zip File """
|
||||||
recipe: Recipe = db.recipes.get(session, recipe_slug)
|
recipe: Recipe = db.recipes.get(session, slug)
|
||||||
|
|
||||||
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
|
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
|
||||||
|
|
||||||
with ZipFile(temp_path, "w") as myzip:
|
with ZipFile(temp_path, "w") as myzip:
|
||||||
myzip.writestr(f"{recipe_slug}.json", recipe.json())
|
myzip.writestr(f"{slug}.json", recipe.json())
|
||||||
|
|
||||||
if image_asset.is_file():
|
if image_asset.is_file():
|
||||||
myzip.write(image_asset, arcname=image_asset.name)
|
myzip.write(image_asset, arcname=image_asset.name)
|
||||||
|
|
||||||
return FileResponse(temp_path, filename=f"{recipe_slug}.zip")
|
return FileResponse(temp_path, filename=f"{slug}.zip")
|
||||||
|
|
||||||
|
|
||||||
@user_router.put("/{recipe_slug}")
|
@user_router.put("/{slug}")
|
||||||
def update_recipe(
|
def update_recipe(data: Recipe, recipe_service: RecipeService = Depends(RecipeService.write_existing)):
|
||||||
recipe_slug: str,
|
|
||||||
data: Recipe,
|
|
||||||
session: Session = Depends(generate_session),
|
|
||||||
):
|
|
||||||
""" Updates a recipe by existing slug and data. """
|
""" Updates a recipe by existing slug and data. """
|
||||||
|
|
||||||
recipe: Recipe = db.recipes.update(session, recipe_slug, data.dict())
|
return recipe_service.update_recipe(data)
|
||||||
|
|
||||||
check_assets(original_slug=recipe_slug, recipe=recipe)
|
|
||||||
|
|
||||||
return recipe
|
|
||||||
|
|
||||||
|
|
||||||
@user_router.patch("/{recipe_slug}")
|
@user_router.patch("/{slug}")
|
||||||
def patch_recipe(
|
def patch_recipe(data: Recipe, recipe_service: RecipeService = Depends(RecipeService.write_existing)):
|
||||||
recipe_slug: str,
|
|
||||||
data: Recipe,
|
|
||||||
session: Session = Depends(generate_session),
|
|
||||||
):
|
|
||||||
""" Updates a recipe by existing slug and data. """
|
""" Updates a recipe by existing slug and data. """
|
||||||
|
|
||||||
recipe: Recipe = db.recipes.patch(
|
return recipe_service.patch_recipe(data)
|
||||||
session, recipe_slug, new_data=data.dict(exclude_unset=True, exclude_defaults=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
check_assets(original_slug=recipe_slug, recipe=recipe)
|
|
||||||
|
|
||||||
return recipe
|
|
||||||
|
|
||||||
|
|
||||||
@user_router.delete("/{slug}")
|
@user_router.delete("/{slug}")
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.schema.meal_plan import ShoppingListIn, ShoppingListOut
|
from mealie.schema.meal_plan import ShoppingListIn, ShoppingListOut
|
||||||
from mealie.schema.user import UserInDB
|
from mealie.schema.user import UserInDB
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from fastapi import APIRouter, Depends, HTTPException, status
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import AdminAPIRouter
|
from mealie.routes.routers import AdminAPIRouter
|
||||||
from mealie.schema.admin import SiteSettings
|
from mealie.schema.admin import SiteSettings
|
||||||
from mealie.schema.user import GroupInDB, UserInDB
|
from mealie.schema.user import GroupInDB, UserInDB
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from fastapi import APIRouter, Depends, HTTPException, status
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import is_logged_in
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import is_logged_in
|
|
||||||
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
||||||
from mealie.schema.recipe import RecipeTagResponse, TagIn
|
from mealie.schema.recipe import RecipeTagResponse, TagIn
|
||||||
|
|
||||||
|
@ -4,10 +4,10 @@ from fastapi import HTTPException, status
|
|||||||
from fastapi.param_functions import Depends
|
from fastapi.param_functions import Depends
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.core.security import create_access_token
|
from mealie.core.security import create_access_token
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.schema.user import CreateToken, LoingLiveTokenIn, LongLiveTokenInDB, UserInDB
|
from mealie.schema.user import CreateToken, LoingLiveTokenIn, LongLiveTokenInDB, UserInDB
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@ from fastapi import BackgroundTasks, Depends, HTTPException, status
|
|||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
from mealie.core import security
|
from mealie.core import security
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.core.security import get_password_hash
|
from mealie.core.security import get_password_hash
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
from mealie.routes.routers import AdminAPIRouter, UserAPIRouter
|
||||||
from mealie.routes.users._helpers import assert_user_change_allowed
|
from mealie.routes.users._helpers import assert_user_change_allowed
|
||||||
from mealie.schema.user import UserBase, UserIn, UserInDB, UserOut
|
from mealie.schema.user import UserBase, UserIn, UserInDB, UserOut
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from fastapi import Depends
|
from fastapi import Depends
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.routes.users._helpers import assert_user_change_allowed
|
from mealie.routes.users._helpers import assert_user_change_allowed
|
||||||
from mealie.schema.user import UserFavorites, UserInDB
|
from mealie.schema.user import UserFavorites, UserInDB
|
||||||
|
@ -2,10 +2,10 @@ from fastapi import Depends, HTTPException, status
|
|||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
from mealie.core.config import settings
|
from mealie.core.config import settings
|
||||||
|
from mealie.core.dependencies import get_current_user
|
||||||
from mealie.core.security import get_password_hash, verify_password
|
from mealie.core.security import get_password_hash, verify_password
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_current_user
|
|
||||||
from mealie.routes.routers import UserAPIRouter
|
from mealie.routes.routers import UserAPIRouter
|
||||||
from mealie.routes.users._helpers import assert_user_change_allowed
|
from mealie.routes.users._helpers import assert_user_change_allowed
|
||||||
from mealie.schema.user import ChangePassword, UserInDB
|
from mealie.schema.user import ChangePassword, UserInDB
|
||||||
|
@ -3,10 +3,10 @@ import uuid
|
|||||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status
|
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import get_admin_user
|
||||||
from mealie.core.security import get_password_hash
|
from mealie.core.security import get_password_hash
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.core.dependencies import get_admin_user
|
|
||||||
from mealie.routes.routers import AdminAPIRouter
|
from mealie.routes.routers import AdminAPIRouter
|
||||||
from mealie.schema.user import SignUpIn, SignUpOut, SignUpToken, UserIn, UserInDB
|
from mealie.schema.user import SignUpIn, SignUpOut, SignUpToken, UserIn, UserInDB
|
||||||
from mealie.services.events import create_user_event
|
from mealie.services.events import create_user_event
|
||||||
|
@ -5,10 +5,10 @@ from fastapi import Depends, Response
|
|||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
from mealie.core.dependencies import is_logged_in
|
||||||
from mealie.core.root_logger import get_logger
|
from mealie.core.root_logger import get_logger
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import SessionLocal, generate_session
|
from mealie.db.db_setup import SessionLocal, generate_session
|
||||||
from mealie.core.dependencies import is_logged_in
|
|
||||||
from mealie.schema.recipe import RecipeSummary
|
from mealie.schema.recipe import RecipeSummary
|
||||||
|
|
||||||
logger = get_logger()
|
logger = get_logger()
|
@ -1,41 +0,0 @@
|
|||||||
from typing import Any
|
|
||||||
|
|
||||||
from fastapi import BackgroundTasks, Depends
|
|
||||||
from pydantic import BaseModel
|
|
||||||
from sqlalchemy.orm.session import Session
|
|
||||||
|
|
||||||
from mealie.db.db_setup import generate_session
|
|
||||||
from mealie.core.dependencies import get_current_user, is_logged_in
|
|
||||||
|
|
||||||
|
|
||||||
class CommonDeps(BaseModel):
|
|
||||||
session: Session
|
|
||||||
background_tasks: BackgroundTasks
|
|
||||||
user: Any
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
arbitrary_types_allowed = True
|
|
||||||
|
|
||||||
|
|
||||||
def read_deps(
|
|
||||||
background_tasks: BackgroundTasks,
|
|
||||||
session: Session = Depends(generate_session),
|
|
||||||
current_user=Depends(is_logged_in),
|
|
||||||
):
|
|
||||||
return CommonDeps(
|
|
||||||
session=session,
|
|
||||||
background_tasks=background_tasks,
|
|
||||||
user=current_user,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def write_deps(
|
|
||||||
background_tasks: BackgroundTasks,
|
|
||||||
session: Session = Depends(generate_session),
|
|
||||||
current_user=Depends(get_current_user),
|
|
||||||
):
|
|
||||||
return CommonDeps(
|
|
||||||
session=session,
|
|
||||||
background_tasks=background_tasks,
|
|
||||||
user=current_user,
|
|
||||||
)
|
|
@ -1,34 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
from shutil import copytree, rmtree
|
|
||||||
|
|
||||||
from mealie.core.config import app_dirs
|
|
||||||
from mealie.core.root_logger import get_logger
|
|
||||||
from mealie.schema.recipe import Recipe
|
|
||||||
|
|
||||||
logger = get_logger()
|
|
||||||
|
|
||||||
|
|
||||||
def check_assets(original_slug, recipe: Recipe) -> None:
|
|
||||||
if original_slug != recipe.slug:
|
|
||||||
current_dir = app_dirs.RECIPE_DATA_DIR.joinpath(original_slug)
|
|
||||||
|
|
||||||
try:
|
|
||||||
copytree(current_dir, recipe.directory, dirs_exist_ok=True)
|
|
||||||
|
|
||||||
except FileNotFoundError:
|
|
||||||
logger.error(f"Recipe Directory not Found: {original_slug}")
|
|
||||||
logger.info(f"Renaming Recipe Directory: {original_slug} -> {recipe.slug}")
|
|
||||||
|
|
||||||
all_asset_files = [x.file_name for x in recipe.assets]
|
|
||||||
for file in recipe.asset_dir.iterdir():
|
|
||||||
file: Path
|
|
||||||
if file.is_dir():
|
|
||||||
continue
|
|
||||||
if file.name not in all_asset_files:
|
|
||||||
file.unlink()
|
|
||||||
|
|
||||||
|
|
||||||
def delete_assets(recipe_slug):
|
|
||||||
recipe_dir = Recipe(slug=recipe_slug).directory
|
|
||||||
rmtree(recipe_dir, ignore_errors=True)
|
|
||||||
logger.info(f"Recipe Directory Removed: {recipe_slug}")
|
|
@ -1,20 +1,33 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from shutil import copytree, rmtree
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import BackgroundTasks, Depends, HTTPException, status
|
from fastapi import BackgroundTasks, Depends, HTTPException, status
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
from mealie.core.config import get_settings
|
from mealie.core.config import get_app_dirs, get_settings
|
||||||
from mealie.core.dependencies import ReadDeps
|
from mealie.core.dependencies import ReadDeps
|
||||||
from mealie.core.dependencies.grouped import WriteDeps
|
from mealie.core.dependencies.grouped import WriteDeps
|
||||||
|
from mealie.core.root_logger import get_logger
|
||||||
from mealie.db.database import get_database
|
from mealie.db.database import get_database
|
||||||
from mealie.db.db_setup import SessionLocal
|
from mealie.db.db_setup import SessionLocal
|
||||||
from mealie.schema.recipe.recipe import CreateRecipe, Recipe
|
from mealie.schema.recipe.recipe import CreateRecipe, Recipe
|
||||||
from mealie.schema.user.user import UserInDB
|
from mealie.schema.user.user import UserInDB
|
||||||
from mealie.services.events import create_recipe_event
|
from mealie.services.events import create_recipe_event
|
||||||
from mealie.services.recipe.media import delete_assets
|
|
||||||
|
logger = get_logger(module=__name__)
|
||||||
|
|
||||||
|
|
||||||
class RecipeService:
|
class RecipeService:
|
||||||
recipe: Recipe
|
"""
|
||||||
|
Class Methods:
|
||||||
|
`read_existing`: Reads an existing recipe from the database.
|
||||||
|
`write_existing`: Updates an existing recipe in the database.
|
||||||
|
`base`: Requires write permissions, but doesn't perform recipe checks
|
||||||
|
"""
|
||||||
|
|
||||||
|
recipe: Recipe # Required for proper type hints
|
||||||
|
|
||||||
def __init__(self, session: Session, user: UserInDB, background_tasks: BackgroundTasks = None) -> None:
|
def __init__(self, session: Session, user: UserInDB, background_tasks: BackgroundTasks = None) -> None:
|
||||||
self.session = session or SessionLocal()
|
self.session = session or SessionLocal()
|
||||||
@ -22,8 +35,9 @@ class RecipeService:
|
|||||||
self.background_tasks = background_tasks
|
self.background_tasks = background_tasks
|
||||||
self.recipe: Recipe = None
|
self.recipe: Recipe = None
|
||||||
|
|
||||||
# Static Globals
|
# Static Globals Dependency Injection
|
||||||
self.db = get_database()
|
self.db = get_database()
|
||||||
|
self.app_dirs = get_app_dirs()
|
||||||
self.settings = get_settings()
|
self.settings = get_settings()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -99,10 +113,11 @@ class RecipeService:
|
|||||||
raise HTTPException(status.HTTP_403_FORBIDDEN)
|
raise HTTPException(status.HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
# CRUD METHODS
|
# CRUD METHODS
|
||||||
def create_recipe(self, new_recipe: CreateRecipe) -> Recipe:
|
def create_recipe(self, create_data: Union[Recipe, CreateRecipe]) -> Recipe:
|
||||||
|
if isinstance(create_data, CreateRecipe):
|
||||||
|
create_data = Recipe(name=create_data.name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
create_data = Recipe(name=new_recipe.name)
|
|
||||||
self.recipe = self.db.recipes.create(self.session, create_data)
|
self.recipe = self.db.recipes.create(self.session, create_data)
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "RECIPE_ALREADY_EXISTS"})
|
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "RECIPE_ALREADY_EXISTS"})
|
||||||
@ -114,6 +129,32 @@ class RecipeService:
|
|||||||
|
|
||||||
return self.recipe
|
return self.recipe
|
||||||
|
|
||||||
|
def update_recipe(self, update_data: Recipe) -> Recipe:
|
||||||
|
original_slug = self.recipe.slug
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.recipe = self.db.recipes.update(self.session, original_slug, update_data)
|
||||||
|
except IntegrityError:
|
||||||
|
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "RECIPE_ALREADY_EXISTS"})
|
||||||
|
|
||||||
|
self._check_assets(original_slug)
|
||||||
|
|
||||||
|
return self.recipe
|
||||||
|
|
||||||
|
def patch_recipe(self, patch_data: Recipe) -> Recipe:
|
||||||
|
original_slug = self.recipe.slug
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.recipe = self.db.recipes.patch(
|
||||||
|
self.session, original_slug, patch_data.dict(exclude_unset=True, exclude_defaults=True)
|
||||||
|
)
|
||||||
|
except IntegrityError:
|
||||||
|
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "RECIPE_ALREADY_EXISTS"})
|
||||||
|
|
||||||
|
self._check_assets(original_slug)
|
||||||
|
|
||||||
|
return self.recipe
|
||||||
|
|
||||||
def delete_recipe(self) -> Recipe:
|
def delete_recipe(self) -> Recipe:
|
||||||
"""removes a recipe from the database and purges the existing files from the filesystem.
|
"""removes a recipe from the database and purges the existing files from the filesystem.
|
||||||
|
|
||||||
@ -126,7 +167,7 @@ class RecipeService:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
recipe: Recipe = self.db.recipes.delete(self.session, self.recipe.slug)
|
recipe: Recipe = self.db.recipes.delete(self.session, self.recipe.slug)
|
||||||
delete_assets(recipe_slug=self.recipe.slug)
|
self._delete_assets()
|
||||||
except Exception:
|
except Exception:
|
||||||
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@ -135,3 +176,27 @@ class RecipeService:
|
|||||||
|
|
||||||
def _create_event(self, title: str, message: str) -> None:
|
def _create_event(self, title: str, message: str) -> None:
|
||||||
self.background_tasks.add_task(create_recipe_event, title, message, self.session)
|
self.background_tasks.add_task(create_recipe_event, title, message, self.session)
|
||||||
|
|
||||||
|
def _check_assets(self, original_slug) -> None:
|
||||||
|
if original_slug != self.recipe.slug:
|
||||||
|
current_dir = self.app_dirs.RECIPE_DATA_DIR.joinpath(original_slug)
|
||||||
|
|
||||||
|
try:
|
||||||
|
copytree(current_dir, self.recipe.directory, dirs_exist_ok=True)
|
||||||
|
logger.info(f"Renaming Recipe Directory: {original_slug} -> {self.recipe.slug}")
|
||||||
|
except FileNotFoundError:
|
||||||
|
logger.error(f"Recipe Directory not Found: {original_slug}")
|
||||||
|
|
||||||
|
all_asset_files = [x.file_name for x in self.recipe.assets]
|
||||||
|
|
||||||
|
for file in self.recipe.asset_dir.iterdir():
|
||||||
|
file: Path
|
||||||
|
if file.is_dir():
|
||||||
|
continue
|
||||||
|
if file.name not in all_asset_files:
|
||||||
|
file.unlink()
|
||||||
|
|
||||||
|
def _delete_assets(self) -> None:
|
||||||
|
recipe_dir = self.recipe.directory
|
||||||
|
rmtree(recipe_dir, ignore_errors=True)
|
||||||
|
logger.info(f"Recipe Directory Removed: {self.recipe.slug}")
|
||||||
|
@ -5,6 +5,4 @@ Cron = collections.namedtuple("Cron", "hours minutes")
|
|||||||
|
|
||||||
def cron_parser(time_str: str) -> Cron:
|
def cron_parser(time_str: str) -> Cron:
|
||||||
time = time_str.split(":")
|
time = time_str.split(":")
|
||||||
cron = Cron(hours=int(time[0]), minutes=int(time[1]))
|
return Cron(hours=int(time[0]), minutes=int(time[1]))
|
||||||
|
|
||||||
return cron
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user