Добавлено хеширование паролей для аккаунтов, обновлены функции авторизации и заполнения базы данных. Теперь пароли хранятся в виде хешей, улучшена безопасность системы.
This commit is contained in:
parent
4c4a84eefe
commit
1f11bd8012
@ -5,6 +5,7 @@ from main import AUTH_DB_ENGINE, TgAgent, Ref, Sale, Transaction, Account
|
||||
from sqlalchemy import text
|
||||
from datetime import datetime, timedelta
|
||||
from hashlib import sha256
|
||||
from passlib.context import CryptContext
|
||||
|
||||
|
||||
# Константа: список user_ids
|
||||
@ -62,6 +63,11 @@ LOGINS = [
|
||||
ALL_DESCRIPTIONS = DESCRIPTIONS
|
||||
|
||||
# ---
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
def get_password_hash(password):
|
||||
return pwd_context.hash(password)
|
||||
|
||||
def get_date_list(days=7):
|
||||
today = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
return [today - timedelta(days=i) for i in range(days, -1, -1)]
|
||||
@ -80,7 +86,7 @@ def fill_db():
|
||||
for i in range(4):
|
||||
acc = Account(
|
||||
login=f"user{i+1}",
|
||||
password="password123", # В реальном проекте пароли должны быть захешированы!
|
||||
password_hash=get_password_hash("password123"), # теперь храним хеш
|
||||
name=NAMES[i % len(NAMES)],
|
||||
email=f"user{i+1}@example.com",
|
||||
balance=round(random.uniform(1000, 10000), 2)
|
||||
|
||||
51
main.py
51
main.py
@ -9,6 +9,7 @@ from uuid import uuid4
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlalchemy import func
|
||||
from hashlib import sha256
|
||||
import jwt
|
||||
|
||||
# Конфигурация
|
||||
AUTH_DATABASE_ADDRESS = "sqlite:///partner.db"
|
||||
@ -54,7 +55,7 @@ class Transaction(SQLModel, table=True):
|
||||
class Account(SQLModel, table=True):
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
login: str = Field(index=True, unique=True)
|
||||
password: str
|
||||
password_hash: str # теперь хранится hash пароля
|
||||
name: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
balance: float = 0.0
|
||||
@ -127,25 +128,41 @@ def authenticate_tg_agent(engine, tg_id: int):
|
||||
return None
|
||||
return tg_agent
|
||||
|
||||
# Защищённый эндпоинт
|
||||
@app.get("/protected", tags=["partner-tg"])
|
||||
def protected_route(current_tg_agent: TgAgent = Depends(get_current_tg_agent)):
|
||||
return {"msg": f"Hello, {current_tg_agent.tg_id}! This is a protected route."}
|
||||
|
||||
|
||||
# Авторизация
|
||||
|
||||
SECRET_KEY = "supersecretkey" # Лучше вынести в .env
|
||||
ALGORITHM = "HS256"
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES = 60
|
||||
|
||||
@app.post("/token", response_model=Token, tags=["partner-tg"])
|
||||
async def login_for_access_token(req: TokenRequest):
|
||||
tg_id = req.tg_id
|
||||
tg_agent = authenticate_tg_agent(AUTH_DB_ENGINE, tg_id)
|
||||
if not tg_agent:
|
||||
def create_access_token(data: dict, expires_delta: timedelta = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@app.post("/token", response_model=Token, tags=["bff"])
|
||||
def login_account_for_access_token(
|
||||
login: str = Body(...),
|
||||
password: str = Body(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
account = get_account_by_login(db, login)
|
||||
if not account or not verify_password(password, account.password_hash):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect tg_id",
|
||||
detail="Incorrect login or password",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
access_token = f"session_for_{tg_agent.tg_id}"
|
||||
access_token = create_access_token(
|
||||
data={"sub": account.login},
|
||||
expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
)
|
||||
return Token(access_token=access_token, token_type="bearer")
|
||||
|
||||
|
||||
@ -474,3 +491,13 @@ def tg_auth(hash: str = Body(..., embed=True), db: Session = Depends(get_db)):
|
||||
if not tg_agent:
|
||||
raise HTTPException(status_code=401, detail="Hash not found")
|
||||
return {"msg": "Auth success", "tg_id": tg_agent.tg_id}
|
||||
|
||||
# --- Новый функционал для Account ---
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
def verify_password(plain_password, hashed_password):
|
||||
return pwd_context.verify(plain_password, hashed_password)
|
||||
|
||||
def get_account_by_login(db: Session, login: str) -> Optional[Account]:
|
||||
statement = select(Account).where(Account.login == login)
|
||||
return db.exec(statement).first()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user