""" Server Pydantic schemas. """ from typing import Optional from pydantic import BaseModel, Field, field_validator class ServerCreate(BaseModel): """ Schema for creating a new server. """ name: str = Field(..., min_length=1, max_length=100, description="Server name") url: str = Field(..., min_length=1, max_length=500, description="Gitea server URL") api_token: str = Field(..., min_length=1, description="Gitea API token") ssh_key_id: int = Field(..., gt=0, description="SSH key ID to use") local_path: str = Field(..., min_length=1, max_length=500, description="Local storage path") sync_enabled: bool = Field(default=False, description="Whether sync is enabled") schedule_cron: Optional[str] = Field( default=None, max_length=50, description="Cron expression for scheduled sync" ) @field_validator("name") @classmethod def name_must_not_be_empty(cls, v: str) -> str: """Validate that name is not empty or whitespace only.""" if not v or not v.strip(): raise ValueError("name must not be empty") return v.strip() @field_validator("url") @classmethod def url_must_not_be_empty(cls, v: str) -> str: """Validate that url is not empty or whitespace only.""" if not v or not v.strip(): raise ValueError("url must not be empty") return v.strip() @field_validator("api_token") @classmethod def api_token_must_not_be_empty(cls, v: str) -> str: """Validate that api_token is not empty or whitespace only.""" if not v or not v.strip(): raise ValueError("api_token must not be empty") return v.strip() @field_validator("local_path") @classmethod def local_path_must_not_be_empty(cls, v: str) -> str: """Validate that local_path is not empty or whitespace only.""" if not v or not v.strip(): raise ValueError("local_path must not be empty") return v.strip() model_config = { "json_schema_extra": { "examples": [ { "name": "my-gitea", "url": "https://gitea.example.com", "api_token": "your_api_token_here", "ssh_key_id": 1, "local_path": "/data/gitea-mirror", "sync_enabled": False, "schedule_cron": None } ] } } class ServerUpdate(BaseModel): """ Schema for updating a server. All fields are optional. """ name: Optional[str] = Field(None, min_length=1, max_length=100, description="Server name") url: Optional[str] = Field(None, min_length=1, max_length=500, description="Gitea server URL") api_token: Optional[str] = Field(None, min_length=1, description="Gitea API token") ssh_key_id: Optional[int] = Field(None, gt=0, description="SSH key ID to use") local_path: Optional[str] = Field(None, min_length=1, max_length=500, description="Local storage path") sync_enabled: Optional[bool] = Field(None, description="Whether sync is enabled") schedule_cron: Optional[str] = Field( None, max_length=50, description="Cron expression for scheduled sync" ) status: Optional[str] = Field( None, pattern="^(untested|testing|success|error)$", description="Server status" ) @field_validator("name") @classmethod def name_must_not_be_empty(cls, v: Optional[str]) -> Optional[str]: """Validate that name is not empty or whitespace only.""" if v is not None and (not v or not v.strip()): raise ValueError("name must not be empty") return v.strip() if v else None @field_validator("url") @classmethod def url_must_not_be_empty(cls, v: Optional[str]) -> Optional[str]: """Validate that url is not empty or whitespace only.""" if v is not None and (not v or not v.strip()): raise ValueError("url must not be empty") return v.strip() if v else None @field_validator("api_token") @classmethod def api_token_must_not_be_empty(cls, v: Optional[str]) -> Optional[str]: """Validate that api_token is not empty or whitespace only.""" if v is not None and (not v or not v.strip()): raise ValueError("api_token must not be empty") return v.strip() if v else None @field_validator("local_path") @classmethod def local_path_must_not_be_empty(cls, v: Optional[str]) -> Optional[str]: """Validate that local_path is not empty or whitespace only.""" if v is not None and (not v or not v.strip()): raise ValueError("local_path must not be empty") return v.strip() if v else None model_config = { "json_schema_extra": { "examples": [ { "name": "updated-gitea", "sync_enabled": True, "schedule_cron": "0 */6 * * *" } ] } } class ServerResponse(BaseModel): """ Schema for server response. """ id: int = Field(description="Server ID") name: str = Field(description="Server name") url: str = Field(description="Gitea server URL") ssh_key_id: int = Field(description="SSH key ID") sync_enabled: bool = Field(description="Whether sync is enabled") schedule_cron: Optional[str] = Field(default=None, description="Cron expression") local_path: str = Field(description="Local storage path") status: str = Field(description="Server status") created_at: int = Field(description="Creation timestamp (Unix timestamp)") updated_at: int = Field(description="Last update timestamp (Unix timestamp)") model_config = { "json_schema_extra": { "examples": [ { "id": 1, "name": "my-gitea", "url": "https://gitea.example.com", "ssh_key_id": 1, "sync_enabled": True, "schedule_cron": "0 */6 * * *", "local_path": "/data/gitea-mirror", "status": "success", "created_at": 1711804800, "updated_at": 1711891200 } ] } }