add: verify code in telegram
All checks were successful
Build and Deploy / deploy (push) Successful in 41s

This commit is contained in:
2025-07-21 08:07:21 +05:00
parent dd71c19c6b
commit c8d8c65251
7 changed files with 123 additions and 9 deletions

View File

@ -1,5 +1,5 @@
from fastapi import APIRouter, HTTPException, Body, Response
from app.models.user import UserCreate, UserLogin
from app.models.user import UserCreate, UserLogin, VerifyCode
from app.models.request import ValidateRequest
from app.services.auth import AuthService
from app.db.database import users_collection, sessions_collection
@ -117,3 +117,11 @@ async def get_user_by_uuid(uuid: str):
safe_user["total_time_formatted"] = f"{hours}ч {minutes}м {seconds}с"
return safe_user
@router.post("/auth/verify_code")
async def verify_code(verify_code: VerifyCode):
return await AuthService().verify_code(verify_code.username, verify_code.code, verify_code.telegram_chat_id)
@router.post("/auth/generate_code")
async def generate_code(username: str):
return await AuthService().generate_code(username)

View File

@ -1,10 +1,9 @@
from pydantic import BaseModel, EmailStr
from pydantic import BaseModel
from datetime import datetime
from typing import Optional
class UserCreate(BaseModel):
username: str
email: EmailStr
password: str
class UserLogin(BaseModel):
@ -13,7 +12,6 @@ class UserLogin(BaseModel):
class UserInDB(BaseModel):
username: str
email: EmailStr
hashed_password: str
uuid: str
skin_url: Optional[str] = None
@ -23,9 +21,17 @@ class UserInDB(BaseModel):
total_time_played: int = 0 # Общее время игры в секундах
is_active: bool = True
created_at: datetime = datetime.utcnow()
code: Optional[str] = None
telegram_id: Optional[str] = None
is_verified: bool = False
code_expires_at: Optional[datetime] = None
class Session(BaseModel):
access_token: str
client_token: str
user_uuid: str
expires_at: datetime
class VerifyCode(BaseModel):
username: str
code: str
telegram_chat_id: int

View File

@ -17,6 +17,7 @@ from cryptography.hazmat.primitives.asymmetric import padding
from dotenv import load_dotenv
import os
from pathlib import Path
import secrets
env_path = Path(__file__).parent.parent / ".env"
load_dotenv(dotenv_path=env_path)
@ -37,18 +38,59 @@ class AuthService:
# Сохраняем в MongoDB
new_user = UserInDB(
username=user.username,
email=user.email,
hashed_password=hashed_password,
uuid=user_uuid,
is_verified=False,
code=None,
code_expires_at=None
)
await users_collection.insert_one(new_user.dict())
return {"status": "success", "uuid": user_uuid}
async def generate_code(self, username: str):
if await users_collection.find_one({"username": username}):
if await users_collection.find_one({"username": username, "is_verified": True}):
raise HTTPException(400, "User already verified")
code = secrets.token_hex(3).upper()
await users_collection.update_one({"username": username}, {"$set": {"code": code, "code_expires_at": datetime.utcnow() + timedelta(minutes=10)}})
return {"status": "success", "code": code}
else:
raise HTTPException(404, "User not found")
async def verify_code(self, username: str, code: str, telegram_chat_id: int):
user = await users_collection.find_one({"username": username})
if not user:
raise HTTPException(404, "User not found")
if user["is_verified"]:
raise HTTPException(400, "User already verified")
# Проверяем код и привязку к Telegram
if user.get("telegram_chat_id") and user["telegram_chat_id"] != telegram_chat_id:
raise HTTPException(403, "This account is linked to another Telegram")
if user.get("code") != code:
raise HTTPException(400, "Invalid code")
# Обновляем chat_id при первом подтверждении
await users_collection.update_one(
{"username": username},
{"$set": {
"is_verified": True,
"telegram_chat_id": telegram_chat_id,
"code": None
}}
)
return {"status": "success"}
async def login(self, credentials: UserLogin):
# Ищем пользователя
user = await users_collection.find_one({"username": credentials.username})
if not user or not verify_password(credentials.password, user["hashed_password"]):
raise HTTPException(status_code=401, detail="Invalid credentials")
if not user["is_verified"]:
raise HTTPException(status_code=401, detail="User not verified")
# Генерируем токены
access_token = create_access_token({"sub": user["username"], "uuid": user["uuid"]})