From 41be800175912b5fa47a53385f35f11e0f206d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=9F=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BF=D0=BE=D0=B2?= Date: Wed, 11 Jun 2025 00:38:44 +0400 Subject: [PATCH] =?UTF-8?q?=D1=87=D0=B5=D1=82=D0=BE=20=D0=BA=D0=B0=D0=BA?= =?UTF-8?q?=D0=B8=D0=B5=D1=82=D0=BE=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/auth/router.py | 17 +++++----- backend/app/main.py | 4 +++ backend/app/routers/__init__.py | 5 +++ backend/app/routers/user.py | 32 ------------------ backend/app/routers/users.py | 58 +++++++++++++++++++++++++++++++++ backend/app/schemas/__init__.py | 4 +-- backend/app/schemas/general.py | 20 ++++++++++-- backend/app/schemas/user.py | 32 ++++-------------- 8 files changed, 102 insertions(+), 70 deletions(-) delete mode 100644 backend/app/routers/user.py create mode 100644 backend/app/routers/users.py diff --git a/backend/app/auth/router.py b/backend/app/auth/router.py index a7cb511..6c77501 100644 --- a/backend/app/auth/router.py +++ b/backend/app/auth/router.py @@ -10,30 +10,29 @@ from app.dependencies.auth_dep import ( from app.dependencies.dao_dep import get_session_with_commit, get_session_without_commit from app.exceptions import UserAlreadyExistsException, IncorrectEmailOrPasswordException from app.models import User -from app.schemas import SUserRegister, SUserAuth, EmailModel, SUserAddDB, SUserInfo +from app.schemas import UserCreateSchema, UserAuthSchema, EmailSchema, UserAddDBSchema, UserSchema router = APIRouter() @router.post("/register") async def register_user( - user_data: SUserRegister, session: AsyncSession = Depends(get_session_with_commit) + user_data: UserCreateSchema, session: AsyncSession = Depends(get_session_with_commit) ) -> dict: # Проверка существования пользователя user_dao = UsersDAO(session) existing_user = await user_dao.find_one_or_none( - filters=EmailModel(email=user_data.email) + filters=EmailSchema(email=user_data.email) ) if existing_user: raise UserAlreadyExistsException # Подготовка данных для добавления user_data_dict = user_data.model_dump() - user_data_dict.pop("confirm_password", None) # Добавление пользователя - await user_dao.add(values=SUserAddDB(**user_data_dict)) + await user_dao.add(values=UserAddDBSchema(**user_data_dict)) return {"message": "Вы успешно зарегистрированы!"} @@ -41,11 +40,11 @@ async def register_user( @router.post("/login") async def auth_user( response: Response, - user_data: SUserAuth, + user_data: UserAuthSchema, session: AsyncSession = Depends(get_session_without_commit), ) -> dict: users_dao = UsersDAO(session) - user = await users_dao.find_one_or_none(filters=EmailModel(email=user_data.email)) + user = await users_dao.find_one_or_none(filters=EmailSchema(email=user_data.email)) if not (user and await authenticate_user(user=user, password=user_data.password)): raise IncorrectEmailOrPasswordException @@ -61,8 +60,8 @@ async def logout(response: Response): @router.get("/me") -async def get_me(user_data: User = Depends(get_current_user)) -> SUserInfo: - return SUserInfo.model_validate(user_data) +async def get_me(user_data: User = Depends(get_current_user)) -> UserSchema: + return UserSchema.model_validate(user_data) @router.post("/refresh") diff --git a/backend/app/main.py b/backend/app/main.py index 0fdc48d..b2fac5b 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -7,6 +7,7 @@ from fastapi.staticfiles import StaticFiles from loguru import logger from app.auth import router as auth_router +from app.routers import all_routers @asynccontextmanager @@ -58,6 +59,9 @@ def register_routers(app: FastAPI) -> None: # Подключение роутеров app.include_router(auth_router, prefix="/auth", tags=["Auth"]) + for router in all_routers: + app.include_router(router) + # Создание экземпляра приложения app = create_app() diff --git a/backend/app/routers/__init__.py b/backend/app/routers/__init__.py index e69de29..8a7f129 100644 --- a/backend/app/routers/__init__.py +++ b/backend/app/routers/__init__.py @@ -0,0 +1,5 @@ +from .users import router as users_router + +all_routers = [ + users_router +] diff --git a/backend/app/routers/user.py b/backend/app/routers/user.py deleted file mode 100644 index 175f625..0000000 --- a/backend/app/routers/user.py +++ /dev/null @@ -1,32 +0,0 @@ -from fastapi import APIRouter, Depends -from sqlalchemy.ext.asyncio import AsyncSession - -from app.schemas import SUserInfo -from app.dependencies.dao_dep import get_session_with_commit, get_session_without_commit - -router = APIRouter(prefix="/user") - - -@router.get("/{user_id}") -async def get_user_by_id(user_id: int, session: AsyncSession = Depends(get_session_without_commit)) -> SUserInfo: - pass - - -@router.get("/") -async def get_all_users(session: AsyncSession = Depends(get_session_without_commit)) -> list[SUserInfo]: - pass - - -@router.post("/") -async def create_user(user_data, session: AsyncSession = Depends(get_session_with_commit)) -> dict: - pass - - -@router.put("/{user_id}") -async def update_user(user_id: int, user_data, session: AsyncSession = Depends(get_session_with_commit)): - pass - - -@router.delete("/{user_id}") -async def delete_user(user_id: int, session: AsyncSession = Depends(get_session_with_commit)): - pass diff --git a/backend/app/routers/users.py b/backend/app/routers/users.py new file mode 100644 index 0000000..d597c99 --- /dev/null +++ b/backend/app/routers/users.py @@ -0,0 +1,58 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.ext.asyncio import AsyncSession + +from app.dao import UsersDAO +from app.dependencies.dao_dep import get_session_with_commit, get_session_without_commit +from app.exceptions import UserAlreadyExistsException +from app.schemas import UserSchema, EmailSchema, UserAddDBSchema + +router = APIRouter(prefix="/users", tags=["Users"]) + + +@router.get("/{user_id}") +async def get_user_by_id(user_id: int, session: AsyncSession = Depends(get_session_without_commit)) -> UserSchema: + user = await UsersDAO(session).find_one_or_none_by_id(data_id=user_id) + + if not user: + raise HTTPException(status_code=404) + + return UserSchema.model_validate(user) + + +@router.get("") +async def get_all_users(session: AsyncSession = Depends(get_session_without_commit)) -> list[UserSchema]: + users_dao = UsersDAO(session) + users = await users_dao.find_all() + return [UserSchema.model_validate(user) for user in users] + + +@router.post("") +async def create_user(user_data, session: AsyncSession = Depends(get_session_with_commit)) -> dict: + # Проверка существования пользователя + user_dao = UsersDAO(session) + + existing_user = await user_dao.find_one_or_none( + filters=EmailSchema(email=user_data.email) + ) + + if existing_user: + raise UserAlreadyExistsException + + # Подготовка данных для добавления + user_data_dict = user_data.model_dump() + user_data_dict.pop("confirm_password", None) + + # Добавление пользователя + await user_dao.add(values=UserAddDBSchema(**user_data_dict)) + + return {"message": "Вы успешно зарегистрированы!"} + + +@router.put("/{user_id}") +async def update_user(user_id: int, user_data, session: AsyncSession = Depends(get_session_with_commit)): + pass + + +@router.delete("/{user_id}") +async def delete_user(user_id: int, session: AsyncSession = Depends(get_session_with_commit)): + pass diff --git a/backend/app/schemas/__init__.py b/backend/app/schemas/__init__.py index 4c5a7d0..a4b6877 100644 --- a/backend/app/schemas/__init__.py +++ b/backend/app/schemas/__init__.py @@ -1,2 +1,2 @@ -from .general import EmailModel -from .user import UserBase, SUserInfo, SUserAddDB, SUserRegister, SUserAuth +from .general import EmailSchema +from .user import UserBaseSchema, UserSchema, UserAddDBSchema, UserCreateSchema, UserAuthSchema diff --git a/backend/app/schemas/general.py b/backend/app/schemas/general.py index 3582cb4..241bd08 100644 --- a/backend/app/schemas/general.py +++ b/backend/app/schemas/general.py @@ -1,11 +1,27 @@ +from typing import Self + from pydantic import ( BaseModel, ConfigDict, EmailStr, - Field, + Field, model_validator, ) +from app.auth.utils import get_password_hash -class EmailModel(BaseModel): + +class EmailSchema(BaseModel): email: EmailStr = Field(description="Электронная почта") model_config = ConfigDict(from_attributes=True) + + +class PasswordSchema(BaseModel): + password: str = Field( + min_length=5, max_length=50, description="Пароль, от 5 до 50 знаков" + ) + model_config = ConfigDict(from_attributes=True) + + @model_validator(mode="after") + def check_password(self) -> Self: + self.password = get_password_hash(self.password) + return self diff --git a/backend/app/schemas/user.py b/backend/app/schemas/user.py index 934ff61..9c79923 100644 --- a/backend/app/schemas/user.py +++ b/backend/app/schemas/user.py @@ -1,16 +1,12 @@ -from typing import Self - from pydantic import ( Field, - model_validator, ) -from app.auth.utils import get_password_hash from app.models.user import UserRole -from .general import EmailModel +from .general import EmailSchema, PasswordSchema -class UserBase(EmailModel): +class UserBaseSchema(EmailSchema): name: str = Field( min_length=3, max_length=50, description="Имя, от 3 до 50 символов" ) @@ -26,33 +22,19 @@ class UserBase(EmailModel): role: UserRole = Field(description="Роль пользователя в системе", default=UserRole.GUEST) -class SUserRegister(UserBase): - password: str = Field( - min_length=5, max_length=50, description="Пароль, от 5 до 50 знаков" - ) - confirm_password: str = Field( - min_length=5, max_length=50, description="Повторите пароль" - ) - - @model_validator(mode="after") - def check_password(self) -> Self: - if self.password != self.confirm_password: - raise ValueError("Пароли не совпадают") - self.password = get_password_hash( - self.password - ) # хешируем пароль до сохранения в базе данных - return self +class UserCreateSchema(PasswordSchema, UserBaseSchema): + pass -class SUserAddDB(UserBase): +class UserAddDBSchema(UserBaseSchema): password: str = Field(min_length=5, description="Пароль в формате HASH-строки") -class SUserAuth(EmailModel): +class UserAuthSchema(EmailSchema): password: str = Field( min_length=5, max_length=50, description="Пароль, от 5 до 50 знаков" ) -class SUserInfo(UserBase): +class UserSchema(UserBaseSchema): id: int = Field(description="Идентификатор пользователя") -- 2.25.1