from datetime import datetime, timezone from enum import Enum from uuid import UUID from pydantic import AnyHttpUrl, BaseModel, ConfigDict, Field, field_validator def utc_now() -> datetime: return datetime.now(timezone.utc) class MonitorState(str, Enum): UNKNOWN = "unknown" UP = "up" DOWN = "down" ERROR = "error" class CurrentStatus(BaseModel): state: MonitorState = MonitorState.UNKNOWN checked_at: datetime | None = None latency_ms: float | None = Field(default=None, ge=0) http_status: int | None = Field(default=None, ge=100, le=599) error: str | None = Field(default=None, max_length=500) class MonitorFields(BaseModel): model_config = ConfigDict(str_strip_whitespace=True) name: str = Field(min_length=1, max_length=100) target_url: AnyHttpUrl @field_validator("target_url") @classmethod def reject_credentials(cls, value: AnyHttpUrl) -> AnyHttpUrl: if value.username is not None or value.password is not None: raise ValueError("URL credentials are not allowed") return value class MonitorCreate(MonitorFields): pass class MonitorUpdate(MonitorFields): pass class Monitor(MonitorFields): id: UUID created_at: datetime updated_at: datetime current_status: CurrentStatus class Health(BaseModel): status: str