refactor: move dependencies to controllers (#1550)

* Moves dependencies directly to controllers
* Reduces use of @cached_property - (I have a suspicion that this is a factor in memory usage)
* reduce duplicate ways to access the same property on a controller.
This commit is contained in:
Hayden 2022-08-11 20:13:22 -08:00 committed by GitHub
parent 8a98288248
commit 71d3db7aef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 183 additions and 215 deletions

View File

@ -1,4 +1,3 @@
from .base_controllers import * from .base_controllers import *
from .controller import * from .controller import *
from .dependencies import *
from .mixins import * from .mixins import *

View File

@ -1,70 +1,107 @@
from abc import ABC from abc import ABC
from functools import cached_property from logging import Logger
from fastapi import Depends from fastapi import Depends
from pydantic import UUID4 from pydantic import UUID4
from sqlalchemy.orm import Session
from mealie.core.config import get_app_dirs, get_app_settings
from mealie.core.dependencies.dependencies import get_admin_user, get_current_user
from mealie.core.exceptions import mealie_registered_exceptions from mealie.core.exceptions import mealie_registered_exceptions
from mealie.core.root_logger import get_logger
from mealie.core.settings.directories import AppDirectories
from mealie.core.settings.settings import AppSettings
from mealie.db.db_setup import generate_session
from mealie.lang import local_provider from mealie.lang import local_provider
from mealie.lang.providers import Translator from mealie.lang.providers import Translator
from mealie.repos.all_repositories import AllRepositories from mealie.repos.all_repositories import AllRepositories
from mealie.routes._base.checks import OperationChecks from mealie.routes._base.checks import OperationChecks
from mealie.routes._base.dependencies import SharedDependencies
from mealie.schema.user.user import GroupInDB, PrivateUser from mealie.schema.user.user import GroupInDB, PrivateUser
class BasePublicController(ABC): class _BaseController(ABC):
session: Session = Depends(generate_session)
translator: Translator = Depends(local_provider)
_repos: AllRepositories | None
_logger: Logger | None
_settings: AppSettings | None
_folders: AppDirectories | None
@property
def t(self):
return self.translator.t if self.translator else local_provider().t
@property
def repos(self):
if not self._repos:
self._repos = AllRepositories(self.session)
return self._repos
@property
def logger(self) -> Logger:
if not self._logger:
self._logger = get_logger()
return self._logger
@property
def settings(self) -> AppSettings:
if not self._settings:
self._settings = get_app_settings()
return self._settings
@property
def folders(self) -> AppDirectories:
if not self._folders:
self._folders = get_app_dirs()
return self._folders
class Config:
arbitrary_types_allowed = True
class BasePublicController(_BaseController):
""" """
This is a public class for all User restricted controllers in the API. This is a public class for all User restricted controllers in the API.
It includes the common SharedDependencies and some common methods used It includes the common SharedDependencies and some common methods used
by all Admin controllers. by all Admin controllers.
""" """
deps: SharedDependencies = Depends(SharedDependencies.public) ...
translator: Translator = Depends(local_provider)
def __init__(self):
self.t = self.translator.t if self.translator else local_provider().t
class BaseUserController(ABC): class BaseUserController(_BaseController):
""" """
This is a base class for all User restricted controllers in the API. This is a base class for all User restricted controllers in the API.
It includes the common SharedDependencies and some common methods used It includes the common SharedDependencies and some common methods used
by all Admin controllers. by all Admin controllers.
""" """
deps: SharedDependencies = Depends(SharedDependencies.user) user: PrivateUser = Depends(get_current_user)
translator: Translator = Depends(local_provider) translator: Translator = Depends(local_provider)
def __init__(self): # Manual Cache
self.t = self.translator.t if self.translator else local_provider().t _checks: OperationChecks
def registered_exceptions(self, ex: type[Exception]) -> str: def registered_exceptions(self, ex: type[Exception]) -> str:
registered = { registered = {
**mealie_registered_exceptions(self.deps.t), **mealie_registered_exceptions(self.translator),
} }
return registered.get(ex, "An unexpected error occurred.") return registered.get(ex, "An unexpected error occurred.")
@cached_property
def repos(self):
return AllRepositories(self.deps.session)
@property @property
def group_id(self) -> UUID4: def group_id(self) -> UUID4:
return self.deps.acting_user.group_id return self.user.group_id
@property
def user(self) -> PrivateUser:
return self.deps.acting_user
@property @property
def group(self) -> GroupInDB: def group(self) -> GroupInDB:
return self.deps.repos.groups.get_one(self.group_id) return self.repos.groups.get_one(self.group_id)
@cached_property @property
def checks(self) -> OperationChecks: def checks(self) -> OperationChecks:
return OperationChecks(self.deps.acting_user) if not self._checks:
self._checks = OperationChecks(self.user)
return self._checks
class BaseAdminController(BaseUserController): class BaseAdminController(BaseUserController):
@ -74,8 +111,4 @@ class BaseAdminController(BaseUserController):
by all Admin controllers. by all Admin controllers.
""" """
deps: SharedDependencies = Depends(SharedDependencies.admin) user: PrivateUser = Depends(get_admin_user)
translator: Translator = Depends(local_provider)
def __init__(self):
self.t = self.translator.t if self.translator else local_provider().t

View File

@ -51,6 +51,7 @@ def _init_cbv(cls: type[Any], instance: Any = None) -> None:
Idempotently modifies the provided `cls`, performing the following modifications: Idempotently modifies the provided `cls`, performing the following modifications:
* The `__init__` function is updated to set any class-annotated dependencies as instance attributes * The `__init__` function is updated to set any class-annotated dependencies as instance attributes
* The `__signature__` attribute is updated to indicate to FastAPI what arguments should be passed to the initializer * The `__signature__` attribute is updated to indicate to FastAPI what arguments should be passed to the initializer
* Variables starting with `_` are NOT included in the `__signature__` and will be set to None.
""" """
if getattr(cls, CBV_CLASS_KEY, False): # pragma: no cover if getattr(cls, CBV_CLASS_KEY, False): # pragma: no cover
return # Already initialized return # Already initialized
@ -61,10 +62,17 @@ def _init_cbv(cls: type[Any], instance: Any = None) -> None:
x for x in old_parameters if x.kind not in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD) x for x in old_parameters if x.kind not in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD)
] ]
private_attributes = []
dependency_names: list[str] = [] dependency_names: list[str] = []
for name, hint in get_type_hints(cls).items(): for name, hint in get_type_hints(cls).items():
if is_classvar(hint): if is_classvar(hint):
continue continue
if name.startswith("_"):
private_attributes.append(name)
continue
parameter_kwargs = {"default": getattr(cls, name, Ellipsis)} parameter_kwargs = {"default": getattr(cls, name, Ellipsis)}
dependency_names.append(name) dependency_names.append(name)
new_parameters.append( new_parameters.append(
@ -88,6 +96,9 @@ def _init_cbv(cls: type[Any], instance: Any = None) -> None:
setattr(cls, "__init__", new_init) setattr(cls, "__init__", new_init)
setattr(cls, CBV_CLASS_KEY, True) setattr(cls, CBV_CLASS_KEY, True)
for name in private_attributes:
setattr(cls, name, None)
def _register_endpoints(router: APIRouter, cls: type[Any], *urls: str) -> None: def _register_endpoints(router: APIRouter, cls: type[Any], *urls: str) -> None:
cbv_router = APIRouter() cbv_router = APIRouter()

View File

@ -1,68 +0,0 @@
from functools import cached_property
from logging import Logger
from fastapi import Depends
from sqlalchemy.orm import Session
from mealie.core.config import get_app_dirs, get_app_settings
from mealie.core.dependencies.dependencies import get_admin_user, get_current_user
from mealie.core.root_logger import get_logger
from mealie.core.settings.directories import AppDirectories
from mealie.core.settings.settings import AppSettings
from mealie.db.db_setup import generate_session
from mealie.lang import Translator, local_provider
from mealie.repos import AllRepositories
from mealie.schema.user.user import PrivateUser
class SharedDependencies:
session: Session
t: Translator
acting_user: PrivateUser | None
def __init__(self, session: Session, acting_user: PrivateUser | None, provider: Translator | None = None) -> None:
self.t = provider or local_provider()
self.session = session
self.acting_user = acting_user
@classmethod
def public(
cls,
session: Session = Depends(generate_session),
translator: Translator = Depends(local_provider),
) -> "SharedDependencies":
return cls(session, None, translator)
@classmethod
def user(
cls,
session: Session = Depends(generate_session),
user: PrivateUser = Depends(get_current_user),
translator: Translator = Depends(local_provider),
) -> "SharedDependencies":
return cls(session, user, translator)
@classmethod
def admin(
cls,
session: Session = Depends(generate_session),
admin: PrivateUser = Depends(get_admin_user),
translator: Translator = Depends(local_provider),
) -> "SharedDependencies":
return cls(session, admin, translator)
@cached_property
def logger(self) -> Logger:
return get_logger()
@cached_property
def settings(self) -> AppSettings:
return get_app_settings()
@cached_property
def folders(self) -> AppDirectories:
return get_app_dirs()
@cached_property
def repos(self) -> AllRepositories:
return AllRepositories(self.session)

View File

@ -20,7 +20,7 @@ class AdminAboutController(BaseAdminController):
def get_app_info(self): def get_app_info(self):
"""Get general application information""" """Get general application information"""
settings = self.deps.settings settings = self.settings
return AdminAboutInfo( return AdminAboutInfo(
production=settings.PRODUCTION, production=settings.PRODUCTION,
@ -50,7 +50,7 @@ class AdminAboutController(BaseAdminController):
@router.get("/check", response_model=CheckAppConfig) @router.get("/check", response_model=CheckAppConfig)
def check_app_config(self): def check_app_config(self):
settings = self.deps.settings settings = self.settings
return CheckAppConfig( return CheckAppConfig(
email_ready=settings.SMTP_ENABLE, email_ready=settings.SMTP_ENABLE,
@ -61,7 +61,7 @@ class AdminAboutController(BaseAdminController):
@router.get("/docker/validate", response_model=DockerVolumeText) @router.get("/docker/validate", response_model=DockerVolumeText)
def validate_docker_volume(self, bg: BackgroundTasks): def validate_docker_volume(self, bg: BackgroundTasks):
validation_dir = self.deps.folders.DATA_DIR / "docker-validation" validation_dir = self.folders.DATA_DIR / "docker-validation"
validation_dir.mkdir(exist_ok=True) validation_dir.mkdir(exist_ok=True)
random_string = "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(100)) random_string = "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(100))
@ -75,7 +75,7 @@ class AdminAboutController(BaseAdminController):
try: try:
shutil.rmtree(validation_dir) shutil.rmtree(validation_dir)
except Exception as e: except Exception as e:
self.deps.logger.error(f"Failed to remove docker validation directory: {e}") self.logger.error(f"Failed to remove docker validation directory: {e}")
bg.add_task(cleanup) bg.add_task(cleanup)

View File

@ -12,7 +12,7 @@ class AdminEmailController(BaseAdminController):
@router.get("", response_model=EmailReady) @router.get("", response_model=EmailReady)
async def check_email_config(self): async def check_email_config(self):
"""Get general application information""" """Get general application information"""
return EmailReady(ready=self.deps.settings.SMTP_ENABLE) return EmailReady(ready=self.settings.SMTP_ENABLE)
@router.post("", response_model=EmailSuccess) @router.post("", response_model=EmailSuccess)
async def send_test_email(self, data: EmailTest): async def send_test_email(self, data: EmailTest):
@ -23,7 +23,7 @@ class AdminEmailController(BaseAdminController):
try: try:
status = service.send_test_email(data.email) status = service.send_test_email(data.email)
except Exception as e: except Exception as e:
self.deps.logger.error(e) self.logger.error(e)
error = str(e) error = str(e)
return EmailSuccess(success=status, error=error) return EmailSuccess(success=status, error=error)

View File

@ -77,10 +77,10 @@ class AdminMaintenanceController(BaseAdminController):
log_file_size = os.path.getsize(LOGGER_FILE) log_file_size = os.path.getsize(LOGGER_FILE)
return MaintenanceSummary( return MaintenanceSummary(
data_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.deps.folders.DATA_DIR)), data_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.folders.DATA_DIR)),
log_file_size=fs_stats.pretty_size(log_file_size), log_file_size=fs_stats.pretty_size(log_file_size),
cleanable_images=clean_images(self.deps.folders.RECIPE_DATA_DIR, dry_run=True), cleanable_images=clean_images(self.folders.RECIPE_DATA_DIR, dry_run=True),
cleanable_dirs=clean_recipe_folders(self.deps.folders.RECIPE_DATA_DIR, dry_run=True), cleanable_dirs=clean_recipe_folders(self.folders.RECIPE_DATA_DIR, dry_run=True),
) )
@router.get("/logs", response_model=MaintenanceLogs) @router.get("/logs", response_model=MaintenanceLogs)
@ -91,11 +91,11 @@ class AdminMaintenanceController(BaseAdminController):
@router.get("/storage", response_model=MaintenanceStorageDetails) @router.get("/storage", response_model=MaintenanceStorageDetails)
def get_storage_details(self): def get_storage_details(self):
return MaintenanceStorageDetails( return MaintenanceStorageDetails(
temp_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.deps.folders.TEMP_DIR)), temp_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.folders.TEMP_DIR)),
backups_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.deps.folders.BACKUP_DIR)), backups_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.folders.BACKUP_DIR)),
groups_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.deps.folders.GROUPS_DIR)), groups_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.folders.GROUPS_DIR)),
recipes_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.deps.folders.RECIPE_DATA_DIR)), recipes_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.folders.RECIPE_DATA_DIR)),
user_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.deps.folders.USER_DIR)), user_dir_size=fs_stats.pretty_size(fs_stats.get_dir_size(self.folders.USER_DIR)),
) )
@router.post("/clean/images", response_model=SuccessResponse) @router.post("/clean/images", response_model=SuccessResponse)
@ -104,7 +104,7 @@ class AdminMaintenanceController(BaseAdminController):
Purges all the images from the filesystem that aren't .webp Purges all the images from the filesystem that aren't .webp
""" """
try: try:
cleaned_images = clean_images(self.deps.folders.RECIPE_DATA_DIR, dry_run=False) cleaned_images = clean_images(self.folders.RECIPE_DATA_DIR, dry_run=False)
return SuccessResponse.respond(f"{cleaned_images} Images cleaned") return SuccessResponse.respond(f"{cleaned_images} Images cleaned")
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=ErrorResponse.respond("Failed to clean images")) from e raise HTTPException(status_code=500, detail=ErrorResponse.respond("Failed to clean images")) from e
@ -112,8 +112,8 @@ class AdminMaintenanceController(BaseAdminController):
@router.post("/clean/temp", response_model=SuccessResponse) @router.post("/clean/temp", response_model=SuccessResponse)
def clean_temp(self): def clean_temp(self):
try: try:
shutil.rmtree(self.deps.folders.TEMP_DIR) shutil.rmtree(self.folders.TEMP_DIR)
self.deps.folders.TEMP_DIR.mkdir(parents=True, exist_ok=True) self.folders.TEMP_DIR.mkdir(parents=True, exist_ok=True)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=ErrorResponse.respond("Failed to clean temp")) from e raise HTTPException(status_code=500, detail=ErrorResponse.respond("Failed to clean temp")) from e
@ -125,7 +125,7 @@ class AdminMaintenanceController(BaseAdminController):
Deletes all the recipe folders that don't have names that are valid UUIDs Deletes all the recipe folders that don't have names that are valid UUIDs
""" """
try: try:
cleaned_dirs = clean_recipe_folders(self.deps.folders.RECIPE_DATA_DIR, dry_run=False) cleaned_dirs = clean_recipe_folders(self.folders.RECIPE_DATA_DIR, dry_run=False)
return SuccessResponse.respond(f"{cleaned_dirs} Recipe folders removed") return SuccessResponse.respond(f"{cleaned_dirs} Recipe folders removed")
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=ErrorResponse.respond("Failed to clean directories")) from e raise HTTPException(status_code=500, detail=ErrorResponse.respond("Failed to clean directories")) from e

View File

@ -11,7 +11,6 @@ from mealie.schema.user.user import GroupBase, GroupInDB, GroupPagination
from mealie.services.group_services.group_service import GroupService from mealie.services.group_services.group_service import GroupService
from .._base import BaseAdminController, controller from .._base import BaseAdminController, controller
from .._base.dependencies import SharedDependencies
from .._base.mixins import HttpRepo from .._base.mixins import HttpRepo
router = APIRouter(prefix="/groups", tags=["Admin: Groups"]) router = APIRouter(prefix="/groups", tags=["Admin: Groups"])
@ -19,14 +18,12 @@ router = APIRouter(prefix="/groups", tags=["Admin: Groups"])
@controller(router) @controller(router)
class AdminUserManagementRoutes(BaseAdminController): class AdminUserManagementRoutes(BaseAdminController):
deps: SharedDependencies = Depends(SharedDependencies.user)
@cached_property @cached_property
def repo(self): def repo(self):
if not self.deps.acting_user: if not self.user:
raise Exception("No user is logged in.") raise Exception("No user is logged in.")
return self.deps.repos.groups return self.repos.groups
# ======================================================================= # =======================================================================
# CRUD Operations # CRUD Operations
@ -35,7 +32,7 @@ class AdminUserManagementRoutes(BaseAdminController):
def mixins(self): def mixins(self):
return HttpRepo[GroupBase, GroupInDB, GroupAdminUpdate]( return HttpRepo[GroupBase, GroupInDB, GroupAdminUpdate](
self.repo, self.repo,
self.deps.logger, self.logger,
self.registered_exceptions, self.registered_exceptions,
) )
@ -51,7 +48,7 @@ class AdminUserManagementRoutes(BaseAdminController):
@router.post("", response_model=GroupInDB, status_code=status.HTTP_201_CREATED) @router.post("", response_model=GroupInDB, status_code=status.HTTP_201_CREATED)
def create_one(self, data: GroupBase): def create_one(self, data: GroupBase):
return GroupService.create_group(self.deps.repos, data) return GroupService.create_group(self.repos, data)
@router.get("/{item_id}", response_model=GroupInDB) @router.get("/{item_id}", response_model=GroupInDB)
def get_one(self, item_id: UUID4): def get_one(self, item_id: UUID4):

View File

@ -5,7 +5,6 @@ from pydantic import UUID4
from mealie.core import security from mealie.core import security
from mealie.routes._base import BaseAdminController, controller from mealie.routes._base import BaseAdminController, controller
from mealie.routes._base.dependencies import SharedDependencies
from mealie.routes._base.mixins import HttpRepo from mealie.routes._base.mixins import HttpRepo
from mealie.schema.response.pagination import PaginationQuery from mealie.schema.response.pagination import PaginationQuery
from mealie.schema.response.responses import ErrorResponse from mealie.schema.response.responses import ErrorResponse
@ -16,21 +15,19 @@ router = APIRouter(prefix="/users", tags=["Admin: Users"])
@controller(router) @controller(router)
class AdminUserManagementRoutes(BaseAdminController): class AdminUserManagementRoutes(BaseAdminController):
deps: SharedDependencies = Depends(SharedDependencies.user)
@cached_property @cached_property
def repo(self): def repo(self):
if not self.deps.acting_user: if not self.user:
raise Exception("No user is logged in.") raise Exception("No user is logged in.")
return self.deps.repos.users return self.repos.users
# ======================================================================= # =======================================================================
# CRUD Operations # CRUD Operations
@property @property
def mixins(self): def mixins(self):
return HttpRepo[UserIn, UserOut, UserOut](self.repo, self.deps.logger, self.registered_exceptions) return HttpRepo[UserIn, UserOut, UserOut](self.repo, self.logger, self.registered_exceptions)
@router.get("", response_model=UserPagination) @router.get("", response_model=UserPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):
@ -54,7 +51,7 @@ class AdminUserManagementRoutes(BaseAdminController):
@router.put("/{item_id}", response_model=UserOut) @router.put("/{item_id}", response_model=UserOut)
def update_one(self, item_id: UUID4, data: UserOut): def update_one(self, item_id: UUID4, data: UserOut):
# Prevent self demotion # Prevent self demotion
if self.deps.acting_user.id == item_id and self.deps.acting_user.admin != data.admin: if self.user.id == item_id and self.user.admin != data.admin:
raise HTTPException(status_code=403, detail=ErrorResponse.respond("you cannot demote yourself")) raise HTTPException(status_code=403, detail=ErrorResponse.respond("you cannot demote yourself"))
return self.mixins.update_one(data, item_id) return self.mixins.update_one(data, item_id)

View File

@ -25,18 +25,18 @@ router = APIRouter(prefix="/comments", tags=["Recipe: Comments"])
class RecipeCommentRoutes(BaseUserController): class RecipeCommentRoutes(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
return self.deps.repos.comments return self.repos.comments
# ======================================================================= # =======================================================================
# CRUD Operations # CRUD Operations
@property @property
def mixins(self) -> HttpRepo: def mixins(self) -> HttpRepo:
return HttpRepo(self.repo, self.deps.logger, self.registered_exceptions, "An unexpected error occurred.") return HttpRepo(self.repo, self.logger, self.registered_exceptions, "An unexpected error occurred.")
def _check_comment_belongs_to_user(self, item_id: UUID4) -> None: def _check_comment_belongs_to_user(self, item_id: UUID4) -> None:
comment = self.repo.get_one(item_id) comment = self.repo.get_one(item_id)
if comment.user_id != self.deps.acting_user.id and not self.deps.acting_user.admin: if comment.user_id != self.user.id and not self.user.admin:
raise HTTPException( raise HTTPException(
status_code=403, status_code=403,
detail=ErrorResponse(message="Comment does not belong to user"), detail=ErrorResponse(message="Comment does not belong to user"),
@ -54,7 +54,7 @@ class RecipeCommentRoutes(BaseUserController):
@router.post("", response_model=RecipeCommentOut, status_code=201) @router.post("", response_model=RecipeCommentOut, status_code=201)
def create_one(self, data: RecipeCommentCreate): def create_one(self, data: RecipeCommentCreate):
save_data = RecipeCommentSave(text=data.text, user_id=self.deps.acting_user.id, recipe_id=data.recipe_id) save_data = RecipeCommentSave(text=data.text, user_id=self.user.id, recipe_id=data.recipe_id)
return self.mixins.create_one(save_data) return self.mixins.create_one(save_data)
@router.get("/{item_id}", response_model=RecipeCommentOut) @router.get("/{item_id}", response_model=RecipeCommentOut)

View File

@ -24,11 +24,11 @@ class GroupCookbookController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
return self.deps.repos.cookbooks.by_group(self.group_id) return self.repos.cookbooks.by_group(self.group_id)
def registered_exceptions(self, ex: type[Exception]) -> str: def registered_exceptions(self, ex: type[Exception]) -> str:
registered = { registered = {
**mealie_registered_exceptions(self.deps.t), **mealie_registered_exceptions(self.translator),
} }
return registered.get(ex, "An unexpected error occurred.") return registered.get(ex, "An unexpected error occurred.")
@ -36,7 +36,7 @@ class GroupCookbookController(BaseUserController):
def mixins(self): def mixins(self):
return HttpRepo[CreateCookBook, ReadCookBook, UpdateCookBook]( return HttpRepo[CreateCookBook, ReadCookBook, UpdateCookBook](
self.repo, self.repo,
self.deps.logger, self.logger,
self.registered_exceptions, self.registered_exceptions,
) )
@ -57,7 +57,7 @@ class GroupCookbookController(BaseUserController):
if val: if val:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.cookbook_created, EventTypes.cookbook_created,
msg=self.t("notifications.generic-created", name=val.name), msg=self.t("notifications.generic-created", name=val.name),
event_source=EventSource(event_type="create", item_type="cookbook", item_id=val.id, slug=val.slug), event_source=EventSource(event_type="create", item_type="cookbook", item_id=val.id, slug=val.slug),
@ -99,7 +99,7 @@ class GroupCookbookController(BaseUserController):
val = self.mixins.update_one(data, item_id) # type: ignore val = self.mixins.update_one(data, item_id) # type: ignore
if val: if val:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.cookbook_updated, EventTypes.cookbook_updated,
msg=self.t("notifications.generic-updated", name=val.name), msg=self.t("notifications.generic-updated", name=val.name),
event_source=EventSource(event_type="update", item_type="cookbook", item_id=val.id, slug=val.slug), event_source=EventSource(event_type="update", item_type="cookbook", item_id=val.id, slug=val.slug),
@ -112,7 +112,7 @@ class GroupCookbookController(BaseUserController):
val = self.mixins.delete_one(item_id) val = self.mixins.delete_one(item_id)
if val: if val:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.cookbook_deleted, EventTypes.cookbook_deleted,
msg=self.t("notifications.generic-deleted", name=val.name), msg=self.t("notifications.generic-deleted", name=val.name),
event_source=EventSource(event_type="delete", item_type="cookbook", item_id=val.id, slug=val.slug), event_source=EventSource(event_type="delete", item_type="cookbook", item_id=val.id, slug=val.slug),

View File

@ -30,17 +30,17 @@ class GroupEventsNotifierController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
if not self.deps.acting_user: if not self.user:
raise Exception("No user is logged in.") raise Exception("No user is logged in.")
return self.deps.repos.group_event_notifier.by_group(self.deps.acting_user.group_id) return self.repos.group_event_notifier.by_group(self.user.group_id)
# ======================================================================= # =======================================================================
# CRUD Operations # CRUD Operations
@property @property
def mixins(self) -> HttpRepo: def mixins(self) -> HttpRepo:
return HttpRepo(self.repo, self.deps.logger, self.registered_exceptions, "An unexpected error occurred.") return HttpRepo(self.repo, self.logger, self.registered_exceptions, "An unexpected error occurred.")
@router.get("", response_model=GroupEventPagination) @router.get("", response_model=GroupEventPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):
@ -54,7 +54,7 @@ class GroupEventsNotifierController(BaseUserController):
@router.post("", response_model=GroupEventNotifierOut, status_code=201) @router.post("", response_model=GroupEventNotifierOut, status_code=201)
def create_one(self, data: GroupEventNotifierCreate): def create_one(self, data: GroupEventNotifierCreate):
save_data = cast(data, GroupEventNotifierSave, group_id=self.deps.acting_user.group_id) save_data = cast(data, GroupEventNotifierSave, group_id=self.user.group_id)
return self.mixins.create_one(save_data) return self.mixins.create_one(save_data)
@router.get("/{item_id}", response_model=GroupEventNotifierOut) @router.get("/{item_id}", response_model=GroupEventNotifierOut)

View File

@ -17,18 +17,18 @@ router = APIRouter(prefix="/groups/reports", tags=["Groups: Reports"])
class GroupReportsController(BaseUserController): class GroupReportsController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
return self.deps.repos.group_reports.by_group(self.deps.acting_user.group_id) return self.repos.group_reports.by_group(self.user.group_id)
def registered_exceptions(self, ex: type[Exception]) -> str: def registered_exceptions(self, ex: type[Exception]) -> str:
return { return {
**mealie_registered_exceptions(self.deps.t), **mealie_registered_exceptions(self.translator),
}.get(ex, "An unexpected error occurred.") }.get(ex, "An unexpected error occurred.")
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo[ReportCreate, ReportOut, ReportCreate]( return HttpRepo[ReportCreate, ReportOut, ReportCreate](
self.repo, self.repo,
self.deps.logger, self.logger,
self.registered_exceptions, self.registered_exceptions,
) )

View File

@ -22,7 +22,7 @@ class GroupInvitationsController(BaseUserController):
@router.post("", response_model=ReadInviteToken, status_code=status.HTTP_201_CREATED) @router.post("", response_model=ReadInviteToken, status_code=status.HTTP_201_CREATED)
def create_invite_token(self, uses: CreateInviteToken): def create_invite_token(self, uses: CreateInviteToken):
if not self.deps.acting_user.can_invite: if not self.user.can_invite:
raise HTTPException(status.HTTP_403_FORBIDDEN, detail="User is not allowed to create invite tokens") raise HTTPException(status.HTTP_403_FORBIDDEN, detail="User is not allowed to create invite tokens")
token = SaveInviteToken(uses_left=uses.uses, group_id=self.group_id, token=url_safe_token()) token = SaveInviteToken(uses_left=uses.uses, group_id=self.group_id, token=url_safe_token())
@ -31,7 +31,7 @@ class GroupInvitationsController(BaseUserController):
@router.post("/email", response_model=EmailInitationResponse) @router.post("/email", response_model=EmailInitationResponse)
def email_invitation(self, invite: EmailInvitation): def email_invitation(self, invite: EmailInvitation):
email_service = EmailService() email_service = EmailService()
url = f"{self.deps.settings.BASE_URL}/register?token={invite.token}" url = f"{self.settings.BASE_URL}/register?token={invite.token}"
success = False success = False
error = None error = None

View File

@ -25,17 +25,17 @@ router = APIRouter(prefix="/groups/labels", tags=["Group: Multi Purpose Labels"]
class MultiPurposeLabelsController(BaseUserController): class MultiPurposeLabelsController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
if not self.deps.acting_user: if not self.user:
raise Exception("No user is logged in.") raise Exception("No user is logged in.")
return self.deps.repos.group_multi_purpose_labels.by_group(self.deps.acting_user.group_id) return self.repos.group_multi_purpose_labels.by_group(self.user.group_id)
# ======================================================================= # =======================================================================
# CRUD Operations # CRUD Operations
@property @property
def mixins(self) -> HttpRepo: def mixins(self) -> HttpRepo:
return HttpRepo(self.repo, self.deps.logger, self.registered_exceptions, "An unexpected error occurred.") return HttpRepo(self.repo, self.logger, self.registered_exceptions, "An unexpected error occurred.")
@router.get("", response_model=MultiPurposeLabelPagination) @router.get("", response_model=MultiPurposeLabelPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):
@ -49,7 +49,7 @@ class MultiPurposeLabelsController(BaseUserController):
@router.post("", response_model=MultiPurposeLabelOut) @router.post("", response_model=MultiPurposeLabelOut)
def create_one(self, data: MultiPurposeLabelCreate): def create_one(self, data: MultiPurposeLabelCreate):
save_data = cast(data, MultiPurposeLabelSave, group_id=self.deps.acting_user.group_id) save_data = cast(data, MultiPurposeLabelSave, group_id=self.user.group_id)
return self.mixins.create_one(save_data) return self.mixins.create_one(save_data)
@router.get("/{item_id}", response_model=MultiPurposeLabelOut) @router.get("/{item_id}", response_model=MultiPurposeLabelOut)

View File

@ -27,7 +27,7 @@ class GroupMealplanController(BaseUserController):
def registered_exceptions(self, ex: type[Exception]) -> str: def registered_exceptions(self, ex: type[Exception]) -> str:
registered = { registered = {
**mealie_registered_exceptions(self.deps.t), **mealie_registered_exceptions(self.translator),
} }
return registered.get(ex, "An unexpected error occurred.") return registered.get(ex, "An unexpected error occurred.")
@ -35,7 +35,7 @@ class GroupMealplanController(BaseUserController):
def mixins(self): def mixins(self):
return HttpRepo[CreatePlanEntry, ReadPlanEntry, UpdatePlanEntry]( return HttpRepo[CreatePlanEntry, ReadPlanEntry, UpdatePlanEntry](
self.repo, self.repo,
self.deps.logger, self.logger,
self.registered_exceptions, self.registered_exceptions,
) )

View File

@ -12,15 +12,15 @@ router = UserAPIRouter(prefix="/groups/categories", tags=["Groups: Mealplan Cate
class GroupMealplanConfigController(BaseUserController): class GroupMealplanConfigController(BaseUserController):
@property @property
def mixins(self): def mixins(self):
return HttpRepo[GroupInDB, GroupInDB, GroupInDB](self.repos.groups, self.deps.logger) return HttpRepo[GroupInDB, GroupInDB, GroupInDB](self.repos.groups, self.logger)
@router.get("", response_model=list[CategoryBase]) @router.get("", response_model=list[CategoryBase])
def get_mealplan_categories(self): def get_mealplan_categories(self):
data = self.mixins.get_one(self.deps.acting_user.group_id) data = self.mixins.get_one(self.user.group_id)
return data.categories return data.categories
@router.put("", response_model=list[CategoryBase]) @router.put("", response_model=list[CategoryBase])
def update_mealplan_categories(self, new_categories: list[CategoryBase]): def update_mealplan_categories(self, new_categories: list[CategoryBase]):
data = self.mixins.get_one(self.deps.acting_user.group_id) data = self.mixins.get_one(self.user.group_id)
data.categories = new_categories data.categories = new_categories
return self.mixins.update_one(data, data.id).categories return self.mixins.update_one(data, data.id).categories

View File

@ -22,7 +22,7 @@ class GroupMealplanConfigController(BaseUserController):
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo[PlanRulesCreate, PlanRulesOut, PlanRulesOut](self.repo, self.deps.logger) return HttpRepo[PlanRulesCreate, PlanRulesOut, PlanRulesOut](self.repo, self.logger)
@router.get("", response_model=PlanRulesPagination) @router.get("", response_model=PlanRulesPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):

View File

@ -37,7 +37,7 @@ class GroupMigrationController(BaseUserController):
args = { args = {
"archive": temp_path, "archive": temp_path,
"db": self.repos, "db": self.repos,
"session": self.deps.session, "session": self.session,
"user_id": self.user.id, "user_id": self.user.id,
"group_id": self.group_id, "group_id": self.group_id,
"add_migration_tag": add_migration_tag, "add_migration_tag": add_migration_tag,

View File

@ -38,13 +38,13 @@ class ShoppingListItemController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
return self.deps.repos.group_shopping_list_item return self.repos.group_shopping_list_item
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo[ShoppingListItemCreate, ShoppingListItemOut, ShoppingListItemCreate]( return HttpRepo[ShoppingListItemCreate, ShoppingListItemOut, ShoppingListItemCreate](
self.repo, self.repo,
self.deps.logger, self.logger,
) )
@item_router.put("", response_model=list[ShoppingListItemOut]) @item_router.put("", response_model=list[ShoppingListItemOut])
@ -80,7 +80,7 @@ class ShoppingListItemController(BaseUserController):
if shopping_list_item: if shopping_list_item:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_updated, EventTypes.shopping_list_updated,
msg=self.t( msg=self.t(
"notifications.generic-created", "notifications.generic-created",
@ -106,7 +106,7 @@ class ShoppingListItemController(BaseUserController):
if shopping_list_item: if shopping_list_item:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_updated, EventTypes.shopping_list_updated,
msg=self.t( msg=self.t(
"notifications.generic-updated", "notifications.generic-updated",
@ -128,7 +128,7 @@ class ShoppingListItemController(BaseUserController):
if shopping_list_item: if shopping_list_item:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_updated, EventTypes.shopping_list_updated,
msg=self.t( msg=self.t(
"notifications.generic-deleted", "notifications.generic-deleted",
@ -158,14 +158,14 @@ class ShoppingListController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
return self.deps.repos.group_shopping_lists.by_group(self.deps.acting_user.group_id) return self.repos.group_shopping_lists.by_group(self.user.group_id)
# ======================================================================= # =======================================================================
# CRUD Operations # CRUD Operations
@cached_property @cached_property
def mixins(self) -> HttpRepo[ShoppingListCreate, ShoppingListOut, ShoppingListSave]: def mixins(self) -> HttpRepo[ShoppingListCreate, ShoppingListOut, ShoppingListSave]:
return HttpRepo(self.repo, self.deps.logger, self.registered_exceptions, "An unexpected error occurred.") return HttpRepo(self.repo, self.logger, self.registered_exceptions, "An unexpected error occurred.")
@router.get("", response_model=ShoppingListPagination) @router.get("", response_model=ShoppingListPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):
@ -179,12 +179,12 @@ class ShoppingListController(BaseUserController):
@router.post("", response_model=ShoppingListOut, status_code=201) @router.post("", response_model=ShoppingListOut, status_code=201)
def create_one(self, data: ShoppingListCreate): def create_one(self, data: ShoppingListCreate):
save_data = cast(data, ShoppingListSave, group_id=self.deps.acting_user.group_id) save_data = cast(data, ShoppingListSave, group_id=self.user.group_id)
val = self.mixins.create_one(save_data) val = self.mixins.create_one(save_data)
if val: if val:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_created, EventTypes.shopping_list_created,
msg=self.t("notifications.generic-created", name=val.name), msg=self.t("notifications.generic-created", name=val.name),
event_source=EventSource( event_source=EventSource(
@ -205,7 +205,7 @@ class ShoppingListController(BaseUserController):
data = self.mixins.update_one(data, item_id) # type: ignore data = self.mixins.update_one(data, item_id) # type: ignore
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_updated, EventTypes.shopping_list_updated,
msg=self.t("notifications.generic-updated", name=data.name), msg=self.t("notifications.generic-updated", name=data.name),
event_source=EventSource( event_source=EventSource(
@ -221,7 +221,7 @@ class ShoppingListController(BaseUserController):
data = self.mixins.delete_one(item_id) # type: ignore data = self.mixins.delete_one(item_id) # type: ignore
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_deleted, EventTypes.shopping_list_deleted,
msg=self.t("notifications.generic-deleted", name=data.name), msg=self.t("notifications.generic-deleted", name=data.name),
event_source=EventSource( event_source=EventSource(
@ -240,7 +240,7 @@ class ShoppingListController(BaseUserController):
shopping_list = self.service.add_recipe_ingredients_to_list(item_id, recipe_id) shopping_list = self.service.add_recipe_ingredients_to_list(item_id, recipe_id)
if shopping_list: if shopping_list:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_updated, EventTypes.shopping_list_updated,
msg=self.t( msg=self.t(
"notifications.generic-updated", "notifications.generic-updated",
@ -260,7 +260,7 @@ class ShoppingListController(BaseUserController):
shopping_list = self.service.remove_recipe_ingredients_from_list(item_id, recipe_id) shopping_list = self.service.remove_recipe_ingredients_from_list(item_id, recipe_id)
if shopping_list: if shopping_list:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.shopping_list_updated, EventTypes.shopping_list_updated,
msg=self.t( msg=self.t(
"notifications.generic-updated", "notifications.generic-updated",

View File

@ -21,7 +21,7 @@ class ReadWebhookController(BaseUserController):
@property @property
def mixins(self) -> HttpRepo: def mixins(self) -> HttpRepo:
return HttpRepo[CreateWebhook, SaveWebhook, CreateWebhook](self.repo, self.deps.logger) return HttpRepo[CreateWebhook, SaveWebhook, CreateWebhook](self.repo, self.logger)
@router.get("", response_model=WebhookPagination) @router.get("", response_model=WebhookPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):

View File

@ -39,7 +39,7 @@ class RecipeCategoryController(BaseUserController):
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo(self.repo, self.deps.logger) return HttpRepo(self.repo, self.logger)
@router.get("", response_model=RecipeCategoryPagination) @router.get("", response_model=RecipeCategoryPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):
@ -59,12 +59,12 @@ class RecipeCategoryController(BaseUserController):
data = self.mixins.create_one(save_data) data = self.mixins.create_one(save_data)
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.category_created, EventTypes.category_created,
msg=self.t( msg=self.t(
"notifications.generic-created-with-url", "notifications.generic-created-with-url",
name=data.name, name=data.name,
url=urls.category_url(data.slug, self.deps.settings.BASE_URL), url=urls.category_url(data.slug, self.settings.BASE_URL),
), ),
event_source=EventSource(event_type="create", item_type="category", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="create", item_type="category", item_id=data.id, slug=data.slug),
) )
@ -85,12 +85,12 @@ class RecipeCategoryController(BaseUserController):
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.category_updated, EventTypes.category_updated,
msg=self.t( msg=self.t(
"notifications.generic-updated-with-url", "notifications.generic-updated-with-url",
name=data.name, name=data.name,
url=urls.category_url(data.slug, self.deps.settings.BASE_URL), url=urls.category_url(data.slug, self.settings.BASE_URL),
), ),
event_source=EventSource(event_type="update", item_type="category", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="update", item_type="category", item_id=data.id, slug=data.slug),
) )
@ -105,7 +105,7 @@ class RecipeCategoryController(BaseUserController):
""" """
if data := self.mixins.delete_one(item_id): if data := self.mixins.delete_one(item_id):
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.category_deleted, EventTypes.category_deleted,
msg=self.t("notifications.generic-deleted", name=data.name), msg=self.t("notifications.generic-deleted", name=data.name),
event_source=EventSource(event_type="delete", item_type="category", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="delete", item_type="category", item_id=data.id, slug=data.slug),

View File

@ -28,7 +28,7 @@ class TagController(BaseUserController):
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo(self.repo, self.deps.logger) return HttpRepo(self.repo, self.logger)
@router.get("", response_model=RecipeTagPagination) @router.get("", response_model=RecipeTagPagination)
async def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): async def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):
@ -58,12 +58,12 @@ class TagController(BaseUserController):
data = self.repo.create(save_data) data = self.repo.create(save_data)
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.tag_created, EventTypes.tag_created,
msg=self.t( msg=self.t(
"notifications.generic-created-with-url", "notifications.generic-created-with-url",
name=data.name, name=data.name,
url=urls.tag_url(data.slug, self.deps.settings.BASE_URL), url=urls.tag_url(data.slug, self.settings.BASE_URL),
), ),
event_source=EventSource(event_type="create", item_type="tag", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="create", item_type="tag", item_id=data.id, slug=data.slug),
) )
@ -76,12 +76,12 @@ class TagController(BaseUserController):
data = self.repo.update(item_id, save_data) data = self.repo.update(item_id, save_data)
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.tag_updated, EventTypes.tag_updated,
msg=self.t( msg=self.t(
"notifications.generic-updated-with-url", "notifications.generic-updated-with-url",
name=data.name, name=data.name,
url=urls.tag_url(data.slug, self.deps.settings.BASE_URL), url=urls.tag_url(data.slug, self.settings.BASE_URL),
), ),
event_source=EventSource(event_type="update", item_type="tag", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="update", item_type="tag", item_id=data.id, slug=data.slug),
) )
@ -100,7 +100,7 @@ class TagController(BaseUserController):
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.tag_deleted, EventTypes.tag_deleted,
msg=self.t("notifications.generic-deleted", name=data.name), msg=self.t("notifications.generic-deleted", name=data.name),
event_source=EventSource(event_type="delete", item_type="tag", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="delete", item_type="tag", item_id=data.id, slug=data.slug),

View File

@ -22,7 +22,7 @@ class RecipeToolController(BaseUserController):
@property @property
def mixins(self) -> HttpRepo: def mixins(self) -> HttpRepo:
return HttpRepo[RecipeToolCreate, RecipeTool, RecipeToolCreate](self.repo, self.deps.logger) return HttpRepo[RecipeToolCreate, RecipeTool, RecipeToolCreate](self.repo, self.logger)
@router.get("", response_model=RecipeToolPagination) @router.get("", response_model=RecipeToolPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):

View File

@ -56,7 +56,7 @@ class BaseRecipeController(BaseUserController):
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo[CreateRecipe, Recipe, Recipe](self.repo, self.deps.logger) return HttpRepo[CreateRecipe, Recipe, Recipe](self.repo, self.logger)
class FormatResponse(BaseModel): class FormatResponse(BaseModel):
@ -124,18 +124,18 @@ class RecipeController(BaseRecipeController):
def handle_exceptions(self, ex: Exception) -> None: def handle_exceptions(self, ex: Exception) -> None:
match type(ex): match type(ex):
case exceptions.PermissionDenied: case exceptions.PermissionDenied:
self.deps.logger.error("Permission Denied on recipe controller action") self.logger.error("Permission Denied on recipe controller action")
raise HTTPException(status_code=403, detail=ErrorResponse.respond(message="Permission Denied")) raise HTTPException(status_code=403, detail=ErrorResponse.respond(message="Permission Denied"))
case exceptions.NoEntryFound: case exceptions.NoEntryFound:
self.deps.logger.error("No Entry Found on recipe controller action") self.logger.error("No Entry Found on recipe controller action")
raise HTTPException(status_code=404, detail=ErrorResponse.respond(message="No Entry Found")) raise HTTPException(status_code=404, detail=ErrorResponse.respond(message="No Entry Found"))
case sqlalchemy.exc.IntegrityError: case sqlalchemy.exc.IntegrityError:
self.deps.logger.error("SQL Integrity Error on recipe controller action") self.logger.error("SQL Integrity Error on recipe controller action")
raise HTTPException(status_code=400, detail=ErrorResponse.respond(message="Recipe already exists")) raise HTTPException(status_code=400, detail=ErrorResponse.respond(message="Recipe already exists"))
case _: case _:
self.deps.logger.error("Unknown Error on recipe controller action") self.logger.error("Unknown Error on recipe controller action")
self.deps.logger.exception(ex) self.logger.exception(ex)
raise HTTPException( raise HTTPException(
status_code=500, detail=ErrorResponse.respond(message="Unknown Error", exception=str(ex)) status_code=500, detail=ErrorResponse.respond(message="Unknown Error", exception=str(ex))
) )
@ -162,12 +162,12 @@ class RecipeController(BaseRecipeController):
if new_recipe: if new_recipe:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.recipe_created, EventTypes.recipe_created,
msg=self.t( msg=self.t(
"notifications.generic-created-with-url", "notifications.generic-created-with-url",
name=new_recipe.name, name=new_recipe.name,
url=urls.recipe_url(new_recipe.slug, self.deps.settings.BASE_URL), url=urls.recipe_url(new_recipe.slug, self.settings.BASE_URL),
), ),
event_source=EventSource( event_source=EventSource(
event_type="create", item_type="recipe", item_id=new_recipe.id, slug=new_recipe.slug event_type="create", item_type="recipe", item_id=new_recipe.id, slug=new_recipe.slug
@ -255,12 +255,12 @@ class RecipeController(BaseRecipeController):
if new_recipe: if new_recipe:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.recipe_created, EventTypes.recipe_created,
msg=self.t( msg=self.t(
"notifications.generic-created-with-url", "notifications.generic-created-with-url",
name=new_recipe.name, name=new_recipe.name,
url=urls.recipe_url(new_recipe.slug, self.deps.settings.BASE_URL), url=urls.recipe_url(new_recipe.slug, self.settings.BASE_URL),
), ),
event_source=EventSource( event_source=EventSource(
event_type="create", item_type="recipe", item_id=new_recipe.id, slug=new_recipe.slug event_type="create", item_type="recipe", item_id=new_recipe.id, slug=new_recipe.slug
@ -279,12 +279,12 @@ class RecipeController(BaseRecipeController):
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.recipe_updated, EventTypes.recipe_updated,
msg=self.t( msg=self.t(
"notifications.generic-updated-with-url", "notifications.generic-updated-with-url",
name=data.name, name=data.name,
url=urls.recipe_url(data.slug, self.deps.settings.BASE_URL), url=urls.recipe_url(data.slug, self.settings.BASE_URL),
), ),
event_source=EventSource(event_type="update", item_type="recipe", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="update", item_type="recipe", item_id=data.id, slug=data.slug),
) )
@ -301,12 +301,12 @@ class RecipeController(BaseRecipeController):
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.recipe_updated, EventTypes.recipe_updated,
msg=self.t( msg=self.t(
"notifications.generic-updated-with-url", "notifications.generic-updated-with-url",
name=data.name, name=data.name,
url=urls.recipe_url(data.slug, self.deps.settings.BASE_URL), url=urls.recipe_url(data.slug, self.settings.BASE_URL),
), ),
event_source=EventSource(event_type="update", item_type="recipe", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="update", item_type="recipe", item_id=data.id, slug=data.slug),
) )
@ -323,7 +323,7 @@ class RecipeController(BaseRecipeController):
if data: if data:
self.event_bus.dispatch( self.event_bus.dispatch(
self.deps.acting_user.group_id, self.user.group_id,
EventTypes.recipe_deleted, EventTypes.recipe_deleted,
msg=self.t("notifications.generic-deleted", name=data.name), msg=self.t("notifications.generic-deleted", name=data.name),
event_source=EventSource(event_type="delete", item_type="recipe", item_id=data.id, slug=data.slug), event_source=EventSource(event_type="delete", item_type="recipe", item_id=data.id, slug=data.slug),

View File

@ -19,7 +19,7 @@ class RecipeSharedController(BaseUserController):
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo[RecipeShareTokenSave, RecipeShareToken, RecipeShareTokenCreate](self.repo, self.deps.logger) return HttpRepo[RecipeShareTokenSave, RecipeShareToken, RecipeShareTokenCreate](self.repo, self.logger)
@router.get("", response_model=list[RecipeShareTokenSummary]) @router.get("", response_model=list[RecipeShareTokenSummary])
def get_all(self, recipe_id: UUID4 = None): def get_all(self, recipe_id: UUID4 = None):

View File

@ -25,13 +25,13 @@ router = APIRouter(prefix="/foods", tags=["Recipes: Foods"], route_class=MealieC
class IngredientFoodsController(BaseUserController): class IngredientFoodsController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
return self.deps.repos.ingredient_foods.by_group(self.group_id) return self.repos.ingredient_foods.by_group(self.group_id)
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo[SaveIngredientFood, IngredientFood, CreateIngredientFood]( return HttpRepo[SaveIngredientFood, IngredientFood, CreateIngredientFood](
self.repo, self.repo,
self.deps.logger, self.logger,
self.registered_exceptions, self.registered_exceptions,
) )
@ -41,7 +41,7 @@ class IngredientFoodsController(BaseUserController):
self.repo.merge(data.from_food, data.to_food) self.repo.merge(data.from_food, data.to_food)
return SuccessResponse.respond("Successfully merged foods") return SuccessResponse.respond("Successfully merged foods")
except Exception as e: except Exception as e:
self.deps.logger.error(e) self.logger.error(e)
raise HTTPException(500, "Failed to merge foods") from e raise HTTPException(500, "Failed to merge foods") from e
@router.get("", response_model=IngredientFoodPagination) @router.get("", response_model=IngredientFoodPagination)

View File

@ -25,13 +25,13 @@ router = APIRouter(prefix="/units", tags=["Recipes: Units"], route_class=MealieC
class IngredientUnitsController(BaseUserController): class IngredientUnitsController(BaseUserController):
@cached_property @cached_property
def repo(self): def repo(self):
return self.deps.repos.ingredient_units.by_group(self.group_id) return self.repos.ingredient_units.by_group(self.group_id)
@cached_property @cached_property
def mixins(self): def mixins(self):
return HttpRepo[CreateIngredientUnit, IngredientUnit, CreateIngredientUnit]( return HttpRepo[CreateIngredientUnit, IngredientUnit, CreateIngredientUnit](
self.repo, self.repo,
self.deps.logger, self.logger,
self.registered_exceptions, self.registered_exceptions,
) )
@ -41,7 +41,7 @@ class IngredientUnitsController(BaseUserController):
self.repo.merge(data.from_unit, data.to_unit) self.repo.merge(data.from_unit, data.to_unit)
return SuccessResponse.respond("Successfully merged units") return SuccessResponse.respond("Successfully merged units")
except Exception as e: except Exception as e:
self.deps.logger.error(e) self.logger.error(e)
raise HTTPException(500, "Failed to merge units") from e raise HTTPException(500, "Failed to merge units") from e
@router.get("", response_model=IngredientUnitPagination) @router.get("", response_model=IngredientUnitPagination)

View File

@ -2,8 +2,7 @@ from fastapi import Depends, HTTPException, status
from pydantic import UUID4 from pydantic import UUID4
from mealie.core.security import hash_password, verify_password from mealie.core.security import hash_password, verify_password
from mealie.routes._base import BaseAdminController, controller from mealie.routes._base import BaseAdminController, BaseUserController, controller
from mealie.routes._base.base_controllers import BaseUserController
from mealie.routes._base.mixins import HttpRepo from mealie.routes._base.mixins import HttpRepo
from mealie.routes._base.routers import AdminAPIRouter, UserAPIRouter from mealie.routes._base.routers import AdminAPIRouter, UserAPIRouter
from mealie.routes.users._helpers import assert_user_change_allowed from mealie.routes.users._helpers import assert_user_change_allowed
@ -20,7 +19,7 @@ admin_router = AdminAPIRouter(prefix="/users", tags=["Users: Admin CRUD"])
class AdminUserController(BaseAdminController): class AdminUserController(BaseAdminController):
@property @property
def mixins(self) -> HttpRepo: def mixins(self) -> HttpRepo:
return HttpRepo[UserIn, UserOut, UserBase](self.repos.users, self.deps.logger) return HttpRepo[UserIn, UserOut, UserBase](self.repos.users, self.logger)
@admin_router.get("", response_model=UserPagination) @admin_router.get("", response_model=UserPagination)
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):

View File

@ -24,8 +24,8 @@ class RegistrationController(BasePublicController):
) )
registration_service = RegistrationService( registration_service = RegistrationService(
self.deps.logger, self.logger,
get_repositories(self.deps.session), get_repositories(self.session),
self.translator, self.translator,
) )