From 177a430d8c4d9d63e65e620bffeff89b43f72fac Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Tue, 22 Feb 2022 11:36:58 -0900 Subject: [PATCH] Feature/new-login-page (#989) * login page refresh * use user_id for token identification --- frontend/pages/login.vue | 232 ++++++++--------------- mealie/core/dependencies/dependencies.py | 36 ++-- mealie/routes/auth/auth.py | 9 +- mealie/routes/users/crud.py | 2 +- mealie/schema/user/auth.py | 3 +- 5 files changed, 103 insertions(+), 179 deletions(-) diff --git a/frontend/pages/login.vue b/frontend/pages/login.vue index 1711b1627550..b07400b7d76f 100644 --- a/frontend/pages/login.vue +++ b/frontend/pages/login.vue @@ -1,159 +1,29 @@ @@ -259,4 +162,27 @@ export default defineComponent({ .max-button { width: 300px; } + +.icon-primary { + fill: var(--v-primary-base); +} + +.icon-container { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + position: relative; + margin-top: 3.5rem; +} + +.icon-divider { + width: 100%; + margin-bottom: -3.5rem; +} + +.icon-avatar { + border-color: rgba(0, 0, 0, 0.12); + border: 2px; +} diff --git a/mealie/core/dependencies/dependencies.py b/mealie/core/dependencies/dependencies.py index f2d4ae26bca5..03cd1f352b47 100644 --- a/mealie/core/dependencies/dependencies.py +++ b/mealie/core/dependencies/dependencies.py @@ -36,18 +36,17 @@ async def is_logged_in(token: str = Depends(oauth2_scheme_soft_fail), session=De """ try: payload = jwt.decode(token, settings.SECRET, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + user_id: str = payload.get("sub") long_token: str = payload.get("long_token") if long_token is not None: try: - user = validate_long_live_token(session, token, payload.get("id")) - if user: + if validate_long_live_token(session, token, payload.get("id")): return True except Exception: return False - return username is not None + return user_id is not None except Exception: return False @@ -61,37 +60,38 @@ async def get_current_user(token: str = Depends(oauth2_scheme), session=Depends( ) try: payload = jwt.decode(token, settings.SECRET, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + user_id: str = payload.get("sub") long_token: str = payload.get("long_token") if long_token is not None: return validate_long_live_token(session, token, payload.get("id")) - if username is None: + if user_id is None: raise credentials_exception - token_data = TokenData(username=username) - except JWTError: - raise credentials_exception + token_data = TokenData(user_id=user_id) + except JWTError as e: + raise credentials_exception from e - db = get_repositories(session) + repos = get_repositories(session) + + user = repos.users.get(token_data.user_id, "id", any_case=False) - user = db.users.get(token_data.username, "email", any_case=True) if user is None: raise credentials_exception return user -async def get_admin_user(current_user=Depends(get_current_user)) -> PrivateUser: +async def get_admin_user(current_user: PrivateUser = Depends(get_current_user)) -> PrivateUser: if not current_user.admin: raise HTTPException(status.HTTP_403_FORBIDDEN) return current_user def validate_long_live_token(session: Session, client_token: str, id: int) -> PrivateUser: - db = get_repositories(session) + repos = get_repositories(session) - tokens: list[LongLiveTokenInDB] = db.api_tokens.get(id, "user_id", limit=9999) + tokens: list[LongLiveTokenInDB] = repos.api_tokens.get(id, "user_id", limit=9999) for token in tokens: token: LongLiveTokenInDB @@ -110,8 +110,8 @@ def validate_file_token(token: Optional[str] = None) -> Path: try: payload = jwt.decode(token, settings.SECRET, algorithms=[ALGORITHM]) file_path = Path(payload.get("file")) - except JWTError: - raise credentials_exception + except JWTError as e: + raise credentials_exception from e return file_path @@ -127,8 +127,8 @@ def validate_recipe_token(token: Optional[str] = None) -> str: try: payload = jwt.decode(token, settings.SECRET, algorithms=[ALGORITHM]) slug = payload.get("slug") - except JWTError: - raise credentials_exception + except JWTError as e: + raise credentials_exception from e return slug diff --git a/mealie/routes/auth/auth.py b/mealie/routes/auth/auth.py index baf06fd606fc..7dd63e7e387b 100644 --- a/mealie/routes/auth/auth.py +++ b/mealie/routes/auth/auth.py @@ -48,10 +48,7 @@ class MealieAuthToken(BaseModel): @public_router.post("/token") -def get_token( - data: CustomOAuth2Form = Depends(), - session: Session = Depends(generate_session), -): +def get_token(data: CustomOAuth2Form = Depends(), session: Session = Depends(generate_session)): email = data.username password = data.password @@ -64,12 +61,12 @@ def get_token( ) duration = timedelta(days=14) if data.remember_me else None - access_token = security.create_access_token(dict(sub=user.email), duration) + access_token = security.create_access_token(dict(sub=str(user.id)), duration) return MealieAuthToken.respond(access_token) @user_router.get("/refresh") async def refresh_token(current_user: PrivateUser = Depends(get_current_user)): """Use a valid token to get another token""" - access_token = security.create_access_token(data=dict(sub=current_user.email)) + access_token = security.create_access_token(data=dict(sub=str(current_user.id))) return MealieAuthToken.respond(access_token) diff --git a/mealie/routes/users/crud.py b/mealie/routes/users/crud.py index 1c30702f1107..12f88a79d0ac 100644 --- a/mealie/routes/users/crud.py +++ b/mealie/routes/users/crud.py @@ -66,7 +66,7 @@ class UserController(BaseUserController): self.repos.users.update(item_id, new_data.dict()) if self.user.id == item_id: - access_token = security.create_access_token(data=dict(sub=new_data.email)) + access_token = security.create_access_token(data=dict(sub=str(self.user.id))) return {"access_token": access_token, "token_type": "bearer"} @user_router.put("/{item_id}/password") diff --git a/mealie/schema/user/auth.py b/mealie/schema/user/auth.py index 0a3148fec15d..92b1e9199345 100644 --- a/mealie/schema/user/auth.py +++ b/mealie/schema/user/auth.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import BaseModel +from pydantic import UUID4, BaseModel from pydantic.types import constr @@ -10,4 +10,5 @@ class Token(BaseModel): class TokenData(BaseModel): + user_id: Optional[UUID4] username: Optional[constr(to_lower=True, strip_whitespace=True)] = None