From 74e13682cb6e68962333c4f6cd25951a475b4621 Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Sat, 18 Dec 2021 20:52:36 -0900 Subject: [PATCH] Refactor/define repository layer (#883) * move data access layer * rename dal -> repo --- mealie/core/dependencies/dependencies.py | 6 +- mealie/core/security.py | 8 +- mealie/db/data_access_layer/__init__.py | 1 - .../data_access_layer/access_model_factory.py | 178 ------------------ mealie/db/database.py | 7 - mealie/db/init_db.py | 14 +- mealie/repos/__init__.py | 1 + mealie/repos/all_repositories.py | 7 + mealie/repos/repository_factory.py | 178 ++++++++++++++++++ .../repository_generic.py} | 6 +- .../repository_group.py} | 4 +- .../repository_meals.py} | 4 +- .../repository_recipes.py} | 4 +- .../repository_users.py} | 4 +- .../seed}/__init__.py | 0 .../seed}/init_units_foods.py | 4 +- .../seed}/init_users.py | 4 +- .../seed}/resources/foods/en-us.json | 0 .../seed}/resources/units/en-us.json | 0 mealie/routes/about/events.py | 8 +- mealie/routes/about/notifications.py | 10 +- mealie/routes/admin/admin_about.py | 4 +- mealie/routes/categories/categories.py | 14 +- mealie/routes/recipe/all_recipe_routes.py | 6 +- mealie/routes/recipe/comments.py | 4 +- mealie/routes/recipe/image_and_assets.py | 6 +- mealie/routes/recipe/recipe_crud_routes.py | 4 +- mealie/routes/recipe/recipe_export.py | 4 +- mealie/routes/recipe/shared_routes.py | 4 +- mealie/routes/shopping_lists/__init__.py | 10 +- mealie/routes/site_settings/site_settings.py | 6 +- mealie/routes/tags/tags.py | 14 +- mealie/routes/users/api_tokens.py | 6 +- mealie/routes/users/crud.py | 12 +- mealie/routes/users/favorites.py | 8 +- mealie/routes/users/images.py | 4 +- mealie/routes/users/passwords.py | 4 +- .../_base_http_service/base_http_service.py | 4 +- .../_base_http_service/crud_http_mixins.py | 16 +- mealie/services/admin/admin_group_service.py | 8 +- mealie/services/admin/admin_user_service.py | 6 +- mealie/services/backups/exports.py | 4 +- mealie/services/backups/imports.py | 4 +- mealie/services/events.py | 4 +- mealie/services/exporter/_abc_exporter.py | 4 +- mealie/services/exporter/exporter.py | 4 +- mealie/services/exporter/recipe_exporter.py | 4 +- .../group_services/cookbook_service.py | 10 +- mealie/services/group_services/group_utils.py | 4 +- .../services/group_services/meal_service.py | 8 +- .../group_services/migration_service.py | 2 +- .../group_services/reports_service.py | 6 +- .../group_services/webhook_service.py | 6 +- mealie/services/migrations/_migration_base.py | 6 +- .../migrations/utils/database_helpers.py | 8 +- .../recipe/recipe_comments_service.py | 6 +- mealie/services/recipe/recipe_food_service.py | 6 +- mealie/services/recipe/recipe_service.py | 4 +- mealie/services/recipe/recipe_tool_service.py | 6 +- mealie/services/recipe/recipe_unit_service.py | 6 +- mealie/services/scheduler/tasks/webhooks.py | 6 +- .../server_tasks/background_executory.py | 4 +- .../server_tasks/tasks_http_service.py | 12 +- .../services/shared/recipe_shared_service.py | 6 +- .../user_services/password_reset_service.py | 4 +- mealie/utils/post_webhooks.py | 4 +- tests/fixtures/fixture_database.py | 6 +- .../repository_tests/test_user_repository.py | 4 +- 68 files changed, 371 insertions(+), 369 deletions(-) delete mode 100644 mealie/db/data_access_layer/__init__.py delete mode 100644 mealie/db/data_access_layer/access_model_factory.py delete mode 100644 mealie/db/database.py create mode 100644 mealie/repos/__init__.py create mode 100644 mealie/repos/all_repositories.py create mode 100644 mealie/repos/repository_factory.py rename mealie/{db/data_access_layer/_access_model.py => repos/repository_generic.py} (98%) rename mealie/{db/data_access_layer/group_access_model.py => repos/repository_group.py} (87%) rename mealie/{db/data_access_layer/meal_access_model.py => repos/repository_meals.py} (87%) rename mealie/{db/data_access_layer/recipe_access_model.py => repos/repository_recipes.py} (95%) rename mealie/{db/data_access_layer/user_access_model.py => repos/repository_users.py} (89%) rename mealie/{db/data_initialization => repos/seed}/__init__.py (100%) rename mealie/{db/data_initialization => repos/seed}/init_units_foods.py (89%) rename mealie/{db/data_initialization => repos/seed}/init_users.py (94%) rename mealie/{db/data_initialization => repos/seed}/resources/foods/en-us.json (100%) rename mealie/{db/data_initialization => repos/seed}/resources/units/en-us.json (100%) diff --git a/mealie/core/dependencies/dependencies.py b/mealie/core/dependencies/dependencies.py index a54f0543597c..f2d4ae26bca5 100644 --- a/mealie/core/dependencies/dependencies.py +++ b/mealie/core/dependencies/dependencies.py @@ -10,8 +10,8 @@ from jose import JWTError, jwt from sqlalchemy.orm.session import Session from mealie.core.config import get_app_dirs, get_app_settings -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.schema.user import LongLiveTokenInDB, PrivateUser, TokenData oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/token") @@ -74,7 +74,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme), session=Depends( except JWTError: raise credentials_exception - db = get_database(session) + db = get_repositories(session) user = db.users.get(token_data.username, "email", any_case=True) if user is None: @@ -89,7 +89,7 @@ async def get_admin_user(current_user=Depends(get_current_user)) -> PrivateUser: def validate_long_live_token(session: Session, client_token: str, id: int) -> PrivateUser: - db = get_database(session) + db = get_repositories(session) tokens: list[LongLiveTokenInDB] = db.api_tokens.get(id, "user_id", limit=9999) diff --git a/mealie/core/security.py b/mealie/core/security.py index 426b5c85ea15..2b61dd383e09 100644 --- a/mealie/core/security.py +++ b/mealie/core/security.py @@ -8,8 +8,8 @@ from jose import jwt from passlib.context import CryptContext from mealie.core.config import get_app_settings -from mealie.db.data_access_layer.access_model_factory import Database -from mealie.db.database import get_database +from mealie.repos.all_repositories import get_repositories +from mealie.repos.repository_factory import AllRepositories from mealie.schema.user import PrivateUser pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @@ -38,7 +38,7 @@ def create_recipe_slug_token(file_path: str) -> str: return create_access_token(token_data, expires_delta=timedelta(minutes=30)) -def user_from_ldap(db: Database, session, username: str, password: str) -> PrivateUser: +def user_from_ldap(db: AllRepositories, session, username: str, password: str) -> PrivateUser: """Given a username and password, tries to authenticate by BINDing to an LDAP server @@ -81,7 +81,7 @@ def user_from_ldap(db: Database, session, username: str, password: str) -> Priva def authenticate_user(session, email: str, password: str) -> PrivateUser | bool: settings = get_app_settings() - db = get_database(session) + db = get_repositories(session) user: PrivateUser = db.users.get(email, "email", any_case=True) if not user: diff --git a/mealie/db/data_access_layer/__init__.py b/mealie/db/data_access_layer/__init__.py deleted file mode 100644 index 1ece7c14c61d..000000000000 --- a/mealie/db/data_access_layer/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .access_model_factory import Database diff --git a/mealie/db/data_access_layer/access_model_factory.py b/mealie/db/data_access_layer/access_model_factory.py deleted file mode 100644 index 4f8887e437b2..000000000000 --- a/mealie/db/data_access_layer/access_model_factory.py +++ /dev/null @@ -1,178 +0,0 @@ -from functools import cached_property - -from sqlalchemy.orm import Session - -from mealie.db.models.event import Event, EventNotification -from mealie.db.models.group import Group, GroupMealPlan, ReportEntryModel, ReportModel -from mealie.db.models.group.cookbook import CookBook -from mealie.db.models.group.exports import GroupDataExportsModel -from mealie.db.models.group.invite_tokens import GroupInviteToken -from mealie.db.models.group.preferences import GroupPreferencesModel -from mealie.db.models.group.webhooks import GroupWebhooksModel -from mealie.db.models.recipe.category import Category -from mealie.db.models.recipe.comment import RecipeComment -from mealie.db.models.recipe.ingredient import IngredientFoodModel, IngredientUnitModel -from mealie.db.models.recipe.recipe import RecipeModel -from mealie.db.models.recipe.shared import RecipeShareTokenModel -from mealie.db.models.recipe.tag import Tag -from mealie.db.models.recipe.tool import Tool -from mealie.db.models.server.task import ServerTaskModel -from mealie.db.models.sign_up import SignUp -from mealie.db.models.users import LongLiveToken, User -from mealie.db.models.users.password_reset import PasswordResetModel -from mealie.schema.cookbook.cookbook import ReadCookBook -from mealie.schema.events import Event as EventSchema -from mealie.schema.events import EventNotificationIn -from mealie.schema.group.group_exports import GroupDataExport -from mealie.schema.group.group_preferences import ReadGroupPreferences -from mealie.schema.group.invite_token import ReadInviteToken -from mealie.schema.group.webhook import ReadWebhook -from mealie.schema.meal_plan.new_meal import ReadPlanEntry -from mealie.schema.recipe import Recipe, RecipeCategoryResponse, RecipeCommentOut, RecipeTagResponse, RecipeTool -from mealie.schema.recipe.recipe_ingredient import IngredientFood, IngredientUnit -from mealie.schema.recipe.recipe_share_token import RecipeShareToken -from mealie.schema.reports.reports import ReportEntryOut, ReportOut -from mealie.schema.server import ServerTask -from mealie.schema.user import GroupInDB, LongLiveTokenInDB, PrivateUser, SignUpOut -from mealie.schema.user.user_passwords import PrivatePasswordResetToken - -from ._access_model import AccessModel -from .group_access_model import GroupDataAccessModel -from .meal_access_model import MealDataAccessModel -from .recipe_access_model import RecipeDataAccessModel -from .user_access_model import UserDataAccessModel - -pk_id = "id" -pk_slug = "slug" -pk_token = "token" -pk_group_id = "group_id" - - -class CategoryDataAccessModel(AccessModel): - def get_empty(self): - return self.session.query(Category).filter(~Category.recipes.any()).all() - - -class TagsDataAccessModel(AccessModel): - def get_empty(self): - return self.session.query(Tag).filter(~Tag.recipes.any()).all() - - -class Database: - def __init__(self, session: Session) -> None: - """ - `DatabaseAccessLayer` class is the data access layer for all database actions within - Mealie. Database uses composition from classes derived from AccessModel. These - can be substantiated from the AccessModel class or through inheritance when - additional methods are required. - """ - - self.session = session - - # ================================================================ - # Recipe Items - - @cached_property - def recipes(self) -> RecipeDataAccessModel: - return RecipeDataAccessModel(self.session, pk_slug, RecipeModel, Recipe) - - @cached_property - def ingredient_foods(self) -> AccessModel[IngredientFood, IngredientFoodModel]: - return AccessModel(self.session, pk_id, IngredientFoodModel, IngredientFood) - - @cached_property - def ingredient_units(self) -> AccessModel[IngredientUnit, IngredientUnitModel]: - return AccessModel(self.session, pk_id, IngredientUnitModel, IngredientUnit) - - @cached_property - def tools(self) -> AccessModel[RecipeTool, Tool]: - return AccessModel(self.session, pk_id, Tool, RecipeTool) - - @cached_property - def comments(self) -> AccessModel[RecipeCommentOut, RecipeComment]: - return AccessModel(self.session, pk_id, RecipeComment, RecipeCommentOut) - - @cached_property - def categories(self) -> CategoryDataAccessModel: - return CategoryDataAccessModel(self.session, pk_slug, Category, RecipeCategoryResponse) - - @cached_property - def tags(self) -> TagsDataAccessModel: - return TagsDataAccessModel(self.session, pk_slug, Tag, RecipeTagResponse) - - @cached_property - def recipe_share_tokens(self) -> AccessModel[RecipeShareToken, RecipeShareTokenModel]: - return AccessModel(self.session, pk_id, RecipeShareTokenModel, RecipeShareToken) - - # ================================================================ - # Site Items - - @cached_property - def sign_up(self) -> AccessModel[SignUpOut, SignUp]: - return AccessModel(self.session, pk_id, SignUp, SignUpOut) - - @cached_property - def event_notifications(self) -> AccessModel[EventNotificationIn, EventNotification]: - return AccessModel(self.session, pk_id, EventNotification, EventNotificationIn) - - @cached_property - def events(self) -> AccessModel[EventSchema, Event]: - return AccessModel(self.session, pk_id, Event, EventSchema) - - # ================================================================ - # User Items - - @cached_property - def users(self) -> UserDataAccessModel: - return UserDataAccessModel(self.session, pk_id, User, PrivateUser) - - @cached_property - def api_tokens(self) -> AccessModel[LongLiveTokenInDB, LongLiveToken]: - return AccessModel(self.session, pk_id, LongLiveToken, LongLiveTokenInDB) - - @cached_property - def tokens_pw_reset(self) -> AccessModel[PrivatePasswordResetToken, PasswordResetModel]: - return AccessModel(self.session, pk_token, PasswordResetModel, PrivatePasswordResetToken) - - # ================================================================ - # Group Items - - @cached_property - def server_tasks(self) -> AccessModel[ServerTask, ServerTaskModel]: - return AccessModel(self.session, pk_id, ServerTaskModel, ServerTask) - - @cached_property - def groups(self) -> GroupDataAccessModel: - return GroupDataAccessModel(self.session, pk_id, Group, GroupInDB) - - @cached_property - def group_invite_tokens(self) -> AccessModel[ReadInviteToken, GroupInviteToken]: - return AccessModel(self.session, pk_token, GroupInviteToken, ReadInviteToken) - - @cached_property - def group_preferences(self) -> AccessModel[ReadGroupPreferences, GroupPreferencesModel]: - return AccessModel(self.session, pk_group_id, GroupPreferencesModel, ReadGroupPreferences) - - @cached_property - def group_exports(self) -> AccessModel[GroupDataExport, GroupDataExportsModel]: - return AccessModel(self.session, pk_id, GroupDataExportsModel, GroupDataExport) - - @cached_property - def meals(self) -> MealDataAccessModel: - return MealDataAccessModel(self.session, pk_id, GroupMealPlan, ReadPlanEntry) - - @cached_property - def cookbooks(self) -> AccessModel[ReadCookBook, CookBook]: - return AccessModel(self.session, pk_id, CookBook, ReadCookBook) - - @cached_property - def webhooks(self) -> AccessModel[ReadWebhook, GroupWebhooksModel]: - return AccessModel(self.session, pk_id, GroupWebhooksModel, ReadWebhook) - - @cached_property - def group_reports(self) -> AccessModel[ReportOut, ReportModel]: - return AccessModel(self.session, pk_id, ReportModel, ReportOut) - - @cached_property - def group_report_entries(self) -> AccessModel[ReportEntryOut, ReportEntryModel]: - return AccessModel(self.session, pk_id, ReportEntryModel, ReportEntryOut) diff --git a/mealie/db/database.py b/mealie/db/database.py deleted file mode 100644 index 730900e0d928..000000000000 --- a/mealie/db/database.py +++ /dev/null @@ -1,7 +0,0 @@ -from sqlalchemy.orm import Session - -from .data_access_layer.access_model_factory import Database - - -def get_database(session: Session): - return Database(session) diff --git a/mealie/db/init_db.py b/mealie/db/init_db.py index 8332d99a75ad..30bfa854ef45 100644 --- a/mealie/db/init_db.py +++ b/mealie/db/init_db.py @@ -1,11 +1,11 @@ from mealie.core import root_logger from mealie.core.config import get_app_settings -from mealie.db.data_access_layer.access_model_factory import Database -from mealie.db.data_initialization.init_units_foods import default_recipe_unit_init -from mealie.db.data_initialization.init_users import default_user_init -from mealie.db.database import get_database from mealie.db.db_setup import create_session, engine from mealie.db.models._model_base import SqlAlchemyBase +from mealie.repos.all_repositories import get_repositories +from mealie.repos.repository_factory import AllRepositories +from mealie.repos.seed.init_units_foods import default_recipe_unit_init +from mealie.repos.seed.init_users import default_user_init from mealie.schema.user.user import GroupBase from mealie.services.events import create_general_event from mealie.services.group_services.group_utils import create_new_group @@ -21,13 +21,13 @@ def create_all_models(): SqlAlchemyBase.metadata.create_all(engine) -def init_db(db: Database) -> None: +def init_db(db: AllRepositories) -> None: default_group_init(db) default_user_init(db) default_recipe_unit_init(db) -def default_group_init(db: Database): +def default_group_init(db: AllRepositories): logger.info("Generating Default Group") create_new_group(db, GroupBase(name=settings.DEFAULT_GROUP)) @@ -36,7 +36,7 @@ def main(): create_all_models() session = create_session() - db = get_database(session) + db = get_repositories(session) try: init_user = db.users.get_all() diff --git a/mealie/repos/__init__.py b/mealie/repos/__init__.py new file mode 100644 index 000000000000..6bcf533607a0 --- /dev/null +++ b/mealie/repos/__init__.py @@ -0,0 +1 @@ +from .repository_factory import AllRepositories diff --git a/mealie/repos/all_repositories.py b/mealie/repos/all_repositories.py new file mode 100644 index 000000000000..7c14d53341e6 --- /dev/null +++ b/mealie/repos/all_repositories.py @@ -0,0 +1,7 @@ +from sqlalchemy.orm import Session + +from .repository_factory import AllRepositories + + +def get_repositories(session: Session): + return AllRepositories(session) diff --git a/mealie/repos/repository_factory.py b/mealie/repos/repository_factory.py new file mode 100644 index 000000000000..a506e1c90cf7 --- /dev/null +++ b/mealie/repos/repository_factory.py @@ -0,0 +1,178 @@ +from functools import cached_property + +from sqlalchemy.orm import Session + +from mealie.db.models.event import Event, EventNotification +from mealie.db.models.group import Group, GroupMealPlan, ReportEntryModel, ReportModel +from mealie.db.models.group.cookbook import CookBook +from mealie.db.models.group.exports import GroupDataExportsModel +from mealie.db.models.group.invite_tokens import GroupInviteToken +from mealie.db.models.group.preferences import GroupPreferencesModel +from mealie.db.models.group.webhooks import GroupWebhooksModel +from mealie.db.models.recipe.category import Category +from mealie.db.models.recipe.comment import RecipeComment +from mealie.db.models.recipe.ingredient import IngredientFoodModel, IngredientUnitModel +from mealie.db.models.recipe.recipe import RecipeModel +from mealie.db.models.recipe.shared import RecipeShareTokenModel +from mealie.db.models.recipe.tag import Tag +from mealie.db.models.recipe.tool import Tool +from mealie.db.models.server.task import ServerTaskModel +from mealie.db.models.sign_up import SignUp +from mealie.db.models.users import LongLiveToken, User +from mealie.db.models.users.password_reset import PasswordResetModel +from mealie.schema.cookbook.cookbook import ReadCookBook +from mealie.schema.events import Event as EventSchema +from mealie.schema.events import EventNotificationIn +from mealie.schema.group.group_exports import GroupDataExport +from mealie.schema.group.group_preferences import ReadGroupPreferences +from mealie.schema.group.invite_token import ReadInviteToken +from mealie.schema.group.webhook import ReadWebhook +from mealie.schema.meal_plan.new_meal import ReadPlanEntry +from mealie.schema.recipe import Recipe, RecipeCategoryResponse, RecipeCommentOut, RecipeTagResponse, RecipeTool +from mealie.schema.recipe.recipe_ingredient import IngredientFood, IngredientUnit +from mealie.schema.recipe.recipe_share_token import RecipeShareToken +from mealie.schema.reports.reports import ReportEntryOut, ReportOut +from mealie.schema.server import ServerTask +from mealie.schema.user import GroupInDB, LongLiveTokenInDB, PrivateUser, SignUpOut +from mealie.schema.user.user_passwords import PrivatePasswordResetToken + +from .repository_generic import RepositoryGeneric +from .repository_group import RepositoryGroup +from .repository_meals import RepositoryMeals +from .repository_recipes import RepositoryRecipes +from .repository_users import RepositoryUsers + +pk_id = "id" +pk_slug = "slug" +pk_token = "token" +pk_group_id = "group_id" + + +class RepositoryCategories(RepositoryGeneric): + def get_empty(self): + return self.session.query(Category).filter(~Category.recipes.any()).all() + + +class RepositoryTags(RepositoryGeneric): + def get_empty(self): + return self.session.query(Tag).filter(~Tag.recipes.any()).all() + + +class AllRepositories: + def __init__(self, session: Session) -> None: + """ + `AllRepositories` class is the data access layer for all database actions within + Mealie. Database uses composition from classes derived from AccessModel. These + can be substantiated from the AccessModel class or through inheritance when + additional methods are required. + """ + + self.session = session + + # ================================================================ + # Recipe Items + + @cached_property + def recipes(self) -> RepositoryRecipes: + return RepositoryRecipes(self.session, pk_slug, RecipeModel, Recipe) + + @cached_property + def ingredient_foods(self) -> RepositoryGeneric[IngredientFood, IngredientFoodModel]: + return RepositoryGeneric(self.session, pk_id, IngredientFoodModel, IngredientFood) + + @cached_property + def ingredient_units(self) -> RepositoryGeneric[IngredientUnit, IngredientUnitModel]: + return RepositoryGeneric(self.session, pk_id, IngredientUnitModel, IngredientUnit) + + @cached_property + def tools(self) -> RepositoryGeneric[RecipeTool, Tool]: + return RepositoryGeneric(self.session, pk_id, Tool, RecipeTool) + + @cached_property + def comments(self) -> RepositoryGeneric[RecipeCommentOut, RecipeComment]: + return RepositoryGeneric(self.session, pk_id, RecipeComment, RecipeCommentOut) + + @cached_property + def categories(self) -> RepositoryCategories: + return RepositoryCategories(self.session, pk_slug, Category, RecipeCategoryResponse) + + @cached_property + def tags(self) -> RepositoryTags: + return RepositoryTags(self.session, pk_slug, Tag, RecipeTagResponse) + + @cached_property + def recipe_share_tokens(self) -> RepositoryGeneric[RecipeShareToken, RecipeShareTokenModel]: + return RepositoryGeneric(self.session, pk_id, RecipeShareTokenModel, RecipeShareToken) + + # ================================================================ + # Site Items + + @cached_property + def sign_up(self) -> RepositoryGeneric[SignUpOut, SignUp]: + return RepositoryGeneric(self.session, pk_id, SignUp, SignUpOut) + + @cached_property + def event_notifications(self) -> RepositoryGeneric[EventNotificationIn, EventNotification]: + return RepositoryGeneric(self.session, pk_id, EventNotification, EventNotificationIn) + + @cached_property + def events(self) -> RepositoryGeneric[EventSchema, Event]: + return RepositoryGeneric(self.session, pk_id, Event, EventSchema) + + # ================================================================ + # User Items + + @cached_property + def users(self) -> RepositoryUsers: + return RepositoryUsers(self.session, pk_id, User, PrivateUser) + + @cached_property + def api_tokens(self) -> RepositoryGeneric[LongLiveTokenInDB, LongLiveToken]: + return RepositoryGeneric(self.session, pk_id, LongLiveToken, LongLiveTokenInDB) + + @cached_property + def tokens_pw_reset(self) -> RepositoryGeneric[PrivatePasswordResetToken, PasswordResetModel]: + return RepositoryGeneric(self.session, pk_token, PasswordResetModel, PrivatePasswordResetToken) + + # ================================================================ + # Group Items + + @cached_property + def server_tasks(self) -> RepositoryGeneric[ServerTask, ServerTaskModel]: + return RepositoryGeneric(self.session, pk_id, ServerTaskModel, ServerTask) + + @cached_property + def groups(self) -> RepositoryGroup: + return RepositoryGroup(self.session, pk_id, Group, GroupInDB) + + @cached_property + def group_invite_tokens(self) -> RepositoryGeneric[ReadInviteToken, GroupInviteToken]: + return RepositoryGeneric(self.session, pk_token, GroupInviteToken, ReadInviteToken) + + @cached_property + def group_preferences(self) -> RepositoryGeneric[ReadGroupPreferences, GroupPreferencesModel]: + return RepositoryGeneric(self.session, pk_group_id, GroupPreferencesModel, ReadGroupPreferences) + + @cached_property + def group_exports(self) -> RepositoryGeneric[GroupDataExport, GroupDataExportsModel]: + return RepositoryGeneric(self.session, pk_id, GroupDataExportsModel, GroupDataExport) + + @cached_property + def meals(self) -> RepositoryMeals: + return RepositoryMeals(self.session, pk_id, GroupMealPlan, ReadPlanEntry) + + @cached_property + def cookbooks(self) -> RepositoryGeneric[ReadCookBook, CookBook]: + return RepositoryGeneric(self.session, pk_id, CookBook, ReadCookBook) + + @cached_property + def webhooks(self) -> RepositoryGeneric[ReadWebhook, GroupWebhooksModel]: + return RepositoryGeneric(self.session, pk_id, GroupWebhooksModel, ReadWebhook) + + @cached_property + def group_reports(self) -> RepositoryGeneric[ReportOut, ReportModel]: + return RepositoryGeneric(self.session, pk_id, ReportModel, ReportOut) + + @cached_property + def group_report_entries(self) -> RepositoryGeneric[ReportEntryOut, ReportEntryModel]: + return RepositoryGeneric(self.session, pk_id, ReportEntryModel, ReportEntryOut) diff --git a/mealie/db/data_access_layer/_access_model.py b/mealie/repos/repository_generic.py similarity index 98% rename from mealie/db/data_access_layer/_access_model.py rename to mealie/repos/repository_generic.py index 99858e32efba..7456949f80a2 100644 --- a/mealie/db/data_access_layer/_access_model.py +++ b/mealie/repos/repository_generic.py @@ -16,7 +16,7 @@ T = TypeVar("T") D = TypeVar("D") -class AccessModel(Generic[T, D]): +class RepositoryGeneric(Generic[T, D]): """A Generic BaseAccess Model method to perform common operations on the database Args: @@ -40,12 +40,12 @@ class AccessModel(Generic[T, D]): def subscribe(self, func: Callable) -> None: self.observers.append(func) - def by_user(self, user_id: UUID4) -> AccessModel: + def by_user(self, user_id: UUID4) -> RepositoryGeneric: self.limit_by_user = True self.user_id = user_id return self - def by_group(self, group_id: UUID) -> AccessModel: + def by_group(self, group_id: UUID) -> RepositoryGeneric: self.limit_by_group = True self.group_id = group_id return self diff --git a/mealie/db/data_access_layer/group_access_model.py b/mealie/repos/repository_group.py similarity index 87% rename from mealie/db/data_access_layer/group_access_model.py rename to mealie/repos/repository_group.py index 56f97fd49dcb..37115df77e49 100644 --- a/mealie/db/data_access_layer/group_access_model.py +++ b/mealie/repos/repository_group.py @@ -4,10 +4,10 @@ from mealie.db.models.group import Group from mealie.schema.meal_plan.meal import MealPlanOut from mealie.schema.user.user import GroupInDB -from ._access_model import AccessModel +from .repository_generic import RepositoryGeneric -class GroupDataAccessModel(AccessModel[GroupInDB, Group]): +class RepositoryGroup(RepositoryGeneric[GroupInDB, Group]): def get_meals(self, session: Session, match_value: str, match_key: str = "name") -> list[MealPlanOut]: """A Helper function to get the group from the database and return a sorted list of diff --git a/mealie/db/data_access_layer/meal_access_model.py b/mealie/repos/repository_meals.py similarity index 87% rename from mealie/db/data_access_layer/meal_access_model.py rename to mealie/repos/repository_meals.py index 8ac4cc8633ef..27bff973c461 100644 --- a/mealie/db/data_access_layer/meal_access_model.py +++ b/mealie/repos/repository_meals.py @@ -4,10 +4,10 @@ from uuid import UUID from mealie.db.models.group import GroupMealPlan from mealie.schema.meal_plan.new_meal import ReadPlanEntry -from ._access_model import AccessModel +from .repository_generic import RepositoryGeneric -class MealDataAccessModel(AccessModel[ReadPlanEntry, GroupMealPlan]): +class RepositoryMeals(RepositoryGeneric[ReadPlanEntry, GroupMealPlan]): def get_slice(self, start: date, end: date, group_id: UUID) -> list[ReadPlanEntry]: start = start.strftime("%Y-%m-%d") end = end.strftime("%Y-%m-%d") diff --git a/mealie/db/data_access_layer/recipe_access_model.py b/mealie/repos/repository_recipes.py similarity index 95% rename from mealie/db/data_access_layer/recipe_access_model.py rename to mealie/repos/repository_recipes.py index 9a5f7f6d4e45..3fa54cd19895 100644 --- a/mealie/db/data_access_layer/recipe_access_model.py +++ b/mealie/repos/repository_recipes.py @@ -8,10 +8,10 @@ from mealie.db.models.recipe.recipe import RecipeModel from mealie.db.models.recipe.settings import RecipeSettings from mealie.schema.recipe import Recipe -from ._access_model import AccessModel +from .repository_generic import RepositoryGeneric -class RecipeDataAccessModel(AccessModel[Recipe, RecipeModel]): +class RepositoryRecipes(RepositoryGeneric[Recipe, RecipeModel]): def get_all_public(self, limit: int = None, order_by: str = None, start=0, override_schema=None): eff_schema = override_schema or self.schema diff --git a/mealie/db/data_access_layer/user_access_model.py b/mealie/repos/repository_users.py similarity index 89% rename from mealie/db/data_access_layer/user_access_model.py rename to mealie/repos/repository_users.py index 7b3b6fc23fe1..78eb1b079a18 100644 --- a/mealie/db/data_access_layer/user_access_model.py +++ b/mealie/repos/repository_users.py @@ -4,10 +4,10 @@ import shutil from mealie.assets import users as users_assets from mealie.schema.user.user import PrivateUser, User -from ._access_model import AccessModel +from .repository_generic import RepositoryGeneric -class UserDataAccessModel(AccessModel[PrivateUser, User]): +class RepositoryUsers(RepositoryGeneric[PrivateUser, User]): def update_password(self, id, password: str): entry = self._query_one(match_value=id) entry.update_password(password) diff --git a/mealie/db/data_initialization/__init__.py b/mealie/repos/seed/__init__.py similarity index 100% rename from mealie/db/data_initialization/__init__.py rename to mealie/repos/seed/__init__.py diff --git a/mealie/db/data_initialization/init_units_foods.py b/mealie/repos/seed/init_units_foods.py similarity index 89% rename from mealie/db/data_initialization/init_units_foods.py rename to mealie/repos/seed/init_units_foods.py index 78b67ae54a98..b42303101b34 100644 --- a/mealie/db/data_initialization/init_units_foods.py +++ b/mealie/repos/seed/init_units_foods.py @@ -2,7 +2,7 @@ import json from pathlib import Path from mealie.core.root_logger import get_logger -from mealie.db.data_access_layer.access_model_factory import Database +from mealie.repos.repository_factory import AllRepositories from mealie.schema.recipe import CreateIngredientFood, CreateIngredientUnit CWD = Path(__file__).parent @@ -21,7 +21,7 @@ def get_default_units() -> dict[str, str]: return units -def default_recipe_unit_init(db: Database) -> None: +def default_recipe_unit_init(db: AllRepositories) -> None: for unit in get_default_units().values(): try: db.ingredient_units.create( diff --git a/mealie/db/data_initialization/init_users.py b/mealie/repos/seed/init_users.py similarity index 94% rename from mealie/db/data_initialization/init_users.py rename to mealie/repos/seed/init_users.py index dd8a2cd95d1e..ad347a0d8639 100644 --- a/mealie/db/data_initialization/init_users.py +++ b/mealie/repos/seed/init_users.py @@ -1,7 +1,7 @@ from mealie.core import root_logger from mealie.core.config import get_app_settings from mealie.core.security import hash_password -from mealie.db.data_access_layer.access_model_factory import Database +from mealie.repos.repository_factory import AllRepositories logger = root_logger.get_logger("init_users") settings = get_app_settings() @@ -44,7 +44,7 @@ def dev_users() -> list[dict]: ] -def default_user_init(db: Database): +def default_user_init(db: AllRepositories): default_user = { "full_name": "Change Me", "username": "admin", diff --git a/mealie/db/data_initialization/resources/foods/en-us.json b/mealie/repos/seed/resources/foods/en-us.json similarity index 100% rename from mealie/db/data_initialization/resources/foods/en-us.json rename to mealie/repos/seed/resources/foods/en-us.json diff --git a/mealie/db/data_initialization/resources/units/en-us.json b/mealie/repos/seed/resources/units/en-us.json similarity index 100% rename from mealie/db/data_initialization/resources/units/en-us.json rename to mealie/repos/seed/resources/units/en-us.json diff --git a/mealie/routes/about/events.py b/mealie/routes/about/events.py index f1752f3bf85b..27d7109aae8c 100644 --- a/mealie/routes/about/events.py +++ b/mealie/routes/about/events.py @@ -2,8 +2,8 @@ from fastapi import Depends from sqlalchemy.orm.session import Session from mealie.core.root_logger import get_logger -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import AdminAPIRouter from mealie.schema.events import EventsOut @@ -15,7 +15,7 @@ logger = get_logger() @router.get("", response_model=EventsOut) async def get_events(session: Session = Depends(generate_session)): """Get event from the Database""" - db = get_database(session) + db = get_repositories(session) return EventsOut(total=db.events.count_all(), events=db.events.get_all(order_by="time_stamp")) @@ -23,7 +23,7 @@ async def get_events(session: Session = Depends(generate_session)): @router.delete("") async def delete_events(session: Session = Depends(generate_session)): """Get event from the Database""" - db = get_database(session) + db = get_repositories(session) db.events.delete_all() return {"message": "All events deleted"} @@ -31,5 +31,5 @@ async def delete_events(session: Session = Depends(generate_session)): @router.delete("/{id}") async def delete_event(id: int, session: Session = Depends(generate_session)): """Delete event from the Database""" - db = get_database(session) + db = get_repositories(session) return db.events.delete(id) diff --git a/mealie/routes/about/notifications.py b/mealie/routes/about/notifications.py index 6951b761d12d..7df5257f4917 100644 --- a/mealie/routes/about/notifications.py +++ b/mealie/routes/about/notifications.py @@ -4,8 +4,8 @@ from fastapi import Depends, status from sqlalchemy.orm.session import Session from mealie.core.root_logger import get_logger -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import AdminAPIRouter from mealie.schema.events import EventNotificationIn, EventNotificationOut, TestEvent from mealie.services.events import test_notification @@ -21,7 +21,7 @@ async def create_event_notification( session: Session = Depends(generate_session), ): """Create event_notification in the Database""" - db = get_database(session) + db = get_repositories(session) return db.event_notifications.create(event_data) @@ -32,7 +32,7 @@ async def test_notification_route( session: Session = Depends(generate_session), ): """Create event_notification in the Database""" - db = get_database(session) + db = get_repositories(session) if test_data.id: event_obj: EventNotificationIn = db.event_notifications.get(test_data.id) @@ -48,7 +48,7 @@ async def test_notification_route( @router.get("/notifications", response_model=list[EventNotificationOut]) async def get_all_event_notification(session: Session = Depends(generate_session)): """Get all event_notification from the Database""" - db = get_database(session) + db = get_repositories(session) return db.event_notifications.get_all(override_schema=EventNotificationOut) @@ -63,5 +63,5 @@ async def update_event_notification(id: int, session: Session = Depends(generate async def delete_event_notification(id: int, session: Session = Depends(generate_session)): """Delete event_notification from the Database""" # Delete Item - db = get_database(session) + db = get_repositories(session) return db.event_notifications.delete(id) diff --git a/mealie/routes/admin/admin_about.py b/mealie/routes/admin/admin_about.py index 46bc2aff84b6..245f58bffa0a 100644 --- a/mealie/routes/admin/admin_about.py +++ b/mealie/routes/admin/admin_about.py @@ -4,8 +4,8 @@ from sqlalchemy.orm.session import Session from mealie.core.config import get_app_settings from mealie.core.release_checker import get_latest_version from mealie.core.settings.static import APP_VERSION -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.schema.admin.about import AdminAboutInfo, AppStatistics, CheckAppConfig router = APIRouter(prefix="/about") @@ -31,7 +31,7 @@ async def get_app_info(): @router.get("/statistics", response_model=AppStatistics) async def get_app_statistics(session: Session = Depends(generate_session)): - db = get_database(session) + db = get_repositories(session) return AppStatistics( total_recipes=db.recipes.count_all(), uncategorized_recipes=db.recipes.count_uncategorized(), diff --git a/mealie/routes/categories/categories.py b/mealie/routes/categories/categories.py index e1a807e04487..8c581edb1852 100644 --- a/mealie/routes/categories/categories.py +++ b/mealie/routes/categories/categories.py @@ -3,8 +3,8 @@ from sqlalchemy.orm.session import Session from mealie.core.dependencies import is_logged_in from mealie.core.root_logger import get_logger -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import AdminAPIRouter, UserAPIRouter from mealie.schema.recipe import CategoryIn, RecipeCategoryResponse @@ -17,14 +17,14 @@ logger = get_logger() @public_router.get("") async def get_all_recipe_categories(session: Session = Depends(generate_session)): """Returns a list of available categories in the database""" - db = get_database(session) + db = get_repositories(session) return db.categories.get_all_limit_columns(fields=["slug", "name"]) @public_router.get("/empty") def get_empty_categories(session: Session = Depends(generate_session)): """Returns a list of categories that do not contain any recipes""" - db = get_database(session) + db = get_repositories(session) return db.categories.get_empty() @@ -33,7 +33,7 @@ def get_all_recipes_by_category( category: str, session: Session = Depends(generate_session), is_user: bool = Depends(is_logged_in) ): """Returns a list of recipes associated with the provided category.""" - db = get_database(session) + db = get_repositories(session) category_obj = db.categories.get(category) category_obj = RecipeCategoryResponse.from_orm(category_obj) @@ -47,7 +47,7 @@ def get_all_recipes_by_category( @user_router.post("") async def create_recipe_category(category: CategoryIn, session: Session = Depends(generate_session)): """Creates a Category in the database""" - db = get_database(session) + db = get_repositories(session) try: return db.categories.create(category.dict()) @@ -58,7 +58,7 @@ async def create_recipe_category(category: CategoryIn, session: Session = Depend @admin_router.put("/{category}", response_model=RecipeCategoryResponse) async def update_recipe_category(category: str, new_category: CategoryIn, session: Session = Depends(generate_session)): """Updates an existing Tag in the database""" - db = get_database(session) + db = get_repositories(session) try: return db.categories.update(category, new_category.dict()) @@ -74,7 +74,7 @@ async def delete_recipe_category(category: str, session: Session = Depends(gener category does not impact a recipe. The category will be removed from any recipes that contain it """ - db = get_database(session) + db = get_repositories(session) try: db.categories.delete(category) diff --git a/mealie/routes/recipe/all_recipe_routes.py b/mealie/routes/recipe/all_recipe_routes.py index 4a7b2e9e98e0..d910f548ef29 100644 --- a/mealie/routes/recipe/all_recipe_routes.py +++ b/mealie/routes/recipe/all_recipe_routes.py @@ -1,8 +1,8 @@ from fastapi import APIRouter, Depends from sqlalchemy.orm.session import Session -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.schema.recipe import RecipeSummary router = APIRouter() @@ -10,11 +10,11 @@ router = APIRouter() @router.get("/summary/untagged", response_model=list[RecipeSummary]) async def get_untagged_recipes(count: bool = False, session: Session = Depends(generate_session)): - db = get_database(session) + db = get_repositories(session) return db.recipes.count_untagged(count=count, override_schema=RecipeSummary) @router.get("/summary/uncategorized", response_model=list[RecipeSummary]) async def get_uncategorized_recipes(count: bool = False, session: Session = Depends(generate_session)): - db = get_database(session) + db = get_repositories(session) return db.recipes.count_uncategorized(count=count, override_schema=RecipeSummary) diff --git a/mealie/routes/recipe/comments.py b/mealie/routes/recipe/comments.py index 4f05998fdb8a..d32cc7cd3e05 100644 --- a/mealie/routes/recipe/comments.py +++ b/mealie/routes/recipe/comments.py @@ -1,8 +1,8 @@ from fastapi import Depends from sqlalchemy.orm.session import Session -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.schema.recipe.recipe_comments import RecipeCommentOut @@ -15,6 +15,6 @@ async def get_recipe_comments( session: Session = Depends(generate_session), ): """Get all comments for a recipe""" - db = get_database(session) + db = get_repositories(session) recipe = db.recipes.get_one(slug) return db.comments.multi_query({"recipe_id": recipe.id}) diff --git a/mealie/routes/recipe/image_and_assets.py b/mealie/routes/recipe/image_and_assets.py index 038d50b27c7e..9a03fc380dcb 100644 --- a/mealie/routes/recipe/image_and_assets.py +++ b/mealie/routes/recipe/image_and_assets.py @@ -5,8 +5,8 @@ from fastapi.datastructures import UploadFile from slugify import slugify from sqlalchemy.orm.session import Session -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.schema.recipe import CreateRecipeByUrl, Recipe, RecipeAsset from mealie.services.image.image import scrape_image, write_image @@ -29,7 +29,7 @@ def update_recipe_image( session: Session = Depends(generate_session), ): """Removes an existing image and replaces it with the incoming file.""" - db = get_database(session) + db = get_repositories(session) write_image(slug, image, extension) new_version = db.recipes.update_image(slug, extension) @@ -56,7 +56,7 @@ def upload_recipe_asset( if not dest.is_file(): raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR) - db = get_database(session) + db = get_repositories(session) recipe: Recipe = db.recipes.get(slug) recipe.assets.append(asset_in) diff --git a/mealie/routes/recipe/recipe_crud_routes.py b/mealie/routes/recipe/recipe_crud_routes.py index e820084d2dcb..f351654cf889 100644 --- a/mealie/routes/recipe/recipe_crud_routes.py +++ b/mealie/routes/recipe/recipe_crud_routes.py @@ -6,7 +6,7 @@ from sqlalchemy.orm.session import Session from mealie.core.dependencies import temporary_zip_path from mealie.core.root_logger import get_logger -from mealie.db.database import get_database +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.schema.recipe import CreateRecipeByUrl, Recipe from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipeSummary @@ -53,7 +53,7 @@ def parse_recipe_url_bulk( """Takes in a URL and attempts to scrape data and load it into the database""" def bulk_import_func(task_id: int, session: Session) -> None: - database = get_database(session) + database = get_repositories(session) task = database.server_tasks.get_one(task_id) task.append_log("test task has started") diff --git a/mealie/routes/recipe/recipe_export.py b/mealie/routes/recipe/recipe_export.py index 9b05210a710c..77bd18c12fe4 100644 --- a/mealie/routes/recipe/recipe_export.py +++ b/mealie/routes/recipe/recipe_export.py @@ -9,8 +9,8 @@ from mealie.core.dependencies import temporary_zip_path from mealie.core.dependencies.dependencies import temporary_dir, validate_recipe_token from mealie.core.root_logger import get_logger from mealie.core.security import create_recipe_slug_token -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.schema.recipe import Recipe, RecipeImageTypes from mealie.services.recipe.recipe_service import RecipeService @@ -68,7 +68,7 @@ async def get_recipe_as_zip( if slug != slug: raise HTTPException(status_code=400, detail="Invalid Slug") - db = get_database(session) + db = get_repositories(session) recipe: Recipe = db.recipes.get(slug) image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value) with ZipFile(temp_path, "w") as myzip: diff --git a/mealie/routes/recipe/shared_routes.py b/mealie/routes/recipe/shared_routes.py index b92cb04b067b..0b5435f53929 100644 --- a/mealie/routes/recipe/shared_routes.py +++ b/mealie/routes/recipe/shared_routes.py @@ -2,8 +2,8 @@ from fastapi import APIRouter, Depends from pydantic import UUID4 from sqlalchemy.orm.session import Session -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.schema.recipe import Recipe router = APIRouter() @@ -11,7 +11,7 @@ router = APIRouter() @router.get("/shared/{token_id}", response_model=Recipe) def get_shared_recipe(token_id: UUID4, session: Session = Depends(generate_session)): - db = get_database(session) + db = get_repositories(session) token_summary = db.recipe_share_tokens.get_one(token_id) diff --git a/mealie/routes/shopping_lists/__init__.py b/mealie/routes/shopping_lists/__init__.py index b5f49492f3ad..9e17d926472d 100644 --- a/mealie/routes/shopping_lists/__init__.py +++ b/mealie/routes/shopping_lists/__init__.py @@ -2,8 +2,8 @@ from fastapi import Depends from sqlalchemy.orm.session import Session from mealie.core.dependencies import get_current_user -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.schema.meal_plan import ShoppingListIn, ShoppingListOut from mealie.schema.user import PrivateUser @@ -18,7 +18,7 @@ async def create_shopping_list( session: Session = Depends(generate_session), ): """Create Shopping List in the Database""" - db = get_database(session) + db = get_repositories(session) list_in.group = current_user.group return db.shopping_lists.create(list_in) @@ -27,19 +27,19 @@ async def create_shopping_list( @router.get("/{id}", response_model=ShoppingListOut) async def get_shopping_list(id: int, session: Session = Depends(generate_session)): """Get Shopping List from the Database""" - db = get_database(session) + db = get_repositories(session) return db.shopping_lists.get(id) @router.put("/{id}", response_model=ShoppingListOut) async def update_shopping_list(id: int, new_data: ShoppingListIn, session: Session = Depends(generate_session)): """Update Shopping List in the Database""" - db = get_database(session) + db = get_repositories(session) return db.shopping_lists.update(id, new_data) @router.delete("/{id}") async def delete_shopping_list(id: int, session: Session = Depends(generate_session)): """Delete Shopping List from the Database""" - db = get_database(session) + db = get_repositories(session) return db.shopping_lists.delete(id) diff --git a/mealie/routes/site_settings/site_settings.py b/mealie/routes/site_settings/site_settings.py index 84e827b95305..70c39cb1b0d8 100644 --- a/mealie/routes/site_settings/site_settings.py +++ b/mealie/routes/site_settings/site_settings.py @@ -2,8 +2,8 @@ from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm.session import Session from mealie.core.dependencies import get_current_user -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import AdminAPIRouter from mealie.schema.user import GroupInDB, PrivateUser from mealie.utils.post_webhooks import post_webhooks @@ -15,7 +15,7 @@ admin_router = AdminAPIRouter(prefix="/api/site-settings", tags=["Settings"]) @public_router.get("") def get_main_settings(session: Session = Depends(generate_session)): """Returns basic site settings""" - db = get_database(session) + db = get_repositories(session) return db.settings.get(1) @@ -26,7 +26,7 @@ def test_webhooks( session: Session = Depends(generate_session), ): """Run the function to test your webhooks""" - db = get_database(session) + db = get_repositories(session) group_entry: GroupInDB = db.groups.get(current_user.group, "name") try: diff --git a/mealie/routes/tags/tags.py b/mealie/routes/tags/tags.py index e736bbdbf455..d63bbcb13379 100644 --- a/mealie/routes/tags/tags.py +++ b/mealie/routes/tags/tags.py @@ -2,8 +2,8 @@ from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from mealie.core.dependencies import is_logged_in -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import AdminAPIRouter, UserAPIRouter from mealie.schema.recipe import RecipeTagResponse, TagIn @@ -15,14 +15,14 @@ admin_router = AdminAPIRouter() @public_router.get("") async def get_all_recipe_tags(session: Session = Depends(generate_session)): """Returns a list of available tags in the database""" - db = get_database(session) + db = get_repositories(session) return db.tags.get_all_limit_columns(["slug", "name"]) @public_router.get("/empty") def get_empty_tags(session: Session = Depends(generate_session)): """Returns a list of tags that do not contain any recipes""" - db = get_database(session) + db = get_repositories(session) return db.tags.get_empty() @@ -31,7 +31,7 @@ def get_all_recipes_by_tag( tag: str, session: Session = Depends(generate_session), is_user: bool = Depends(is_logged_in) ): """Returns a list of recipes associated with the provided tag.""" - db = get_database(session) + db = get_repositories(session) tag_obj = db.tags.get(tag) tag_obj = RecipeTagResponse.from_orm(tag_obj) @@ -44,14 +44,14 @@ def get_all_recipes_by_tag( @user_router.post("") async def create_recipe_tag(tag: TagIn, session: Session = Depends(generate_session)): """Creates a Tag in the database""" - db = get_database(session) + db = get_repositories(session) return db.tags.create(tag.dict()) @admin_router.put("/{tag}", response_model=RecipeTagResponse) async def update_recipe_tag(tag: str, new_tag: TagIn, session: Session = Depends(generate_session)): """Updates an existing Tag in the database""" - db = get_database(session) + db = get_repositories(session) return db.tags.update(tag, new_tag.dict()) @@ -62,7 +62,7 @@ async def delete_recipe_tag(tag: str, session: Session = Depends(generate_sessio from any recipes that contain it""" try: - db = get_database(session) + db = get_repositories(session) db.tags.delete(tag) except Exception: raise HTTPException(status.HTTP_400_BAD_REQUEST) diff --git a/mealie/routes/users/api_tokens.py b/mealie/routes/users/api_tokens.py index ac26264e7124..2e085ab92a80 100644 --- a/mealie/routes/users/api_tokens.py +++ b/mealie/routes/users/api_tokens.py @@ -6,8 +6,8 @@ from sqlalchemy.orm.session import Session from mealie.core.dependencies import get_current_user from mealie.core.security import create_access_token -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.schema.user import CreateToken, LoingLiveTokenIn, LongLiveTokenInDB, PrivateUser @@ -33,7 +33,7 @@ async def create_api_token( user_id=current_user.id, ) - db = get_database(session) + db = get_repositories(session) new_token_in_db = db.api_tokens.create(token_model) @@ -48,7 +48,7 @@ async def delete_api_token( session: Session = Depends(generate_session), ): """Delete api_token from the Database""" - db = get_database(session) + db = get_repositories(session) token: LongLiveTokenInDB = db.api_tokens.get(token_id) if not token: diff --git a/mealie/routes/users/crud.py b/mealie/routes/users/crud.py index 6e48e526b7de..64a9858e953f 100644 --- a/mealie/routes/users/crud.py +++ b/mealie/routes/users/crud.py @@ -5,8 +5,8 @@ from sqlalchemy.orm.session import Session from mealie.core import security from mealie.core.dependencies import get_current_user from mealie.core.security import hash_password -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import AdminAPIRouter, UserAPIRouter from mealie.routes.users._helpers import assert_user_change_allowed from mealie.schema.user import PrivateUser, UserBase, UserIn, UserOut @@ -18,7 +18,7 @@ admin_router = AdminAPIRouter(prefix="") @admin_router.get("", response_model=list[UserOut]) async def get_all_users(session: Session = Depends(generate_session)): - db = get_database(session) + db = get_repositories(session) return db.users.get_all() @@ -35,13 +35,13 @@ async def create_user( create_user_event, "User Created", f"Created by {current_user.full_name}", session=session ) - db = get_database(session) + db = get_repositories(session) return db.users.create(new_user.dict()) @admin_router.get("/{id}", response_model=UserOut) async def get_user(id: UUID4, session: Session = Depends(generate_session)): - db = get_database(session) + db = get_repositories(session) return db.users.get(id) @@ -60,7 +60,7 @@ def delete_user( raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="SUPER_USER") try: - db = get_database(session) + db = get_repositories(session) db.users.delete(id) background_tasks.add_task(create_user_event, "User Deleted", f"User ID: {id}", session=session) except Exception: @@ -92,7 +92,7 @@ async def update_user( # prevent an admin from demoting themself raise HTTPException(status.HTTP_403_FORBIDDEN) - db = get_database(session) + db = get_repositories(session) db.users.update(id, new_data.dict()) if current_user.id == id: diff --git a/mealie/routes/users/favorites.py b/mealie/routes/users/favorites.py index 0b90592cc071..7d8d99dceb21 100644 --- a/mealie/routes/users/favorites.py +++ b/mealie/routes/users/favorites.py @@ -2,8 +2,8 @@ from fastapi import Depends from sqlalchemy.orm.session import Session from mealie.core.dependencies import get_current_user -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.routes.users._helpers import assert_user_change_allowed from mealie.schema.user import PrivateUser, UserFavorites @@ -14,7 +14,7 @@ user_router = UserAPIRouter() @user_router.get("/{id}/favorites", response_model=UserFavorites) async def get_favorites(id: str, session: Session = Depends(generate_session)): """Get user's favorite recipes""" - db = get_database(session) + db = get_repositories(session) return db.users.get(id, override_schema=UserFavorites) @@ -27,7 +27,7 @@ def add_favorite( """Adds a Recipe to the users favorites""" current_user.favorite_recipes.append(slug) - db = get_database(session) + db = get_repositories(session) db.users.update(current_user.id, current_user) @@ -42,7 +42,7 @@ def remove_favorite( assert_user_change_allowed(id, current_user) current_user.favorite_recipes = [x for x in current_user.favorite_recipes if x != slug] - db = get_database(session) + db = get_repositories(session) db.users.update(current_user.id, current_user) return diff --git a/mealie/routes/users/images.py b/mealie/routes/users/images.py index 1999ae7ed502..daf713c02df4 100644 --- a/mealie/routes/users/images.py +++ b/mealie/routes/users/images.py @@ -9,8 +9,8 @@ from sqlalchemy.orm.session import Session from mealie import utils from mealie.core.dependencies import get_current_user from mealie.core.dependencies.dependencies import temporary_dir -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.routes.users._helpers import assert_user_change_allowed from mealie.schema.user import PrivateUser @@ -41,7 +41,7 @@ def update_user_image( shutil.copyfile(image, dest) - db = get_database(session) + db = get_repositories(session) db.users.patch(id, {"cache_key": utils.new_cache_key()}) diff --git a/mealie/routes/users/passwords.py b/mealie/routes/users/passwords.py index b96158e29610..2e09b078e05a 100644 --- a/mealie/routes/users/passwords.py +++ b/mealie/routes/users/passwords.py @@ -3,8 +3,8 @@ from sqlalchemy.orm.session import Session from mealie.core.config import get_app_settings from mealie.core.security import hash_password -from mealie.db.database import get_database from mealie.db.db_setup import generate_session +from mealie.repos.all_repositories import get_repositories from mealie.routes.routers import UserAPIRouter from mealie.schema.user import ChangePassword from mealie.schema.user.user_passwords import ForgotPassword, ResetPassword @@ -20,7 +20,7 @@ settings = get_app_settings() async def reset_user_password(id: int, session: Session = Depends(generate_session)): new_password = hash_password(settings.DEFAULT_PASSWORD) - db = get_database(session) + db = get_repositories(session) db.users.update_password(id, new_password) diff --git a/mealie/services/_base_http_service/base_http_service.py b/mealie/services/_base_http_service/base_http_service.py index a5d686890336..296ca649f788 100644 --- a/mealie/services/_base_http_service/base_http_service.py +++ b/mealie/services/_base_http_service/base_http_service.py @@ -7,9 +7,9 @@ from sqlalchemy.orm.session import Session from mealie.core.config import get_app_dirs, get_app_settings from mealie.core.root_logger import get_logger -from mealie.db.database import get_database from mealie.db.db_setup import SessionLocal from mealie.lang import get_locale_provider +from mealie.repos.all_repositories import get_repositories from mealie.schema.user.user import PrivateUser logger = get_logger() @@ -62,7 +62,7 @@ class BaseHttpService(Generic[T, D], ABC): self.background_tasks = background_tasks # Static Globals Dependency Injection - self.db = get_database(session) + self.db = get_repositories(session) self.app_dirs = get_app_dirs() self.settings = get_app_settings() self.t = get_locale_provider().t diff --git a/mealie/services/_base_http_service/crud_http_mixins.py b/mealie/services/_base_http_service/crud_http_mixins.py index 5b6b8d4114f2..3fc0835b16ee 100644 --- a/mealie/services/_base_http_service/crud_http_mixins.py +++ b/mealie/services/_base_http_service/crud_http_mixins.py @@ -9,13 +9,13 @@ from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import Session from mealie.core.root_logger import get_logger -from mealie.db.data_access_layer._access_model import AccessModel +from mealie.repos.repository_generic import RepositoryGeneric from mealie.schema.response import ErrorResponse C = TypeVar("C", bound=BaseModel) R = TypeVar("R", bound=BaseModel) U = TypeVar("U", bound=BaseModel) -DAL = TypeVar("DAL", bound=AccessModel) +DAL = TypeVar("DAL", bound=RepositoryGeneric) logger = get_logger() @@ -25,16 +25,16 @@ class CrudHttpMixins(Generic[C, R, U], ABC): @property @abstractmethod - def dal(self) -> DAL: + def repo(self) -> DAL: ... def populate_item(self, id: int) -> R: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def _create_one(self, data: C, default_msg="generic-create-error", exception_msgs: dict | None = None) -> R: try: - self.item = self.dal.create(data) + self.item = self.repo.create(data) except Exception as ex: logger.exception(ex) self.session.rollback() @@ -58,13 +58,13 @@ class CrudHttpMixins(Generic[C, R, U], ABC): return target_id = item_id or self.item.id - self.item = self.dal.update(target_id, data) + self.item = self.repo.update(target_id, data) return self.item def _patch_one(self, data: U, item_id: int) -> None: try: - self.item = self.dal.patch(item_id, data.dict(exclude_unset=True, exclude_defaults=True)) + self.item = self.repo.patch(item_id, data.dict(exclude_unset=True, exclude_defaults=True)) except IntegrityError: raise HTTPException(status.HTTP_400_BAD_REQUEST, detail={"message": "generic-patch-error"}) @@ -73,7 +73,7 @@ class CrudHttpMixins(Generic[C, R, U], ABC): logger.info(f"Deleting item with id {target_id}") try: - self.item = self.dal.delete(target_id) + self.item = self.repo.delete(target_id) except Exception as ex: logger.exception(ex) raise HTTPException( diff --git a/mealie/services/admin/admin_group_service.py b/mealie/services/admin/admin_group_service.py index 0a3d540af705..167ee991b56a 100644 --- a/mealie/services/admin/admin_group_service.py +++ b/mealie/services/admin/admin_group_service.py @@ -23,15 +23,15 @@ class AdminGroupService( _schema = GroupInDB @cached_property - def dal(self): + def repo(self): return self.db.groups def populate_item(self, id: UUID4) -> GroupInDB: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[GroupInDB]: - return self.dal.get_all() + return self.repo.get_all() def create_one(self, data: GroupBase) -> GroupInDB: return create_new_group(self.db, data) @@ -46,7 +46,7 @@ class AdminGroupService( if data.name not in ["", self.item.name]: self.item.name = data.name - self.item = self.dal.update(target_id, self.item) + self.item = self.repo.update(target_id, self.item) return self.item diff --git a/mealie/services/admin/admin_user_service.py b/mealie/services/admin/admin_user_service.py index 185941148947..9c2b3e226322 100644 --- a/mealie/services/admin/admin_user_service.py +++ b/mealie/services/admin/admin_user_service.py @@ -16,15 +16,15 @@ class AdminUserService( _schema = UserOut @cached_property - def dal(self): + def repo(self): return self.db.users def populate_item(self, id: int) -> UserOut: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[UserOut]: - return self.dal.get_all() + return self.repo.get_all() def create_one(self, data: UserIn) -> UserOut: return self._create_one(data) diff --git a/mealie/services/backups/exports.py b/mealie/services/backups/exports.py index 080521debb20..fe1f0fb173d8 100644 --- a/mealie/services/backups/exports.py +++ b/mealie/services/backups/exports.py @@ -12,7 +12,7 @@ from mealie.core import root_logger from mealie.core.config import get_app_dirs app_dirs = get_app_dirs() -from mealie.db.database import get_database +from mealie.repos.all_repositories import get_repositories logger = root_logger.get_logger() @@ -113,7 +113,7 @@ def backup_all( ): db_export = ExportDatabase(tag=tag, templates=templates) - db = get_database(session) + db = get_repositories(session) if export_users: all_users = db.users.get_all() diff --git a/mealie/services/backups/imports.py b/mealie/services/backups/imports.py index c4d62997fc1d..312921a0af7b 100644 --- a/mealie/services/backups/imports.py +++ b/mealie/services/backups/imports.py @@ -8,7 +8,7 @@ from pydantic.main import BaseModel from sqlalchemy.orm.session import Session from mealie.core.config import get_app_dirs -from mealie.db.database import get_database +from mealie.repos.all_repositories import get_repositories from mealie.schema.admin import CommentImport, GroupImport, NotificationImport, RecipeImport, UserImport from mealie.schema.events import EventNotificationIn from mealie.schema.recipe import Recipe, RecipeCommentOut @@ -38,7 +38,7 @@ class ImportDatabase: """ self.user = user self.session = session - self.db = get_database(session) + self.db = get_repositories(session) self.archive = app_dirs.BACKUP_DIR.joinpath(zip_archive) self.force_imports = force_import diff --git a/mealie/services/events.py b/mealie/services/events.py index 0840c272b22b..0e68da5e9bfb 100644 --- a/mealie/services/events.py +++ b/mealie/services/events.py @@ -1,8 +1,8 @@ import apprise from sqlalchemy.orm.session import Session -from mealie.db.database import get_database from mealie.db.db_setup import create_session +from mealie.repos.all_repositories import get_repositories from mealie.schema.events import Event, EventCategory @@ -37,7 +37,7 @@ def post_notifications(event: Event, notification_urls=list[str], hard_fail=Fals def save_event(title, text, category, session: Session, attachment=None): event = Event(title=title, text=text, category=category) session = session or create_session() - db = get_database(session) + db = get_repositories(session) db.events.create(event.dict()) notification_objects = db.event_notifications.get(match_value=True, match_key=category, limit=9999) diff --git a/mealie/services/exporter/_abc_exporter.py b/mealie/services/exporter/_abc_exporter.py index 70c7b6b08f5c..f7f8f9fc9ed1 100644 --- a/mealie/services/exporter/_abc_exporter.py +++ b/mealie/services/exporter/_abc_exporter.py @@ -8,7 +8,7 @@ from uuid import UUID from pydantic import BaseModel from mealie.core.root_logger import get_logger -from mealie.db.database import Database +from mealie.repos.all_repositories import AllRepositories from mealie.schema.reports.reports import ReportEntryCreate from .._base_service import BaseService @@ -29,7 +29,7 @@ class ExportedItem: class ABCExporter(BaseService): write_dir_to_zip: Callable[[Path, str, Optional[list[str]]], None] - def __init__(self, db: Database, group_id: UUID) -> None: + def __init__(self, db: AllRepositories, group_id: UUID) -> None: self.logger = get_logger() self.db = db self.group_id = group_id diff --git a/mealie/services/exporter/exporter.py b/mealie/services/exporter/exporter.py index 8f72c04d8f0e..4a5200e7884f 100644 --- a/mealie/services/exporter/exporter.py +++ b/mealie/services/exporter/exporter.py @@ -4,7 +4,7 @@ import zipfile from pathlib import Path from uuid import UUID, uuid4 -from mealie.db.database import Database +from mealie.repos.all_repositories import AllRepositories from mealie.schema.group.group_exports import GroupDataExport from mealie.schema.user import GroupInDB from mealie.utils.fs_stats import pretty_size @@ -21,7 +21,7 @@ class Exporter(BaseService): self.temp_path = temp_zip self.exporters = exporters - def run(self, db: Database) -> GroupDataExport: + def run(self, db: AllRepositories) -> GroupDataExport: # Create Zip File self.temp_path.touch() diff --git a/mealie/services/exporter/recipe_exporter.py b/mealie/services/exporter/recipe_exporter.py index e6913c42f90d..781da970b655 100644 --- a/mealie/services/exporter/recipe_exporter.py +++ b/mealie/services/exporter/recipe_exporter.py @@ -1,14 +1,14 @@ from typing import Iterator from uuid import UUID -from mealie.db.database import Database +from mealie.repos.all_repositories import AllRepositories from mealie.schema.recipe import Recipe from ._abc_exporter import ABCExporter, ExportedItem class RecipeExporter(ABCExporter): - def __init__(self, db: Database, group_id: UUID, recipes: list[str]) -> None: + def __init__(self, db: AllRepositories, group_id: UUID, recipes: list[str]) -> None: """ RecipeExporter is used to export a list of recipes to a zip file. The zip file is then saved to a temporary directory and then available for a one-time diff --git a/mealie/services/group_services/cookbook_service.py b/mealie/services/group_services/cookbook_service.py index f9601a886151..fd889a4ba788 100644 --- a/mealie/services/group_services/cookbook_service.py +++ b/mealie/services/group_services/cookbook_service.py @@ -21,7 +21,7 @@ class CookbookService( _schema = ReadCookBook @cached_property - def dal(self): + def repo(self): return self.db.cookbooks def populate_item(self, item_id: int) -> RecipeCookBook: @@ -31,13 +31,13 @@ class CookbookService( pass if isinstance(item_id, int): - self.item = self.dal.get_one(item_id, override_schema=RecipeCookBook) + self.item = self.repo.get_one(item_id, override_schema=RecipeCookBook) else: - self.item = self.dal.get_one(item_id, key="slug", override_schema=RecipeCookBook) + self.item = self.repo.get_one(item_id, key="slug", override_schema=RecipeCookBook) def get_all(self) -> list[ReadCookBook]: - items = self.dal.get(self.group_id, "group_id", limit=999) + items = self.repo.get(self.group_id, "group_id", limit=999) items.sort(key=lambda x: x.position) return items @@ -52,7 +52,7 @@ class CookbookService( updated = [] for cookbook in data: - cb = self.dal.update(cookbook.id, cookbook) + cb = self.repo.update(cookbook.id, cookbook) updated.append(cb) return updated diff --git a/mealie/services/group_services/group_utils.py b/mealie/services/group_services/group_utils.py index 78f9e5a10b53..3faa95c4102b 100644 --- a/mealie/services/group_services/group_utils.py +++ b/mealie/services/group_services/group_utils.py @@ -1,11 +1,11 @@ from uuid import uuid4 -from mealie.db.data_access_layer.access_model_factory import Database +from mealie.repos.repository_factory import AllRepositories from mealie.schema.group.group_preferences import CreateGroupPreferences from mealie.schema.user.user import GroupBase, GroupInDB -def create_new_group(db: Database, g_base: GroupBase, g_preferences: CreateGroupPreferences = None) -> GroupInDB: +def create_new_group(db: AllRepositories, g_base: GroupBase, g_preferences: CreateGroupPreferences = None) -> GroupInDB: created_group = db.groups.create(g_base) # Assign Temporary ID before group is created diff --git a/mealie/services/group_services/meal_service.py b/mealie/services/group_services/meal_service.py index c3226ce2080f..4aed9aa59d20 100644 --- a/mealie/services/group_services/meal_service.py +++ b/mealie/services/group_services/meal_service.py @@ -21,19 +21,19 @@ class MealService(CrudHttpMixins[CreatePlanEntry, ReadPlanEntry, UpdatePlanEntry item: ReadPlanEntry @cached_property - def dal(self): + def repo(self): return self.db.meals def populate_item(self, id: int) -> ReadPlanEntry: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_slice(self, start: date = None, end: date = None) -> list[ReadPlanEntry]: # 2 days ago - return self.dal.get_slice(start, end, group_id=self.group_id) + return self.repo.get_slice(start, end, group_id=self.group_id) def get_today(self) -> list[ReadPlanEntry]: - return self.dal.get_today(group_id=self.group_id) + return self.repo.get_today(group_id=self.group_id) def create_one(self, data: CreatePlanEntry) -> ReadPlanEntry: data = self.cast(data, SavePlanEntry) diff --git a/mealie/services/group_services/migration_service.py b/mealie/services/group_services/migration_service.py index 102b3951db85..c8f0d98fe983 100644 --- a/mealie/services/group_services/migration_service.py +++ b/mealie/services/group_services/migration_service.py @@ -23,7 +23,7 @@ class GroupMigrationService(UserHttpService[int, ReportOut]): _schema = ReportOut @cached_property - def dal(self): + def repo(self): raise NotImplementedError def populate_item(self, _: UUID4) -> ReportOut: diff --git a/mealie/services/group_services/reports_service.py b/mealie/services/group_services/reports_service.py index e4b2eb2ad843..65df00de421e 100644 --- a/mealie/services/group_services/reports_service.py +++ b/mealie/services/group_services/reports_service.py @@ -17,15 +17,15 @@ class GroupReportService(CrudHttpMixins[ReportOut, ReportCreate, ReportCreate], _schema = ReportOut @cached_property - def dal(self): + def repo(self): return self.db.group_reports def populate_item(self, id: int) -> ReportOut: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def _get_all(self, report_type: ReportCategory = None) -> list[ReportSummary]: - return self.dal.multi_query({"group_id": self.group_id, "category": report_type}, limit=9999) + return self.repo.multi_query({"group_id": self.group_id, "category": report_type}, limit=9999) def delete_one(self, id: int = None) -> ReportOut: return self._delete_one(id) diff --git a/mealie/services/group_services/webhook_service.py b/mealie/services/group_services/webhook_service.py index a9dbb9a474a7..ef5fb5468f5d 100644 --- a/mealie/services/group_services/webhook_service.py +++ b/mealie/services/group_services/webhook_service.py @@ -18,15 +18,15 @@ class WebhookService(CrudHttpMixins[ReadWebhook, CreateWebhook, CreateWebhook], _schema = ReadWebhook @cached_property - def dal(self): + def repo(self): return self.db.webhooks def populate_item(self, id: int) -> ReadWebhook: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[ReadWebhook]: - return self.dal.get(self.group_id, match_key="group_id", limit=9999) + return self.repo.get(self.group_id, match_key="group_id", limit=9999) def create_one(self, data: CreateWebhook) -> ReadWebhook: data = self.cast(data, SaveWebhook) diff --git a/mealie/services/migrations/_migration_base.py b/mealie/services/migrations/_migration_base.py index c28056757f8d..86e418bcc5a4 100644 --- a/mealie/services/migrations/_migration_base.py +++ b/mealie/services/migrations/_migration_base.py @@ -5,7 +5,7 @@ from uuid import UUID from pydantic import UUID4 from mealie.core import root_logger -from mealie.db.database import Database +from mealie.repos.all_repositories import AllRepositories from mealie.schema.recipe import Recipe from mealie.schema.reports.reports import ( ReportCategory, @@ -29,7 +29,9 @@ class BaseMigrator(BaseService): report_id: int report: ReportOut - def __init__(self, archive: Path, db: Database, session, user_id: UUID4, group_id: UUID, add_migration_tag: bool): + def __init__( + self, archive: Path, db: AllRepositories, session, user_id: UUID4, group_id: UUID, add_migration_tag: bool + ): self.archive = archive self.db = db self.session = session diff --git a/mealie/services/migrations/utils/database_helpers.py b/mealie/services/migrations/utils/database_helpers.py index a64faa298c80..e2a9b650506b 100644 --- a/mealie/services/migrations/utils/database_helpers.py +++ b/mealie/services/migrations/utils/database_helpers.py @@ -4,8 +4,8 @@ from pydantic import UUID4, BaseModel from slugify import slugify from sqlalchemy.orm import Session -from mealie.db.data_access_layer.access_model_factory import AccessModel -from mealie.db.database import Database +from mealie.repos.all_repositories import AllRepositories +from mealie.repos.repository_factory import RepositoryGeneric from mealie.schema.recipe import RecipeCategory from mealie.schema.recipe.recipe import RecipeTag @@ -13,13 +13,13 @@ T = TypeVar("T", bound=BaseModel) class DatabaseMigrationHelpers: - def __init__(self, db: Database, session: Session, group_id: int, user_id: UUID4) -> None: + def __init__(self, db: AllRepositories, session: Session, group_id: int, user_id: UUID4) -> None: self.group_id = group_id self.user_id = user_id self.session = session self.db = db - def _get_or_set_generic(self, accessor: AccessModel, items: list[str], out_model: T) -> list[T]: + def _get_or_set_generic(self, accessor: RepositoryGeneric, items: list[str], out_model: T) -> list[T]: """ Utility model for getting or setting categories or tags. This will only work for those two cases. diff --git a/mealie/services/recipe/recipe_comments_service.py b/mealie/services/recipe/recipe_comments_service.py index 3fb59709fcd9..43cf378f8cef 100644 --- a/mealie/services/recipe/recipe_comments_service.py +++ b/mealie/services/recipe/recipe_comments_service.py @@ -25,7 +25,7 @@ class RecipeCommentsService( _schema = RecipeCommentOut @cached_property - def dal(self): + def repo(self): return self.db.comments def _check_comment_belongs_to_user(self) -> None: @@ -33,11 +33,11 @@ class RecipeCommentsService( raise HTTPException(detail="Comment does not belong to user") def populate_item(self, id: UUID) -> RecipeCommentOut: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[RecipeCommentOut]: - return self.dal.get_all() + return self.repo.get_all() def create_one(self, data: RecipeCommentCreate) -> RecipeCommentOut: save_data = RecipeCommentSave(text=data.text, user_id=self.user.id, recipe_id=data.recipe_id) diff --git a/mealie/services/recipe/recipe_food_service.py b/mealie/services/recipe/recipe_food_service.py index 04c1ffe93f7b..16e99cf4b219 100644 --- a/mealie/services/recipe/recipe_food_service.py +++ b/mealie/services/recipe/recipe_food_service.py @@ -17,15 +17,15 @@ class RecipeFoodService( _schema = IngredientFood @cached_property - def dal(self): + def repo(self): return self.db.ingredient_foods def populate_item(self, id: int) -> IngredientFood: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[IngredientFood]: - return self.dal.get_all() + return self.repo.get_all() def create_one(self, data: CreateIngredientFood) -> IngredientFood: return self._create_one(data) diff --git a/mealie/services/recipe/recipe_service.py b/mealie/services/recipe/recipe_service.py index d116ee6c49b3..b80606b297fb 100644 --- a/mealie/services/recipe/recipe_service.py +++ b/mealie/services/recipe/recipe_service.py @@ -11,7 +11,7 @@ from sqlalchemy import exc from mealie.core.dependencies.grouped import UserDeps from mealie.core.root_logger import get_logger -from mealie.db.data_access_layer.recipe_access_model import RecipeDataAccessModel +from mealie.repos.repository_recipes import RepositoryRecipes from mealie.schema.recipe.recipe import CreateRecipe, Recipe, RecipeSummary from mealie.schema.recipe.recipe_settings import RecipeSettings from mealie.services._base_http_service.crud_http_mixins import CrudHttpMixins @@ -40,7 +40,7 @@ class RecipeService(CrudHttpMixins[CreateRecipe, Recipe, Recipe], UserHttpServic return {exc.IntegrityError: self.t("recipe.unique-name-error")} @cached_property - def dal(self) -> RecipeDataAccessModel: + def repo(self) -> RepositoryRecipes: return self.db.recipes.by_group(self.group_id) @classmethod diff --git a/mealie/services/recipe/recipe_tool_service.py b/mealie/services/recipe/recipe_tool_service.py index adf39f4d06da..3c2d5ad15444 100644 --- a/mealie/services/recipe/recipe_tool_service.py +++ b/mealie/services/recipe/recipe_tool_service.py @@ -17,15 +17,15 @@ class RecipeToolService( _schema = RecipeTool @cached_property - def dal(self): + def repo(self): return self.db.tools def populate_item(self, id: int) -> RecipeTool: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[RecipeTool]: - return self.dal.get_all() + return self.repo.get_all() def create_one(self, data: RecipeToolCreate) -> RecipeTool: return self._create_one(data) diff --git a/mealie/services/recipe/recipe_unit_service.py b/mealie/services/recipe/recipe_unit_service.py index 12f485129513..b6c44d0e59ba 100644 --- a/mealie/services/recipe/recipe_unit_service.py +++ b/mealie/services/recipe/recipe_unit_service.py @@ -17,15 +17,15 @@ class RecipeUnitService( _schema = IngredientUnit @cached_property - def dal(self): + def repo(self): return self.db.ingredient_units def populate_item(self, id: int) -> IngredientUnit: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[IngredientUnit]: - return self.dal.get_all() + return self.repo.get_all() def create_one(self, data: CreateIngredientUnit) -> IngredientUnit: return self._create_one(data) diff --git a/mealie/services/scheduler/tasks/webhooks.py b/mealie/services/scheduler/tasks/webhooks.py index 4ea6b69414cd..e74459c1ab78 100644 --- a/mealie/services/scheduler/tasks/webhooks.py +++ b/mealie/services/scheduler/tasks/webhooks.py @@ -4,8 +4,8 @@ import requests from sqlalchemy.orm.session import Session from mealie.core import root_logger -from mealie.db.database import get_database from mealie.db.db_setup import create_session +from mealie.repos.all_repositories import get_repositories from mealie.schema.group.webhook import ReadWebhook from ..scheduled_func import Cron, ScheduledFunc @@ -16,7 +16,7 @@ logger = root_logger.get_logger() def post_webhooks(webhook_id: int, session: Session = None): session = session or create_session() - db = get_database(session) + db = get_repositories(session) webhook: ReadWebhook = db.webhooks.get_one(webhook_id) if not webhook.enabled: @@ -39,7 +39,7 @@ def post_webhooks(webhook_id: int, session: Session = None): def update_group_webhooks(): session = create_session() - db = get_database(session) + db = get_repositories(session) webhooks: list[ReadWebhook] = db.webhooks.get_all() diff --git a/mealie/services/server_tasks/background_executory.py b/mealie/services/server_tasks/background_executory.py index e5afd244b07b..feb0dc7aa2b1 100644 --- a/mealie/services/server_tasks/background_executory.py +++ b/mealie/services/server_tasks/background_executory.py @@ -4,7 +4,7 @@ from typing import Any, Callable from sqlalchemy.orm import Session -from mealie.db.database import get_database +from mealie.repos.all_repositories import get_repositories from mealie.schema.server.tasks import ServerTask, ServerTaskCreate, ServerTaskNames from .._base_http_service.http_services import UserHttpService @@ -32,7 +32,7 @@ class BackgroundExecutor(UserHttpService): def test_executor_func(task_id: int, session: Session) -> None: - database = get_database(session) + database = get_repositories(session) task = database.server_tasks.get_one(task_id) task.append_log("test task has started") diff --git a/mealie/services/server_tasks/tasks_http_service.py b/mealie/services/server_tasks/tasks_http_service.py index d1cf55efae29..9d06f3c269b7 100644 --- a/mealie/services/server_tasks/tasks_http_service.py +++ b/mealie/services/server_tasks/tasks_http_service.py @@ -9,15 +9,15 @@ class ServerTasksHttpService(UserHttpService[int, ServerTask]): _schema = ServerTask @cached_property - def dal(self): + def repo(self): return self.db.server_tasks def populate_item(self, id: int) -> ServerTask: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[ServerTask]: - return self.dal.multi_query(query_by={"group_id": self.group_id}, order_by="created_at") + return self.repo.multi_query(query_by={"group_id": self.group_id}, order_by="created_at") class AdminServerTasks(AdminHttpService[int, ServerTask]): @@ -25,12 +25,12 @@ class AdminServerTasks(AdminHttpService[int, ServerTask]): _schema = ServerTask @cached_property - def dal(self): + def repo(self): return self.db.server_tasks def populate_item(self, id: int) -> ServerTask: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self) -> list[ServerTask]: - return self.dal.get_all(order_by="created_at") + return self.repo.get_all(order_by="created_at") diff --git a/mealie/services/shared/recipe_shared_service.py b/mealie/services/shared/recipe_shared_service.py index 6d0e758694cd..51ec00d25957 100644 --- a/mealie/services/shared/recipe_shared_service.py +++ b/mealie/services/shared/recipe_shared_service.py @@ -22,11 +22,11 @@ class SharedRecipeService( _schema = RecipeShareToken @cached_property - def dal(self): + def repo(self): return self.db.recipe_share_tokens def populate_item(self, id: UUID4) -> RecipeShareToken: - self.item = self.dal.get_one(id) + self.item = self.repo.get_one(id) return self.item def get_all(self, recipe_id=None) -> list[RecipeShareTokenSummary]: @@ -48,4 +48,4 @@ class SharedRecipeService( def delete_one(self, item_id: UUID4 = None) -> None: item_id = item_id or self.item.id - return self.dal.delete(item_id) + return self.repo.delete(item_id) diff --git a/mealie/services/user_services/password_reset_service.py b/mealie/services/user_services/password_reset_service.py index ab70577239b4..f8b7187d4256 100644 --- a/mealie/services/user_services/password_reset_service.py +++ b/mealie/services/user_services/password_reset_service.py @@ -3,7 +3,7 @@ from sqlalchemy.orm.session import Session from mealie.core.root_logger import get_logger from mealie.core.security import hash_password, url_safe_token -from mealie.db.database import get_database +from mealie.repos.all_repositories import get_repositories from mealie.schema.user.user_passwords import SavePasswordResetToken from mealie.services._base_service import BaseService from mealie.services.email import EmailService @@ -13,7 +13,7 @@ logger = get_logger(__name__) class PasswordResetService(BaseService): def __init__(self, session: Session) -> None: - self.db = get_database(session) + self.db = get_repositories(session) super().__init__() def generate_reset_token(self, email: str) -> SavePasswordResetToken: diff --git a/mealie/utils/post_webhooks.py b/mealie/utils/post_webhooks.py index d84cb2094582..d421608df440 100644 --- a/mealie/utils/post_webhooks.py +++ b/mealie/utils/post_webhooks.py @@ -3,15 +3,15 @@ import json import requests from sqlalchemy.orm.session import Session -from mealie.db.database import get_database from mealie.db.db_setup import create_session +from mealie.repos.all_repositories import get_repositories from mealie.schema.user import GroupInDB from mealie.services.events import create_scheduled_event def post_webhooks(group: int, session: Session = None, force=True): session = session or create_session() - db = get_database(session) + db = get_repositories(session) group_settings: GroupInDB = db.groups.get(group) if not group_settings.webhook_enable and not force: diff --git a/tests/fixtures/fixture_database.py b/tests/fixtures/fixture_database.py index 57c9d86dbeda..e57ad816e782 100644 --- a/tests/fixtures/fixture_database.py +++ b/tests/fixtures/fixture_database.py @@ -1,14 +1,14 @@ import pytest -from mealie.db.database import Database, get_database from mealie.db.db_setup import SessionLocal +from mealie.repos.all_repositories import AllRepositories, get_repositories @pytest.fixture() -def database() -> Database: +def database() -> AllRepositories: try: db = SessionLocal() - yield get_database(db) + yield get_repositories(db) finally: db.close() diff --git a/tests/unit_tests/repository_tests/test_user_repository.py b/tests/unit_tests/repository_tests/test_user_repository.py index ea924ea2341c..27b915605698 100644 --- a/tests/unit_tests/repository_tests/test_user_repository.py +++ b/tests/unit_tests/repository_tests/test_user_repository.py @@ -1,9 +1,9 @@ -from mealie.db.database import Database +from mealie.repos.all_repositories import AllRepositories from mealie.schema.user import PrivateUser from tests.utils.fixture_schemas import TestUser -def test_user_directory_deleted_on_delete(database: Database, unique_user: TestUser) -> None: +def test_user_directory_deleted_on_delete(database: AllRepositories, unique_user: TestUser) -> None: user_dir = PrivateUser.get_directory(unique_user.user_id) assert user_dir.exists() database.users.delete(unique_user.user_id)