feature: proper multi-tenant-support (#969)(WIP)

* update naming

* refactor tests to use shared structure

* shorten names

* add tools test case

* refactor to support multi-tenant

* set group_id on creation

* initial refactor for multitenant tags/cats

* spelling

* additional test case for same valued resources

* fix recipe update tests

* apply indexes to foreign keys

* fix performance regressions

* handle unknown exception

* utility decorator for function debugging

* migrate recipe_id to UUID

* GUID for recipes

* remove unused import

* move image functions into package

* move utilities to packages dir

* update import

* linter

* image image and asset routes

* update assets and images to use UUIDs

* fix migration base

* image asset test coverage

* use ids for categories and tag crud functions

* refactor recipe organizer test suite to reduce duplication

* add uuid serlization utility

* organizer base router

* slug routes testing and fixes

* fix postgres error

* adopt UUIDs

* move tags, categories, and tools under "organizers" umbrella

* update composite label

* generate ts types

* fix import error

* update frontend types

* fix type errors

* fix postgres errors

* fix #978

* add null check for title validation

* add note in docs on multi-tenancy
This commit is contained in:
Hayden
2022-02-13 12:23:42 -09:00
committed by GitHub
parent 9a82a172cb
commit c617251f4c
157 changed files with 1866 additions and 1578 deletions

View File

@@ -24,7 +24,7 @@ app_dirs = get_app_dirs()
class RecipeTag(CamelModel):
id: int = 0
id: UUID4 = None
name: str
slug: str
@@ -37,7 +37,7 @@ class RecipeCategory(RecipeTag):
class RecipeTool(RecipeTag):
id: int = 0
id: UUID4
on_hand: bool = False
@@ -63,7 +63,7 @@ class CreateRecipe(CamelModel):
class RecipeSummary(CamelModel):
id: Optional[int]
id: Optional[UUID4]
user_id: UUID4 = Field(default_factory=uuid4)
group_id: UUID4 = Field(default_factory=uuid4)
@@ -96,13 +96,13 @@ class RecipeSummary(CamelModel):
@validator("tags", always=True, pre=True, allow_reuse=True)
def validate_tags(cats: list[Any]): # type: ignore
if isinstance(cats, list) and cats and isinstance(cats[0], str):
return [RecipeTag(name=c, slug=slugify(c)) for c in cats]
return [RecipeTag(id=uuid4(), name=c, slug=slugify(c)) for c in cats]
return cats
@validator("recipe_category", always=True, pre=True, allow_reuse=True)
def validate_categories(cats: list[Any]): # type: ignore
if isinstance(cats, list) and cats and isinstance(cats[0], str):
return [RecipeCategory(name=c, slug=slugify(c)) for c in cats]
return [RecipeCategory(id=uuid4(), name=c, slug=slugify(c)) for c in cats]
return cats
@validator("group_id", always=True, pre=True, allow_reuse=True)
@@ -132,12 +132,15 @@ class Recipe(RecipeSummary):
comments: Optional[list[RecipeCommentOut]] = []
@staticmethod
def directory_from_slug(slug) -> Path:
return app_dirs.RECIPE_DATA_DIR.joinpath(slug)
def directory_from_id(recipe_id: UUID4 | str) -> Path:
return app_dirs.RECIPE_DATA_DIR.joinpath(str(recipe_id))
@property
def directory(self) -> Path:
dir = app_dirs.RECIPE_DATA_DIR.joinpath(self.slug)
if not self.id:
raise ValueError("Recipe has no ID")
dir = app_dirs.RECIPE_DATA_DIR.joinpath(str(self.id))
dir.mkdir(exist_ok=True, parents=True)
return dir