Fix backend bugs: password hash column rename, dynamic import, AuditLog response_model, websocket reference, missing exports, bcrypt version pin
This commit is contained in:
@@ -29,6 +29,9 @@ class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
|
||||
__all__ = ["Base", "get_db", "async_session", "engine"]
|
||||
|
||||
|
||||
async def get_db() -> AsyncSession:
|
||||
"""FastAPI dependency that provides a database session."""
|
||||
async with async_session() as session:
|
||||
|
||||
@@ -15,7 +15,7 @@ class User(Base):
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
username = Column(String(64), unique=True, nullable=False, index=True)
|
||||
password_sha512 = Column(String(128), nullable=False) # bcrypt hash
|
||||
password_hash = Column(String(128), nullable=False) # bcrypt hash
|
||||
salt = Column(String(128), nullable=False) # password salt
|
||||
email = Column(String(255), nullable=True, index=True)
|
||||
country = Column(String(2), nullable=True)
|
||||
|
||||
@@ -184,7 +184,7 @@ async def list_logs(
|
||||
]
|
||||
|
||||
|
||||
@router.post("/audit", response_model=AuditLog)
|
||||
@router.post("/audit", response_model=dict)
|
||||
async def log_audit(
|
||||
action_type: str,
|
||||
target_user_id: Optional[int] = None,
|
||||
@@ -210,4 +210,11 @@ async def log_audit(
|
||||
db.add(new_audit)
|
||||
await db.flush()
|
||||
|
||||
return AuditLog.model_validate(new_audit)
|
||||
return {
|
||||
"id": new_audit.id,
|
||||
"admin_id": new_audit.admin_id,
|
||||
"action_type": new_audit.action_type,
|
||||
"target_user_id": new_audit.target_user_id,
|
||||
"details": new_audit.details,
|
||||
"timestamp": new_audit.timestamp,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from typing import Optional
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.security import (
|
||||
verify_password,
|
||||
@@ -33,7 +35,7 @@ async def login(request: LoginRequest, db: AsyncSession = Depends(get_db)):
|
||||
result = await db.execute(stmt)
|
||||
user = result.scalar_one_or_none()
|
||||
|
||||
if not user or not verify_password(request.password, user.password_sha512):
|
||||
if not user or not verify_password(request.password, user.password_hash):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid username or password",
|
||||
@@ -120,7 +122,7 @@ async def register(request: UserCreate, db: AsyncSession = Depends(get_db)):
|
||||
# Create new user
|
||||
new_user = User(
|
||||
username=request.username,
|
||||
password_sha512=hash_password(request.password),
|
||||
password_hash=hash_password(request.password),
|
||||
salt="random_salt", # In production, generate random salt
|
||||
email=request.email,
|
||||
country=request.country,
|
||||
|
||||
@@ -62,7 +62,7 @@ async def update_user(
|
||||
|
||||
# Hash new password if provided
|
||||
if "new_password" in update_data:
|
||||
update_data["password_sha512"] = hash_password(update_data.pop("new_password"))
|
||||
update_data["password_hash"] = hash_password(update_data.pop("new_password"))
|
||||
|
||||
# Update user
|
||||
stmt = (
|
||||
|
||||
@@ -236,7 +236,7 @@ async def game_websocket_endpoint(websocket: WebSocket, game_id: int):
|
||||
})
|
||||
elif message.get("type") == "ping":
|
||||
# Respond to ping
|
||||
await websocket.send_text(json.dumps({
|
||||
await room.send_to_player(player_id, {
|
||||
"type": "pong",
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
}))
|
||||
@@ -294,7 +294,7 @@ async def process_game_command(room: GameRoom, player_id: int, command: dict):
|
||||
GAME_COMMAND_JUDGE,
|
||||
GAME_COMMAND_REVERSE_TURN,
|
||||
]:
|
||||
await websocket.send_text(json.dumps({
|
||||
await room.send_to_player(player_id, {
|
||||
"type": "error",
|
||||
"message": f"Invalid command type: {cmd_type}",
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user