Merge commit '509747d4d9a6310520542db16b004b6c7cd049a5'

This commit is contained in:
Alexa Amundson
2025-11-16 01:59:54 -06:00
4 changed files with 114 additions and 9 deletions

View File

@@ -1,8 +1,8 @@
"""Authentication routes"""
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from fastapi import APIRouter, Depends, HTTPException, status, Form
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import Optional
from app.database import get_db
from app.models.user import User
@@ -21,6 +21,29 @@ from datetime import datetime
router = APIRouter(prefix="/api/auth", tags=["Authentication"])
# Backwards compatibility for modules importing get_current_user from this router
get_current_user = get_current_active_user
class SimpleOAuth2PasswordRequestForm:
"""Minimal form parser compatible with OAuth2 password flow"""
def __init__(
self,
grant_type: Optional[str] = Form(default=None),
username: str = Form(...),
password: str = Form(...),
scope: str = Form(default=""),
client_id: Optional[str] = Form(default=None),
client_secret: Optional[str] = Form(default=None)
):
self.grant_type = grant_type
self.username = username
self.password = password
self.scopes = scope.split()
self.client_id = client_id
self.client_secret = client_secret
@router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def register(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
@@ -84,7 +107,7 @@ async def register(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
@router.post("/login", response_model=Token)
async def login(
form_data: OAuth2PasswordRequestForm = Depends(),
form_data: SimpleOAuth2PasswordRequestForm = Depends(),
db: AsyncSession = Depends(get_db)
):
"""Login and get access token"""

View File

@@ -3,7 +3,7 @@ from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_, or_, desc, func
from typing import List, Optional
from pydantic import BaseModel
from pydantic import BaseModel, Field
from datetime import datetime
from app.database import get_db
@@ -16,9 +16,12 @@ from app.services.crypto import WalletKeyDecryptionError
router = APIRouter(prefix="/api/blockchain", tags=["Blockchain"])
MIN_TRANSACTION_AMOUNT = 0.0001
class TransactionCreate(BaseModel):
to_address: str
amount: float
amount: float = Field(gt=0, description="Amount to transfer; must be positive")
message: Optional[str] = None
@@ -93,6 +96,18 @@ async def create_transaction(
db: AsyncSession = Depends(get_db)
):
"""Create a new transaction"""
if tx_data.amount <= 0:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Transaction amount must be greater than zero"
)
if tx_data.amount < MIN_TRANSACTION_AMOUNT:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Transactions must be at least {MIN_TRANSACTION_AMOUNT} tokens"
)
# Check balance
if current_user.balance < tx_data.amount:
raise HTTPException(
@@ -128,6 +143,11 @@ async def create_transaction(
)
# Update balances (simplified - in production would be done on block confirmation)
if tx_data.amount <= 0:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Transaction amount must be greater than zero"
)
current_user.balance -= tx_data.amount
recipient.balance += tx_data.amount