refactor(backend): ♻️ change error messages to follow standard pattern to match locals on frontend (#668)
Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
parent
abc0d0d59f
commit
b550dae593
11 changed files with 415 additions and 72 deletions
159
dev/scripts/gen_error_messages.py
Normal file
159
dev/scripts/gen_error_messages.py
Normal file
|
@ -0,0 +1,159 @@
|
|||
import json
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from slugify import slugify
|
||||
|
||||
CWD = Path(__file__).parent
|
||||
|
||||
PROJECT_BASE = CWD.parent.parent
|
||||
|
||||
server_side_msgs = PROJECT_BASE / "mealie" / "utils" / "error_messages.py"
|
||||
en_us_msgs = PROJECT_BASE / "frontend" / "lang" / "errors" / "en-US.json"
|
||||
client_side_msgs = PROJECT_BASE / "frontend" / "utils" / "error-messages.ts"
|
||||
|
||||
GENERATE_MESSAGES = [
|
||||
# User Related
|
||||
"user",
|
||||
"webhook",
|
||||
"token",
|
||||
# Group Related
|
||||
"group",
|
||||
"cookbook",
|
||||
"mealplan",
|
||||
# Recipe Related
|
||||
"scraper",
|
||||
"recipe",
|
||||
"ingredient",
|
||||
"food",
|
||||
"unit",
|
||||
# Admin Related
|
||||
"backup",
|
||||
"migration",
|
||||
"event",
|
||||
]
|
||||
|
||||
|
||||
class ErrorMessage:
|
||||
def __init__(self, prefix, verb) -> None:
|
||||
self.message = f"{prefix.title()} {verb.title()} Failed"
|
||||
self.snake = slugify(self.message, separator="_")
|
||||
self.kabab = slugify(self.message, separator="-")
|
||||
|
||||
def factory(prefix) -> list["ErrorMessage"]:
|
||||
verbs = ["Create", "Update", "Delete"]
|
||||
return [ErrorMessage(prefix, verb) for verb in verbs]
|
||||
|
||||
|
||||
@dataclass
|
||||
class CodeGenLines:
|
||||
start: int
|
||||
end: int
|
||||
|
||||
indentation: str
|
||||
text: list[str]
|
||||
|
||||
_next_line = None
|
||||
|
||||
def purge_lines(self) -> None:
|
||||
start = self.start + 1
|
||||
end = self.end
|
||||
del self.text[start:end]
|
||||
|
||||
def push_line(self, string: str) -> None:
|
||||
self._next_line = self._next_line or self.start + 1
|
||||
self.text.insert(self._next_line, self.indentation + string)
|
||||
self._next_line += 1
|
||||
|
||||
|
||||
def find_start(file_text: list[str], gen_id: str):
|
||||
for x, line in enumerate(file_text):
|
||||
if "CODE_GEN_ID:" in line and gen_id in line:
|
||||
return x, line
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_end(file_text: list[str], gen_id: str):
|
||||
for x, line in enumerate(file_text):
|
||||
if f"END {gen_id}" in line:
|
||||
return x, line
|
||||
return None
|
||||
|
||||
|
||||
def get_indentation_of_string(line: str):
|
||||
return re.sub(r"#.*", "", line).removesuffix("\n")
|
||||
|
||||
|
||||
def get_messages(message_prefix: str) -> str:
|
||||
prefix = message_prefix.lower()
|
||||
|
||||
return [
|
||||
f'{prefix}_create_failure = "{prefix}-create-failure"\n',
|
||||
f'{prefix}_update_failure = "{prefix}-update-failure"\n',
|
||||
f'{prefix}_delete_failure = "{prefix}-delete-failure"\n',
|
||||
]
|
||||
|
||||
|
||||
def code_gen_factory(file_path: Path) -> CodeGenLines:
|
||||
with open(file_path, "r") as file:
|
||||
text = file.readlines()
|
||||
start_num, line = find_start(text, "ERROR_MESSAGE_ENUMS")
|
||||
indentation = get_indentation_of_string(line)
|
||||
end_num, line = find_end(text, "ERROR_MESSAGE_ENUMS")
|
||||
|
||||
return CodeGenLines(
|
||||
start=start_num,
|
||||
end=end_num,
|
||||
indentation=indentation,
|
||||
text=text,
|
||||
)
|
||||
|
||||
|
||||
def write_to_locals(messages: list[ErrorMessage]) -> None:
|
||||
with open(en_us_msgs, "r") as f:
|
||||
existing_msg = json.loads(f.read())
|
||||
|
||||
for msg in messages:
|
||||
if msg.kabab in existing_msg:
|
||||
continue
|
||||
|
||||
existing_msg[msg.kabab] = msg.message
|
||||
print(f"Added Key {msg.kabab} to 'en-US.json'")
|
||||
|
||||
with open(en_us_msgs, "w") as f:
|
||||
f.write(json.dumps(existing_msg, indent=4))
|
||||
|
||||
|
||||
def main():
|
||||
print("Starting...")
|
||||
GENERATE_MESSAGES.sort()
|
||||
|
||||
code_gen = code_gen_factory(server_side_msgs)
|
||||
code_gen.purge_lines()
|
||||
|
||||
messages = []
|
||||
for msg_type in GENERATE_MESSAGES:
|
||||
messages += get_messages(msg_type)
|
||||
messages.append("\n")
|
||||
|
||||
for msg in messages:
|
||||
code_gen.push_line(msg)
|
||||
|
||||
with open(server_side_msgs, "w") as file:
|
||||
file.writelines(code_gen.text)
|
||||
|
||||
# Locals
|
||||
|
||||
local_msgs = []
|
||||
for msg_type in GENERATE_MESSAGES:
|
||||
local_msgs += ErrorMessage.factory(msg_type)
|
||||
|
||||
write_to_locals(local_msgs)
|
||||
|
||||
print("Done!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
File diff suppressed because one or more lines are too long
44
frontend/lang/errors/en-US.json
Normal file
44
frontend/lang/errors/en-US.json
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"backup-create-failed": "Backup Create Failed",
|
||||
"backup-update-failed": "Backup Update Failed",
|
||||
"backup-delete-failed": "Backup Delete Failed",
|
||||
"cookbook-create-failed": "Cookbook Create Failed",
|
||||
"cookbook-update-failed": "Cookbook Update Failed",
|
||||
"cookbook-delete-failed": "Cookbook Delete Failed",
|
||||
"event-create-failed": "Event Create Failed",
|
||||
"event-update-failed": "Event Update Failed",
|
||||
"event-delete-failed": "Event Delete Failed",
|
||||
"food-create-failed": "Food Create Failed",
|
||||
"food-update-failed": "Food Update Failed",
|
||||
"food-delete-failed": "Food Delete Failed",
|
||||
"group-create-failed": "Group Create Failed",
|
||||
"group-update-failed": "Group Update Failed",
|
||||
"group-delete-failed": "Group Delete Failed",
|
||||
"ingredient-create-failed": "Ingredient Create Failed",
|
||||
"ingredient-update-failed": "Ingredient Update Failed",
|
||||
"ingredient-delete-failed": "Ingredient Delete Failed",
|
||||
"mealplan-create-failed": "Mealplan Create Failed",
|
||||
"mealplan-update-failed": "Mealplan Update Failed",
|
||||
"mealplan-delete-failed": "Mealplan Delete Failed",
|
||||
"migration-create-failed": "Migration Create Failed",
|
||||
"migration-update-failed": "Migration Update Failed",
|
||||
"migration-delete-failed": "Migration Delete Failed",
|
||||
"recipe-create-failed": "Recipe Create Failed",
|
||||
"recipe-update-failed": "Recipe Update Failed",
|
||||
"recipe-delete-failed": "Recipe Delete Failed",
|
||||
"scraper-create-failed": "Scraper Create Failed",
|
||||
"scraper-update-failed": "Scraper Update Failed",
|
||||
"scraper-delete-failed": "Scraper Delete Failed",
|
||||
"token-create-failed": "Token Create Failed",
|
||||
"token-update-failed": "Token Update Failed",
|
||||
"token-delete-failed": "Token Delete Failed",
|
||||
"unit-create-failed": "Unit Create Failed",
|
||||
"unit-update-failed": "Unit Update Failed",
|
||||
"unit-delete-failed": "Unit Delete Failed",
|
||||
"user-create-failed": "User Create Failed",
|
||||
"user-update-failed": "User Update Failed",
|
||||
"user-delete-failed": "User Delete Failed",
|
||||
"webhook-create-failed": "Webhook Create Failed",
|
||||
"webhook-update-failed": "Webhook Update Failed",
|
||||
"webhook-delete-failed": "Webhook Delete Failed"
|
||||
}
|
|
@ -3,12 +3,12 @@ from sqlalchemy.orm.session import Session
|
|||
|
||||
from mealie.schema.user.user import PrivateUser
|
||||
|
||||
from .dependencies import generate_session, get_current_user, is_logged_in
|
||||
from .dependencies import generate_session, get_admin_user, get_current_user, is_logged_in
|
||||
|
||||
|
||||
class ReadDeps:
|
||||
class PublicDeps:
|
||||
"""
|
||||
ReadDeps contains the common dependencies for all read operations through the API.
|
||||
PublicDeps contains the common dependencies for all read operations through the API.
|
||||
Note: The user object is used to definer what assets the user has access to.
|
||||
|
||||
Args:
|
||||
|
@ -28,9 +28,9 @@ class ReadDeps:
|
|||
self.user: bool = user
|
||||
|
||||
|
||||
class WriteDeps:
|
||||
class UserDeps:
|
||||
"""
|
||||
WriteDeps contains the common dependencies for all read operations through the API.
|
||||
UserDeps contains the common dependencies for all read operations through the API.
|
||||
Note: The user must be logged in or the route will return a 401 error.
|
||||
|
||||
Args:
|
||||
|
@ -48,3 +48,15 @@ class WriteDeps:
|
|||
self.session: Session = session
|
||||
self.bg_task: BackgroundTasks = background_tasks
|
||||
self.user: PrivateUser = user
|
||||
|
||||
|
||||
class AdminDeps:
|
||||
def __init__(
|
||||
self,
|
||||
background_tasks: BackgroundTasks,
|
||||
session: Session = Depends(generate_session),
|
||||
user=Depends(get_admin_user),
|
||||
):
|
||||
self.session: Session = session
|
||||
self.bg_task: BackgroundTasks = background_tasks
|
||||
self.user: PrivateUser = user
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from typing import Callable, Generic, TypeVar
|
||||
from typing import Callable, Generic, Type, TypeVar
|
||||
|
||||
from fastapi import BackgroundTasks, Depends, HTTPException, status
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
from mealie.core.config import get_app_dirs, get_settings
|
||||
from mealie.core.dependencies.grouped import ReadDeps, WriteDeps
|
||||
from mealie.core.dependencies.grouped import PublicDeps, UserDeps
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.db.database import get_database
|
||||
from mealie.db.db_setup import SessionLocal
|
||||
|
@ -17,25 +17,25 @@ T = TypeVar("T")
|
|||
D = TypeVar("D")
|
||||
|
||||
|
||||
CLS_DEP = TypeVar("CLS_DEP") # Generic Used for the class method dependencies
|
||||
|
||||
|
||||
class BaseHttpService(Generic[T, D], ABC):
|
||||
"""The BaseHttpService class is a generic class that can be used to create
|
||||
"""
|
||||
The BaseHttpService class is a generic class that can be used to create
|
||||
http services that are injected via `Depends` into a route function. To use,
|
||||
you must define the Generic type arguments:
|
||||
|
||||
`T`: The type passed into the *_existing functions (e.g. id) which is then passed into assert_existing
|
||||
`D`: Item returned from database layer
|
||||
|
||||
Child Requirements:
|
||||
Define the following functions:
|
||||
`assert_existing(self, data: T) -> None:`
|
||||
|
||||
Define the following variables:
|
||||
`event_func`: A function that is called when an event is created.
|
||||
"""
|
||||
|
||||
item: D = None
|
||||
|
||||
# Function that Generate Corrsesponding Routes through RouterFactor
|
||||
# Function that Generate Corrsesponding Routes through RouterFactory:
|
||||
# if the method is defined or != `None` than the corresponding route is defined through the RouterFactory.
|
||||
# If the method is not defined, then the route will be excluded from creation. This service based articheture
|
||||
# is being adopted as apart of the v1 migration
|
||||
get_all: Callable = None
|
||||
create_one: Callable = None
|
||||
update_one: Callable = None
|
||||
|
@ -75,48 +75,35 @@ class BaseHttpService(Generic[T, D], ABC):
|
|||
self._group_id_cache = group.id
|
||||
return self._group_id_cache
|
||||
|
||||
@classmethod
|
||||
def read_existing(cls, item_id: T, deps: ReadDeps = Depends()):
|
||||
"""
|
||||
Used for dependency injection for routes that require an existing recipe. If the recipe doesn't exist
|
||||
or the user doens't not have the required permissions, the proper HTTP Status code will be raised.
|
||||
"""
|
||||
new_class = cls(deps.session, deps.user, deps.bg_task)
|
||||
new_class.assert_existing(item_id)
|
||||
return new_class
|
||||
def _existing_factory(dependency: Type[CLS_DEP]) -> classmethod:
|
||||
def cls_method(cls, item_id: T, deps: CLS_DEP = Depends(dependency)):
|
||||
new_class = cls(deps.session, deps.user, deps.bg_task)
|
||||
new_class.assert_existing(item_id)
|
||||
return new_class
|
||||
|
||||
@classmethod
|
||||
def write_existing(cls, item_id: T, deps: WriteDeps = Depends()):
|
||||
"""
|
||||
Used for dependency injection for routes that require an existing recipe. The only difference between
|
||||
read_existing and write_existing is that the user is required to be logged in on write_existing method.
|
||||
"""
|
||||
new_class = cls(deps.session, deps.user, deps.bg_task)
|
||||
new_class.assert_existing(item_id)
|
||||
return new_class
|
||||
return classmethod(cls_method)
|
||||
|
||||
@classmethod
|
||||
def public(cls, deps: ReadDeps = Depends()):
|
||||
"""
|
||||
A Base instance to be used as a router dependency
|
||||
"""
|
||||
return cls(deps.session, deps.user, deps.bg_task)
|
||||
def _class_method_factory(dependency: Type[CLS_DEP]) -> classmethod:
|
||||
def cls_method(cls, deps: CLS_DEP = Depends(dependency)):
|
||||
return cls(deps.session, deps.user, deps.bg_task)
|
||||
|
||||
@classmethod
|
||||
def private(cls, deps: WriteDeps = Depends()):
|
||||
"""
|
||||
A Base instance to be used as a router dependency
|
||||
"""
|
||||
return cls(deps.session, deps.user, deps.bg_task)
|
||||
return classmethod(cls_method)
|
||||
|
||||
@abstractmethod
|
||||
def populate_item(self) -> None:
|
||||
...
|
||||
# TODO: Refactor to allow for configurable dependencies base on substantiation
|
||||
read_existing = _existing_factory(PublicDeps)
|
||||
write_existing = _existing_factory(UserDeps)
|
||||
|
||||
public = _class_method_factory(PublicDeps)
|
||||
private = _class_method_factory(UserDeps)
|
||||
|
||||
def assert_existing(self, id: T) -> None:
|
||||
self.populate_item(id)
|
||||
self._check_item()
|
||||
|
||||
@abstractmethod
|
||||
def populate_item(self) -> None:
|
||||
...
|
||||
|
||||
def _check_item(self) -> None:
|
||||
if not self.item:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
|
|
60
mealie/services/base_http_service/http_services.py
Normal file
60
mealie/services/base_http_service/http_services.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
from abc import abstractmethod
|
||||
from typing import TypeVar
|
||||
|
||||
from mealie.core.dependencies.grouped import AdminDeps, PublicDeps, UserDeps
|
||||
|
||||
from .base_http_service import BaseHttpService
|
||||
|
||||
T = TypeVar("T")
|
||||
D = TypeVar("D")
|
||||
|
||||
|
||||
class PublicHttpService(BaseHttpService[T, D]):
|
||||
"""
|
||||
PublicHttpService sets the class methods to PublicDeps for read actions
|
||||
and UserDeps for write actions which are inaccessible to not logged in users.
|
||||
"""
|
||||
|
||||
read_existing = BaseHttpService._existing_factory(PublicDeps)
|
||||
write_existing = BaseHttpService._existing_factory(UserDeps)
|
||||
|
||||
public = BaseHttpService._class_method_factory(PublicDeps)
|
||||
private = BaseHttpService._class_method_factory(UserDeps)
|
||||
|
||||
@abstractmethod
|
||||
def populate_item(self) -> None:
|
||||
...
|
||||
|
||||
|
||||
class UserHttpService(BaseHttpService[T, D]):
|
||||
"""
|
||||
UserHttpService sets the class methods to UserDeps which are inaccessible
|
||||
to not logged in users.
|
||||
"""
|
||||
|
||||
read_existing = BaseHttpService._existing_factory(UserDeps)
|
||||
write_existing = BaseHttpService._existing_factory(UserDeps)
|
||||
|
||||
public = BaseHttpService._class_method_factory(UserDeps)
|
||||
private = BaseHttpService._class_method_factory(UserDeps)
|
||||
|
||||
@abstractmethod
|
||||
def populate_item(self) -> None:
|
||||
...
|
||||
|
||||
|
||||
class AdminHttpService(BaseHttpService[T, D]):
|
||||
"""
|
||||
AdminHttpService restricts the class methods to AdminDeps which are restricts
|
||||
all class methods to users who are administrators.
|
||||
"""
|
||||
|
||||
read_existing = BaseHttpService._existing_factory(AdminDeps)
|
||||
write_existing = BaseHttpService._existing_factory(AdminDeps)
|
||||
|
||||
public = BaseHttpService._class_method_factory(AdminDeps)
|
||||
private = BaseHttpService._class_method_factory(AdminDeps)
|
||||
|
||||
@abstractmethod
|
||||
def populate_item(self) -> None:
|
||||
...
|
|
@ -1,3 +1,4 @@
|
|||
import inspect
|
||||
from typing import Any, Callable, Optional, Sequence, Type, TypeVar
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
@ -23,15 +24,7 @@ class RouterFactory(APIRouter):
|
|||
update_schema: Type[T]
|
||||
_base_path: str = "/"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
service: Type[S],
|
||||
prefix: Optional[str] = None,
|
||||
tags: Optional[list[str]] = None,
|
||||
*args,
|
||||
**kwargs,
|
||||
):
|
||||
|
||||
def __init__(self, service: Type[S], prefix: Optional[str] = None, tags: Optional[list[str]] = None, *_, **kwargs):
|
||||
self.service: Type[S] = service
|
||||
self.schema: Type[T] = service._schema
|
||||
|
||||
|
@ -57,6 +50,7 @@ class RouterFactory(APIRouter):
|
|||
methods=["GET"],
|
||||
response_model=Optional[list[self.schema]], # type: ignore
|
||||
summary="Get All",
|
||||
description=inspect.cleandoc(self.service.get_all.__doc__ or ""),
|
||||
)
|
||||
|
||||
if self.service.create_one:
|
||||
|
@ -66,6 +60,7 @@ class RouterFactory(APIRouter):
|
|||
methods=["POST"],
|
||||
response_model=self.schema,
|
||||
summary="Create One",
|
||||
description=inspect.cleandoc(self.service.create_one.__doc__ or ""),
|
||||
)
|
||||
|
||||
if self.service.update_many:
|
||||
|
@ -75,6 +70,7 @@ class RouterFactory(APIRouter):
|
|||
methods=["PUT"],
|
||||
response_model=Optional[list[self.schema]], # type: ignore
|
||||
summary="Update Many",
|
||||
description=inspect.cleandoc(self.service.update_many.__doc__ or ""),
|
||||
)
|
||||
|
||||
if self.service.delete_all:
|
||||
|
@ -84,6 +80,7 @@ class RouterFactory(APIRouter):
|
|||
methods=["DELETE"],
|
||||
response_model=Optional[list[self.schema]], # type: ignore
|
||||
summary="Delete All",
|
||||
description=inspect.cleandoc(self.service.delete_all.__doc__ or ""),
|
||||
)
|
||||
|
||||
if self.service.populate_item:
|
||||
|
@ -93,6 +90,7 @@ class RouterFactory(APIRouter):
|
|||
methods=["GET"],
|
||||
response_model=self.get_one_schema,
|
||||
summary="Get One",
|
||||
description=inspect.cleandoc(self.service.populate_item.__doc__ or ""),
|
||||
)
|
||||
|
||||
if self.service.update_one:
|
||||
|
@ -102,15 +100,18 @@ class RouterFactory(APIRouter):
|
|||
methods=["PUT"],
|
||||
response_model=self.schema,
|
||||
summary="Update One",
|
||||
description=inspect.cleandoc(self.service.update_one.__doc__ or ""),
|
||||
)
|
||||
|
||||
if self.service.delete_one:
|
||||
print(self.service.delete_one.__doc__)
|
||||
self._add_api_route(
|
||||
"/{item_id}",
|
||||
self._delete_one(),
|
||||
methods=["DELETE"],
|
||||
response_model=self.schema,
|
||||
summary="Delete One",
|
||||
description=inspect.cleandoc(self.service.delete_one.__doc__ or ""),
|
||||
)
|
||||
|
||||
def _add_api_route(self, path: str, endpoint: Callable[..., Any], **kwargs: Any) -> None:
|
||||
|
|
|
@ -4,13 +4,13 @@ from fastapi import HTTPException, status
|
|||
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.schema.cookbook.cookbook import CreateCookBook, ReadCookBook, RecipeCookBook, SaveCookBook, UpdateCookBook
|
||||
from mealie.services.base_http_service.base_http_service import BaseHttpService
|
||||
from mealie.services.base_http_service.http_services import UserHttpService
|
||||
from mealie.services.events import create_group_event
|
||||
|
||||
logger = get_logger(module=__name__)
|
||||
|
||||
|
||||
class CookbookService(BaseHttpService[int, ReadCookBook]):
|
||||
class CookbookService(UserHttpService[int, ReadCookBook]):
|
||||
event_func = create_group_event
|
||||
_restrict_by_group = True
|
||||
|
||||
|
@ -19,17 +19,17 @@ class CookbookService(BaseHttpService[int, ReadCookBook]):
|
|||
_update_schema = UpdateCookBook
|
||||
_get_one_schema = RecipeCookBook
|
||||
|
||||
def populate_item(self, id: int | str):
|
||||
def populate_item(self, item_id: int | str):
|
||||
try:
|
||||
id = int(id)
|
||||
item_id = int(item_id)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if isinstance(id, int):
|
||||
self.item = self.db.cookbooks.get_one(self.session, id, override_schema=RecipeCookBook)
|
||||
if isinstance(item_id, int):
|
||||
self.item = self.db.cookbooks.get_one(self.session, item_id, override_schema=RecipeCookBook)
|
||||
|
||||
else:
|
||||
self.item = self.db.cookbooks.get_one(self.session, id, key="slug", override_schema=RecipeCookBook)
|
||||
self.item = self.db.cookbooks.get_one(self.session, item_id, key="slug", override_schema=RecipeCookBook)
|
||||
|
||||
def get_all(self) -> list[ReadCookBook]:
|
||||
items = self.db.cookbooks.get(self.session, self.group_id, "group_id", limit=999)
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||
|
||||
from fastapi import Depends, HTTPException, status
|
||||
|
||||
from mealie.core.dependencies.grouped import WriteDeps
|
||||
from mealie.core.dependencies.grouped import UserDeps
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.schema.recipe.recipe_category import CategoryBase
|
||||
from mealie.schema.user.user import GroupInDB
|
||||
|
@ -18,12 +18,12 @@ class GroupSelfService(BaseHttpService[int, str]):
|
|||
item: GroupInDB
|
||||
|
||||
@classmethod
|
||||
def read_existing(cls, deps: WriteDeps = Depends()):
|
||||
def read_existing(cls, deps: UserDeps = Depends()):
|
||||
"""Override parent method to remove `item_id` from arguments"""
|
||||
return super().read_existing(item_id=0, deps=deps)
|
||||
|
||||
@classmethod
|
||||
def write_existing(cls, deps: WriteDeps = Depends()):
|
||||
def write_existing(cls, deps: UserDeps = Depends()):
|
||||
"""Override parent method to remove `item_id` from arguments"""
|
||||
return super().write_existing(item_id=0, deps=deps)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from typing import Union
|
|||
from fastapi import Depends, HTTPException, status
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from mealie.core.dependencies.grouped import ReadDeps, WriteDeps
|
||||
from mealie.core.dependencies.grouped import PublicDeps, UserDeps
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.schema.recipe.recipe import CreateRecipe, Recipe
|
||||
from mealie.services.base_http_service.base_http_service import BaseHttpService
|
||||
|
@ -25,11 +25,11 @@ class RecipeService(BaseHttpService[str, Recipe]):
|
|||
event_func = create_recipe_event
|
||||
|
||||
@classmethod
|
||||
def write_existing(cls, slug: str, deps: WriteDeps = Depends()):
|
||||
def write_existing(cls, slug: str, deps: UserDeps = Depends()):
|
||||
return super().write_existing(slug, deps)
|
||||
|
||||
@classmethod
|
||||
def read_existing(cls, slug: str, deps: ReadDeps = Depends()):
|
||||
def read_existing(cls, slug: str, deps: PublicDeps = Depends()):
|
||||
return super().write_existing(slug, deps)
|
||||
|
||||
def assert_existing(self, slug: str):
|
||||
|
|
81
mealie/utils/error_messages.py
Normal file
81
mealie/utils/error_messages.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class ErrorMessages:
|
||||
"""
|
||||
This enum class holds the text values that represent the errors returned when
|
||||
something goes wrong on the server side.
|
||||
|
||||
Example: {"details": "general-failure"}
|
||||
|
||||
The items contained within the '#' are automatically generated by a script in the scripts directory.
|
||||
DO NOT EDIT THE CONTENTS BETWEEN THOSE. If you need to add a custom error message, do so in the lines
|
||||
above.
|
||||
|
||||
Why Generate This!?!?! If we generate static errors on the backend we can ensure that a constant
|
||||
set or error messages will be returned to the frontend. As such we can use the "details" key to
|
||||
look up localized messages in the frontend. as such DO NOT change the generated or manual codes
|
||||
without making the necessary changes on the client side code.
|
||||
"""
|
||||
|
||||
general_failure = "general-failure"
|
||||
|
||||
# CODE_GEN_ID: ERROR_MESSAGE_ENUMS
|
||||
backup_create_failure = "backup-create-failure"
|
||||
backup_update_failure = "backup-update-failure"
|
||||
backup_delete_failure = "backup-delete-failure"
|
||||
|
||||
cookbook_create_failure = "cookbook-create-failure"
|
||||
cookbook_update_failure = "cookbook-update-failure"
|
||||
cookbook_delete_failure = "cookbook-delete-failure"
|
||||
|
||||
event_create_failure = "event-create-failure"
|
||||
event_update_failure = "event-update-failure"
|
||||
event_delete_failure = "event-delete-failure"
|
||||
|
||||
food_create_failure = "food-create-failure"
|
||||
food_update_failure = "food-update-failure"
|
||||
food_delete_failure = "food-delete-failure"
|
||||
|
||||
group_create_failure = "group-create-failure"
|
||||
group_update_failure = "group-update-failure"
|
||||
group_delete_failure = "group-delete-failure"
|
||||
|
||||
ingredient_create_failure = "ingredient-create-failure"
|
||||
ingredient_update_failure = "ingredient-update-failure"
|
||||
ingredient_delete_failure = "ingredient-delete-failure"
|
||||
|
||||
mealplan_create_failure = "mealplan-create-failure"
|
||||
mealplan_update_failure = "mealplan-update-failure"
|
||||
mealplan_delete_failure = "mealplan-delete-failure"
|
||||
|
||||
migration_create_failure = "migration-create-failure"
|
||||
migration_update_failure = "migration-update-failure"
|
||||
migration_delete_failure = "migration-delete-failure"
|
||||
|
||||
recipe_create_failure = "recipe-create-failure"
|
||||
recipe_update_failure = "recipe-update-failure"
|
||||
recipe_delete_failure = "recipe-delete-failure"
|
||||
|
||||
scraper_create_failure = "scraper-create-failure"
|
||||
scraper_update_failure = "scraper-update-failure"
|
||||
scraper_delete_failure = "scraper-delete-failure"
|
||||
|
||||
token_create_failure = "token-create-failure"
|
||||
token_update_failure = "token-update-failure"
|
||||
token_delete_failure = "token-delete-failure"
|
||||
|
||||
unit_create_failure = "unit-create-failure"
|
||||
unit_update_failure = "unit-update-failure"
|
||||
unit_delete_failure = "unit-delete-failure"
|
||||
|
||||
user_create_failure = "user-create-failure"
|
||||
user_update_failure = "user-update-failure"
|
||||
user_delete_failure = "user-delete-failure"
|
||||
|
||||
webhook_create_failure = "webhook-create-failure"
|
||||
webhook_update_failure = "webhook-update-failure"
|
||||
webhook_delete_failure = "webhook-delete-failure"
|
||||
|
||||
# END ERROR_MESSAGE_ENUMS
|
Loading…
Reference in a new issue