
- Built complete CEX platform with FastAPI and Python - JWT-based authentication system with secure password hashing - Multi-currency crypto wallet support (BTC, ETH, USDT) - Fiat account management (USD, EUR, GBP) - Local transaction signing without external APIs - Comprehensive transaction handling (send/receive/deposit/withdraw) - SQLAlchemy models with Alembic migrations - Security middleware (rate limiting, headers, logging) - Input validation and sanitization - Encrypted private key storage with PBKDF2 - Standardized codebase architecture with service layer pattern - Complete API documentation with health endpoints - Comprehensive README with setup instructions Features: - User registration and authentication - Crypto wallet creation and management - Secure transaction signing using local private keys - Fiat deposit/withdrawal system - Transaction history and tracking - Rate limiting and security headers - Input validation for all endpoints - Error handling and logging
80 lines
2.6 KiB
Python
80 lines
2.6 KiB
Python
from sqlalchemy.orm import Session
|
|
from fastapi import HTTPException, status, Depends
|
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
from app.models.user import User
|
|
from app.schemas.user import UserCreate, UserLogin
|
|
from app.core.security import verify_password, get_password_hash, verify_token
|
|
from app.db.session import get_db
|
|
|
|
security = HTTPBearer()
|
|
|
|
|
|
class AuthService:
|
|
def __init__(self, db: Session):
|
|
self.db = db
|
|
|
|
def create_user(self, user_data: UserCreate) -> User:
|
|
# Check if user already exists
|
|
existing_user = self.db.query(User).filter(User.email == user_data.email).first()
|
|
if existing_user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Email already registered"
|
|
)
|
|
|
|
# Create new user
|
|
hashed_password = get_password_hash(user_data.password)
|
|
db_user = User(
|
|
email=user_data.email,
|
|
hashed_password=hashed_password,
|
|
full_name=user_data.full_name,
|
|
phone_number=user_data.phone_number,
|
|
country=user_data.country
|
|
)
|
|
|
|
self.db.add(db_user)
|
|
self.db.commit()
|
|
self.db.refresh(db_user)
|
|
return db_user
|
|
|
|
def authenticate_user(self, login_data: UserLogin) -> User:
|
|
user = self.db.query(User).filter(User.email == login_data.email).first()
|
|
if not user or not verify_password(login_data.password, user.hashed_password):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Incorrect email or password"
|
|
)
|
|
|
|
if not user.is_active:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Account is inactive"
|
|
)
|
|
|
|
return user
|
|
|
|
def get_user_by_email(self, email: str) -> User:
|
|
return self.db.query(User).filter(User.email == email).first()
|
|
|
|
|
|
def get_current_user(
|
|
credentials: HTTPAuthorizationCredentials = Depends(security),
|
|
db: Session = Depends(get_db)
|
|
) -> User:
|
|
token = credentials.credentials
|
|
email = verify_token(token)
|
|
if email is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Could not validate credentials"
|
|
)
|
|
|
|
auth_service = AuthService(db)
|
|
user = auth_service.get_user_by_email(email)
|
|
if user is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="User not found"
|
|
)
|
|
|
|
return user |