Spaces:
Runtime error
Runtime error
| from pydantic import BaseModel, EmailStr, Field, field_validator, HttpUrl | |
| from typing import List, Optional | |
| import re | |
| from enum import Enum | |
| # Define UserRole as an Enum | |
| class UserRole(str, Enum): | |
| USER = "user" | |
| ADMIN = "admin" | |
| class RegisterRequest(BaseModel): | |
| username: str = Field( | |
| ..., | |
| min_length=4, | |
| max_length=30, | |
| description="Tên đăng nhập của người dùng, chỉ chấp nhận chữ cái, số và dấu gạch dưới", | |
| example="john_doe123" | |
| ) | |
| password: str = Field( | |
| ..., | |
| min_length=8, | |
| max_length=64, | |
| description="Mật khẩu của người dùng, yêu cầu ít nhất 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt", | |
| example="StrongP@ss123" | |
| ) | |
| email: EmailStr = Field( | |
| ..., | |
| description="Địa chỉ email hợp lệ của người dùng", | |
| example="[email protected]", | |
| pattern=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" | |
| ) | |
| role: UserRole = Field( | |
| default=UserRole.USER, | |
| description="Vai trò của người dùng trong hệ thống", | |
| example=UserRole.USER | |
| ) | |
| avatar_url: Optional[HttpUrl] = Field( | |
| None, | |
| description="URL ảnh đại diện của người dùng", | |
| example="https://example.com/avatars/default.png" | |
| ) | |
| is_active: bool = Field( | |
| default=True, | |
| description="Trạng thái hoạt động của người dùng", | |
| example=True | |
| ) | |
| # Custom validators | |
| def username_alphanumeric(cls, v): | |
| if not re.match(r'^[a-zA-Z0-9_]+$', v): | |
| raise ValueError('Tên đăng nhập chỉ được chứa chữ cái, số và dấu gạch dưới') | |
| return v | |
| def password_strength(cls, v): | |
| if not re.search(r'[A-Z]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự viết hoa') | |
| if not re.search(r'[a-z]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự viết thường') | |
| if not re.search(r'[0-9]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một chữ số') | |
| if not re.search(r'[^a-zA-Z0-9]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự đặc biệt') | |
| return v | |
| def validate_role(cls, v): | |
| if v not in UserRole: | |
| raise ValueError(f'Vai trò không hợp lệ. Các vai trò được hỗ trợ: {", ".join([role.value for role in UserRole])}') | |
| return v | |
| def validate_avatar_url(cls, v): | |
| if v is None: | |
| return v | |
| try: | |
| from urllib.parse import urlparse | |
| parsed = urlparse(str(v)) | |
| if not all([parsed.scheme, parsed.netloc]): | |
| raise ValueError('URL ảnh đại diện không hợp lệ') | |
| except Exception: | |
| raise ValueError('URL ảnh đại diện không hợp lệ') | |
| return v | |
| class RegisterResponse(BaseModel): | |
| message: str | |
| class LoginRequest(BaseModel): | |
| email: str | |
| password: str | |
| class UserResponse(BaseModel): | |
| email: EmailStr | |
| username: str = "N/A" | |
| role: str | |
| avatar_url: Optional[str] = None | |
| class LoginResponse(BaseModel): | |
| # accessToken: str | |
| # token_type: str = "bearer" | |
| user: UserResponse | |
| message: str | |
| class VerifyLoginRequest(BaseModel): | |
| email: str | |
| code: str | |
| class VerifyForgotPassRequest(BaseModel): | |
| email: str | |
| code: str | |
| class UserOut(BaseModel): | |
| username: str | |
| email: EmailStr | |
| role: UserRole = Field(default=UserRole.USER, description="User role", example=UserRole.USER) | |
| avatar_url: Optional[str] = None | |
| is_active:bool = Field(default=True) | |
| class RefreshTokenRequest(BaseModel): | |
| refresh_token: str | |
| class PaginationMetadata(BaseModel): | |
| total: int | |
| page: int | |
| page_size: int | |
| pages: int | |
| has_more: bool | |
| class PaginatedResponse(BaseModel): | |
| items: List[UserOut] | |
| metadata: PaginationMetadata | |
| class ProfileResponse(BaseModel): | |
| username: str | |
| email: EmailStr | |
| role: UserRole = Field(default=UserRole.USER, description="User role", example=UserRole.USER) | |
| avatar_url: Optional[str] = Field( | |
| None, | |
| description="URL ảnh đại diện của người dùng", | |
| example="https://example.com/avatars/default.png" | |
| ) | |
| is_active: bool = Field( | |
| default=True, | |
| description="Trạng thái hoạt động của người dùng", | |
| ) | |
| class ChangePasswordRequest(BaseModel): | |
| current_password: str = Field(..., min_length=8, description="Mật khẩu hiện tại", example="CurrentPassword123@") | |
| new_password: str = Field( | |
| ..., | |
| min_length=8, | |
| max_length=64, | |
| description="Mật khẩu của người dùng, yêu cầu ít nhất 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt", | |
| example="NewPassword123@" | |
| ) | |
| def password_strength(cls, v): | |
| if not re.search(r'[A-Z]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự viết hoa') | |
| if not re.search(r'[a-z]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự viết thường') | |
| if not re.search(r'[0-9]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một chữ số') | |
| if not re.search(r'[^a-zA-Z0-9]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự đặc biệt') | |
| return v | |
| class PasswordResetRequest(BaseModel): | |
| email: EmailStr | |
| class PasswordReset(BaseModel): | |
| code: str | |
| newPassword: str = Field( | |
| ..., | |
| min_length=8, | |
| max_length=64, | |
| description="Mật khẩu của người dùng, yêu cầu ít nhất 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt", | |
| example="NewPassword123@" | |
| ) | |
| def password_strength(cls, v): | |
| if not re.search(r'[A-Z]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự viết hoa') | |
| if not re.search(r'[a-z]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự viết thường') | |
| if not re.search(r'[0-9]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một chữ số') | |
| if not re.search(r'[^a-zA-Z0-9]', v): | |
| raise ValueError('Mật khẩu phải chứa ít nhất một ký tự đặc biệt') | |
| return v | |
| class ResentVerifyCode(BaseModel): | |
| email: str | |
| class TokenValidationRequest(BaseModel): | |
| token: str | |
| # Response model | |
| class TokenValidationResponse(BaseModel): | |
| valid: bool | |
| message: str = None |