mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-04 23:13:12 -05:00
Refactor/conver to controllers (#923)
* add dependency injection for get_repositories * convert events api to controller * update generic typing * add abstract controllers * update test naming * migrate admin services to controllers * add additional admin route tests * remove print * add public shared dependencies * add types * fix typo * add static variables for recipe json keys * add coverage gutters config * update controller routers * add generic success response * add category/tag/tool tests * add token refresh test * add coverage utilities * covert comments to controller * add todo * add helper properties * delete old service * update test notes * add unit test for pretty_stats * remove dead code from post_webhooks * update group routes to use controllers * add additional group test coverage * abstract common permission checks * convert ingredient parser to controller * update recipe crud to use controller * remove dead-code * add class lifespan tracker for debugging * convert bulk export to controller * migrate tools router to controller * update recipe share to controller * move customer router to _base * ignore prints in flake8 * convert units and foods to new controllers * migrate user routes to controllers * centralize error handling * fix invalid ref * reorder fields * update routers to share common handling * update tests * remove prints * fix cookbooks delete * fix cookbook get * add controller for mealplanner * cover report routes to controller * remove __future__ imports * remove dead code * remove all base_http children and remove dead code
This commit is contained in:
@@ -1,59 +1,29 @@
|
||||
from datetime import date, timedelta
|
||||
from fastapi import APIRouter
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from mealie.schema.reports.reports import ReportCategory
|
||||
from mealie.services._base_http_service import RouterFactory
|
||||
from mealie.services.group_services import CookbookService, WebhookService
|
||||
from mealie.services.group_services.meal_service import MealService
|
||||
from mealie.services.group_services.reports_service import GroupReportService
|
||||
|
||||
from . import categories, invitations, labels, migrations, notifications, preferences, self_service, shopping_lists
|
||||
from . import (
|
||||
controller_cookbooks,
|
||||
controller_group_notifications,
|
||||
controller_group_reports,
|
||||
controller_group_self_service,
|
||||
controller_invitations,
|
||||
controller_labels,
|
||||
controller_mealplan,
|
||||
controller_meaplan_config,
|
||||
controller_migrations,
|
||||
controller_shopping_lists,
|
||||
controller_webhooks,
|
||||
)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
router.include_router(self_service.user_router)
|
||||
|
||||
|
||||
webhook_router = RouterFactory(service=WebhookService, prefix="/groups/webhooks", tags=["Groups: Webhooks"])
|
||||
cookbook_router = RouterFactory(service=CookbookService, prefix="/groups/cookbooks", tags=["Groups: Cookbooks"])
|
||||
|
||||
|
||||
@router.get("/groups/mealplans/today", tags=["Groups: Mealplans"])
|
||||
def get_todays_meals(ms: MealService = Depends(MealService.private)):
|
||||
return ms.get_today()
|
||||
|
||||
|
||||
meal_plan_router = RouterFactory(service=MealService, prefix="/groups/mealplans", tags=["Groups: Mealplans"])
|
||||
|
||||
|
||||
@meal_plan_router.get("")
|
||||
def get_all(start: date = None, limit: date = None, ms: MealService = Depends(MealService.private)):
|
||||
start = start or date.today() - timedelta(days=999)
|
||||
limit = limit or date.today() + timedelta(days=999)
|
||||
return ms.get_slice(start, limit)
|
||||
|
||||
|
||||
router.include_router(cookbook_router)
|
||||
router.include_router(meal_plan_router)
|
||||
router.include_router(categories.user_router)
|
||||
router.include_router(webhook_router)
|
||||
router.include_router(invitations.router, prefix="/groups/invitations", tags=["Groups: Invitations"])
|
||||
router.include_router(preferences.router, prefix="/groups/preferences", tags=["Group: Preferences"])
|
||||
router.include_router(migrations.router, prefix="/groups/migrations", tags=["Group: Migrations"])
|
||||
|
||||
report_router = RouterFactory(service=GroupReportService, prefix="/groups/reports", tags=["Groups: Reports"])
|
||||
|
||||
|
||||
@report_router.get("")
|
||||
def get_all_reports(
|
||||
report_type: ReportCategory = None,
|
||||
gs: GroupReportService = Depends(GroupReportService.private),
|
||||
):
|
||||
return gs._get_all(report_type)
|
||||
|
||||
|
||||
router.include_router(report_router)
|
||||
router.include_router(shopping_lists.router)
|
||||
router.include_router(labels.router)
|
||||
router.include_router(notifications.router)
|
||||
router.include_router(controller_group_self_service.router)
|
||||
router.include_router(controller_mealplan.router)
|
||||
router.include_router(controller_cookbooks.router)
|
||||
router.include_router(controller_meaplan_config.router)
|
||||
router.include_router(controller_webhooks.router)
|
||||
router.include_router(controller_invitations.router)
|
||||
router.include_router(controller_migrations.router)
|
||||
router.include_router(controller_group_reports.router)
|
||||
router.include_router(controller_shopping_lists.router)
|
||||
router.include_router(controller_labels.router)
|
||||
router.include_router(controller_group_notifications.router)
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
from fastapi import Depends
|
||||
|
||||
from mealie.routes.routers import UserAPIRouter
|
||||
from mealie.schema.recipe.recipe_category import CategoryBase
|
||||
from mealie.services.group_services.group_service import GroupSelfService
|
||||
|
||||
user_router = UserAPIRouter(prefix="/groups/categories", tags=["Groups: Mealplan Categories"])
|
||||
|
||||
|
||||
@user_router.get("", response_model=list[CategoryBase])
|
||||
def get_mealplan_categories(group_service: GroupSelfService = Depends(GroupSelfService.read_existing)):
|
||||
return group_service.item.categories
|
||||
|
||||
|
||||
@user_router.put("", response_model=list[CategoryBase])
|
||||
def update_mealplan_categories(
|
||||
new_categories: list[CategoryBase], group_service: GroupSelfService = Depends(GroupSelfService.write_existing)
|
||||
):
|
||||
|
||||
items = group_service.update_categories(new_categories)
|
||||
|
||||
return items.categories
|
||||
70
mealie/routes/groups/controller_cookbooks.py
Normal file
70
mealie/routes/groups/controller_cookbooks.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from functools import cached_property
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from mealie.core.exceptions import mealie_registered_exceptions
|
||||
from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema import mapper
|
||||
from mealie.schema.cookbook import CreateCookBook, ReadCookBook, RecipeCookBook, SaveCookBook, UpdateCookBook
|
||||
|
||||
router = APIRouter(prefix="/groups/cookbooks", tags=["Groups: Cookbooks"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupCookbookController(BaseUserController):
|
||||
@cached_property
|
||||
def repo(self):
|
||||
return self.deps.repos.cookbooks.by_group(self.group_id)
|
||||
|
||||
def registered_exceptions(self, ex: Type[Exception]) -> str:
|
||||
registered = {
|
||||
**mealie_registered_exceptions(self.deps.t),
|
||||
}
|
||||
return registered.get(ex, "An unexpected error occurred.")
|
||||
|
||||
@cached_property
|
||||
def mixins(self):
|
||||
return CrudMixins[CreateCookBook, ReadCookBook, UpdateCookBook](
|
||||
self.repo,
|
||||
self.deps.logger,
|
||||
self.registered_exceptions,
|
||||
)
|
||||
|
||||
@router.get("", response_model=list[RecipeCookBook])
|
||||
def get_all(self):
|
||||
items = self.repo.get_all()
|
||||
items.sort(key=lambda x: x.position)
|
||||
return items
|
||||
|
||||
@router.post("", response_model=RecipeCookBook, status_code=201)
|
||||
def create_one(self, data: CreateCookBook):
|
||||
data = mapper.cast(data, SaveCookBook, group_id=self.group_id)
|
||||
return self.mixins.create_one(data)
|
||||
|
||||
@router.put("", response_model=list[ReadCookBook])
|
||||
def update_many(self, data: list[UpdateCookBook]):
|
||||
updated = []
|
||||
|
||||
for cookbook in data:
|
||||
cb = self.mixins.update_one(cookbook, cookbook.id)
|
||||
updated.append(cb)
|
||||
|
||||
return updated
|
||||
|
||||
@router.get("/{item_id}", response_model=RecipeCookBook)
|
||||
def get_one(self, item_id: str):
|
||||
try:
|
||||
item_id = int(item_id)
|
||||
return self.mixins.get_one(item_id)
|
||||
except Exception:
|
||||
self.mixins.get_one(item_id, key="slug")
|
||||
|
||||
@router.put("/{item_id}", response_model=RecipeCookBook)
|
||||
def update_one(self, item_id: int, data: CreateCookBook):
|
||||
return self.mixins.update_one(data, item_id)
|
||||
|
||||
@router.delete("/{item_id}", response_model=RecipeCookBook)
|
||||
def delete_one(self, item_id: int):
|
||||
return self.mixins.delete_one(item_id)
|
||||
@@ -1,10 +1,10 @@
|
||||
from functools import cached_property
|
||||
from sqlite3 import IntegrityError
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.core.exceptions import mealie_registered_exceptions
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.dependencies import SharedDependencies
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
@@ -35,9 +35,9 @@ class GroupEventsNotifierController:
|
||||
return self.deps.repos.group_event_notifier.by_group(self.deps.acting_user.group_id)
|
||||
|
||||
def registered_exceptions(self, ex: Type[Exception]) -> str:
|
||||
|
||||
registered = {
|
||||
Exception: "An unexpected error occurred.",
|
||||
IntegrityError: "An unexpected error occurred.",
|
||||
**mealie_registered_exceptions(self.deps.t),
|
||||
}
|
||||
|
||||
return registered.get(ex, "An unexpected error occurred.")
|
||||
45
mealie/routes/groups/controller_group_reports.py
Normal file
45
mealie/routes/groups/controller_group_reports.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from functools import cached_property
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.core.exceptions import mealie_registered_exceptions
|
||||
from mealie.routes._base.abc_controller import BaseUserController
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema.reports.reports import ReportCategory, ReportCreate, ReportOut, ReportSummary
|
||||
|
||||
router = APIRouter(prefix="/groups/reports", tags=["Groups: Reports"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupReportsController(BaseUserController):
|
||||
@cached_property
|
||||
def repo(self):
|
||||
return self.deps.repos.group_reports.by_group(self.deps.acting_user.group_id)
|
||||
|
||||
def registered_exceptions(self, ex: Type[Exception]) -> str:
|
||||
return {
|
||||
**mealie_registered_exceptions(self.deps.t),
|
||||
}.get(ex, "An unexpected error occurred.")
|
||||
|
||||
@cached_property
|
||||
def mixins(self):
|
||||
return CrudMixins[ReportCreate, ReportOut, ReportCreate](
|
||||
self.repo,
|
||||
self.deps.logger,
|
||||
self.registered_exceptions,
|
||||
)
|
||||
|
||||
@router.get("", response_model=list[ReportSummary])
|
||||
def get_all(self, report_type: ReportCategory = None):
|
||||
return self.repo.multi_query({"group_id": self.group_id, "category": report_type}, limit=9999)
|
||||
|
||||
@router.get("/{item_id}", response_model=ReportOut)
|
||||
def get_one(self, item_id: UUID4):
|
||||
return self.mixins.get_one(item_id)
|
||||
|
||||
@router.delete("/{item_id}", status_code=204)
|
||||
def delete_one(self, item_id: UUID4):
|
||||
self.mixins.delete_one(item_id) # type: ignore
|
||||
49
mealie/routes/groups/controller_group_self_service.py
Normal file
49
mealie/routes/groups/controller_group_self_service.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
from mealie.routes._base.abc_controller import BaseUserController
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.routers import UserAPIRouter
|
||||
from mealie.schema.group.group_permissions import SetPermissions
|
||||
from mealie.schema.group.group_preferences import ReadGroupPreferences, UpdateGroupPreferences
|
||||
from mealie.schema.user.user import GroupInDB, UserOut
|
||||
|
||||
router = UserAPIRouter(prefix="/groups", tags=["Groups: Self Service"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupSelfServiceController(BaseUserController):
|
||||
@router.get("/preferences", response_model=ReadGroupPreferences)
|
||||
def get_group_preferences(self):
|
||||
return self.group.preferences
|
||||
|
||||
@router.put("/preferences", response_model=ReadGroupPreferences)
|
||||
def update_group_preferences(self, new_pref: UpdateGroupPreferences):
|
||||
return self.repos.group_preferences.update(self.group_id, new_pref)
|
||||
|
||||
@router.get("/self", response_model=GroupInDB)
|
||||
async def get_logged_in_user_group(self):
|
||||
"""Returns the Group Data for the Current User"""
|
||||
return self.group
|
||||
|
||||
@router.get("/members", response_model=list[UserOut])
|
||||
async def get_group_members(self):
|
||||
"""Returns the Group of user lists"""
|
||||
return self.repos.users.multi_query(query_by={"group_id": self.group.id}, override_schema=UserOut)
|
||||
|
||||
@router.put("/permissions", response_model=UserOut)
|
||||
async def set_member_permissions(self, permissions: SetPermissions):
|
||||
self.checks.can_manage()
|
||||
|
||||
target_user = self.repos.users.get(permissions.user_id)
|
||||
|
||||
if not target_user:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="User not found")
|
||||
|
||||
if target_user.group_id != self.group_id:
|
||||
raise HTTPException(status.HTTP_403_FORBIDDEN, detail="User is not a member of this group")
|
||||
|
||||
target_user.can_invite = permissions.can_invite
|
||||
target_user.can_manage = permissions.can_manage
|
||||
target_user.can_organize = permissions.can_organize
|
||||
|
||||
return self.repos.users.update(permissions.user_id, target_user)
|
||||
43
mealie/routes/groups/controller_invitations.py
Normal file
43
mealie/routes/groups/controller_invitations.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from fastapi import APIRouter, HTTPException, status
|
||||
|
||||
from mealie.core.security import url_safe_token
|
||||
from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.schema.group.invite_token import (
|
||||
CreateInviteToken,
|
||||
EmailInitationResponse,
|
||||
EmailInvitation,
|
||||
ReadInviteToken,
|
||||
SaveInviteToken,
|
||||
)
|
||||
from mealie.services.email.email_service import EmailService
|
||||
|
||||
router = APIRouter(prefix="/groups/invitations", tags=["Groups: Invitations"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupInvitationsController(BaseUserController):
|
||||
@router.get("", response_model=list[ReadInviteToken])
|
||||
def get_invite_tokens(self):
|
||||
return self.repos.group_invite_tokens.multi_query({"group_id": self.group_id})
|
||||
|
||||
@router.post("", response_model=ReadInviteToken, status_code=status.HTTP_201_CREATED)
|
||||
def create_invite_token(self, uses: CreateInviteToken):
|
||||
if not self.deps.acting_user.can_invite:
|
||||
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())
|
||||
return self.repos.group_invite_tokens.create(token)
|
||||
|
||||
@router.post("/email", response_model=EmailInitationResponse)
|
||||
def email_invitation(self, invite: EmailInvitation):
|
||||
email_service = EmailService()
|
||||
url = f"{self.deps.settings.BASE_URL}/register?token={invite.token}"
|
||||
|
||||
success = False
|
||||
error = None
|
||||
try:
|
||||
success = email_service.send_invitation(address=invite.email, invitation_url=url)
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
|
||||
return EmailInitationResponse(success=success, error=error)
|
||||
@@ -1,10 +1,10 @@
|
||||
from functools import cached_property
|
||||
from sqlite3 import IntegrityError
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.core.exceptions import mealie_registered_exceptions
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.dependencies import SharedDependencies
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
@@ -17,15 +17,13 @@ from mealie.schema.labels import (
|
||||
)
|
||||
from mealie.schema.mapper import cast
|
||||
from mealie.schema.query import GetAll
|
||||
from mealie.services.group_services.shopping_lists import ShoppingListService
|
||||
|
||||
router = APIRouter(prefix="/groups/labels", tags=["Group: Multi Purpose Labels"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class ShoppingListRoutes:
|
||||
class MultiPurposeLabelsController:
|
||||
deps: SharedDependencies = Depends(SharedDependencies.user)
|
||||
service: ShoppingListService = Depends(ShoppingListService.private)
|
||||
|
||||
@cached_property
|
||||
def repo(self):
|
||||
@@ -35,9 +33,9 @@ class ShoppingListRoutes:
|
||||
return self.deps.repos.group_multi_purpose_labels.by_group(self.deps.acting_user.group_id)
|
||||
|
||||
def registered_exceptions(self, ex: Type[Exception]) -> str:
|
||||
|
||||
registered = {
|
||||
Exception: "An unexpected error occurred.",
|
||||
IntegrityError: "An unexpected error occurred.",
|
||||
**mealie_registered_exceptions(self.deps.t),
|
||||
}
|
||||
|
||||
return registered.get(ex, "An unexpected error occurred.")
|
||||
62
mealie/routes/groups/controller_mealplan.py
Normal file
62
mealie/routes/groups/controller_mealplan.py
Normal file
@@ -0,0 +1,62 @@
|
||||
from datetime import date, timedelta
|
||||
from functools import cached_property
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from mealie.core.exceptions import mealie_registered_exceptions
|
||||
from mealie.repos.repository_meals import RepositoryMeals
|
||||
from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema import mapper
|
||||
from mealie.schema.meal_plan import CreatePlanEntry, ReadPlanEntry, SavePlanEntry, UpdatePlanEntry
|
||||
|
||||
router = APIRouter(prefix="/groups/mealplans", tags=["Groups: Mealplans"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupMealplanController(BaseUserController):
|
||||
@cached_property
|
||||
def repo(self) -> RepositoryMeals:
|
||||
return self.repos.meals.by_group(self.group_id)
|
||||
|
||||
def registered_exceptions(self, ex: Type[Exception]) -> str:
|
||||
registered = {
|
||||
**mealie_registered_exceptions(self.deps.t),
|
||||
}
|
||||
return registered.get(ex, "An unexpected error occurred.")
|
||||
|
||||
@cached_property
|
||||
def mixins(self):
|
||||
return CrudMixins[CreatePlanEntry, ReadPlanEntry, UpdatePlanEntry](
|
||||
self.repo,
|
||||
self.deps.logger,
|
||||
self.registered_exceptions,
|
||||
)
|
||||
|
||||
@router.get("/today", tags=["Groups: Mealplans"])
|
||||
def get_todays_meals(self):
|
||||
return self.repo.get_today(group_id=self.group_id)
|
||||
|
||||
@router.get("", response_model=list[ReadPlanEntry])
|
||||
def get_all(self, start: date = None, limit: date = None):
|
||||
start = start or date.today() - timedelta(days=999)
|
||||
limit = limit or date.today() + timedelta(days=999)
|
||||
return self.repo.get_slice(start, limit, group_id=self.group.id)
|
||||
|
||||
@router.post("", response_model=ReadPlanEntry, status_code=201)
|
||||
def create_one(self, data: CreatePlanEntry):
|
||||
data = mapper.cast(data, SavePlanEntry, group_id=self.group.id)
|
||||
return self.mixins.create_one(data)
|
||||
|
||||
@router.get("/{item_id}", response_model=ReadPlanEntry)
|
||||
def get_one(self, item_id: int):
|
||||
return self.mixins.get_one(item_id)
|
||||
|
||||
@router.put("/{item_id}", response_model=ReadPlanEntry)
|
||||
def update_one(self, item_id: int, data: UpdatePlanEntry):
|
||||
return self.mixins.update_one(data, item_id)
|
||||
|
||||
@router.delete("/{item_id}", response_model=ReadPlanEntry)
|
||||
def delete_one(self, item_id: int):
|
||||
return self.mixins.delete_one(item_id)
|
||||
26
mealie/routes/groups/controller_meaplan_config.py
Normal file
26
mealie/routes/groups/controller_meaplan_config.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from mealie.routes._base.abc_controller import BaseUserController
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.routes._base.routers import UserAPIRouter
|
||||
from mealie.schema.recipe.recipe_category import CategoryBase
|
||||
from mealie.schema.user.user import GroupInDB
|
||||
|
||||
router = UserAPIRouter(prefix="/groups/categories", tags=["Groups: Mealplan Categories"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupMealplanConfigController(BaseUserController):
|
||||
@property
|
||||
def mixins(self):
|
||||
return CrudMixins[GroupInDB, GroupInDB, GroupInDB](self.repos.groups, self.deps.logger)
|
||||
|
||||
@router.get("", response_model=list[CategoryBase])
|
||||
def get_mealplan_categories(self):
|
||||
data = self.mixins.get_one(self.deps.acting_user.group_id)
|
||||
return data.categories
|
||||
|
||||
@router.put("", response_model=list[CategoryBase])
|
||||
def update_mealplan_categories(self, new_categories: list[CategoryBase]):
|
||||
data = self.mixins.get_one(self.deps.acting_user.group_id)
|
||||
data.categories = new_categories
|
||||
return self.mixins.update_one(data, data.id).categories
|
||||
51
mealie/routes/groups/controller_migrations.py
Normal file
51
mealie/routes/groups/controller_migrations.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import shutil
|
||||
|
||||
from fastapi import Depends, File, Form
|
||||
from fastapi.datastructures import UploadFile
|
||||
|
||||
from mealie.core.dependencies import temporary_zip_path
|
||||
from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.routes._base.routers import UserAPIRouter
|
||||
from mealie.schema.group.group_migration import SupportedMigrations
|
||||
from mealie.schema.reports.reports import ReportSummary
|
||||
from mealie.services.migrations import ChowdownMigrator, MealieAlphaMigrator, NextcloudMigrator, PaprikaMigrator
|
||||
|
||||
router = UserAPIRouter(prefix="/groups/migrations", tags=["Group: Migrations"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupMigrationController(BaseUserController):
|
||||
@router.post("", response_model=ReportSummary)
|
||||
def start_data_migration(
|
||||
self,
|
||||
add_migration_tag: bool = Form(False),
|
||||
migration_type: SupportedMigrations = Form(...),
|
||||
archive: UploadFile = File(...),
|
||||
temp_path: str = Depends(temporary_zip_path),
|
||||
):
|
||||
# Save archive to temp_path
|
||||
with temp_path.open("wb") as buffer:
|
||||
shutil.copyfileobj(archive.file, buffer)
|
||||
|
||||
args = {
|
||||
"archive": temp_path,
|
||||
"db": self.repos,
|
||||
"session": self.deps.session,
|
||||
"user_id": self.user.id,
|
||||
"group_id": self.group_id,
|
||||
"add_migration_tag": add_migration_tag,
|
||||
}
|
||||
|
||||
match migration_type:
|
||||
case SupportedMigrations.chowdown:
|
||||
migrator = ChowdownMigrator(**args)
|
||||
case SupportedMigrations.mealie_alpha:
|
||||
migrator = MealieAlphaMigrator(**args)
|
||||
case SupportedMigrations.nextcloud:
|
||||
migrator = NextcloudMigrator(**args)
|
||||
case SupportedMigrations.paprika:
|
||||
migrator = PaprikaMigrator(**args)
|
||||
case _:
|
||||
raise ValueError(f"Unsupported migration type: {migration_type}")
|
||||
|
||||
return migrator.migrate(f"{migration_type.value.title()} Migration")
|
||||
@@ -1,12 +1,12 @@
|
||||
from functools import cached_property
|
||||
from sqlite3 import IntegrityError
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.core.exceptions import mealie_registered_exceptions
|
||||
from mealie.routes._base.abc_controller import BaseUserController
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.dependencies import SharedDependencies
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema.group.group_shopping_list import (
|
||||
ShoppingListCreate,
|
||||
@@ -25,11 +25,13 @@ router = APIRouter(prefix="/groups/shopping/lists", tags=["Group: Shopping Lists
|
||||
|
||||
|
||||
@controller(router)
|
||||
class ShoppingListRoutes:
|
||||
deps: SharedDependencies = Depends(SharedDependencies.user)
|
||||
service: ShoppingListService = Depends(ShoppingListService.private)
|
||||
class ShoppingListController(BaseUserController):
|
||||
event_bus: EventBusService = Depends(EventBusService)
|
||||
|
||||
@cached_property
|
||||
def service(self):
|
||||
return ShoppingListService(self.repos)
|
||||
|
||||
@cached_property
|
||||
def repo(self):
|
||||
if not self.deps.acting_user:
|
||||
@@ -38,9 +40,9 @@ class ShoppingListRoutes:
|
||||
return self.deps.repos.group_shopping_lists.by_group(self.deps.acting_user.group_id)
|
||||
|
||||
def registered_exceptions(self, ex: Type[Exception]) -> str:
|
||||
|
||||
registered = {
|
||||
Exception: "An unexpected error occurred.",
|
||||
IntegrityError: "An unexpected error occurred.",
|
||||
**mealie_registered_exceptions(self.deps.t),
|
||||
}
|
||||
|
||||
return registered.get(ex, "An unexpected error occurred.")
|
||||
44
mealie/routes/groups/controller_webhooks.py
Normal file
44
mealie/routes/groups/controller_webhooks.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from functools import cached_property
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from mealie.routes._base.abc_controller import BaseUserController
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema import mapper
|
||||
from mealie.schema.group.webhook import CreateWebhook, ReadWebhook, SaveWebhook
|
||||
from mealie.schema.query import GetAll
|
||||
|
||||
router = APIRouter(prefix="/groups/webhooks", tags=["Groups: Webhooks"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class ReadWebhookController(BaseUserController):
|
||||
@cached_property
|
||||
def repo(self):
|
||||
return self.repos.webhooks.by_group(self.group_id)
|
||||
|
||||
@property
|
||||
def mixins(self) -> CrudMixins:
|
||||
return CrudMixins[CreateWebhook, SaveWebhook, CreateWebhook](self.repo, self.deps.logger)
|
||||
|
||||
@router.get("", response_model=list[ReadWebhook])
|
||||
def get_all(self, q: GetAll = Depends(GetAll)):
|
||||
return self.repo.get_all(start=q.start, limit=q.limit, override_schema=ReadWebhook)
|
||||
|
||||
@router.post("", response_model=ReadWebhook, status_code=201)
|
||||
def create_one(self, data: CreateWebhook):
|
||||
save = mapper.cast(data, SaveWebhook, group_id=self.group.id)
|
||||
return self.mixins.create_one(save)
|
||||
|
||||
@router.get("/{item_id}", response_model=ReadWebhook)
|
||||
def get_one(self, item_id: int):
|
||||
return self.mixins.get_one(item_id)
|
||||
|
||||
@router.put("/{item_id}", response_model=ReadWebhook)
|
||||
def update_one(self, item_id: int, data: CreateWebhook):
|
||||
return self.mixins.update_one(data, item_id)
|
||||
|
||||
@router.delete("/{item_id}", response_model=ReadWebhook)
|
||||
def delete_one(self, item_id: int):
|
||||
return self.mixins.delete_one(item_id) # type: ignore
|
||||
@@ -1,21 +0,0 @@
|
||||
from fastapi import APIRouter, Depends, status
|
||||
|
||||
from mealie.schema.group.invite_token import CreateInviteToken, EmailInitationResponse, EmailInvitation, ReadInviteToken
|
||||
from mealie.services.group_services.group_service import GroupSelfService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("", response_model=list[ReadInviteToken])
|
||||
def get_invite_tokens(g_service: GroupSelfService = Depends(GroupSelfService.private)):
|
||||
return g_service.get_invite_tokens()
|
||||
|
||||
|
||||
@router.post("", response_model=ReadInviteToken, status_code=status.HTTP_201_CREATED)
|
||||
def create_invite_token(uses: CreateInviteToken, g_service: GroupSelfService = Depends(GroupSelfService.private)):
|
||||
return g_service.create_invite_token(uses.uses)
|
||||
|
||||
|
||||
@router.post("/email", response_model=EmailInitationResponse)
|
||||
def email_invitation(invite: EmailInvitation, g_service: GroupSelfService = Depends(GroupSelfService.private)):
|
||||
return g_service.email_invitation(invite)
|
||||
@@ -1,27 +0,0 @@
|
||||
import shutil
|
||||
|
||||
from fastapi import Depends, File, Form
|
||||
from fastapi.datastructures import UploadFile
|
||||
|
||||
from mealie.core.dependencies import temporary_zip_path
|
||||
from mealie.routes.routers import UserAPIRouter
|
||||
from mealie.schema.group.group_migration import SupportedMigrations
|
||||
from mealie.schema.reports.reports import ReportSummary
|
||||
from mealie.services.group_services.migration_service import GroupMigrationService
|
||||
|
||||
router = UserAPIRouter()
|
||||
|
||||
|
||||
@router.post("", response_model=ReportSummary)
|
||||
def start_data_migration(
|
||||
add_migration_tag: bool = Form(False),
|
||||
migration_type: SupportedMigrations = Form(...),
|
||||
archive: UploadFile = File(...),
|
||||
temp_path: str = Depends(temporary_zip_path),
|
||||
gm_service: GroupMigrationService = Depends(GroupMigrationService.private),
|
||||
):
|
||||
# Save archive to temp_path
|
||||
with temp_path.open("wb") as buffer:
|
||||
shutil.copyfileobj(archive.file, buffer)
|
||||
|
||||
return gm_service.migrate(migration_type, add_migration_tag, temp_path)
|
||||
@@ -1,19 +0,0 @@
|
||||
from fastapi import Depends
|
||||
|
||||
from mealie.routes.routers import UserAPIRouter
|
||||
from mealie.schema.group.group_preferences import ReadGroupPreferences, UpdateGroupPreferences
|
||||
from mealie.services.group_services.group_service import GroupSelfService
|
||||
|
||||
router = UserAPIRouter()
|
||||
|
||||
|
||||
@router.put("", response_model=ReadGroupPreferences)
|
||||
def update_group_preferences(
|
||||
new_pref: UpdateGroupPreferences, g_service: GroupSelfService = Depends(GroupSelfService.write_existing)
|
||||
):
|
||||
return g_service.update_preferences(new_pref).preferences
|
||||
|
||||
|
||||
@router.get("", response_model=ReadGroupPreferences)
|
||||
def get_group_preferences(g_service: GroupSelfService = Depends(GroupSelfService.write_existing)):
|
||||
return g_service.item.preferences
|
||||
@@ -1,27 +0,0 @@
|
||||
from fastapi import Depends
|
||||
|
||||
from mealie.routes.routers import UserAPIRouter
|
||||
from mealie.schema.group.group_permissions import SetPermissions
|
||||
from mealie.schema.user.user import GroupInDB, UserOut
|
||||
from mealie.services.group_services.group_service import GroupSelfService
|
||||
|
||||
user_router = UserAPIRouter(prefix="/groups", tags=["Groups: Self Service"])
|
||||
|
||||
|
||||
@user_router.get("/self", response_model=GroupInDB)
|
||||
async def get_logged_in_user_group(g_service: GroupSelfService = Depends(GroupSelfService.write_existing)):
|
||||
"""Returns the Group Data for the Current User"""
|
||||
return g_service.item
|
||||
|
||||
|
||||
@user_router.get("/members", response_model=list[UserOut])
|
||||
async def get_group_members(g_service: GroupSelfService = Depends(GroupSelfService.write_existing)):
|
||||
"""Returns the Group of user lists"""
|
||||
return g_service.get_members()
|
||||
|
||||
|
||||
@user_router.put("/permissions", response_model=UserOut)
|
||||
async def set_member_permissions(
|
||||
payload: SetPermissions, g_service: GroupSelfService = Depends(GroupSelfService.manage_existing)
|
||||
):
|
||||
return g_service.set_member_permissions(payload)
|
||||
Reference in New Issue
Block a user