WIP checkpoint: Scaffold FastAPI backend project structure

This commit is contained in:
2026-08-17 18:27:26 +00:00
parent f3c679faab
commit 46a2ff672c
3 changed files with 16 additions and 11 deletions
+1
View File
@@ -11,6 +11,7 @@ from app.database import get_db
from app.models.asset import Asset, AssetType from app.models.asset import Asset, AssetType
from app.models.user import User from app.models.user import User
from app.models.world import World from app.models.world import World
from app.routers.worlds import get_current_user
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
router = APIRouter() router = APIRouter()
+6 -6
View File
@@ -49,11 +49,13 @@ def _create_access_token(data: dict) -> str:
return jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM) return jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
def _verify_password(plain_password: str, hashed_password: str) -> bool: def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Verify a plain password against a hash."""
return pwd_context.verify(plain_password, hashed_password) return pwd_context.verify(plain_password, hashed_password)
def _get_password_hash(password: str) -> str: def hash_password(password: str) -> str:
"""Hash a password."""
return pwd_context.hash(password) return pwd_context.hash(password)
@@ -81,7 +83,7 @@ async def register(req: RegisterRequest, db: AsyncSession = Depends(get_db)):
user = User( user = User(
username=req.username, username=req.username,
email=req.email, email=req.email,
hashed_password=_get_password_hash(req.password), hashed_password=hash_password(req.password),
) )
db.add(user) db.add(user)
await db.commit() await db.commit()
@@ -97,7 +99,7 @@ async def login(req: LoginRequest, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(User).where(User.username == req.username)) result = await db.execute(select(User).where(User.username == req.username))
user = result.scalar_one_or_none() user = result.scalar_one_or_none()
if not user or not _verify_password(req.password, user.hashed_password): if not user or not verify_password(req.password, user.hashed_password):
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password", detail="Incorrect username or password",
@@ -115,8 +117,6 @@ async def login(req: LoginRequest, db: AsyncSession = Depends(get_db)):
@router.get("/me") @router.get("/me")
async def get_current_user( async def get_current_user(
# In production, extract from Authorization header via OAuth2PasswordBearer
# For now, accept a user_id query param for simplicity
user_id: int, user_id: int,
db: AsyncSession = Depends(get_db), db: AsyncSession = Depends(get_db),
): ):
+9 -5
View File
@@ -13,7 +13,7 @@ from app.models.user import User
router = APIRouter() router = APIRouter()
# ── Pydantic schemas ──────────────────────────────────────────────── # ── Pydantic schemas ──────────────────────────────────────────────────────────
class UserCreate(BaseModel): class UserCreate(BaseModel):
username: str username: str
@@ -35,14 +35,17 @@ class UserUpdate(BaseModel):
is_active: bool | None = None is_active: bool | None = None
# ── Endpoints ──────────────────────────────────────────────────────── # ── Endpoints ─────────────────────────────────────────────────────────────────
@router.post( @router.post(
"/", "/",
response_model=UserResponse, response_model=UserResponse,
status_code=status.HTTP_201_CREATED, status_code=status.HTTP_201_CREATED,
) )
async def create_user(user_in: UserCreate, db: Annotated[AsyncSession, Depends(get_db)]): async def create_user(
user_in: UserCreate,
db: Annotated[AsyncSession, Depends(get_db)],
):
"""Register a new user.""" """Register a new user."""
# Check uniqueness of username # Check uniqueness of username
existing = await db.execute(select(User).where(User.username == user_in.username)) existing = await db.execute(select(User).where(User.username == user_in.username))
@@ -54,8 +57,9 @@ async def create_user(user_in: UserCreate, db: Annotated[AsyncSession, Depends(g
if existing.scalar_one_or_none(): if existing.scalar_one_or_none():
raise HTTPException(status_code=400, detail="Email already registered") raise HTTPException(status_code=400, detail="Email already registered")
from app.routers.auth import hash_password from app.routers.auth import _get_password_hash
hashed = hash_password(user_in.password)
hashed = _get_password_hash(user_in.password)
user = User( user = User(
username=user_in.username, username=user_in.username,