Files
banban/mini-program/app/routers/auth.py
2026-03-26 11:06:10 +08:00

96 lines
3.1 KiB
Python

import hashlib
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import text
from sqlalchemy.orm import Session
try:
# For module mode: `uvicorn app.main:app`
from app.db import get_db
from app.schemas.auth import LoginRequest, LoginResponse
from app.security import create_access_token
except ModuleNotFoundError:
# For script mode: `python app/main.py` or VS Code "Run Python File"
from db import get_db
from schemas.auth import LoginRequest, LoginResponse
from security import create_access_token
router = APIRouter(prefix="/auth", tags=["auth"])
@router.post("/login", response_model=LoginResponse)
def login(payload: LoginRequest, db: Session = Depends(get_db)) -> LoginResponse:
with db.begin():
row = (
db.execute(
text(
"""
SELECT
ua.id AS user_auth_id,
ua.user_id,
ua.password_hash,
ua.status AS auth_status,
u.status AS user_status
FROM chat_user_auth ua
JOIN chat_user u ON u.id = ua.user_id
WHERE ua.auth_type = 6
AND ua.auth_identifier = :username
LIMIT 1
"""
),
{"username": payload.username},
)
.mappings()
.first()
)
if not row:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="invalid username or password",
)
if int(row["auth_status"]) != 1 or int(row["user_status"]) != 1:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="account is disabled",
)
# Seed data currently stores sha256; migrate to bcrypt/argon2 in production.
password_hash = hashlib.sha256(payload.password.encode("utf-8")).hexdigest()
if not row["password_hash"] or password_hash != row["password_hash"]:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="invalid username or password",
)
db.execute(
text(
"""
UPDATE chat_user_auth
SET last_login_at = CURRENT_TIMESTAMP(3),
updated_at = CURRENT_TIMESTAMP(3)
WHERE id = :user_auth_id
"""
),
{"user_auth_id": int(row["user_auth_id"])},
)
db.execute(
text(
"""
UPDATE chat_user
SET last_login_at = CURRENT_TIMESTAMP(3),
updated_at = CURRENT_TIMESTAMP(3)
WHERE id = :user_id
"""
),
{"user_id": int(row["user_id"])},
)
access_token, expires_in = create_access_token(user_id=int(row["user_id"]))
return LoginResponse(
access_token=access_token,
expires_in=expires_in,
user_id=int(row["user_id"]),
)