first commit
This commit is contained in:
191
routes/auth/current_user.py
Normal file
191
routes/auth/current_user.py
Normal file
@@ -0,0 +1,191 @@
|
||||
from fastapi import Depends, HTTPException, status, APIRouter
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, update
|
||||
import logging
|
||||
from database import get_db
|
||||
from models import Account_User, Customer_Customer, Customer_Description, Card
|
||||
from schemas import TokenData, CustomerUpdate
|
||||
from jose import JWTError, jwt
|
||||
from config import load_config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Load JWT configuration from environment
|
||||
ApplicationConfig = load_config()
|
||||
SECRET_KEY = ApplicationConfig.JWT_SECRET_KEY
|
||||
ALGORITHM = ApplicationConfig.JWT_ALGORITHM
|
||||
|
||||
async def get_current_user(token: str = Depends(OAuth2PasswordBearer(tokenUrl="auth/login")), db: AsyncSession = Depends(get_db)):
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
try:
|
||||
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||
username: str = payload.get("sub")
|
||||
if username is None:
|
||||
raise credentials_exception
|
||||
token_data = TokenData(username=username)
|
||||
except JWTError:
|
||||
raise credentials_exception
|
||||
user = await db.execute(select(Account_User).where(Account_User.username == token_data.username))
|
||||
user = user.scalar_one_or_none()
|
||||
if user is None:
|
||||
raise credentials_exception
|
||||
return user
|
||||
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login")
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/me")
|
||||
async def read_users_me(current_user: Account_User = Depends(get_current_user), db: AsyncSession = Depends(get_db)):
|
||||
# Get customer details for the current user using user_id
|
||||
customer = None
|
||||
if current_user.user_id:
|
||||
customer_result = await db.execute(select(Customer_Customer).where(Customer_Customer.id == current_user.user_id))
|
||||
customer = customer_result.scalar_one_or_none()
|
||||
|
||||
# Get house description if exists
|
||||
house_description = None
|
||||
if customer:
|
||||
description_record = await db.execute(
|
||||
select(Customer_Description).where(Customer_Description.customer_id == customer.id)
|
||||
)
|
||||
description_record = description_record.scalar_one_or_none()
|
||||
if description_record:
|
||||
house_description = description_record.description
|
||||
|
||||
# Map state code to name
|
||||
state_mapping = {0: "MA", 1: "NH"} # Add more as needed
|
||||
state_name = state_mapping.get(customer.customer_state, str(customer.customer_state)) if customer else None
|
||||
|
||||
return {
|
||||
"id": current_user.id,
|
||||
"username": current_user.username,
|
||||
"email": current_user.email,
|
||||
"account_number": current_user.account_number,
|
||||
"customer_first_name": customer.customer_first_name if customer else None,
|
||||
"customer_last_name": customer.customer_last_name if customer else None,
|
||||
"customer_address": customer.customer_address if customer else None,
|
||||
"customer_apt": customer.customer_apt if customer else None,
|
||||
"customer_town": customer.customer_town if customer else None,
|
||||
"customer_state": state_name,
|
||||
"customer_zip": customer.customer_zip if customer else None,
|
||||
"customer_phone_number": customer.customer_phone_number if customer else None,
|
||||
"customer_home_type": customer.customer_home_type if customer else None,
|
||||
"customer_email": customer.customer_email if customer else None,
|
||||
"house_description": house_description,
|
||||
"member_since": current_user.member_since,
|
||||
"last_seen": current_user.last_seen
|
||||
}
|
||||
|
||||
@router.put("/update-customer")
|
||||
async def update_customer_info(
|
||||
customer_data: CustomerUpdate,
|
||||
current_user: Account_User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
if not current_user.user_id:
|
||||
raise HTTPException(status_code=404, detail="Customer not found")
|
||||
|
||||
try:
|
||||
# Update Customer_Customer table
|
||||
customer_update_data = customer_data.dict(exclude_unset=True)
|
||||
customer_fields = {
|
||||
'customer_first_name', 'customer_last_name', 'customer_address', 'customer_apt',
|
||||
'customer_town', 'customer_state', 'customer_zip', 'customer_phone_number',
|
||||
'customer_home_type', 'customer_email'
|
||||
}
|
||||
|
||||
customer_update_dict = {k: v for k, v in customer_update_data.items() if k in customer_fields}
|
||||
|
||||
if customer_update_dict:
|
||||
await db.execute(
|
||||
update(Customer_Customer)
|
||||
.where(Customer_Customer.id == current_user.user_id)
|
||||
.values(**customer_update_dict)
|
||||
)
|
||||
|
||||
# Update house description if provided
|
||||
if 'house_description' in customer_update_data and customer_update_data['house_description']:
|
||||
# Get customer record
|
||||
customer = await db.execute(
|
||||
select(Customer_Customer).where(Customer_Customer.id == current_user.user_id)
|
||||
)
|
||||
customer = customer.scalar_one_or_none()
|
||||
|
||||
if customer:
|
||||
# Check if description record exists
|
||||
description_record = await db.execute(
|
||||
select(Customer_Description).where(Customer_Description.customer_id == customer.id)
|
||||
)
|
||||
description_record = description_record.scalar_one_or_none()
|
||||
|
||||
if description_record:
|
||||
# Update existing
|
||||
await db.execute(
|
||||
update(Customer_Description)
|
||||
.where(Customer_Description.customer_id == customer.id)
|
||||
.values(description=customer_update_data['house_description'])
|
||||
)
|
||||
else:
|
||||
# Create new
|
||||
new_description = Customer_Description(
|
||||
customer_id=customer.id,
|
||||
account_number=current_user.account_number,
|
||||
company_id=customer.company_id or 1,
|
||||
fill_location=0,
|
||||
description=customer_update_data['house_description']
|
||||
)
|
||||
db.add(new_description)
|
||||
|
||||
await db.commit()
|
||||
|
||||
# Sync billing info to Authorize.net if address-related fields were updated
|
||||
billing_fields = {
|
||||
'customer_first_name', 'customer_last_name', 'customer_address',
|
||||
'customer_town', 'customer_state', 'customer_zip', 'customer_phone_number',
|
||||
'customer_email'
|
||||
}
|
||||
if any(k in customer_update_dict for k in billing_fields):
|
||||
# Late import to avoid circular dependency
|
||||
from routes.payment.routes import update_customer_profile, update_payment_profile_billing
|
||||
|
||||
# Refetch the updated customer
|
||||
customer_result = await db.execute(
|
||||
select(Customer_Customer).where(Customer_Customer.id == current_user.user_id)
|
||||
)
|
||||
updated_customer = customer_result.scalar_one_or_none()
|
||||
|
||||
if updated_customer and updated_customer.auth_net_profile_id:
|
||||
# Update customer profile in Authorize.net
|
||||
update_customer_profile(updated_customer.auth_net_profile_id, updated_customer)
|
||||
|
||||
# Update all saved payment profiles with new billing info
|
||||
cards_result = await db.execute(
|
||||
select(Card).where(Card.user_id == updated_customer.id)
|
||||
)
|
||||
cards = cards_result.scalars().all()
|
||||
|
||||
for card in cards:
|
||||
if card.auth_net_payment_profile_id:
|
||||
update_payment_profile_billing(
|
||||
customer_profile_id=updated_customer.auth_net_profile_id,
|
||||
payment_profile_id=card.auth_net_payment_profile_id,
|
||||
customer=updated_customer,
|
||||
card=card
|
||||
)
|
||||
|
||||
logger.info(f"Synced billing info to Authorize.net for customer {updated_customer.id}")
|
||||
|
||||
return {"message": "Customer information updated successfully"}
|
||||
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Failed to update customer information: {str(e)}"
|
||||
)
|
||||
Reference in New Issue
Block a user