diff --git a/frontend/composables/use-user.ts b/frontend/composables/use-user.ts index b4c2485a3..35341c99d 100644 --- a/frontend/composables/use-user.ts +++ b/frontend/composables/use-user.ts @@ -1,4 +1,4 @@ -import { useUserApi } from "~/composables/api"; +import { useAdminApi } from "~/composables/api"; import type { UserIn, UserOut } from "~/lib/api/types/user"; /* @@ -8,7 +8,7 @@ to control whether the object is substantiated... but some of the others rely on */ export const useAllUsers = function () { - const api = useUserApi(); + const api = useAdminApi(); const asyncKey = String(Date.now()); const { data: users, refresh: refreshAllUsers } = useLazyAsyncData(asyncKey, async () => { const { data } = await api.users.getAll(); @@ -24,7 +24,7 @@ export const useAllUsers = function () { }; export const useUser = function (refreshFunc: CallableFunction | null = null) { - const api = useUserApi(); + const api = useAdminApi(); const loading = ref(false); function getUser(id: string) { diff --git a/mealie/routes/admin/admin_management_users.py b/mealie/routes/admin/admin_management_users.py index 68dd5d8ce..d87209df5 100644 --- a/mealie/routes/admin/admin_management_users.py +++ b/mealie/routes/admin/admin_management_users.py @@ -1,6 +1,6 @@ from functools import cached_property -from fastapi import APIRouter, Depends, HTTPException +from fastapi import APIRouter, Depends, HTTPException, status from pydantic import UUID4 from mealie.core import security @@ -42,6 +42,11 @@ class AdminUserManagementRoutes(BaseAdminController): @router.post("", response_model=UserOut, status_code=201) def create_one(self, data: UserIn): + if self.repos.users.get_by_username(data.username): + raise HTTPException(status.HTTP_409_CONFLICT, {"message": self.t("exceptions.username-conflict-error")}) + elif self.repos.users.get_one(data.email, "email"): + raise HTTPException(status.HTTP_409_CONFLICT, {"message": self.t("exceptions.email-conflict-error")}) + data.password = security.hash_password(data.password) return self.mixins.create_one(data) diff --git a/mealie/routes/users/__init__.py b/mealie/routes/users/__init__.py index f46c8a54a..962a68b12 100644 --- a/mealie/routes/users/__init__.py +++ b/mealie/routes/users/__init__.py @@ -9,7 +9,6 @@ router = APIRouter() router.include_router(registration.router, prefix=user_prefix, tags=["Users: Registration"]) router.include_router(crud.user_router) -router.include_router(crud.admin_router) router.include_router(forgot_password.router, prefix=user_prefix, tags=["Users: Passwords"]) router.include_router(images.router, prefix=user_prefix, tags=["Users: Images"]) router.include_router(api_tokens.router) diff --git a/mealie/routes/users/crud.py b/mealie/routes/users/crud.py index a246b6fa3..45a571df5 100644 --- a/mealie/routes/users/crud.py +++ b/mealie/routes/users/crud.py @@ -1,52 +1,17 @@ -from fastapi import Depends, HTTPException, status +from fastapi import HTTPException, status from pydantic import UUID4 from mealie.core.security import hash_password from mealie.core.security.providers.credentials_provider import CredentialsProvider from mealie.db.models.users.users import AuthMethod -from mealie.routes._base import BaseAdminController, BaseUserController, controller -from mealie.routes._base.mixins import HttpRepo -from mealie.routes._base.routers import AdminAPIRouter, UserAPIRouter +from mealie.routes._base import BaseUserController, controller +from mealie.routes._base.routers import UserAPIRouter from mealie.routes.users._helpers import assert_user_change_allowed from mealie.schema.response import ErrorResponse, SuccessResponse -from mealie.schema.response.pagination import PaginationQuery -from mealie.schema.user import ChangePassword, UserBase, UserIn, UserOut -from mealie.schema.user.user import UserPagination, UserRatings, UserRatingSummary +from mealie.schema.user import ChangePassword, UserBase, UserOut +from mealie.schema.user.user import UserRatings, UserRatingSummary user_router = UserAPIRouter(prefix="/users", tags=["Users: CRUD"]) -admin_router = AdminAPIRouter(prefix="/users", tags=["Users: Admin CRUD"]) - - -@controller(admin_router) -class AdminUserController(BaseAdminController): - @property - def mixins(self) -> HttpRepo: - return HttpRepo[UserIn, UserOut, UserBase](self.repos.users, self.logger) - - @admin_router.get("", response_model=UserPagination) - def get_all(self, q: PaginationQuery = Depends(PaginationQuery)): - """Returns all users from all groups""" - - response = self.repos.users.page_all( - pagination=q, - override=UserOut, - ) - - response.set_pagination_guides(admin_router.url_path_for("get_all"), q.model_dump()) - return response - - @admin_router.post("", response_model=UserOut, status_code=201) - def create_user(self, new_user: UserIn): - new_user.password = hash_password(new_user.password) - return self.mixins.create_one(new_user) - - @admin_router.get("/{item_id}", response_model=UserOut) - def get_user(self, item_id: UUID4): - return self.mixins.get_one(item_id) - - @admin_router.delete("/{item_id}") - def delete_user(self, item_id: UUID4): - self.mixins.delete_one(item_id) @controller(user_router) diff --git a/tests/fixtures/fixture_users.py b/tests/fixtures/fixture_users.py index 79283c5c6..0c621acb8 100644 --- a/tests/fixtures/fixture_users.py +++ b/tests/fixtures/fixture_users.py @@ -76,7 +76,7 @@ def h2_user(session: Session, admin_token, api_client: TestClient, unique_user: "admin": False, "tokens": [], } - response = api_client.post(api_routes.users, json=user_data, headers=admin_token) + response = api_client.post(api_routes.admin_users, json=user_data, headers=admin_token) assert response.status_code == 201 # Log in as this user @@ -135,7 +135,7 @@ def g2_user(session: Session, admin_token, api_client: TestClient): } api_client.post(api_routes.admin_groups, json={"name": group}, headers=admin_token) - response = api_client.post(api_routes.users, json=create_data, headers=admin_token) + response = api_client.post(api_routes.admin_users, json=create_data, headers=admin_token) assert response.status_code == 201 @@ -258,7 +258,7 @@ def user_tuple(session: Session, admin_token, api_client: TestClient) -> Generat users_out = [] for usr in [create_data_1, create_data_2]: - response = api_client.post(api_routes.users, json=usr, headers=admin_token) + response = api_client.post(api_routes.admin_users, json=usr, headers=admin_token) assert response.status_code == 201 # Log in as this user @@ -312,7 +312,7 @@ def user_token(admin_token, api_client: TestClient): "tokens": [], } - response = api_client.post(api_routes.users, json=create_data, headers=admin_token) + response = api_client.post(api_routes.admin_users, json=create_data, headers=admin_token) assert response.status_code == 201 diff --git a/tests/integration_tests/user_tests/test_user_api_token.py b/tests/integration_tests/user_tests/test_user_api_token.py index 44635addb..56833ed0e 100644 --- a/tests/integration_tests/user_tests/test_user_api_token.py +++ b/tests/integration_tests/user_tests/test_user_api_token.py @@ -24,7 +24,7 @@ def test_api_token_private(api_client: TestClient, admin_token): response = api_client.post(api_routes.users_api_tokens, json={"name": "Test API Token"}, headers=admin_token) assert response.status_code == 201 - response = api_client.get(api_routes.users, headers=admin_token, params={"perPage": -1}) + response = api_client.get(api_routes.admin_users, headers=admin_token, params={"perPage": -1}) assert response.status_code == 200 for user in response.json()["items"]: for user_token in user["tokens"] or []: @@ -39,7 +39,7 @@ def test_api_token_private(api_client: TestClient, admin_token): def test_use_token(api_client: TestClient, long_live_token): - response = api_client.get(api_routes.users, headers=long_live_token) + response = api_client.get(api_routes.admin_users, headers=long_live_token) assert response.status_code == 200 diff --git a/tests/integration_tests/user_tests/test_user_crud.py b/tests/integration_tests/user_tests/test_user_crud.py index 9d4a60e28..81a68bcc9 100644 --- a/tests/integration_tests/user_tests/test_user_crud.py +++ b/tests/integration_tests/user_tests/test_user_crud.py @@ -88,9 +88,11 @@ def test_user_update(api_client: TestClient, unique_user: TestUser, admin_user: def test_admin_updates(api_client: TestClient, admin_user: TestUser, unique_user: TestUser): - response = api_client.get(api_routes.users_item_id(unique_user.user_id), headers=admin_user.token) + response = api_client.get(api_routes.admin_users_item_id(unique_user.user_id), headers=admin_user.token) + assert response.status_code == 200 user = response.json() - response = api_client.get(api_routes.users_item_id(admin_user.user_id), headers=admin_user.token) + + response = api_client.get(api_routes.admin_users_item_id(admin_user.user_id), headers=admin_user.token) admin = response.json() # admin updating themselves