mirror of
https://github.com/remnawave/python-sdk.git
synced 2026-10-21 04:00:47 +00:00
feat: обновить модели пользователей и добавить новые DTO для работы с пользователями и их подписками
This commit is contained in:
parent
18776967b4
commit
38a57b3e31
7 changed files with 539 additions and 286 deletions
|
|
@ -5,58 +5,56 @@ from rapid_api_client.annotations import PydanticBody
|
|||
|
||||
from remnawave.models import (
|
||||
CreateUserRequestDto,
|
||||
CreateUserResponseDto,
|
||||
DeleteUserResponseDto,
|
||||
EmailUserResponseDto,
|
||||
GetAllUsersResponseDto,
|
||||
GetAllTagsResponseDto,
|
||||
GetUserByIdResponseDto,
|
||||
GetUserByShortUuidResponseDto,
|
||||
GetUserByUsernameResponseDto,
|
||||
GetUserByUuidResponseDto,
|
||||
GetUserAccessibleNodesResponseDto,
|
||||
GetUserSubscriptionRequestHistoryResponseDto,
|
||||
TelegramUserResponseDto,
|
||||
UpdateUserRequestDto,
|
||||
UserResponseDto,
|
||||
UsersResponseDto,
|
||||
TagsResponseDto,
|
||||
EmailUserResponseDto,
|
||||
TagUserResponseDto,
|
||||
UpdateUserRequestDto,
|
||||
UpdateUserResponseDto,
|
||||
RevokeUserRequestDto,
|
||||
GetSubscriptionRequestsResponseDto
|
||||
)
|
||||
from remnawave.rapid import BaseController, delete, get, patch, post
|
||||
|
||||
|
||||
class UsersController(BaseController):
|
||||
@post("/users", response_class=UserResponseDto)
|
||||
@post("/users", response_class=CreateUserResponseDto)
|
||||
async def create_user(
|
||||
self,
|
||||
body: Annotated[CreateUserRequestDto, PydanticBody()],
|
||||
) -> UserResponseDto:
|
||||
"""Create User"""
|
||||
) -> CreateUserResponseDto:
|
||||
"""Create a new user"""
|
||||
...
|
||||
|
||||
@patch("/users", response_class=UserResponseDto)
|
||||
@patch("/users", response_class=UpdateUserResponseDto)
|
||||
async def update_user(
|
||||
self,
|
||||
body: Annotated[UpdateUserRequestDto, PydanticBody()],
|
||||
) -> UserResponseDto:
|
||||
"""Update User"""
|
||||
) -> UpdateUserResponseDto:
|
||||
"""Update a user by UUID or username"""
|
||||
...
|
||||
|
||||
@get("/users", response_class=UsersResponseDto)
|
||||
async def get_all_users_v2(
|
||||
@get("/users", response_class=GetAllUsersResponseDto)
|
||||
async def get_all_users(
|
||||
self,
|
||||
start: Annotated[
|
||||
int, Query(default=0, ge=0, description="Index to start pagination from")
|
||||
],
|
||||
Optional[int],
|
||||
Query(default=None, description="Offset for pagination")
|
||||
] = None,
|
||||
size: Annotated[
|
||||
int, Query(default=25, ge=1, description="Number of users per page")
|
||||
],
|
||||
) -> UsersResponseDto:
|
||||
"""
|
||||
Get users page from the end.
|
||||
|
||||
Args:
|
||||
page (int): Page number from the end (1 = last page).
|
||||
size (int): Number of users per page.
|
||||
|
||||
Returns:
|
||||
UsersResponseDto
|
||||
"""
|
||||
Optional[int],
|
||||
Query(default=None, description="Page size for pagination")
|
||||
] = None,
|
||||
) -> GetAllUsersResponseDto:
|
||||
"""Get all users"""
|
||||
...
|
||||
|
||||
@delete("/users/{uuid}", response_class=DeleteUserResponseDto)
|
||||
|
|
@ -64,75 +62,102 @@ class UsersController(BaseController):
|
|||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> DeleteUserResponseDto:
|
||||
"""Delete User"""
|
||||
"""Delete user"""
|
||||
...
|
||||
|
||||
@post("users/{uuid}/actions/revoke", response_class=UserResponseDto)
|
||||
@post("/users/{uuid}/actions/revoke", response_class=UpdateUserResponseDto)
|
||||
async def revoke_user_subscription(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
body: Optional[Annotated[RevokeUserRequestDto, PydanticBody()]] = None,
|
||||
) -> UserResponseDto:
|
||||
) -> UpdateUserResponseDto:
|
||||
"""Revoke User Subscription"""
|
||||
...
|
||||
|
||||
@post("/users/{uuid}/actions/disable", response_class=UserResponseDto)
|
||||
@post("/users/{uuid}/actions/disable", response_class=UpdateUserResponseDto)
|
||||
async def disable_user(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> UserResponseDto:
|
||||
) -> UpdateUserResponseDto:
|
||||
"""Disable User"""
|
||||
...
|
||||
|
||||
@post("/users/{uuid}/actions/enable", response_class=UserResponseDto)
|
||||
@post("/users/{uuid}/actions/enable", response_class=UpdateUserResponseDto)
|
||||
async def enable_user(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> UserResponseDto:
|
||||
) -> UpdateUserResponseDto:
|
||||
"""Enable User"""
|
||||
...
|
||||
|
||||
@post("/users/{uuid}/actions/reset-traffic", response_class=UserResponseDto)
|
||||
@post("/users/{uuid}/actions/reset-traffic", response_class=UpdateUserResponseDto)
|
||||
async def reset_user_traffic(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> UserResponseDto:
|
||||
) -> UpdateUserResponseDto:
|
||||
"""Reset User Traffic"""
|
||||
...
|
||||
|
||||
@get("/users/by-short-uuid/{short_uuid}", response_class=UserResponseDto)
|
||||
async def get_user_by_short_uuid(
|
||||
self,
|
||||
short_uuid: Annotated[str, Path(description="Short UUID of the user")],
|
||||
) -> UserResponseDto:
|
||||
"""Get User By Short UUID"""
|
||||
...
|
||||
|
||||
@get(
|
||||
"/users/by-subscription-uuid/{subscription_uuid}",
|
||||
response_class=UserResponseDto,
|
||||
)
|
||||
async def get_user_by_subscription_uuid(
|
||||
self,
|
||||
subscription_uuid: Annotated[str, Path(description="UUID of the subscription")],
|
||||
) -> UserResponseDto:
|
||||
"""Get User By Subscription UUID"""
|
||||
...
|
||||
|
||||
@get("/users/{uuid}", response_class=UserResponseDto)
|
||||
@get("/users/{uuid}", response_class=GetUserByUuidResponseDto)
|
||||
async def get_user_by_uuid(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> UserResponseDto:
|
||||
"""Get User By UUID"""
|
||||
) -> GetUserByUuidResponseDto:
|
||||
"""Get user by UUID"""
|
||||
...
|
||||
|
||||
@get("/users/by-username/{username}", response_class=UserResponseDto)
|
||||
@get("/users/tags", response_class=GetAllTagsResponseDto)
|
||||
async def get_all_tags(
|
||||
self,
|
||||
) -> GetAllTagsResponseDto:
|
||||
"""Get all existing user tags"""
|
||||
...
|
||||
|
||||
@get(
|
||||
"/users/{uuid}/accessible-nodes",
|
||||
response_class=GetUserAccessibleNodesResponseDto,
|
||||
)
|
||||
async def get_user_accessible_nodes(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> GetUserAccessibleNodesResponseDto:
|
||||
"""Get user accessible nodes"""
|
||||
...
|
||||
|
||||
@get(
|
||||
"/users/{uuid}/subscription-request-history",
|
||||
response_class=GetUserSubscriptionRequestHistoryResponseDto
|
||||
)
|
||||
async def get_user_subscription_request_history(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> GetUserSubscriptionRequestHistoryResponseDto:
|
||||
"""Get user subscription request history, recent 24 records"""
|
||||
...
|
||||
|
||||
@get("/users/by-short-uuid/{short_uuid}", response_class=GetUserByShortUuidResponseDto)
|
||||
async def get_user_by_short_uuid(
|
||||
self,
|
||||
short_uuid: Annotated[str, Path(description="Short UUID of the user", alias="shortUuid")],
|
||||
) -> GetUserByShortUuidResponseDto:
|
||||
"""Get user by Short UUID"""
|
||||
...
|
||||
|
||||
@get("/users/by-username/{username}", response_class=GetUserByUsernameResponseDto)
|
||||
async def get_user_by_username(
|
||||
self,
|
||||
username: Annotated[str, Path(description="Username of the user")],
|
||||
) -> UserResponseDto:
|
||||
"""Get User By Username"""
|
||||
) -> GetUserByUsernameResponseDto:
|
||||
"""Get user by username"""
|
||||
...
|
||||
|
||||
# НОВЫЙ ЭНДПОИНТ
|
||||
@get("/users/by-id/{id}", response_class=GetUserByIdResponseDto)
|
||||
async def get_user_by_id(
|
||||
self,
|
||||
id: Annotated[str, Path(description="ID of the user")],
|
||||
) -> GetUserByIdResponseDto:
|
||||
"""Get user by ID"""
|
||||
...
|
||||
|
||||
@get(
|
||||
|
|
@ -141,7 +166,7 @@ class UsersController(BaseController):
|
|||
)
|
||||
async def get_users_by_telegram_id(
|
||||
self,
|
||||
telegram_id: Annotated[str, Path(description="Telegram ID of the user")],
|
||||
telegram_id: Annotated[str, Path(description="Telegram ID of the user", alias="telegramId")],
|
||||
) -> TelegramUserResponseDto:
|
||||
"""Get Users By Telegram ID"""
|
||||
...
|
||||
|
|
@ -160,30 +185,4 @@ class UsersController(BaseController):
|
|||
tag: Annotated[str, Path(description="Tag of the user")],
|
||||
) -> TagUserResponseDto:
|
||||
"""Get Users By Tag"""
|
||||
...
|
||||
|
||||
@get("/users/tags", response_class=TagsResponseDto)
|
||||
async def get_all_tags(
|
||||
self,
|
||||
) -> TagsResponseDto:
|
||||
"""Get All Tags"""
|
||||
...
|
||||
|
||||
@get(
|
||||
"/users/{uuid}/accessible-nodes",
|
||||
response_class=GetUserAccessibleNodesResponseDto,
|
||||
)
|
||||
async def get_user_accessible_nodes(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> GetUserAccessibleNodesResponseDto:
|
||||
"""Get User Accessible Nodes"""
|
||||
...
|
||||
|
||||
@get("/users/{uuid}/subscription-request-history", response_class=GetSubscriptionRequestsResponseDto)
|
||||
async def get_subscription_requests(
|
||||
self,
|
||||
uuid: Annotated[str, Path(description="UUID of the user")],
|
||||
) -> GetSubscriptionRequestsResponseDto:
|
||||
"""Get Subscription Requests History"""
|
||||
...
|
||||
|
|
@ -5,71 +5,95 @@ from rapid_api_client.annotations import PydanticBody
|
|||
|
||||
from remnawave.enums import UserStatus
|
||||
from remnawave.models import (
|
||||
BulkAllExtendExpirationDateRequestDto,
|
||||
BulkAllExtendExpirationDateResponseDto,
|
||||
BulkAllResetTrafficUsersResponseDto,
|
||||
BulkAllUpdateUsersRequestDto,
|
||||
BulkAllUpdateUsersResponseDto,
|
||||
BulkResponseDto,
|
||||
BulkUpdateUsersInternalSquadsRequestDto,
|
||||
UpdateUserFields,
|
||||
BulkDeleteUsersByStatusRequestDto,
|
||||
BulkDeleteUsersByStatusResponseDto,
|
||||
BulkDeleteUsersRequestDto,
|
||||
BulkDeleteUsersResponseDto,
|
||||
BulkExtendExpirationDateRequestDto,
|
||||
BulkExtendExpirationDateResponseDto,
|
||||
BulkResetTrafficUsersRequestDto,
|
||||
BulkResetTrafficUsersResponseDto,
|
||||
BulkRevokeUsersSubscriptionRequestDto,
|
||||
BulkRevokeUsersSubscriptionResponseDto,
|
||||
BulkUpdateUsersRequestDto,
|
||||
BulkUpdateUsersResponseDto,
|
||||
BulkUpdateUsersSquadsRequestDto,
|
||||
BulkUpdateUsersSquadsResponseDto,
|
||||
)
|
||||
from remnawave.rapid import AttributeBody, BaseController, patch, post
|
||||
from remnawave.rapid import BaseController, post
|
||||
|
||||
|
||||
class UsersBulkActionsController(BaseController):
|
||||
@post(
|
||||
"/users/bulk/delete-by-status",
|
||||
response_class=BulkResponseDto,
|
||||
response_class=BulkDeleteUsersByStatusResponseDto,
|
||||
)
|
||||
async def bulk_delete_users_by_status(
|
||||
self, status: Annotated[UserStatus, AttributeBody()]
|
||||
) -> BulkResponseDto:
|
||||
self,
|
||||
body: Annotated[BulkDeleteUsersByStatusRequestDto, PydanticBody()]
|
||||
) -> BulkDeleteUsersByStatusResponseDto:
|
||||
"""Bulk Delete Users By Status"""
|
||||
...
|
||||
|
||||
@post("/users/bulk/delete", response_class=BulkResponseDto)
|
||||
@post("/users/bulk/delete", response_class=BulkDeleteUsersResponseDto)
|
||||
async def bulk_delete_users(
|
||||
self,
|
||||
uuids: Annotated[List[UUID], AttributeBody()],
|
||||
) -> BulkResponseDto:
|
||||
body: Annotated[BulkDeleteUsersRequestDto, PydanticBody()],
|
||||
) -> BulkDeleteUsersResponseDto:
|
||||
"""Bulk Delete Users By UUIDs"""
|
||||
...
|
||||
|
||||
@post(
|
||||
"/users/bulk/revoke-subscription",
|
||||
response_class=BulkResponseDto,
|
||||
response_class=BulkRevokeUsersSubscriptionResponseDto,
|
||||
)
|
||||
async def bulk_revoke_users_subscription(
|
||||
self,
|
||||
uuids: Annotated[List[UUID], AttributeBody()],
|
||||
) -> BulkResponseDto:
|
||||
body: Annotated[BulkRevokeUsersSubscriptionRequestDto, PydanticBody()],
|
||||
) -> BulkRevokeUsersSubscriptionResponseDto:
|
||||
"""Bulk Revoke Users Subscription"""
|
||||
...
|
||||
|
||||
@post("/users/bulk/reset-traffic", response_class=BulkResponseDto)
|
||||
@post("/users/bulk/reset-traffic", response_class=BulkResetTrafficUsersResponseDto)
|
||||
async def bulk_reset_user_traffic(
|
||||
self,
|
||||
uuids: Annotated[List[UUID], AttributeBody()],
|
||||
) -> BulkResponseDto:
|
||||
body: Annotated[BulkResetTrafficUsersRequestDto, PydanticBody()],
|
||||
) -> BulkResetTrafficUsersResponseDto:
|
||||
"""Bulk Reset User Traffic"""
|
||||
...
|
||||
|
||||
@post("/users/bulk/update", response_class=BulkResponseDto)
|
||||
@post("/users/bulk/update", response_class=BulkUpdateUsersResponseDto)
|
||||
async def bulk_update_users(
|
||||
self,
|
||||
uuids: Annotated[List[UUID], AttributeBody()],
|
||||
fields: Annotated[UpdateUserFields, AttributeBody()],
|
||||
) -> BulkResponseDto:
|
||||
body: Annotated[BulkUpdateUsersRequestDto, PydanticBody()],
|
||||
) -> BulkUpdateUsersResponseDto:
|
||||
"""Bulk Update Users"""
|
||||
...
|
||||
|
||||
@post("/users/bulk/update-squads", response_class=BulkResponseDto)
|
||||
@post("/users/bulk/update-squads", response_class=BulkUpdateUsersSquadsResponseDto)
|
||||
async def bulk_update_users_internal_squads(
|
||||
self,
|
||||
body: Annotated[BulkUpdateUsersInternalSquadsRequestDto, PydanticBody()],
|
||||
) -> BulkResponseDto:
|
||||
body: Annotated[BulkUpdateUsersSquadsRequestDto, PydanticBody()],
|
||||
) -> BulkUpdateUsersSquadsResponseDto:
|
||||
"""Bulk Update Users Internal Squads"""
|
||||
...
|
||||
|
||||
@post(
|
||||
"/users/bulk/extend-expiration-date",
|
||||
response_class=BulkExtendExpirationDateResponseDto,
|
||||
)
|
||||
async def bulk_extend_expiration_date(
|
||||
self,
|
||||
body: Annotated[BulkExtendExpirationDateRequestDto, PydanticBody()],
|
||||
) -> BulkExtendExpirationDateResponseDto:
|
||||
"""Bulk Extend Users Expiration Date"""
|
||||
...
|
||||
|
||||
@post("/users/bulk/all/update", response_class=BulkAllUpdateUsersResponseDto)
|
||||
async def bulk_update_all_users(
|
||||
self,
|
||||
|
|
@ -89,13 +113,12 @@ class UsersBulkActionsController(BaseController):
|
|||
...
|
||||
|
||||
@post(
|
||||
"/users/bulk/update-squads",
|
||||
response_class=BulkResponseDto,
|
||||
)
|
||||
async def bulk_update_users_internal_squad(
|
||||
"/users/bulk/all/extend-expiration-date",
|
||||
response_class=BulkAllExtendExpirationDateResponseDto,
|
||||
)
|
||||
async def bulk_all_extend_expiration_date(
|
||||
self,
|
||||
uuids: Annotated[List[UUID], AttributeBody()],
|
||||
active_internal_squads: Annotated[List[UUID], AttributeBody(serialization_alias="activeInternalSquads")],
|
||||
) -> BulkResponseDto:
|
||||
"""Bulk Update Users External Squad"""
|
||||
body: Annotated[BulkAllExtendExpirationDateRequestDto, PydanticBody()],
|
||||
) -> BulkAllExtendExpirationDateResponseDto:
|
||||
"""Bulk Extend All Users Expiration Date"""
|
||||
...
|
||||
|
|
@ -242,27 +242,81 @@ from .system import (
|
|||
EncryptHappCryptoLinkResponseDto,
|
||||
)
|
||||
from .users import (
|
||||
ActiveInternalSquadDto,
|
||||
# Request DTOs
|
||||
CreateUserRequestDto,
|
||||
DeleteUserResponseDto,
|
||||
EmailUserResponseDto,
|
||||
TelegramUserResponseDto,
|
||||
UpdateUserRequestDto,
|
||||
UserActiveInboundsDto,
|
||||
UserLastConnectedNodeDto,
|
||||
RevokeUserRequestDto,
|
||||
|
||||
# Response DTOs - Single User
|
||||
CreateUserResponseDto,
|
||||
UpdateUserResponseDto,
|
||||
GetUserByUuidResponseDto,
|
||||
GetUserByShortUuidResponseDto,
|
||||
GetUserByUsernameResponseDto,
|
||||
GetUserByIdResponseDto,
|
||||
DisableUserResponseDto,
|
||||
EnableUserResponseDto,
|
||||
ResetUserTrafficResponseDto,
|
||||
RevokeUserSubscriptionResponseDto,
|
||||
ActivateAllInboundsResponseDto,
|
||||
|
||||
# Response DTOs - Collections
|
||||
GetAllUsersResponseDto,
|
||||
GetAllTagsResponseDto,
|
||||
GetUserAccessibleNodesResponseDto,
|
||||
GetUserSubscriptionRequestHistoryResponseDto,
|
||||
|
||||
# Response DTOs - Arrays (RootModel)
|
||||
TelegramUserResponseDto,
|
||||
EmailUserResponseDto,
|
||||
TagUserResponseDto,
|
||||
|
||||
# Other Response DTOs
|
||||
DeleteUserResponseDto,
|
||||
|
||||
# Base DTOs
|
||||
UserResponseDto,
|
||||
UsersResponseDto,
|
||||
TagsResponseDto,
|
||||
TagUserResponseDto,
|
||||
RevokeUserRequestDto,
|
||||
SubscriptionRequestsResponseData,
|
||||
|
||||
# Data DTOs
|
||||
UserTrafficDto,
|
||||
ActiveInternalSquadDto,
|
||||
SubscriptionRequestRecord,
|
||||
HappCrypto,
|
||||
UserActiveInboundsDto,
|
||||
UserLastConnectedNodeDto,
|
||||
|
||||
# Alias
|
||||
GetSubscriptionRequestsResponseDto,
|
||||
)
|
||||
|
||||
from .users_bulk_actions import (
|
||||
BulkAllExtendExpirationDateRequestDto,
|
||||
BulkAllExtendExpirationDateResponseDto,
|
||||
BulkAllResetTrafficUsersResponseDto,
|
||||
BulkAllUpdateUsersRequestDto,
|
||||
BulkAllUpdateUsersResponseDto,
|
||||
BulkDeleteUsersByStatusRequestDto,
|
||||
BulkDeleteUsersByStatusResponseDto,
|
||||
BulkDeleteUsersRequestDto,
|
||||
BulkDeleteUsersResponseDto,
|
||||
BulkEventResponseData,
|
||||
BulkExtendExpirationDateRequestDto,
|
||||
BulkExtendExpirationDateResponseDto,
|
||||
BulkResetTrafficUsersRequestDto,
|
||||
BulkResetTrafficUsersResponseDto,
|
||||
BulkResponseData,
|
||||
BulkResponseDto,
|
||||
BulkRevokeUsersSubscriptionRequestDto,
|
||||
BulkRevokeUsersSubscriptionResponseDto,
|
||||
BulkUpdateUsersInternalSquadsRequestDto,
|
||||
BulkUpdateUsersRequestDto,
|
||||
BulkUpdateUsersResponseDto,
|
||||
BulkUpdateUsersSquadsRequestDto,
|
||||
BulkUpdateUsersSquadsResponseDto,
|
||||
TagStr,
|
||||
UpdateUserFields,
|
||||
)
|
||||
from .users_stats import UserUsageByRange, UserUsageByRangeResponseDto
|
||||
|
|
@ -520,40 +574,64 @@ __all__ = [
|
|||
"SetPortToManyHostsResponseDto",
|
||||
"SetPortToManyHostsRequestDto",
|
||||
# Users models
|
||||
"ActiveInternalSquadDto",
|
||||
"CreateUserRequestDto",
|
||||
"CreateUserResponseDto",
|
||||
"DeleteUserResponseDto",
|
||||
"DisableUserResponseDto",
|
||||
"EmailUserResponseDto",
|
||||
"EnableUserResponseDto",
|
||||
"GetAllUsersResponseDto",
|
||||
"GetUserByEmailResponseDto",
|
||||
"GetUserByShortUuidResponseDto",
|
||||
"GetUserBySubscriptionUuidResponseDto",
|
||||
"GetUserByTagResponseDto",
|
||||
"GetUserByTelegramIdResponseDto",
|
||||
"GetUserByUsernameResponseDto",
|
||||
"GetUserByUuidResponseDto",
|
||||
"ResetUserTrafficResponseDto",
|
||||
"RevokeUserRequestDto",
|
||||
"RevokeUserSubscriptionResponseDto",
|
||||
"TagsResponseDto",
|
||||
"TelegramUserResponseDto",
|
||||
"UpdateUserRequestDto",
|
||||
"RevokeUserRequestDto",
|
||||
"CreateUserResponseDto",
|
||||
"UpdateUserResponseDto",
|
||||
"UserActiveInboundsDto",
|
||||
"UserLastConnectedNodeDto",
|
||||
"GetUserByUuidResponseDto",
|
||||
"GetUserByShortUuidResponseDto",
|
||||
"GetUserByUsernameResponseDto",
|
||||
"GetUserByIdResponseDto",
|
||||
"DisableUserResponseDto",
|
||||
"EnableUserResponseDto",
|
||||
"ResetUserTrafficResponseDto",
|
||||
"RevokeUserSubscriptionResponseDto",
|
||||
"ActivateAllInboundsResponseDto",
|
||||
"GetAllUsersResponseDto",
|
||||
"GetAllTagsResponseDto",
|
||||
"GetUserAccessibleNodesResponseDto",
|
||||
"GetUserSubscriptionRequestHistoryResponseDto",
|
||||
"TelegramUserResponseDto",
|
||||
"EmailUserResponseDto",
|
||||
"TagUserResponseDto",
|
||||
"DeleteUserResponseDto",
|
||||
"UserResponseDto",
|
||||
"UsersResponseDto",
|
||||
"TagUserResponseDto",
|
||||
"TagsResponseDto",
|
||||
"SubscriptionRequestsResponseData",
|
||||
"UserTrafficDto",
|
||||
"ActiveInternalSquadDto",
|
||||
"SubscriptionRequestRecord",
|
||||
"HappCrypto",
|
||||
"UserActiveInboundsDto",
|
||||
"UserLastConnectedNodeDto",
|
||||
"GetSubscriptionRequestsResponseDto",
|
||||
# Users bulk actions models
|
||||
"BulkAllExtendExpirationDateRequestDto",
|
||||
"BulkAllExtendExpirationDateResponseDto",
|
||||
"BulkAllResetTrafficUsersResponseDto",
|
||||
"BulkAllUpdateUsersRequestDto",
|
||||
"BulkAllUpdateUsersResponseDto",
|
||||
"BulkDeleteUsersByStatusRequestDto",
|
||||
"BulkDeleteUsersByStatusResponseDto",
|
||||
"BulkDeleteUsersRequestDto",
|
||||
"BulkDeleteUsersResponseDto",
|
||||
"BulkEventResponseData",
|
||||
"BulkExtendExpirationDateRequestDto",
|
||||
"BulkExtendExpirationDateResponseDto",
|
||||
"BulkResetTrafficUsersRequestDto",
|
||||
"BulkResetTrafficUsersResponseDto",
|
||||
"BulkResponseData",
|
||||
"BulkResponseDto",
|
||||
"BulkRevokeUsersSubscriptionRequestDto",
|
||||
"BulkRevokeUsersSubscriptionResponseDto",
|
||||
"BulkUpdateUsersInternalSquadsRequestDto",
|
||||
"BulkUpdateUsersRequestDto",
|
||||
"BulkUpdateUsersResponseDto",
|
||||
"BulkUpdateUsersSquadsRequestDto",
|
||||
"BulkUpdateUsersSquadsResponseDto",
|
||||
"TagStr",
|
||||
"UpdateUserFields",
|
||||
# Users stats models
|
||||
"UserUsageByRange",
|
||||
|
|
|
|||
|
|
@ -153,15 +153,14 @@ class UpdateHostResponseDto(CreateHostResponseDto):
|
|||
pass
|
||||
|
||||
|
||||
class GetAllHostsResponseDto(BaseModel):
|
||||
"""Get all hosts response"""
|
||||
response: List[HostResponseDto]
|
||||
|
||||
class GetAllHostsResponseDto(RootModel[List[HostResponseDto]]):
|
||||
root: List[HostResponseDto]
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.response)
|
||||
|
||||
return iter(self.root)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.response[item]
|
||||
return self.root[item]
|
||||
|
||||
|
||||
class GetOneHostResponseDto(HostResponseDto):
|
||||
|
|
|
|||
|
|
@ -69,9 +69,9 @@ class RemnawaveSettingsData(BaseModel):
|
|||
branding_settings: Optional[BrandingSettings] = Field(None, alias="brandingSettings")
|
||||
|
||||
|
||||
class GetRemnawaveSettingsResponseDto(BaseModel):
|
||||
class GetRemnawaveSettingsResponseDto(RemnawaveSettingsData):
|
||||
"""Get Remnawave settings response"""
|
||||
response: RemnawaveSettingsData
|
||||
pass
|
||||
|
||||
|
||||
class UpdateRemnawaveSettingsRequestDto(BaseModel):
|
||||
|
|
@ -83,6 +83,6 @@ class UpdateRemnawaveSettingsRequestDto(BaseModel):
|
|||
branding_settings: Optional[BrandingSettings] = Field(None, serialization_alias="brandingSettings")
|
||||
|
||||
|
||||
class UpdateRemnawaveSettingsResponseDto(BaseModel):
|
||||
class UpdateRemnawaveSettingsResponseDto(RemnawaveSettingsData):
|
||||
"""Update Remnawave settings response"""
|
||||
response: RemnawaveSettingsData
|
||||
pass
|
||||
|
|
@ -9,7 +9,6 @@ from pydantic import (
|
|||
RootModel,
|
||||
StringConstraints,
|
||||
)
|
||||
from pydantic.alias_generators import to_camel
|
||||
|
||||
from remnawave.enums import TrafficLimitStrategy, UserStatus
|
||||
from remnawave.utils.happ_crypt import create_happ_crypto_link
|
||||
|
|
@ -34,8 +33,7 @@ class ActiveInternalSquadDto(BaseModel):
|
|||
|
||||
|
||||
class HappCrypto(BaseModel):
|
||||
cryptoLink: str
|
||||
|
||||
crypto_link: str = Field(alias="cryptoLink")
|
||||
|
||||
|
||||
class CreateUserRequestDto(BaseModel):
|
||||
|
|
@ -108,6 +106,7 @@ class UpdateUserRequestDto(BaseModel):
|
|||
)
|
||||
external_squad_uuid: Optional[UUID] = Field(None, serialization_alias="externalSquadUuid")
|
||||
|
||||
|
||||
class UserTrafficDto(BaseModel):
|
||||
"""User traffic information"""
|
||||
used_traffic_bytes: float = Field(alias="usedTrafficBytes")
|
||||
|
|
@ -173,95 +172,19 @@ class UserResponseDto(BaseModel):
|
|||
"""Backward compatibility property"""
|
||||
return self.user_traffic.last_connected_node_uuid
|
||||
|
||||
# generate happ link
|
||||
@property
|
||||
def happ(self) -> HappCrypto:
|
||||
"""Generate Happ Crypto Link"""
|
||||
crypto_link = create_happ_crypto_link(self.subscription_url)
|
||||
return HappCrypto(cryptoLink=crypto_link)
|
||||
|
||||
class EmailUserResponseDto(RootModel[list[UserResponseDto]]):
|
||||
def __iter__(self):
|
||||
return iter(self.root)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.root[item]
|
||||
|
||||
|
||||
class TagUserResponseDto(RootModel[list[UserResponseDto]]):
|
||||
def __iter__(self):
|
||||
return iter(self.root)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.root[item]
|
||||
|
||||
|
||||
class TelegramUserResponseDto(RootModel[list[UserResponseDto]]):
|
||||
def __iter__(self):
|
||||
return iter(self.root)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.root[item]
|
||||
|
||||
|
||||
class UsersResponseDto(BaseModel):
|
||||
users: list[UserResponseDto]
|
||||
total: int
|
||||
|
||||
|
||||
class DeleteUserResponseDto(BaseModel):
|
||||
is_deleted: bool = Field(alias="isDeleted")
|
||||
|
||||
|
||||
class TagsResponseDto(BaseModel):
|
||||
tags: list[str]
|
||||
|
||||
|
||||
class CreateUserResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class UpdateUserResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class DisableUserResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class EnableUserResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class ResetUserTrafficResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class RevokeUserSubscriptionResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class ActivateAllInboundsResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class GetUserByUuidResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class GetUserByShortUuidResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class GetUserByUsernameResponseDto(UserResponseDto):
|
||||
pass
|
||||
|
||||
|
||||
class RevokeUserRequestDto(BaseModel):
|
||||
short_uuid: str | None = Field(
|
||||
"""Request DTO for revoking user subscription"""
|
||||
short_uuid: Optional[str] = Field(
|
||||
None,
|
||||
serialization_alias="shortUuid",
|
||||
description="Optional. If not provided, a new short UUID will be generated by Remnawave. Please note that it is strongly recommended to allow Remnawave to generate the short UUID.",
|
||||
description="Optional. If not provided, a new short UUID will be generated by Remnawave.",
|
||||
min_length=6,
|
||||
max_length=48,
|
||||
pattern=r"^[a-zA-Z0-9_-]+$",
|
||||
|
|
@ -269,6 +192,7 @@ class RevokeUserRequestDto(BaseModel):
|
|||
|
||||
|
||||
class SubscriptionRequestRecord(BaseModel):
|
||||
"""Subscription request history record"""
|
||||
id: int
|
||||
user_uuid: UUID = Field(alias="userUuid")
|
||||
request_at: datetime = Field(alias="requestAt")
|
||||
|
|
@ -277,9 +201,133 @@ class SubscriptionRequestRecord(BaseModel):
|
|||
|
||||
|
||||
class SubscriptionRequestsResponseData(BaseModel):
|
||||
"""Subscription requests response data"""
|
||||
total: int
|
||||
records: List[SubscriptionRequestRecord]
|
||||
|
||||
|
||||
class CreateUserResponseDto(UserResponseDto):
|
||||
"""Response for create user"""
|
||||
pass
|
||||
|
||||
|
||||
class UpdateUserResponseDto(UserResponseDto):
|
||||
"""Response for update user"""
|
||||
pass
|
||||
|
||||
|
||||
class GetUserByUuidResponseDto(UserResponseDto):
|
||||
"""Response for get user by UUID"""
|
||||
pass
|
||||
|
||||
|
||||
class GetUserByShortUuidResponseDto(UserResponseDto):
|
||||
"""Response for get user by short UUID"""
|
||||
pass
|
||||
|
||||
|
||||
class GetUserByUsernameResponseDto(UserResponseDto):
|
||||
"""Response for get user by username"""
|
||||
pass
|
||||
|
||||
|
||||
class GetUserByIdResponseDto(UserResponseDto):
|
||||
"""Response for get user by ID"""
|
||||
pass
|
||||
|
||||
|
||||
class DisableUserResponseDto(UserResponseDto):
|
||||
"""Response for disable user"""
|
||||
pass
|
||||
|
||||
|
||||
class EnableUserResponseDto(UserResponseDto):
|
||||
"""Response for enable user"""
|
||||
pass
|
||||
|
||||
|
||||
class ResetUserTrafficResponseDto(UserResponseDto):
|
||||
"""Response for reset user traffic"""
|
||||
pass
|
||||
|
||||
|
||||
class RevokeUserSubscriptionResponseDto(UserResponseDto):
|
||||
"""Response for revoke user subscription"""
|
||||
pass
|
||||
|
||||
|
||||
class ActivateAllInboundsResponseDto(UserResponseDto):
|
||||
"""Response for activate all inbounds"""
|
||||
pass
|
||||
|
||||
|
||||
class UsersResponseDto(BaseModel):
|
||||
"""Users collection response"""
|
||||
users: list[UserResponseDto]
|
||||
total: int
|
||||
|
||||
|
||||
class GetAllUsersResponseDto(UsersResponseDto):
|
||||
"""Response for get all users"""
|
||||
pass
|
||||
|
||||
|
||||
class TagsResponseDto(BaseModel):
|
||||
"""Tags collection response"""
|
||||
tags: list[str]
|
||||
|
||||
|
||||
class GetAllTagsResponseDto(TagsResponseDto):
|
||||
"""Response for get all tags"""
|
||||
pass
|
||||
|
||||
|
||||
class GetSubscriptionRequestsResponseDto(SubscriptionRequestsResponseData):
|
||||
pass
|
||||
"""Response for get subscription requests"""
|
||||
pass
|
||||
|
||||
|
||||
class GetUserSubscriptionRequestHistoryResponseDto(SubscriptionRequestsResponseData):
|
||||
"""Response for get user subscription request history"""
|
||||
pass
|
||||
|
||||
|
||||
class DeleteUserResponseDto(BaseModel):
|
||||
"""Response for delete user"""
|
||||
is_deleted: bool = Field(alias="isDeleted")
|
||||
|
||||
|
||||
class EmailUserResponseDto(RootModel[list[UserResponseDto]]):
|
||||
"""Response for get users by email"""
|
||||
def __iter__(self):
|
||||
return iter(self.root)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.root[item]
|
||||
|
||||
|
||||
class TagUserResponseDto(RootModel[list[UserResponseDto]]):
|
||||
"""Response for get users by tag"""
|
||||
def __iter__(self):
|
||||
return iter(self.root)
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.root[item]
|
||||
|
||||
|
||||
class TelegramUserResponseDto(RootModel[list[UserResponseDto]]):
|
||||
"""Response for get users by telegram ID"""
|
||||
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]
|
||||
|
|
@ -1,97 +1,203 @@
|
|||
from datetime import datetime
|
||||
from typing import Annotated, List, Literal, Optional
|
||||
from typing import Annotated, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, EmailStr, Field, constr
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from remnawave.enums import UserStatus
|
||||
from remnawave.enums.users import TrafficLimitStrategy
|
||||
from remnawave.enums import UserStatus, TrafficLimitStrategy
|
||||
|
||||
|
||||
class BulkUpdateUsersInternalSquadsRequestDto(BaseModel):
|
||||
uuids: List[UUID]
|
||||
active_internal_squads: List[UUID] = Field(serialization_alias="activeInternalSquads")
|
||||
|
||||
# Type alias for tag validation
|
||||
TagStr = Annotated[
|
||||
str,
|
||||
Field(min_length=1, max_length=16, pattern=r"^[A-Z0-9_]+$")
|
||||
]
|
||||
|
||||
|
||||
# Request DTOs
|
||||
class BulkDeleteUsersByStatusRequestDto(BaseModel):
|
||||
"""Request to delete users by status"""
|
||||
status: UserStatus = Field(default=UserStatus.ACTIVE)
|
||||
|
||||
|
||||
class BulkDeleteUsersRequestDto(BaseModel):
|
||||
"""Request to delete users by UUIDs"""
|
||||
uuids: List[UUID] = Field(min_length=1, max_length=500)
|
||||
|
||||
|
||||
class BulkRevokeUsersSubscriptionRequestDto(BaseModel):
|
||||
"""Request to revoke users subscription"""
|
||||
uuids: List[UUID] = Field(min_length=1, max_length=500)
|
||||
|
||||
|
||||
class BulkResetTrafficUsersRequestDto(BaseModel):
|
||||
"""Request to reset traffic for users"""
|
||||
uuids: List[UUID] = Field(min_length=1, max_length=500)
|
||||
|
||||
|
||||
class UpdateUserFields(BaseModel):
|
||||
"""Fields to update for users"""
|
||||
status: Optional[UserStatus] = None
|
||||
traffic_limit_bytes: Optional[int] = Field(
|
||||
None, serialization_alias="trafficLimitBytes", strict=True, ge=0
|
||||
None,
|
||||
serialization_alias="trafficLimitBytes",
|
||||
ge=0,
|
||||
description="Traffic limit in bytes. 0 - unlimited"
|
||||
)
|
||||
traffic_limit_strategy: Optional[TrafficLimitStrategy] = Field(
|
||||
None, serialization_alias="trafficLimitStrategy"
|
||||
None,
|
||||
serialization_alias="trafficLimitStrategy",
|
||||
description="Traffic limit reset strategy"
|
||||
)
|
||||
expire_at: Optional[datetime] = Field(
|
||||
None,
|
||||
serialization_alias="expireAt",
|
||||
description="Expiration date: 2025-01-17T15:38:45.065Z"
|
||||
)
|
||||
expire_at: Optional[datetime] = Field(None, serialization_alias="expireAt")
|
||||
description: Optional[str] = None
|
||||
telegram_id: Optional[int] = Field(None, serialization_alias="telegramId")
|
||||
email: Optional[str] = None
|
||||
tag: Optional[TagStr] = Field(
|
||||
None,
|
||||
description="Tag for user. Must be uppercase, alphanumeric, and can include underscores. Max length 16 characters."
|
||||
)
|
||||
telegram_id: Optional[int] = Field(None, serialization_alias="telegramId")
|
||||
email: Optional[str] = None
|
||||
hwid_device_limit: Optional[int] = Field(
|
||||
None, serialization_alias="hwidDeviceLimit", strict=True, ge=0
|
||||
None,
|
||||
serialization_alias="hwidDeviceLimit",
|
||||
ge=0
|
||||
)
|
||||
telegram_id: Optional[int] = Field(
|
||||
None, serialization_alias="telegramId"
|
||||
external_squad_uuid: Optional[UUID] = Field(
|
||||
None,
|
||||
serialization_alias="externalSquadUuid",
|
||||
description="Optional. External squad UUID."
|
||||
)
|
||||
|
||||
|
||||
class BulkUpdateUsersRequestDto(BaseModel):
|
||||
"""Request to bulk update users"""
|
||||
uuids: List[UUID] = Field(min_length=1, max_length=500)
|
||||
fields: UpdateUserFields
|
||||
|
||||
|
||||
class BulkUpdateUsersSquadsRequestDto(BaseModel):
|
||||
"""Request to update users internal squads"""
|
||||
uuids: List[UUID] = Field(min_length=1, max_length=500)
|
||||
active_internal_squads: List[UUID] = Field(serialization_alias="activeInternalSquads")
|
||||
|
||||
|
||||
class BulkExtendExpirationDateRequestDto(BaseModel):
|
||||
"""Request to extend expiration date for selected users"""
|
||||
uuids: List[UUID] = Field(min_length=1, max_length=500)
|
||||
extend_days: int = Field(
|
||||
serialization_alias="extendDays",
|
||||
ge=1,
|
||||
le=9999
|
||||
)
|
||||
|
||||
|
||||
|
||||
class BulkAllUpdateUsersRequestDto(BaseModel):
|
||||
status: Optional[Literal["ACTIVE", "DISABLED", "LIMITED", "EXPIRED"]] = Field(
|
||||
"ACTIVE"
|
||||
)
|
||||
|
||||
"""Request to update all users"""
|
||||
status: Optional[UserStatus] = Field(default=UserStatus.ACTIVE)
|
||||
traffic_limit_bytes: Optional[int] = Field(
|
||||
None,
|
||||
serialization_alias="trafficLimitBytes",
|
||||
ge=0,
|
||||
description="Traffic limit in bytes. 0 - unlimited"
|
||||
)
|
||||
|
||||
traffic_limit_strategy: Optional[Literal["NO_RESET", "DAY", "WEEK", "MONTH"]] = Field(
|
||||
traffic_limit_strategy: Optional[TrafficLimitStrategy] = Field(
|
||||
None,
|
||||
serialization_alias="trafficLimitStrategy",
|
||||
description="Traffic limit reset strategy"
|
||||
)
|
||||
|
||||
expire_at: Optional[datetime] = Field(
|
||||
None,
|
||||
serialization_alias="expireAt",
|
||||
description="Expiration date"
|
||||
description="Expiration date: 2025-01-17T15:38:45.065Z"
|
||||
)
|
||||
|
||||
description: Optional[str] = None
|
||||
|
||||
telegram_id: Optional[int] = Field(
|
||||
None,
|
||||
serialization_alias="telegramId"
|
||||
)
|
||||
|
||||
hwid_device_limit: Optional[int] = Field(
|
||||
None, serialization_alias="hwidDeviceLimit", strict=True, ge=0
|
||||
)
|
||||
|
||||
telegram_id: Optional[int] = Field(None, serialization_alias="telegramId")
|
||||
email: Optional[str] = None
|
||||
|
||||
tag: Optional[TagStr] = Field(
|
||||
None,
|
||||
description="Tag for user. Must be uppercase, alphanumeric, and can include underscores. Max length 16 characters."
|
||||
)
|
||||
hwid_device_limit: Optional[int] = Field(
|
||||
None,
|
||||
serialization_alias="hwidDeviceLimit",
|
||||
ge=0
|
||||
)
|
||||
|
||||
|
||||
class BulkResponseDto(BaseModel):
|
||||
class BulkAllExtendExpirationDateRequestDto(BaseModel):
|
||||
"""Request to extend expiration date for all users"""
|
||||
extend_days: int = Field(
|
||||
serialization_alias="extendDays",
|
||||
ge=1
|
||||
)
|
||||
|
||||
|
||||
# Base Response DTOs (без обертки response)
|
||||
class BulkResponseData(BaseModel):
|
||||
"""Common bulk response with affected rows"""
|
||||
affected_rows: int = Field(alias="affectedRows")
|
||||
|
||||
|
||||
class BulkAllResetTrafficUsersResponseDto(BaseModel):
|
||||
class BulkEventResponseData(BaseModel):
|
||||
"""Common bulk response with event sent flag"""
|
||||
event_sent: bool = Field(alias="eventSent")
|
||||
|
||||
|
||||
class BulkAllUpdateUsersResponseDto(BaseModel):
|
||||
event_sent: bool = Field(alias="eventSent")
|
||||
# Response DTOs - наследуются от базовых
|
||||
class BulkDeleteUsersByStatusResponseDto(BulkResponseData):
|
||||
"""Response for bulk delete by status"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkDeleteUsersResponseDto(BulkResponseData):
|
||||
"""Response for bulk delete users"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkRevokeUsersSubscriptionResponseDto(BulkResponseData):
|
||||
"""Response for bulk revoke subscription"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkResetTrafficUsersResponseDto(BulkResponseData):
|
||||
"""Response for bulk reset traffic"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkUpdateUsersResponseDto(BulkResponseData):
|
||||
"""Response for bulk update users"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkUpdateUsersSquadsResponseDto(BulkResponseData):
|
||||
"""Response for bulk update squads"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkExtendExpirationDateResponseDto(BulkResponseData):
|
||||
"""Response for bulk extend expiration date"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkAllUpdateUsersResponseDto(BulkEventResponseData):
|
||||
"""Response for bulk update all users"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkAllResetTrafficUsersResponseDto(BulkEventResponseData):
|
||||
"""Response for bulk reset all users traffic"""
|
||||
pass
|
||||
|
||||
|
||||
class BulkAllExtendExpirationDateResponseDto(BulkEventResponseData):
|
||||
"""Response for bulk extend all users expiration date"""
|
||||
pass
|
||||
|
||||
|
||||
# Legacy compatibility
|
||||
BulkResponseDto = BulkResponseData
|
||||
BulkUpdateUsersInternalSquadsRequestDto = BulkUpdateUsersSquadsRequestDto
|
||||
Loading…
Add table
Add a link
Reference in a new issue