Skip to content

Commit b37d849

Browse files
committed
code update: update Address, Analytics, Cart, CartLine, Catalogue, Checkout, Communication, Customer, Dashboard, Offer, Order, Partner, Payment, Search, Shipping, Voucher, and Wishlist
1 parent adbc8c9 commit b37d849

64 files changed

Lines changed: 2427 additions & 221 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Dockerfile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
FROM python:3.12-slim
22

3-
WORKDIR /app
3+
WORKDIR /fast-api/app
44

55
COPY requirements.txt .
66
RUN pip install --no-cache-dir -r requirements.txt
7+
ENV PYTHONPATH="/fast-api/app"
78

8-
COPY ./app/ .
9+
# Copy the entire app directory
10+
COPY ./app /fast-api/app
911

12+
# Set PYTHONPATH to ensure imports work correctly
13+
ENV PYTHONPATH="/fast-api"
14+
15+
16+
# CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,6 @@ log:
5151

5252
ssh:
5353
docker-compose exec app bash
54+
55+
restart:
56+
docker-compose restart $(target)

app/api/v1/address.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# app/api/v1/address.py
2+
from fastapi import APIRouter, Depends, HTTPException, Request
3+
from sqlalchemy.orm import Session
4+
5+
from app.core.db.connect import get_db
6+
from app.models.address import Address
7+
from app.models.user import User, UserRole
8+
from app.schemas.address import AddressCreate, AddressResponse, AddressUpdate
9+
from app.schemas.base import Failed, Successfully
10+
from app.services.address import AddressService
11+
12+
router = APIRouter(prefix="/addresses", tags=["addresses"])
13+
14+
15+
def get_current_user(request: Request) -> User:
16+
"""Dependency to get the current user from request.state."""
17+
user = request.state.user
18+
if not user:
19+
raise HTTPException(status_code=401, detail="Authentication required")
20+
return user
21+
22+
23+
def get_admin_user(current_user: User = Depends(get_current_user)) -> User:
24+
"""Dependency to ensure the user is an admin."""
25+
if current_user.role != UserRole.ADMIN: # type: ignore[comparison-overlap]
26+
raise HTTPException(status_code=403, detail="Admin access required")
27+
return current_user
28+
29+
30+
@router.post("/", response_model=Successfully[AddressResponse])
31+
async def create_address(
32+
address: AddressCreate,
33+
current_user: User = Depends(get_current_user),
34+
db: Session = Depends(get_db),
35+
):
36+
"""Create a new address for the authenticated user."""
37+
address_service = AddressService(db)
38+
address.user_id = current_user.id
39+
new_address = address_service.create(address)
40+
return Successfully(
41+
code=201,
42+
msg="Address created successfully",
43+
data=AddressResponse.from_orm(new_address),
44+
)
45+
46+
47+
@router.get("/me", response_model=Successfully[list[AddressResponse]])
48+
async def get_my_addresses(
49+
skip: int = 0,
50+
limit: int = 100,
51+
current_user: User = Depends(get_current_user),
52+
db: Session = Depends(get_db),
53+
):
54+
addresses = (
55+
db.query(Address)
56+
.filter(Address.user_id == current_user.id)
57+
.offset(skip)
58+
.limit(limit)
59+
.all()
60+
)
61+
return Successfully(
62+
code=200,
63+
msg="Addresses retrieved successfully",
64+
data=[AddressResponse.from_orm(addr) for addr in addresses],
65+
)
66+
67+
68+
@router.get("/{address_id}", response_model=Successfully[AddressResponse])
69+
async def get_address(
70+
address_id: int,
71+
current_user: User = Depends(get_current_user),
72+
db: Session = Depends(get_db),
73+
):
74+
"""Get a specific address by ID (restricted to owner or admin)."""
75+
address_service = AddressService(db)
76+
address = address_service.get(address_id)
77+
if not address:
78+
return Failed(code=404, msg="Address not found")
79+
if address.user_id != current_user.id and current_user.role != UserRole.ADMIN:
80+
raise HTTPException(
81+
status_code=403, detail="Not authorized to view this address"
82+
)
83+
return Successfully(
84+
code=200,
85+
msg="Address retrieved successfully",
86+
data=AddressResponse.from_orm(address),
87+
)
88+
89+
90+
@router.put("/{address_id}", response_model=Successfully[AddressResponse])
91+
async def update_address(
92+
address_id: int,
93+
address_update: AddressUpdate,
94+
current_user: User = Depends(get_current_user),
95+
db: Session = Depends(get_db),
96+
):
97+
"""Update an address (restricted to owner or admin)."""
98+
address_service = AddressService(db)
99+
address = address_service.get(address_id)
100+
if not address:
101+
return Failed(code=404, msg="Address not found")
102+
if address.user_id != current_user.id and current_user.role != UserRole.ADMIN:
103+
raise HTTPException(
104+
status_code=403, detail="Not authorized to update this address"
105+
)
106+
updated_address = address_service.update(address, address_update)
107+
return Successfully(
108+
code=200,
109+
msg="Address updated successfully",
110+
data=AddressResponse.from_orm(updated_address),
111+
)
112+
113+
114+
@router.delete("/{address_id}", response_model=Successfully[None])
115+
async def delete_address(
116+
address_id: int,
117+
current_user: User = Depends(get_current_user),
118+
db: Session = Depends(get_db),
119+
):
120+
"""Delete an address (restricted to owner or admin)."""
121+
address_service = AddressService(db)
122+
address = address_service.get(address_id)
123+
if not address:
124+
return Failed(code=404, msg="Address not found")
125+
if address.user_id != current_user.id and current_user.role != UserRole.ADMIN:
126+
raise HTTPException(
127+
status_code=403, detail="Not authorized to delete this address"
128+
)
129+
address_service.remove(address_id)
130+
return Successfully(
131+
code=200,
132+
msg="Address deleted successfully",
133+
data=None,
134+
)

app/api/v1/auth.py

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,83 @@
1-
from fastapi import APIRouter, Depends
2-
import jwt
3-
from sqlalchemy.orm import Session
1+
from fastapi import APIRouter, BackgroundTasks, Depends
42
from fastapi.security import OAuth2PasswordRequestForm
3+
from sqlalchemy.orm import Session
54

6-
7-
from app.core.auth_handler import sign_jwt, sign_refresh_token, decode_jwt
85
from app.core.db.connect import get_db
9-
from app.core.security import get_password_hash
10-
from app.models.user import User
116
from app.schemas.auth import (
12-
JWTBearer,
13-
UserCreate,
14-
UserResponse,
7+
ConfirmPasswordRequest,
158
RefreshTokenRequest,
9+
ResetPasswordRequest,
10+
UserCreate,
1611
)
17-
from app.schemas.base import Failed, Successfully
12+
from app.schemas.base import Successfully
13+
from app.services.auth import AuthService
1814

1915
router = APIRouter(prefix="/auth", tags=["auth"])
2016

2117

18+
def get_auth_service(db: Session = Depends(get_db)) -> AuthService:
19+
return AuthService(db)
20+
21+
2222
@router.post("/login")
2323
def login(
2424
form_data: OAuth2PasswordRequestForm = Depends(),
25-
db: Session = Depends(get_db),
25+
auth_service: AuthService = Depends(get_auth_service),
2626
):
27-
user = db.query(User).filter(User.username == form_data.username).first()
28-
print(user)
29-
if not user or not user.verify_password(form_data.password):
30-
return Failed(status="fail", code=404, msg="Invalid username or password")
31-
user.update_last_login()
32-
db.commit()
33-
id = str(user.id)
34-
access_token, refresh_token = sign_jwt(id), sign_refresh_token(id)
35-
jwt_token = JWTBearer(
36-
access_token=access_token, refresh_token=refresh_token, token_type="bearer"
37-
)
27+
jwt_token = auth_service.login(form_data.username, form_data.password)
3828
return Successfully(
3929
code=200, msg="Login successfully", data=jwt_token, status="success"
4030
)
4131

4232

43-
@router.post("/register", response_model=UserResponse)
44-
async def register(user: UserCreate, db: Session = Depends(get_db)):
45-
existing_user = (
46-
db.query(User)
47-
.filter((User.username == user.username) | (User.email == user.email))
48-
.first()
33+
@router.post("/register")
34+
async def register(
35+
user: UserCreate,
36+
background_tasks: BackgroundTasks,
37+
auth_service: AuthService = Depends(get_auth_service),
38+
):
39+
new_user = auth_service.register(user, background_tasks)
40+
return Successfully(status="success", code=201, msg="User created", data=new_user)
41+
42+
43+
@router.post("/refresh")
44+
def refresh_token(
45+
refresh_token_request: RefreshTokenRequest,
46+
auth_service: AuthService = Depends(get_auth_service),
47+
):
48+
new_access_token = auth_service.refresh_token(refresh_token_request)
49+
return Successfully(
50+
status="success", code=200, msg="Refresh token", data=new_access_token
4951
)
5052

51-
if existing_user:
52-
return Failed(status="fail", code=400, msg="Username or email already exists")
53-
hashed_password = get_password_hash(user.password)
5453

55-
new_user = User(
56-
username=user.username, email=user.email, hashed_password=hashed_password
54+
@router.post("/reset-password-request")
55+
def reset_password_request(
56+
email: str,
57+
auth_service: AuthService = Depends(get_auth_service),
58+
):
59+
reset_token = auth_service.reset_password_request(email)
60+
return Successfully(
61+
code=200,
62+
msg="Reset password token sent",
63+
data=reset_token,
64+
status="success",
5765
)
5866

59-
db.add(new_user)
60-
db.commit()
61-
db.refresh(new_user)
6267

63-
return Successfully(status="fail", code=201, msg="User created", data=user)
68+
@router.post("/reset-password")
69+
def reset_password(
70+
request: ResetPasswordRequest,
71+
auth_service: AuthService = Depends(get_auth_service),
72+
):
73+
auth_service.reset_password(request)
74+
return Successfully(code=200, msg="Password reset successfully", status="success")
6475

6576

66-
@router.post("/refresh")
67-
def refresh_token(refresh_token_request: RefreshTokenRequest):
68-
try:
69-
payload = decode_jwt(refresh_token_request.refresh_token)
70-
user_id = payload.get("id")
71-
if not user_id:
72-
return Failed(status="fail", code=401, msg="Invalid refresh token")
73-
new_access_token = sign_jwt(user_id)
74-
75-
return Successfully(
76-
status="success", code=200, msg="Refresh token", data=new_access_token
77-
)
78-
except jwt.ExpiredSignatureError:
79-
return Failed(status="fail", code=401, msg="Refresh token is expired")
80-
except jwt.PyJWKError:
81-
return Failed(status="fail", code=401, msg="Invalid refresh token")
77+
@router.post("/confirm-password")
78+
def confirm_password(
79+
request: ConfirmPasswordRequest,
80+
auth_service: AuthService = Depends(get_auth_service),
81+
):
82+
auth_service.confirm_password(request)
83+
return Successfully(code=200, msg="Password updated successfully", status="success")

0 commit comments

Comments
 (0)