diff --git a/app/models.py b/app/models.py index 47bddcc..c66b69a 100644 --- a/app/models.py +++ b/app/models.py @@ -1,36 +1,37 @@ -from datetime import datetime, timezone +from datetime import UTC, datetime from enum import StrEnum from uuid import UUID -from pydantic import AnyHttpUrl, BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, field_validator +from pydantic.networks import AnyHttpUrl -def utc_now() -> datetime: - return datetime.now(timezone.utc) - - -class HealthState(StrEnum): +class State(StrEnum): unknown = "unknown" up = "up" down = "down" + error = "error" -class MonitorCreate(BaseModel): - name: str = Field(min_length=1, max_length=120) +class MonitorInput(BaseModel): + name: str = Field(min_length=1, max_length=100) url: AnyHttpUrl + timeout_seconds: float | None = Field(default=None, gt=0, le=30) + + @field_validator("url") + @classmethod + def reject_credentials(cls, value: AnyHttpUrl) -> AnyHttpUrl: + if value.username or value.password: + raise ValueError("URL credentials are not allowed") + return value -class MonitorUpdate(MonitorCreate): - pass - - -class CurrentStatus(BaseModel): - state: HealthState - checked_at: datetime - latency_ms: float = Field(ge=0) +class CheckSnapshot(BaseModel): + state: State = State.unknown + checked_at: datetime | None = None + latency_ms: float | None = None http_status: int | None = None - error_code: str | None = None - error_message: str | None = None + error: str | None = None class Monitor(BaseModel): @@ -39,18 +40,16 @@ class Monitor(BaseModel): id: UUID name: str url: AnyHttpUrl + timeout_seconds: float | None created_at: datetime updated_at: datetime revision: int - current_status: CurrentStatus | None = None + status: CheckSnapshot -class CheckResponse(BaseModel): +class CheckResult(CheckSnapshot): monitor_id: UUID - status: CurrentStatus - applied: bool -class ErrorDetail(BaseModel): - code: str - message: str +def now() -> datetime: + return datetime.now(UTC)