feat(frontend): Fix scheduler, forgot password flow, and minor bug fixes (#725)

* feat(frontend): 💄 add recipe title

* fix(frontend): 🐛 fixes #722 side-bar issue

* feat(frontend):  Add page titles to all pages

* minor cleanup

* refactor(backend): ♻️ rewrite scheduler to be more modulare and work

* feat(frontend):  start password reset functionality

* refactor(backend): ♻️ refactor application settings to facilitate dependency injection

* refactor(backend): 🔥 remove RECIPE_SETTINGS env variables in favor of group settings

* formatting

* refactor(backend): ♻️ align naming convention

* feat(backend):  password reset

* test(backend):  password reset

* feat(frontend):  self-service password reset

* purge password schedule

* update user creation for tests

Co-authored-by: Hayden <hay-kot@pm.me>
This commit is contained in:
Hayden
2021-10-07 09:39:47 -08:00
committed by GitHub
parent d1f0441252
commit 2e9026f9ea
121 changed files with 1461 additions and 679 deletions

View File

@@ -16,6 +16,7 @@ from mealie.db.models.recipe.tag import Tag
from mealie.db.models.settings import SiteSettings
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.admin import SiteSettings as SiteSettingsSchema
from mealie.schema.cookbook.cookbook import ReadCookBook
from mealie.schema.events import Event as EventSchema
@@ -27,6 +28,7 @@ from mealie.schema.meal_plan.new_meal import ReadPlanEntry
from mealie.schema.recipe import CommentOut, Recipe, RecipeCategoryResponse, RecipeTagResponse
from mealie.schema.recipe.recipe_ingredient import IngredientFood, IngredientUnit
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
@@ -117,6 +119,10 @@ class Database:
def api_tokens(self) -> AccessModel:
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
@@ -126,7 +132,7 @@ class Database:
@cached_property
def group_invite_tokens(self) -> AccessModel:
return AccessModel(self.session, "token", GroupInviteToken, ReadInviteToken)
return AccessModel(self.session, pk_token, GroupInviteToken, ReadInviteToken)
@cached_property
def group_preferences(self) -> AccessModel:

View File

@@ -5,9 +5,9 @@ from ._access_model import AccessModel
class UserDataAccessModel(AccessModel[PrivateUser, User]):
def update_password(self, session, id, password: str):
def update_password(self, id, password: str):
entry = self._query_one(match_value=id)
entry.update_password(password)
session.commit()
self.session.commit()
return self.schema.from_orm(entry)

View File

@@ -1,9 +1,10 @@
from mealie.core import root_logger
from mealie.core.config import settings
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
logger = root_logger.get_logger("init_users")
settings = get_app_settings()
def dev_users() -> list[dict]:

View File

@@ -2,7 +2,9 @@ import sqlalchemy as sa
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm.session import Session
from mealie.core.config import settings
from mealie.core.config import get_app_settings
settings = get_app_settings()
def sql_global_init(db_url: str):

View File

@@ -1,5 +1,5 @@
from mealie.core import root_logger
from mealie.core.config import settings
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
@@ -13,6 +13,8 @@ from mealie.services.group_services.group_utils import create_new_group
logger = root_logger.get_logger("init_db")
settings = get_app_settings()
def create_all_models():
import mealie.db.models._all_models # noqa: F401

View File

@@ -2,7 +2,7 @@ import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy.orm.session import Session
from mealie.core.config import settings
from mealie.core.config import get_app_settings
from mealie.db.models.group.invite_tokens import GroupInviteToken
from .._model_base import BaseMixins, SqlAlchemyBase
@@ -13,6 +13,8 @@ from .cookbook import CookBook
from .mealplan import GroupMealPlan
from .preferences import GroupPreferencesModel
settings = get_app_settings()
class Group(SqlAlchemyBase, BaseMixins):
__tablename__ = "groups"

View File

@@ -1,2 +1,3 @@
from .password_reset import *
from .user_to_favorite import *
from .users import *

View File

@@ -0,0 +1,15 @@
from sqlalchemy import Column, ForeignKey, Integer, String, orm
from .._model_base import BaseMixins, SqlAlchemyBase
class PasswordResetModel(SqlAlchemyBase, BaseMixins):
__tablename__ = "password_reset_tokens"
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
user = orm.relationship("User", back_populates="password_reset_tokens", uselist=False)
token = Column(String(64), unique=True, nullable=False)
def __init__(self, user_id, token, **_):
self.user_id = user_id
self.token = token

View File

@@ -1,11 +1,13 @@
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, orm
from mealie.core.config import settings
from mealie.core.config import get_app_settings
from .._model_base import BaseMixins, SqlAlchemyBase
from ..group import Group
from .user_to_favorite import users_to_favorites
settings = get_app_settings()
class LongLiveToken(SqlAlchemyBase, BaseMixins):
__tablename__ = "long_live_tokens"
@@ -48,6 +50,10 @@ class User(SqlAlchemyBase, BaseMixins):
"RecipeComment", back_populates="user", cascade="all, delete, delete-orphan", single_parent=True
)
password_reset_tokens = orm.relationship(
"PasswordResetModel", back_populates="user", cascade="all, delete, delete-orphan", single_parent=True
)
owned_recipes_id = Column(Integer, ForeignKey("recipes.id"))
owned_recipes = orm.relationship("RecipeModel", single_parent=True, foreign_keys=[owned_recipes_id])