new web ract

This commit is contained in:
jze9
2026-05-15 03:31:28 +05:00
parent de78624495
commit 2335497226
58 changed files with 7397 additions and 406 deletions

View File

@@ -1,6 +1,6 @@
import os
from datetime import datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException, status
from datetime import datetime, timedelta, timezone
from fastapi import APIRouter, Depends, HTTPException, Request, status
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
@@ -9,17 +9,24 @@ from passlib.context import CryptContext
from bd.database import get_db, AsyncSessionLocal
from bd.models import Admin
from rate_limiter import limiter
router = APIRouter()
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
JWT_SECRET = os.getenv("JWT_SECRET", "changeme")
JWT_ALGO = "HS256"
JWT_EXP_HOURS = 24
_raw_secret = os.getenv("JWT_SECRET", "")
if not _raw_secret:
import secrets as _s
_raw_secret = _s.token_hex(32)
print("[WARN] JWT_SECRET не задан — сгенерирован временный секрет. Установи JWT_SECRET в .env!")
JWT_SECRET = _raw_secret
JWT_ALGO = "HS256"
JWT_EXP_HOURS = 8
def _make_token(username: str) -> str:
exp = datetime.utcnow() + timedelta(hours=JWT_EXP_HOURS)
exp = datetime.now(timezone.utc) + timedelta(hours=JWT_EXP_HOURS)
return jwt.encode({"sub": username, "exp": exp}, JWT_SECRET, algorithm=JWT_ALGO)
@@ -40,7 +47,8 @@ class LoginRequest(BaseModel):
@router.post("/login")
async def login(data: LoginRequest, db: AsyncSession = Depends(get_db)):
@limiter.limit("5/minute")
async def login(request: Request, data: LoginRequest, db: AsyncSession = Depends(get_db)):
admin = (await db.execute(select(Admin).where(Admin.username == data.username))).scalar_one_or_none()
if not admin or not pwd_context.verify(data.password, admin.password_hash):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Неверный логин или пароль")
@@ -48,12 +56,7 @@ async def login(data: LoginRequest, db: AsyncSession = Depends(get_db)):
@router.post("/change-password")
async def change_password(
data: dict,
db: AsyncSession = Depends(get_db),
):
from route.deps import require_admin
# handled with deps in main
async def change_password(data: dict, db: AsyncSession = Depends(get_db)):
admin = (await db.execute(select(Admin).where(Admin.username == data["username"]))).scalar_one_or_none()
if not admin or not pwd_context.verify(data["current_password"], admin.password_hash):
raise HTTPException(status_code=400, detail="Неверный текущий пароль")