|
from pydantic import BaseModel, Field, constr |
|
from typing import Optional, List |
|
from datetime import datetime |
|
from pydantic import BaseModel, Field, validator |
|
from typing import Optional, List, Any, Dict |
|
from .utils.helperfx import PhoneValidator |
|
|
|
|
|
|
|
|
|
PHONE_PATTERN = r"^(?:\+255|0)\d{9}$" |
|
MAC_PATTERN = r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$" |
|
|
|
|
|
|
|
class RegisterUserRequest(BaseModel): |
|
name: str = Field(..., max_length=100) |
|
password: str = Field(..., max_length=100) |
|
phoneNumber: str = Field( |
|
..., |
|
pattern=PHONE_PATTERN, |
|
description="Tanzanian phone number starting with +255 or 0 followed by 9 digits", |
|
) |
|
mac_address: str = Field( |
|
..., pattern=MAC_PATTERN, description="MAC address in standard format" |
|
) |
|
|
|
def hash_password(self): |
|
self.password = pwd_context.hash(self.password) |
|
|
|
class Config: |
|
schema_extra = { |
|
"example": { |
|
"name": "John Doe", |
|
"password": "StrongPassword1!", |
|
"phoneNumber": "+255123456789", |
|
"mac_address": "00:1A:2B:3C:4D:5E", |
|
} |
|
} |
|
|
|
|
|
|
|
class LoginUserRequest(BaseModel): |
|
phoneNumber: str = Field(..., pattern=PHONE_PATTERN) |
|
password: str |
|
mac_address: str = Field(..., pattern=MAC_PATTERN) |
|
|
|
|
|
|
|
class UserSessionData(BaseModel): |
|
phone: str |
|
mac_address: str |
|
ip_address: Optional[str] = None |
|
uptime: Optional[str] = None |
|
bytes_in: int = 0 |
|
bytes_out: int = 0 |
|
status: str |
|
profile: str |
|
login_time: Optional[datetime] = None |
|
logout_time: Optional[datetime] = None |
|
|
|
|
|
|
|
class ActiveUsersResponse(BaseModel): |
|
code: int |
|
message: str |
|
active_users: List[UserSessionData] |
|
|
|
|
|
class UsersListResponse(BaseModel): |
|
code: int |
|
message: str |
|
data: list |
|
|
|
|
|
|
|
class UserStatusResponse(BaseModel): |
|
code: int |
|
message: str |
|
user_status: str |
|
|
|
|
|
|
|
class BaseResponse(BaseModel): |
|
code: int |
|
message: str |
|
payload: Optional[dict] = None |
|
|
|
|
|
|
|
class LoginResponse(BaseResponse): |
|
login_time: Optional[datetime] = None |
|
|
|
|
|
class LogoutResponse(BaseResponse): |
|
logout_time: Optional[datetime] = None |
|
|
|
|
|
|
|
class ForgotPasswordRequest(BaseModel): |
|
phoneNumber: str = Field(..., pattern=PHONE_PATTERN) |
|
|
|
|
|
class ResetPasswordRequest(BaseModel): |
|
phoneNumber: str = Field(..., pattern=PHONE_PATTERN) |
|
new_password: str = Field(..., max_length=100) |
|
|
|
|
|
|
|
class UserStats(BaseModel): |
|
phone: str |
|
profile: str |
|
status: str |
|
uptime: str |
|
bytes_in: int |
|
bytes_out: int |
|
|
|
|
|
class UserListData(BaseModel): |
|
phoneNumber: str = Field(..., description="User phone number") |
|
profile: str = Field(..., description="User profile, e.g., bandwidth limit profile") |
|
status: str = Field(..., description="User status, either 'active' or 'inactive'") |
|
disabled: bool = Field(..., description="Whether the user is disabled") |
|
comment: Optional[str] = Field( |
|
None, description="Additional comments or notes for the user" |
|
) |
|
data_limit: Optional[int] = Field( |
|
None, description="Total data limit for the user in bytes" |
|
) |
|
|
|
|
|
class UserStatsResponse(BaseResponse): |
|
user_stats: List[UserStats] |
|
|
|
|
|
|
|
class ResponseBuilder: |
|
@staticmethod |
|
def success(response_type: BaseModel, message: str, data: dict = None): |
|
return response_type(code=200, message=message, payload=data) |
|
|
|
@staticmethod |
|
def error(response_type: BaseModel, message: str, error_details: str): |
|
return response_type( |
|
code=400, message=message, payload={"error": error_details} |
|
) |
|
|
|
|
|
|
|
class UserBase(BaseModel): |
|
phoneNumber: str = Field(..., description="User phone number") |
|
|
|
@validator("phoneNumber") |
|
def validate_phone(cls, phoneNumber): |
|
is_valid, formatted_phone = PhoneValidator.validate_and_format(phoneNumber) |
|
if not is_valid: |
|
raise ValueError("Invalid phone number format") |
|
return formatted_phone |
|
|
|
|
|
|
|
class UserCreate(UserBase): |
|
password: str = Field(..., min_length=4, description="User password") |
|
profile: str = Field(default="2mbps_profile", description="User profile") |
|
|
|
|
|
class UserLogin(UserBase): |
|
password: str = Field(..., description="User password") |
|
mac_address: str = Field(..., description="Device MAC address") |
|
ip_address: str = Field(..., description="User's IP address") |
|
|
|
|
|
|
|
class ApiResponse(BaseModel): |
|
success: bool = True |
|
message: Optional[str] = Field("success", description="Response message") |
|
error: Optional[str] = None |
|
data: Optional[Dict[str, Any]] = None |
|
|
|
|
|
|
|
class UserParams(BaseModel): |
|
name: str |
|
password: str |
|
profile: str |
|
disabled: bool |
|
|
|
|
|
class ActiveUserData(BaseModel): |
|
phone: str |
|
uptime: str |
|
mac_address: str |
|
ip_address: str |
|
usage: UserStats |
|
|
|
|
|
class UserStatsData(BaseModel): |
|
phoneNumber: str |
|
profile: str |
|
status: str |
|
uptime: str |
|
usage: UserStats |
|
|
|
|
|
class UserListData(BaseModel): |
|
phoneNumber: str |
|
profile: str |
|
status: str |
|
disabled: bool |
|
comment: Optional[str] = "" |
|
data_limit: Optional[int] = None |
|
|
|
|
|
|
|
class RegisterResponse(ApiResponse): |
|
data: Optional[Dict[str, Any]] = Field(None, description="Registration details") |
|
|
|
|
|
class LoginResponse(ApiResponse): |
|
data: Optional[Dict[str, Any]] = Field(None, description="Login details") |
|
|
|
|
|
class LogoutResponse(ApiResponse): |
|
data: Optional[Dict[str, Any]] = Field(None, description="Logout details") |
|
|
|
|
|
class UserStatusResponse(ApiResponse): |
|
data: Optional[Dict[str, Any]] = Field( |
|
None, description="User status change details" |
|
) |
|
|
|
|
|
class ActiveUsersResponse(ApiResponse): |
|
active_users: List[UserSessionData] |
|
|
|
|
|
class UserStatsResponse(ApiResponse): |
|
data: Optional[Dict[str, List[UserStatsData]]] = Field( |
|
None, description="Statistics for users" |
|
) |
|
|
|
|
|
class UsersListResponse(ApiResponse): |
|
data: Optional[Dict[str, List[UserListData]]] = Field( |
|
None, description="List of all users with details" |
|
) |
|
|