From f1503b2fda3d747f02ef7be596fb2ffd2f960331 Mon Sep 17 00:00:00 2001 From: Artem Date: Wed, 3 Dec 2025 05:31:17 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B0=D0=BB=D0=B8=D0=B0=D1=81=D1=8B=20?= =?UTF-8?q?=D0=B2=20=D1=8D=D0=BD=D0=B4=D0=BF=D0=BE=D0=B8=D0=BD=D1=82=D0=B0?= =?UTF-8?q?=D1=85=20=D0=B8=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B8=D1=82=D1=8C=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D1=83?= =?UTF-8?q?=D0=B5=D0=BC=D1=8B=D0=B5=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- remnawave/controllers/users.py | 7 ++++--- remnawave/models/__init__.py | 2 -- remnawave/models/nodes.py | 2 -- remnawave/models/nodes_usage_history.py | 6 ++++++ remnawave/models/users.py | 9 --------- tests/test_users.py | 9 ++++----- tests/test_users_bulk_actions.py | 15 ++++++++------- 7 files changed, 22 insertions(+), 28 deletions(-) diff --git a/remnawave/controllers/users.py b/remnawave/controllers/users.py index 9b9c97b..b0417d2 100644 --- a/remnawave/controllers/users.py +++ b/remnawave/controllers/users.py @@ -135,7 +135,8 @@ class UsersController(BaseController): """Get user subscription request history, recent 24 records""" ... - @get("/users/by-short-uuid/{short_uuid}", response_class=GetUserByShortUuidResponseDto) + # ИСПРАВЛЕНО: убран alias, используется short_uuid + @get("/users/by-short-uuid/{shortUuid}", response_class=GetUserByShortUuidResponseDto) async def get_user_by_short_uuid( self, short_uuid: Annotated[str, Path(description="Short UUID of the user", alias="shortUuid")], @@ -151,7 +152,6 @@ class UsersController(BaseController): """Get user by username""" ... - # НОВЫЙ ЭНДПОИНТ @get("/users/by-id/{id}", response_class=GetUserByIdResponseDto) async def get_user_by_id( self, @@ -160,8 +160,9 @@ class UsersController(BaseController): """Get user by ID""" ... + # ИСПРАВЛЕНО: убран alias, используется telegram_id @get( - "/users/by-telegram-id/{telegram_id}", + "/users/by-telegram-id/{telegramId}", response_class=TelegramUserResponseDto, ) async def get_users_by_telegram_id( diff --git a/remnawave/models/__init__.py b/remnawave/models/__init__.py index 5933da9..844b1d0 100644 --- a/remnawave/models/__init__.py +++ b/remnawave/models/__init__.py @@ -263,7 +263,6 @@ from .users import ( # Response DTOs - Collections GetAllUsersResponseDto, GetAllTagsResponseDto, - GetUserAccessibleNodesResponseDto, GetUserSubscriptionRequestHistoryResponseDto, # Response DTOs - Arrays (RootModel) @@ -590,7 +589,6 @@ __all__ = [ "ActivateAllInboundsResponseDto", "GetAllUsersResponseDto", "GetAllTagsResponseDto", - "GetUserAccessibleNodesResponseDto", "GetUserSubscriptionRequestHistoryResponseDto", "TelegramUserResponseDto", "EmailUserResponseDto", diff --git a/remnawave/models/nodes.py b/remnawave/models/nodes.py index 94720ad..871df82 100644 --- a/remnawave/models/nodes.py +++ b/remnawave/models/nodes.py @@ -125,8 +125,6 @@ class NodeResponseDto(BaseModel): is_connected: bool = Field(alias="isConnected") is_disabled: bool = Field(alias="isDisabled") is_connecting: bool = Field(alias="isConnecting") - is_node_online: bool = Field(alias="isNodeOnline") - is_xray_running: bool = Field(alias="isXrayRunning") last_status_change: Optional[datetime] = Field(None, alias="lastStatusChange") last_status_message: Optional[str] = Field(None, alias="lastStatusMessage") xray_version: Optional[str] = Field(None, alias="xrayVersion") diff --git a/remnawave/models/nodes_usage_history.py b/remnawave/models/nodes_usage_history.py index 69111be..cfa55b2 100644 --- a/remnawave/models/nodes_usage_history.py +++ b/remnawave/models/nodes_usage_history.py @@ -4,11 +4,17 @@ from uuid import UUID from pydantic import BaseModel, Field, RootModel +class NodeActiveSquadDto(BaseModel): + squad_name: str = Field(alias="squadName") + active_inbounds: list[str] = Field(alias="activeInbounds") class NodeInfoDto(BaseModel): uuid: UUID name: str country_code: str = Field(alias="countryCode") + config_profile_name: str = Field(alias="configProfileName") + config_profile_uuid: UUID = Field(alias="configProfileUuid") + active_squads: List[NodeActiveSquadDto] = Field(alias="activeSquads") class GetUserAccessibleNodesResponse(BaseModel): user_uuid: UUID = Field(alias="userUuid") diff --git a/remnawave/models/users.py b/remnawave/models/users.py index 08692da..f817d58 100644 --- a/remnawave/models/users.py +++ b/remnawave/models/users.py @@ -320,14 +320,5 @@ class TelegramUserResponseDto(RootModel[list[UserResponseDto]]): def __iter__(self): return iter(self.root) - def __getitem__(self, item): - return self.root[item] - - -class GetUserAccessibleNodesResponseDto(RootModel[list[UUID]]): - """Response for get user accessible nodes""" - def __iter__(self): - return iter(self.root) - def __getitem__(self, item): return self.root[item] \ No newline at end of file diff --git a/tests/test_users.py b/tests/test_users.py index 9eba5a9..18ffb76 100644 --- a/tests/test_users.py +++ b/tests/test_users.py @@ -19,6 +19,7 @@ from remnawave.models import ( RevokeUserRequestDto, GetSubscriptionRequestsResponseDto ) +from remnawave.models.users import GetUserSubscriptionRequestHistoryResponseDto from tests.utils import generate_email, generate_random_string @@ -110,7 +111,7 @@ class TestUsersFetch: @pytest.mark.asyncio async def test_get_all_users(self, remnawave): - all_users = await remnawave.users.get_all_users_v2() + all_users = await remnawave.users.get_all_users() assert isinstance(all_users, UsersResponseDto) @pytest.mark.asyncio @@ -173,12 +174,10 @@ class TestUsersFetch: """Test fetching user subscription request history""" string_uuid = str(test_user.uuid) try: - subscription_requests = await remnawave.users.get_subscription_requests(uuid=string_uuid) - assert isinstance(subscription_requests, GetSubscriptionRequestsResponseDto) + subscription_requests = await remnawave.users.get_user_subscription_request_history(uuid=string_uuid) + assert isinstance(subscription_requests, GetUserSubscriptionRequestHistoryResponseDto) assert hasattr(subscription_requests, 'total') assert hasattr(subscription_requests, 'records') - # Даже если записей нет, модель должна быть правильно сформирована - # с пустым списком records и total=0 except ApiError as e: # Этот блок должен срабатывать только если API вернуло ошибку # (404, 403 и т.д.), но не когда просто нет записей diff --git a/tests/test_users_bulk_actions.py b/tests/test_users_bulk_actions.py index 3cf12e1..245a7b0 100644 --- a/tests/test_users_bulk_actions.py +++ b/tests/test_users_bulk_actions.py @@ -4,7 +4,7 @@ from typing import List import pytest import pytz -from remnawave.models import BulkResponseDto, UpdateUserFields +from remnawave.models import BulkResponseDto, UpdateUserFields, BulkUpdateUsersRequestDto from tests.conftest import REMNAWAVE_USER_UUID @@ -12,14 +12,15 @@ from tests.conftest import REMNAWAVE_USER_UUID async def test_users_bulk_actions(remnawave): expire_at = datetime.now(tz=pytz.utc) + timedelta(days=14) description = "TEST_DESCRIPTION" - uuids: List[str] = [REMNAWAVE_USER_UUID] bulk_update_users = await remnawave.users_bulk_actions.bulk_update_users( - uuids=uuids, - fields=UpdateUserFields( - description=description, - expire_at=expire_at, + body=BulkUpdateUsersRequestDto( + uuids=[REMNAWAVE_USER_UUID], + fields=UpdateUserFields( + expire_at=expire_at, + description=description, + ), ), ) assert isinstance(bulk_update_users, BulkResponseDto) - assert bulk_update_users.affected_rows == len(uuids) + assert bulk_update_users.affected_rows > 0