From 20822ee8084a1b66bb5507c578bb5bbb0476e48f Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Sun, 20 Mar 2022 16:12:49 -0800 Subject: [PATCH] Feature/improve user feedback (#1076) * add proper type annotations * fix state management and dead code * add response messages --- frontend/pages/user/profile/edit.vue | 31 ++++++++++++++---------- mealie/routes/_base/abc_controller.py | 8 ++++--- mealie/routes/users/_helpers.py | 3 ++- mealie/routes/users/crud.py | 34 ++++++++++++++++++++------- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/frontend/pages/user/profile/edit.vue b/frontend/pages/user/profile/edit.vue index 4e4751a1a81f..0be41232c956 100644 --- a/frontend/pages/user/profile/edit.vue +++ b/frontend/pages/user/profile/edit.vue @@ -50,7 +50,7 @@
- + @@ -60,14 +60,16 @@ :label="$t('user.current-password')" validate-on-blur :type="showPassword ? 'text' : 'password'" - @click:append="showPassword.current = !showPassword.current" + :append-icon="showPassword ? $globals.icons.eye : $globals.icons.eyeOff" + @click:append="showPassword = !showPassword" > - +
@@ -112,7 +119,7 @@ - diff --git a/mealie/routes/_base/abc_controller.py b/mealie/routes/_base/abc_controller.py index 2256483146b2..acfaf474fbd5 100644 --- a/mealie/routes/_base/abc_controller.py +++ b/mealie/routes/_base/abc_controller.py @@ -2,11 +2,13 @@ from abc import ABC from functools import cached_property from fastapi import Depends +from pydantic import UUID4 from mealie.core.exceptions import mealie_registered_exceptions from mealie.repos.all_repositories import AllRepositories from mealie.routes._base.checks import OperationChecks from mealie.routes._base.dependencies import SharedDependencies +from mealie.schema.user.user import GroupInDB, PrivateUser class BasePublicController(ABC): @@ -39,15 +41,15 @@ class BaseUserController(ABC): return AllRepositories(self.deps.session) @property - def group_id(self): + def group_id(self) -> UUID4: return self.deps.acting_user.group_id @property - def user(self): + def user(self) -> PrivateUser: return self.deps.acting_user @property - def group(self): + def group(self) -> GroupInDB: return self.deps.repos.groups.get_one(self.group_id) @cached_property diff --git a/mealie/routes/users/_helpers.py b/mealie/routes/users/_helpers.py index 1669f4e13468..83a5dbb25aa1 100644 --- a/mealie/routes/users/_helpers.py +++ b/mealie/routes/users/_helpers.py @@ -1,9 +1,10 @@ from fastapi import HTTPException, status +from pydantic import UUID4 from mealie.schema.user.user import PrivateUser -def assert_user_change_allowed(id: int, current_user: PrivateUser): +def assert_user_change_allowed(id: UUID4, current_user: PrivateUser): if current_user.id != id and not current_user.admin: # only admins can edit other users raise HTTPException(status.HTTP_403_FORBIDDEN, detail="NOT_AN_ADMIN") diff --git a/mealie/routes/users/crud.py b/mealie/routes/users/crud.py index 12f88a79d0ac..3d15d486bb67 100644 --- a/mealie/routes/users/crud.py +++ b/mealie/routes/users/crud.py @@ -1,13 +1,13 @@ from fastapi import HTTPException, status from pydantic import UUID4 -from mealie.core import security from mealie.core.security import hash_password, verify_password from mealie.routes._base import BaseAdminController, controller from mealie.routes._base.abc_controller import BaseUserController from mealie.routes._base.mixins import CrudMixins from mealie.routes._base.routers import AdminAPIRouter, UserAPIRouter from mealie.routes.users._helpers import assert_user_change_allowed +from mealie.schema.response import ErrorResponse, SuccessResponse from mealie.schema.user import ChangePassword, UserBase, UserIn, UserOut user_router = UserAPIRouter(prefix="/users", tags=["Users: CRUD"]) @@ -57,23 +57,39 @@ class UserController(BaseUserController): if not self.user.admin and (new_data.admin or self.user.group != new_data.group): # prevent a regular user from doing admin tasks on themself - raise HTTPException(status.HTTP_403_FORBIDDEN) + raise HTTPException( + status.HTTP_403_FORBIDDEN, ErrorResponse.respond("User doesn't have permission to change group") + ) if self.user.id == item_id and self.user.admin and not new_data.admin: # prevent an admin from demoting themself - raise HTTPException(status.HTTP_403_FORBIDDEN) + raise HTTPException( + status.HTTP_403_FORBIDDEN, ErrorResponse.respond("User doesn't have permission to change group") + ) - self.repos.users.update(item_id, new_data.dict()) + try: + self.repos.users.update(item_id, new_data.dict()) + except Exception as e: + raise HTTPException( + status.HTTP_400_BAD_REQUEST, + ErrorResponse.respond("Failed to update user"), + ) from e - if self.user.id == item_id: - access_token = security.create_access_token(data=dict(sub=str(self.user.id))) - return {"access_token": access_token, "token_type": "bearer"} + return SuccessResponse.respond("User updated") @user_router.put("/{item_id}/password") def update_password(self, password_change: ChangePassword): """Resets the User Password""" if not verify_password(password_change.current_password, self.user.password): - raise HTTPException(status.HTTP_400_BAD_REQUEST) + raise HTTPException(status.HTTP_400_BAD_REQUEST, ErrorResponse.respond("Invalid current password")) self.user.password = hash_password(password_change.new_password) - return self.repos.users.update_password(self.user.id, self.user.password) + try: + self.repos.users.update_password(self.user.id, self.user.password) + except Exception as e: + raise HTTPException( + status.HTTP_400_BAD_REQUEST, + ErrorResponse.respond("Failed to update password"), + ) from e + + return SuccessResponse.respond("Password updated")