refactor: use backend API for user ID uniqueness validation

- Add GET /api/v1/users/check-id/{user_id} endpoint for real-time validation
- Replace frontend local validation with debounced API calls (500ms)
- Support exclude_user_id parameter for edit scenarios
- Add UserIdCheckResponse schema
- Maintain format validation (alphanumeric + underscore) on frontend
- Clean up timeout on component unmount

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
chengkai3
2026-06-19 11:04:28 +08:00
parent 46fb766861
commit 6cd959c528
3 changed files with 87 additions and 23 deletions
+19
View File
@@ -11,6 +11,7 @@ from ...schemas.user import (
UserPublic,
UserRoleUpdateRequest,
UserUpdateRequest,
UserIdCheckResponse,
)
from ...services.user_service import (
UserCreateError,
@@ -29,6 +30,24 @@ from ...services.user_service import (
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/check-id/{user_id}", response_model=UserIdCheckResponse)
def check_user_id_availability(
user_id: str,
exclude_user_id: str | None = Query(default=None),
_: CurrentUser = Depends(require_permission("user.manage")),
db: Session = Depends(get_db),
) -> UserIdCheckResponse:
"""Check if a user ID is available. Use exclude_user_id when editing an existing user."""
existing_user = get_user_by_id(db, user_id)
if existing_user:
if exclude_user_id and existing_user.id.lower() == exclude_user_id.lower():
return UserIdCheckResponse(available=True, message="Current user ID")
return UserIdCheckResponse(available=False, message="User ID already exists")
return UserIdCheckResponse(available=True, message="User ID is available")
@router.post("", response_model=UserPublic)
def create_user_account(
payload: UserCreateRequest,
+5
View File
@@ -20,6 +20,11 @@ class UserListResponse(BaseModel):
total: int
class UserIdCheckResponse(BaseModel):
available: bool
message: str
class UserUpdateRequest(BaseModel):
email: str | None = None
username: str | None = Field(default=None, min_length=3, max_length=64)