Initial commit

This commit is contained in:
2026-01-18 21:01:43 +03:00
commit 455b6df2ba
3329 changed files with 1143638 additions and 0 deletions
View File
+61
View File
@@ -0,0 +1,61 @@
from datetime import datetime, timedelta
from typing import Optional
from jose import JWTError, jwt
from fastapi import HTTPException, status, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from ..database.config import settings
from ..models.user import User
from ..schemas.token import TokenData
from ..database.database import get_db
security = HTTPBearer()
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
return encoded_jwt
def verify_token(token: str, credentials_exception):
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
except JWTError:
raise credentials_exception
return token_data
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db)
):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
token_data = verify_token(credentials.credentials, credentials_exception)
user = db.query(User).filter(User.username == token_data.username).first()
if user is None:
raise credentials_exception
return user
async def get_current_active_user(current_user: User = Depends(get_current_user)):
if not current_user.is_active:
raise HTTPException(status_code=400, detail="Inactive user")
return current_user
+117
View File
@@ -0,0 +1,117 @@
import hashlib
import hmac
from typing import Dict, Any, Optional
from datetime import datetime, timedelta
from fastapi import HTTPException, status
from sqlalchemy.orm import Session
from ..database.config import settings
from ..models.user import User
from ..schemas.user import UserCreate, UserInDB
from .jwt import create_access_token
def verify_telegram_login_data(auth_data: Dict[str, Any]) -> bool:
"""
Verify the authenticity of Telegram login data
"""
if not settings.TELEGRAM_BOT_TOKEN:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Telegram bot token not configured"
)
# Extract the hash
received_hash = auth_data.pop('hash', None)
if not received_hash:
return False
# Get the auth date
auth_date = auth_data.pop('auth_date', None)
if auth_date:
# Check if the data is not too old (more than 1 day)
auth_time = datetime.fromtimestamp(int(auth_date))
if (datetime.now() - auth_time).days > 0:
return False
# Sort the remaining parameters alphabetically by key
data_check_arr = []
for key, value in sorted(auth_data.items()):
data_check_arr.append(f"{key}={value}")
data_check_string = '\n'.join(data_check_arr)
# Create secret key using SHA256 of bot token
secret_key = hashlib.sha256(settings.TELEGRAM_BOT_TOKEN.encode()).digest()
# Calculate HMAC-SHA256 signature
calculated_hash = hmac.new(
secret_key,
data_check_string.encode(),
hashlib.sha256
).hexdigest()
# Compare the calculated hash with the received hash
return calculated_hash == received_hash
def authenticate_user_telegram(db: Session, auth_data: Dict[str, Any]):
"""
Authenticate user via Telegram login data and return JWT token
"""
# Verify the authenticity of the data
if not verify_telegram_login_data(auth_data.copy()): # Copy to avoid modifying original
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid Telegram login data"
)
# Extract user data
telegram_id = str(auth_data.get('id'))
username = auth_data.get('username')
first_name = auth_data.get('first_name')
last_name = auth_data.get('last_name')
photo_url = auth_data.get('photo_url')
# Try to find existing user by telegram_id
user = db.query(User).filter(User.telegram_id == telegram_id).first()
if user:
# Update user data if it has changed
user.username = username
user.first_name = first_name
user.last_name = last_name
user.avatar_url = photo_url
user.is_verified = True
db.commit()
db.refresh(user)
else:
# Create new user
user = User(
telegram_id=telegram_id,
username=username,
first_name=first_name,
last_name=last_name,
avatar_url=photo_url,
is_verified=True,
is_active=True
)
db.add(user)
db.commit()
db.refresh(user)
# Create JWT token
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username or user.telegram_id},
expires_delta=access_token_expires
)
return {
"access_token": access_token,
"token_type": "bearer",
"user": UserInDB.from_orm(user) if hasattr(UserInDB, 'from_orm') else UserInDB.model_validate(user)
}