add users

This commit is contained in:
itqop 2025-10-18 15:25:28 +03:00
parent 9b857e5caa
commit 880e3c8fec
7 changed files with 117 additions and 0 deletions

View File

@ -9,6 +9,7 @@ from hubgw.context import AppContext
from hubgw.services.homes_service import HomesService
from hubgw.services.kits_service import KitsService
from hubgw.services.cooldowns_service import CooldownsService
from hubgw.services.users_service import UserService
from hubgw.services.warps_service import WarpsService
from hubgw.services.whitelist_service import WhitelistService
from hubgw.services.punishments_service import PunishmentsService
@ -83,3 +84,8 @@ def get_luckperms_service(session: Annotated[AsyncSession, Depends(get_session)]
def get_teleport_history_service(session: Annotated[AsyncSession, Depends(get_session)]) -> TeleportHistoryService:
"""Get teleport history service."""
return TeleportHistoryService(session)
def get_user_service(session: Annotated[AsyncSession, Depends(get_session)]) -> UserService:
"""Get user service."""
return UserService(session)

24
src/hubgw/api/v1/users.py Normal file
View File

@ -0,0 +1,24 @@
"""User endpoints."""
from fastapi import APIRouter, Depends
from typing import Annotated
from hubgw.api.deps import get_user_service, verify_api_key
from hubgw.services.users_service import UserService
from hubgw.schemas.users import GetUserGameIdResponse
from hubgw.core.errors import AppError, create_http_exception
router = APIRouter()
@router.get("/users/{name}/game-id", response_model=GetUserGameIdResponse)
async def get_user_game_id(
name: str,
service: Annotated[UserService, Depends(get_user_service)],
_: Annotated[str, Depends(verify_api_key)]
):
"""Get game ID by user name."""
try:
return await service.get_game_id_by_name(name)
except AppError as e:
raise create_http_exception(e)

36
src/hubgw/models/users.py Normal file
View File

@ -0,0 +1,36 @@
"""User model."""
from sqlalchemy import Column, Integer, String, DateTime, Boolean, Numeric, ForeignKey, Index
from sqlalchemy.dialects.postgresql import UUID
from hubgw.models.base import Base
class User(Base):
"""User model."""
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(191), nullable=False)
email = Column(String(191), unique=True, nullable=True)
email_verified_at = Column(DateTime(timezone=True), nullable=True)
password = Column(String(191), nullable=False)
role_id = Column(Integer, ForeignKey("roles.id"), nullable=False)
money = Column(Numeric(14, 2), default=0)
game_id = Column(String(191), nullable=True)
avatar = Column(String, nullable=True) # TEXT поле
access_token = Column(String(191), nullable=True)
two_factor_secret = Column(String(191), nullable=True)
two_factor_recovery_codes = Column(String(191), nullable=True)
last_login_ip = Column(String(45), nullable=True)
last_login_at = Column(DateTime(timezone=True), nullable=True)
is_banned = Column(Boolean, default=False)
remember_token = Column(String(100), nullable=True)
created_at = Column(DateTime(timezone=True), nullable=True)
updated_at = Column(DateTime(timezone=True), nullable=True)
deleted_at = Column(DateTime(timezone=True), nullable=True)
password_changed_at = Column(DateTime(timezone=True), nullable=True)
__table_args__ = (
Index('idx_users_email', 'email', unique=True),
)

View File

@ -0,0 +1,20 @@
"""User repository."""
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import Optional
from hubgw.models.user import User
class UserRepository:
"""User repository for database operations."""
def __init__(self, session: AsyncSession):
self.session = session
async def get_game_id_by_name(self, name: str) -> Optional[str]:
"""Get game_id by user name."""
stmt = select(User.game_id).where(User.name == name)
result = await self.session.execute(stmt)
return result.scalar_one_or_none()

View File

@ -0,0 +1,10 @@
"""User schemas."""
from pydantic import BaseModel
from typing import Optional
class GetUserGameIdResponse(BaseModel):
"""Response schema for getting user's game ID."""
game_id: Optional[str]

View File

@ -0,0 +1,21 @@
"""User service."""
from sqlalchemy.ext.asyncio import AsyncSession
from hubgw.repositories.user_repo import UserRepository
from hubgw.schemas.user import GetUserGameIdResponse
from hubgw.core.errors import NotFoundError
class UserService:
"""User service for business logic."""
def __init__(self, session: AsyncSession):
self.repo = UserRepository(session)
async def get_game_id_by_name(self, name: str) -> GetUserGameIdResponse:
"""Get game_id by user name."""
game_id = await self.repo.get_game_id_by_name(name)
if game_id is None:
raise NotFoundError(f"User with name '{name}' not found or has no game_id")
return GetUserGameIdResponse(game_id=game_id)

View File