Spaces:
Runtime error
Runtime error
File size: 7,018 Bytes
a6fd1a3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
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
@field_validator("username")
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
@field_validator('password')
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
@field_validator('role')
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
@field_validator('avatar_url')
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@"
)
@field_validator('new_password')
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@"
)
@field_validator('newPassword')
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 |