- Replace `except Exception` with specific exception types in google_wallet_service.py (requests.RequestException, ValueError, etc.) and apple_wallet_service.py (httpx.HTTPError, OSError, ssl.SSLError) - Rename loyalty_onboarding.py -> loyalty_onboarding_service.py to match NAM-002 naming convention (+ test file + imports) - Add PasswordChangeResponse Pydantic model to user_account API, removing raw dict return and noqa suppression Resolves 12 EXC-003 + 1 NAM-002 architecture warnings in loyalty module. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
# app/modules/tenancy/routes/api/user_account.py
|
|
"""
|
|
Self-service account API routes.
|
|
|
|
Provides GET/PUT /account/me and PUT /account/me/password
|
|
for admin, store, and merchant frontends.
|
|
"""
|
|
|
|
import logging
|
|
from collections.abc import Callable
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.database import get_db
|
|
from app.modules.tenancy.schemas.auth import UserContext
|
|
from app.modules.tenancy.schemas.user_account import (
|
|
PasswordChangeResponse,
|
|
UserAccountResponse,
|
|
UserAccountUpdate,
|
|
UserPasswordChange,
|
|
)
|
|
from app.modules.tenancy.services.user_account_service import user_account_service
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def create_account_router(auth_dependency: Callable) -> APIRouter:
|
|
"""Create an account/me router bound to the given auth dependency."""
|
|
router = APIRouter(prefix="/account/me")
|
|
|
|
@router.get("", response_model=UserAccountResponse)
|
|
async def get_my_account(
|
|
current_user: UserContext = Depends(auth_dependency),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Get the logged-in user's account info."""
|
|
return user_account_service.get_account(db, current_user.id)
|
|
|
|
@router.put("", response_model=UserAccountResponse)
|
|
async def update_my_account(
|
|
update_data: UserAccountUpdate,
|
|
current_user: UserContext = Depends(auth_dependency),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Update the logged-in user's account info."""
|
|
result = user_account_service.update_account(
|
|
db, current_user.id, update_data.model_dump(exclude_unset=True)
|
|
)
|
|
db.commit()
|
|
return result
|
|
|
|
@router.put("/password", response_model=PasswordChangeResponse)
|
|
async def change_my_password(
|
|
password_data: UserPasswordChange,
|
|
current_user: UserContext = Depends(auth_dependency),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Change the logged-in user's password."""
|
|
user_account_service.change_password(
|
|
db, current_user.id, password_data.model_dump()
|
|
)
|
|
db.commit()
|
|
return PasswordChangeResponse(message="Password changed successfully")
|
|
|
|
return router
|
|
|
|
|
|
# Create routers for each frontend
|
|
from app.api.deps import (
|
|
get_current_admin_api,
|
|
get_current_merchant_api,
|
|
get_current_store_api,
|
|
)
|
|
|
|
admin_account_router = create_account_router(get_current_admin_api)
|
|
store_account_router = create_account_router(get_current_store_api)
|
|
merchant_account_router = create_account_router(get_current_merchant_api)
|