feat(api): add bulk user creation endpoint

This commit is contained in:
Whispering Wind
2025-08-20 23:59:15 +03:30
committed by GitHub
parent 5a762ad918
commit af2b599dd6
2 changed files with 54 additions and 3 deletions

View File

@ -1,5 +1,6 @@
import re
from typing import Optional, List
from pydantic import BaseModel, RootModel, Field
from pydantic import BaseModel, RootModel, Field, field_validator
class UserInfoResponse(BaseModel):
@ -26,6 +27,27 @@ class AddUserInputBody(BaseModel):
creation_date: Optional[str] = None
unlimited: bool = False
@field_validator('username')
def validate_username(cls, v):
if not re.match(r"^[a-zA-Z0-9_]+$", v):
raise ValueError('Username can only contain letters, numbers, and underscores.')
return v
class AddBulkUsersInputBody(BaseModel):
traffic_gb: float
expiration_days: int
count: int
prefix: str
start_number: int = 1
unlimited: bool = False
@field_validator('prefix')
def validate_prefix(cls, v):
if not re.match(r"^[a-zA-Z0-9_]*$", v):
raise ValueError('Prefix can only contain letters, numbers, and underscores.')
return v
class EditUserInputBody(BaseModel):
new_username: Optional[str] = None
@ -36,6 +58,12 @@ class EditUserInputBody(BaseModel):
blocked: Optional[bool] = None
unlimited_ip: Optional[bool] = None
@field_validator('new_username')
def validate_new_username(cls, v):
if v and not re.match(r"^[a-zA-Z0-9_]+$", v):
raise ValueError('Username can only contain letters, numbers, and underscores.')
return v
class NodeUri(BaseModel):
name: str
uri: str

View File

@ -1,7 +1,7 @@
import json
from fastapi import APIRouter, HTTPException
from .schema.user import UserListResponse, UserInfoResponse, AddUserInputBody, EditUserInputBody, UserUriResponse
from .schema.user import UserListResponse, UserInfoResponse, AddUserInputBody, EditUserInputBody, UserUriResponse, AddBulkUsersInputBody
from .schema.response import DetailResponse
import cli_api
@ -57,6 +57,29 @@ async def add_user_api(body: AddUserInputBody):
detail=f"An unexpected error occurred while adding user '{body.username}': {str(e)}")
@router.post('/bulk/', response_model=DetailResponse, status_code=201)
async def add_bulk_users_api(body: AddBulkUsersInputBody):
"""
Add multiple users in bulk.
"""
try:
cli_api.bulk_user_add(
traffic_gb=body.traffic_gb,
expiration_days=body.expiration_days,
count=body.count,
prefix=body.prefix,
start_number=body.start_number,
unlimited=body.unlimited
)
return DetailResponse(detail=f"Successfully started adding {body.count} users with prefix '{body.prefix}'.")
except cli_api.CommandExecutionError as e:
raise HTTPException(status_code=400,
detail=f'Failed to add bulk users: {str(e)}')
except Exception as e:
raise HTTPException(status_code=500,
detail=f"An unexpected error occurred while adding bulk users: {str(e)}")
@router.get('/{username}', response_model=UserInfoResponse)
async def get_user_api(username: str):
"""
@ -191,4 +214,4 @@ async def show_user_uri_api(username: str):
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=400, detail=f'Unexpected error: {str(e)}')
raise HTTPException(status_code=400, detail=f'Unexpected error: {str(e)}')