diff --git a/backend/app/api/__init__.py b/backend/app/api/__init__.py index 6ba8f42..25ce026 100644 --- a/backend/app/api/__init__.py +++ b/backend/app/api/__init__.py @@ -1,6 +1,8 @@ from fastapi import APIRouter from app.api.routes import cart_routes, shop_routes, user_routes, utils_routes +from app.api.routes.shop import shop_login_routes, shop_user_routes + api_router = APIRouter() diff --git a/backend/app/api/routes/login_routes.py b/backend/app/api/routes/login_routes.py index a9dd21f..37c3cea 100644 --- a/backend/app/api/routes/login_routes.py +++ b/backend/app/api/routes/login_routes.py @@ -6,11 +6,14 @@ from fastapi.security import OAuth2PasswordRequestForm from app.api.dependencies import SessionDep -from app.schemas.user_schemas import Token - from app.core import security from app.core.config import settings +from app.schemas.user_schemas import Token + +from app.crud import user_crud + + router = APIRouter(tags=["login"]) @@ -22,9 +25,9 @@ def login_access_token( OAuth2 compatible token login, get an access token for future requests """ user = None - # user = crud.authenticate( - # session=session, email=form_data.username, password=form_data.password - # ) + user = user_crud.authenticate( + session=session, email=form_data.username, password=form_data.password, shop_id=None + ) if not user: raise HTTPException(status_code=400, detail="Incorrect email or password") elif not user: diff --git a/backend/app/api/routes/shop/__init__.py b/backend/app/api/routes/shop/__init__.py new file mode 100644 index 0000000..356dc67 --- /dev/null +++ b/backend/app/api/routes/shop/__init__.py @@ -0,0 +1,8 @@ +from fastapi import APIRouter + +from app.api.routes.shop import shop_login_routes, shop_user_routes + +api_router = APIRouter() + +api_router.include_router(shop_login_routes.router) +api_router.include_router(shop_user_routes.router) diff --git a/backend/app/api/routes/shop/shop_login_routes.py b/backend/app/api/routes/shop/shop_login_routes.py new file mode 100644 index 0000000..faafd97 --- /dev/null +++ b/backend/app/api/routes/shop/shop_login_routes.py @@ -0,0 +1,41 @@ +from typing import Annotated +from datetime import timedelta + +from fastapi import APIRouter, HTTPException, Depends +from fastapi.security import OAuth2PasswordRequestForm + +from app.api.dependencies import SessionDep + +from app.core import security +from app.core.config import settings + +from app.schemas.user_schemas import Token + +from app.crud import user_crud + + +router = APIRouter(tags=["Shop-Login"]) + + +@router.post("/login/access-token") +def login_access_token( + session: SessionDep, + form_data: Annotated[OAuth2PasswordRequestForm, Depends()] +) -> Token: + """ + OAuth2 compatible token login, get an access token for future requests + """ + user = None + user = user_crud.authenticate( + session=session, email=form_data.username, password=form_data.password, shop_id=None + ) + if not user: + raise HTTPException(status_code=400, detail="Incorrect email or password") + elif not user: + raise HTTPException(status_code=400, detail="Inactive user") + access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) + return Token( + access_token=security.create_access_token( + user.id, expires_delta=access_token_expires + ) + ) diff --git a/backend/app/api/routes/shop/shop_user_routes.py b/backend/app/api/routes/shop/shop_user_routes.py new file mode 100644 index 0000000..db36aa4 --- /dev/null +++ b/backend/app/api/routes/shop/shop_user_routes.py @@ -0,0 +1,37 @@ +import uuid +from typing import Annotated + +from fastapi import APIRouter, Body, Path + +from app.schemas.user_schemas import UserRegisterSchema, UserLoginSchema + + +router = APIRouter( + prefix="/user", + tags=["Shop-Users"] +) + + +@router.delete("/delete", summary="Delete user") +async def delete_user(shop_uuid=Annotated[uuid.UUID, Path(title="UUID of the shop")]): + raise NotImplementedError("delete_user() needs to be implemented.") + + +@router.post("/login", summary="User login") +async def login(login_data: UserLoginSchema, shop_uuid=Annotated[uuid.UUID, Path(title="UUID of the shop")]): + raise NotImplementedError("login() needs to be implemented.") + + +@router.delete("/logout", summary="User logout") +async def logout(): + raise NotImplementedError("logout() needs to be implemented.") + + +@router.post("/register", summary="Register new user") +async def register(user_data: UserRegisterSchema): + raise NotImplementedError() + + +@router.put("/update", summary="Update user details") +async def update_user(data: dict = Body(...)): + raise NotImplementedError("update_user() needs to be implemented.") diff --git a/backend/app/api/routes/shop_routes.py b/backend/app/api/routes/shop_routes.py index f033b78..358a096 100644 --- a/backend/app/api/routes/shop_routes.py +++ b/backend/app/api/routes/shop_routes.py @@ -1,11 +1,14 @@ -from fastapi import APIRouter +import uuid +from typing import Annotated + +from fastapi import APIRouter, Path router = APIRouter( - prefix="/shop", + prefix="/shop/{shop_uuid}", tags=["Shop"] ) -@router.get("/") -async def get_shop_info(): +@router.get("/login") +async def get_shop_info(shop_uuid=Annotated[uuid.UUID, Path(title="UUID of the shop")]): raise NotImplementedError diff --git a/backend/app/api/routes/user_routes.py b/backend/app/api/routes/user_routes.py index 92cfef0..15f1151 100644 --- a/backend/app/api/routes/user_routes.py +++ b/backend/app/api/routes/user_routes.py @@ -2,7 +2,6 @@ from fastapi import APIRouter, Body from app.schemas.user_schemas import UserRegisterSchema, UserLoginSchema -from app.services.user_service import create_user router = APIRouter( prefix="/user", diff --git a/backend/app/services/cart_service.py b/backend/app/crud/cart_service.py similarity index 100% rename from backend/app/services/cart_service.py rename to backend/app/crud/cart_service.py diff --git a/backend/app/services/product/product_create_service.py b/backend/app/crud/product/product_create_service.py similarity index 100% rename from backend/app/services/product/product_create_service.py rename to backend/app/crud/product/product_create_service.py diff --git a/backend/app/services/product/product_delete_service.py b/backend/app/crud/product/product_delete_service.py similarity index 100% rename from backend/app/services/product/product_delete_service.py rename to backend/app/crud/product/product_delete_service.py diff --git a/backend/app/services/product/product_helper.py b/backend/app/crud/product/product_helper.py similarity index 100% rename from backend/app/services/product/product_helper.py rename to backend/app/crud/product/product_helper.py diff --git a/backend/app/services/product/product_info_service.py b/backend/app/crud/product/product_info_service.py similarity index 100% rename from backend/app/services/product/product_info_service.py rename to backend/app/crud/product/product_info_service.py diff --git a/backend/app/services/product/product_list_service.py b/backend/app/crud/product/product_list_service.py similarity index 100% rename from backend/app/services/product/product_list_service.py rename to backend/app/crud/product/product_list_service.py diff --git a/backend/app/services/user/delete_service.py b/backend/app/crud/user/delete_service.py similarity index 100% rename from backend/app/services/user/delete_service.py rename to backend/app/crud/user/delete_service.py diff --git a/backend/app/services/user/login_service.py b/backend/app/crud/user/login_service.py similarity index 100% rename from backend/app/services/user/login_service.py rename to backend/app/crud/user/login_service.py diff --git a/backend/app/services/user/logout_service.py b/backend/app/crud/user/logout_service.py similarity index 100% rename from backend/app/services/user/logout_service.py rename to backend/app/crud/user/logout_service.py diff --git a/backend/app/services/user/register_service.py b/backend/app/crud/user/register_service.py similarity index 100% rename from backend/app/services/user/register_service.py rename to backend/app/crud/user/register_service.py diff --git a/backend/app/services/user/update_user_service.py b/backend/app/crud/user/update_user_service.py similarity index 100% rename from backend/app/services/user/update_user_service.py rename to backend/app/crud/user/update_user_service.py diff --git a/backend/app/services/user/user_helper.py b/backend/app/crud/user/user_helper.py similarity index 100% rename from backend/app/services/user/user_helper.py rename to backend/app/crud/user/user_helper.py diff --git a/backend/app/crud/user_crud.py b/backend/app/crud/user_crud.py new file mode 100644 index 0000000..2193774 --- /dev/null +++ b/backend/app/crud/user_crud.py @@ -0,0 +1,23 @@ +from typing import Optional +from sqlmodel import Session, select + +from app.database.models.user_model import User +from app.core.security import verify_password +from app.utils.models import generate_user_uuid5 + +def get_user_by_generated_uuid(session: Session, email: str, shop_id: Optional[int]) -> Optional[User]: + user_uuid = generate_user_uuid5(email, shop_id) + stmt = select(User).where(User.uuid == user_uuid) + db_user = session.exec(stmt).one_or_none() + return db_user + +def create_user(session: Session): + raise NotImplementedError() + +def authenticate(session: Session, email: str, password: str, shop_id: Optional[int]) -> Optional[User]: + db_user = get_user_by_generated_uuid(session, email, shop_id) + if db_user is None: + return None + if not verify_password(plain_password=password, hashed_password=db_user.password): + return None + return db_user diff --git a/backend/app/services/user_service.py b/backend/app/services/user_service.py deleted file mode 100644 index 98b490a..0000000 --- a/backend/app/services/user_service.py +++ /dev/null @@ -1,19 +0,0 @@ -from app.database.models.user_model import User - -from app.schemas.user_schemas import UserRegisterSchema - -from app.core.security import get_password_hash - - -def create_user(user_data: UserRegisterSchema): - print("Creating account") - with DatabaseManager.get_session() as session: - user = User( - username=user_data.username, - password=get_password_hash(user_data.password), - email=user_data.email, - phone_number=user_data.phone_number, - shop_id=user_data.shop_id - ) - session.add(user) - session.commit()