from collections.abc import AsyncGenerator from fastapi import Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from sqlalchemy.ext.asyncio import AsyncSession from app.database import async_session_factory from app.repositories import ( UserRepository, PaymentRepository, ServerRepository, TariffRepository, NotificationRepository, AdminRepository, ) from app.services import ( UserService, PaymentService, BillingService, NotificationService, ServerService, VPNService, ) from app.services.auth import AuthService security = HTTPBearer() async def get_db() -> AsyncGenerator[AsyncSession, None]: async with async_session_factory() as session: try: yield session await session.commit() except Exception: await session.rollback() raise def get_user_service(db: AsyncSession = Depends(get_db)) -> UserService: return UserService(UserRepository(db)) def get_payment_service(db: AsyncSession = Depends(get_db)) -> PaymentService: return PaymentService( PaymentRepository(db), UserRepository(db), TariffRepository(db), ) def get_billing_service(db: AsyncSession = Depends(get_db)) -> BillingService: return BillingService( PaymentRepository(db), TariffRepository(db), UserRepository(db), ) def get_notification_service( db: AsyncSession = Depends(get_db), ) -> NotificationService: return NotificationService( NotificationRepository(db), UserRepository(db), ) def get_server_service(db: AsyncSession = Depends(get_db)) -> ServerService: return ServerService(ServerRepository(db)) def get_vpn_service(db: AsyncSession = Depends(get_db)) -> VPNService: return VPNService( ServerRepository(db), UserRepository(db), ) def get_tariff_repo(db: AsyncSession = Depends(get_db)) -> TariffRepository: return TariffRepository(db) def get_server_repo(db: AsyncSession = Depends(get_db)) -> ServerRepository: return ServerRepository(db) def get_auth_service(db: AsyncSession = Depends(get_db)) -> AuthService: return AuthService(AdminRepository(db)) async def get_current_admin( credentials: HTTPAuthorizationCredentials = Depends(security), db: AsyncSession = Depends(get_db), ) -> dict: from app.services.auth import AuthService auth_svc = AuthService(AdminRepository(db)) try: payload = auth_svc.decode_token(credentials.credentials) except ValueError as e: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e), ) if payload.get("type") != "access": raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token type", ) telegram_id = int(payload["sub"]) admin = await AdminRepository(db).get_by_telegram_id(telegram_id) if admin is None or not admin.is_active: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Admin not found or deactivated", ) return { "admin_id": admin.id, "telegram_id": admin.telegram_id, "role": admin.role.value, "username": admin.username, } def require_admin(payload: dict = Depends(get_current_admin)) -> dict: return payload def require_superadmin(payload: dict = Depends(get_current_admin)) -> dict: if payload["role"] != "superadmin": raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Superadmin role required", ) return payload