feat(backend): migrate site-settings to groups (#673)

* feat(frontend):  add user registration page (WIP)

* feat(backend):  add user registration (WIP)

* test(backend):  add validator testing for registration schema

* feat(backend):  continued work on user sign-up

* feat(backend):  add signup flow and user/group settings

* test(backend):  user-creation tests and small refactor of existing tests

* fix(backend):  fix failing group tests

* style: 🎨 fix lint issues

Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
Hayden
2021-09-05 22:05:29 -08:00
committed by GitHub
parent e179dcdb10
commit 3c504e7048
63 changed files with 1665 additions and 841 deletions

View File

@@ -6,6 +6,7 @@ from mealie.db.data_access_layer.group_access_model import GroupDataAccessModel
from mealie.db.models.event import Event, EventNotification
from mealie.db.models.group import Group
from mealie.db.models.group.cookbook import CookBook
from mealie.db.models.group.preferences import GroupPreferencesModel
from mealie.db.models.group.shopping_list import ShoppingList
from mealie.db.models.group.webhooks import GroupWebhooksModel
from mealie.db.models.mealplan import MealPlan
@@ -20,6 +21,7 @@ from mealie.schema.admin import SiteSettings as SiteSettingsSchema
from mealie.schema.cookbook import ReadCookBook
from mealie.schema.events import Event as EventSchema
from mealie.schema.events import EventNotificationIn
from mealie.schema.group.group_preferences import ReadGroupPreferences
from mealie.schema.group.webhook import ReadWebhook
from mealie.schema.meal_plan import MealPlanOut, ShoppingListOut
from mealie.schema.recipe import (
@@ -89,3 +91,4 @@ class DatabaseAccessLayer:
self.webhooks = BaseAccessModel(pk_id, GroupWebhooksModel, ReadWebhook)
self.shopping_lists = BaseAccessModel(pk_id, ShoppingList, ShoppingListOut)
self.cookbooks = BaseAccessModel(pk_id, CookBook, ReadCookBook)
self.group_preferences = BaseAccessModel("group_id", GroupPreferencesModel, ReadGroupPreferences)

View File

@@ -24,13 +24,11 @@ def default_recipe_unit_init(db: DatabaseAccessLayer, session: Session) -> None:
for unit in get_default_units():
try:
db.ingredient_units.create(session, unit)
print("Ingredient Unit Created")
except Exception as e:
print(e)
for food in get_default_foods():
try:
db.ingredient_foods.create(session, food)
print("Ingredient Food Created")
except Exception as e:
print(e)

View File

@@ -8,7 +8,9 @@ from mealie.db.database import db
from mealie.db.db_setup import create_session, engine
from mealie.db.models._model_base import SqlAlchemyBase
from mealie.schema.admin import SiteSettings
from mealie.schema.user.user import GroupBase
from mealie.services.events import create_general_event
from mealie.services.group_services.group_mixins import create_new_group
logger = root_logger.get_logger("init_db")
@@ -38,9 +40,8 @@ def default_settings_init(session: Session):
def default_group_init(session: Session):
default_group = {"name": settings.DEFAULT_GROUP}
logger.info("Generating Default Group")
db.groups.create(session, default_group)
create_new_group(session, GroupBase(name=settings.DEFAULT_GROUP))
def default_user_init(session: Session):

View File

@@ -82,8 +82,6 @@ def auto_init(exclude: Union[set, list] = None): # sourcery no-metrics
except Exception:
get_attr = "id"
print(get_attr)
if relation_dir == ONETOMANY.name and use_list:
instances = handle_one_to_many_list(get_attr, relation_cls, val)
setattr(self, key, instances)

View File

@@ -9,6 +9,7 @@ from .._model_utils import auto_init
from ..group.webhooks import GroupWebhooksModel
from ..recipe.category import Category, group2categories
from .cookbook import CookBook
from .preferences import GroupPreferencesModel
class Group(SqlAlchemyBase, BaseMixins):
@@ -16,7 +17,15 @@ class Group(SqlAlchemyBase, BaseMixins):
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String, index=True, nullable=False, unique=True)
users = orm.relationship("User", back_populates="group")
categories = orm.relationship(Category, secondary=group2categories, single_parent=True)
categories = orm.relationship(Category, secondary=group2categories, single_parent=True, uselist=True)
preferences = orm.relationship(
GroupPreferencesModel,
back_populates="group",
uselist=False,
single_parent=True,
cascade="all, delete-orphan",
)
# CRUD From Others
mealplans = orm.relationship("MealPlan", back_populates="group", single_parent=True, order_by="MealPlan.start_date")
@@ -24,7 +33,7 @@ class Group(SqlAlchemyBase, BaseMixins):
cookbooks = orm.relationship(CookBook, back_populates="group", single_parent=True)
shopping_lists = orm.relationship("ShoppingList", back_populates="group", single_parent=True)
@auto_init({"users", "webhooks", "shopping_lists", "cookbooks"})
@auto_init({"users", "webhooks", "shopping_lists", "cookbooks", "preferences"})
def __init__(self, **_) -> None:
pass

View File

@@ -0,0 +1,26 @@
import sqlalchemy as sa
import sqlalchemy.orm as orm
from .._model_base import BaseMixins, SqlAlchemyBase
from .._model_utils import auto_init
class GroupPreferencesModel(SqlAlchemyBase, BaseMixins):
__tablename__ = "group_preferences"
group_id = sa.Column(sa.Integer, sa.ForeignKey("groups.id"))
group = orm.relationship("Group", back_populates="preferences")
private_group: bool = sa.Column(sa.Boolean, default=True)
first_day_of_week = sa.Column(sa.Integer, default=0)
# Recipe Defaults
recipe_public: bool = sa.Column(sa.Boolean, default=True)
recipe_show_nutrition: bool = sa.Column(sa.Boolean, default=False)
recipe_show_assets: bool = sa.Column(sa.Boolean, default=False)
recipe_landscape_view: bool = sa.Column(sa.Boolean, default=False)
recipe_disable_comments: bool = sa.Column(sa.Boolean, default=False)
recipe_disable_amount: bool = sa.Column(sa.Boolean, default=False)
@auto_init()
def __init__(self, **_) -> None:
pass

View File

@@ -28,6 +28,7 @@ class User(SqlAlchemyBase, BaseMixins):
email = Column(String, unique=True, index=True)
password = Column(String)
admin = Column(Boolean, default=False)
advanced = Column(Boolean, default=False)
group_id = Column(Integer, ForeignKey("groups.id"))
group = orm.relationship("Group", back_populates="users")
@@ -51,6 +52,7 @@ class User(SqlAlchemyBase, BaseMixins):
favorite_recipes: list[str] = None,
group: str = settings.DEFAULT_GROUP,
admin=False,
advanced=False,
**_
) -> None:
@@ -61,6 +63,7 @@ class User(SqlAlchemyBase, BaseMixins):
self.group = Group.get_ref(session, group)
self.admin = admin
self.password = password
self.advanced = advanced
self.favorite_recipes = [
RecipeModel.get_ref(session=session, match_value=x, match_attr="slug") for x in favorite_recipes
@@ -69,13 +72,26 @@ class User(SqlAlchemyBase, BaseMixins):
if self.username is None:
self.username = full_name
def update(self, full_name, email, group, admin, username, session=None, favorite_recipes=None, password=None, **_):
def update(
self,
full_name,
email,
group,
admin,
username,
session=None,
favorite_recipes=None,
password=None,
advanced=False,
**_
):
favorite_recipes = favorite_recipes or []
self.username = username
self.full_name = full_name
self.email = email
self.group = Group.get_ref(session, group)
self.admin = admin
self.advanced = advanced
if self.username is None:
self.username = full_name