170 lines
4.9 KiB
Python
170 lines
4.9 KiB
Python
"""资产相关 Schema(请求/响应模型)
|
||
|
||
设计说明:
|
||
- *In 系列:详情表输入模型(不含 id/asset_id,由服务端填充)
|
||
- AssetCreate/AssetUpdate:主表字段 + 按类型嵌套的可选 detail
|
||
- AssetRead:完整输出,含计算字段 days_to_expiry(距到期天数)
|
||
"""
|
||
|
||
from datetime import date, datetime
|
||
from typing import Optional
|
||
|
||
from sqlmodel import SQLModel
|
||
|
||
from app.models.asset import AssetStatus, AssetType
|
||
|
||
|
||
# --------------------------------------------------------------------------- #
|
||
# 详情表输入模型
|
||
# --------------------------------------------------------------------------- #
|
||
class VPSDetailIn(SQLModel):
|
||
"""VPS 详情输入"""
|
||
|
||
ip_address: str
|
||
tailscale_ip: Optional[str] = None
|
||
region: Optional[str] = None
|
||
os: Optional[str] = None
|
||
cpu_cores: int = 1
|
||
memory_gb: float = 1
|
||
disk_gb: int = 20
|
||
bandwidth_gb: Optional[int] = None
|
||
ssh_port: int = 22
|
||
panel_url: Optional[str] = None
|
||
ssh_user: Optional[str] = None
|
||
login_method: Optional[str] = "key"
|
||
ssh_key: Optional[str] = None # 明文输入,服务端加密存储
|
||
password: Optional[str] = None # 明文输入,服务端加密存储
|
||
purpose: Optional[str] = None
|
||
|
||
|
||
class DomainDetailIn(SQLModel):
|
||
"""域名详情输入"""
|
||
|
||
domain_name: str
|
||
registrar: Optional[str] = None
|
||
dns_provider: Optional[str] = None
|
||
cloudflare_account: Optional[str] = None
|
||
is_using: bool = True
|
||
redirect_target: Optional[str] = None
|
||
bind_asset_id: Optional[int] = None
|
||
|
||
|
||
class AIAccountIn(SQLModel):
|
||
"""AI 账号详情输入"""
|
||
|
||
provider: str
|
||
api_key: Optional[str] = None
|
||
plan: Optional[str] = None
|
||
balance: Optional[float] = None
|
||
currency: str = "USD"
|
||
monthly_usage: Optional[float] = None
|
||
monthly_limit: Optional[float] = None
|
||
|
||
|
||
# --------------------------------------------------------------------------- #
|
||
# 资产主表模型
|
||
# --------------------------------------------------------------------------- #
|
||
class AssetBase(SQLModel):
|
||
"""资产主表公共字段"""
|
||
|
||
name: str
|
||
asset_type: AssetType
|
||
provider: str
|
||
provider_id: Optional[int] = None
|
||
renewal_cycle: Optional[str] = None
|
||
account: Optional[str] = None
|
||
expiry_date: Optional[date] = None
|
||
auto_renew: bool = False
|
||
cost: float = 0
|
||
currency: str = "USD"
|
||
status: AssetStatus = AssetStatus.ACTIVE
|
||
is_archived: bool = False
|
||
remark: Optional[str] = None
|
||
|
||
|
||
class AssetCreate(AssetBase):
|
||
"""创建资产:按 asset_type 携带对应 detail"""
|
||
|
||
vps_detail: Optional[VPSDetailIn] = None
|
||
domain_detail: Optional[DomainDetailIn] = None
|
||
ai_detail: Optional[AIAccountIn] = None
|
||
|
||
|
||
class AssetUpdate(SQLModel):
|
||
"""更新资产:所有字段可选,仅更新传入项"""
|
||
|
||
name: Optional[str] = None
|
||
asset_type: Optional[AssetType] = None
|
||
provider: Optional[str] = None
|
||
provider_id: Optional[int] = None
|
||
renewal_cycle: Optional[str] = None
|
||
account: Optional[str] = None
|
||
expiry_date: Optional[date] = None
|
||
auto_renew: Optional[bool] = None
|
||
cost: Optional[float] = None
|
||
currency: Optional[str] = None
|
||
status: Optional[AssetStatus] = None
|
||
is_archived: Optional[bool] = None
|
||
remark: Optional[str] = None
|
||
vps_detail: Optional[VPSDetailIn] = None
|
||
domain_detail: Optional[DomainDetailIn] = None
|
||
ai_detail: Optional[AIAccountIn] = None
|
||
|
||
|
||
# --------------------------------------------------------------------------- #
|
||
# 输出模型
|
||
# --------------------------------------------------------------------------- #
|
||
class VPSDetailRead(SQLModel):
|
||
"""VPS 详情输出(不含敏感明文,仅返回凭证存在标记)"""
|
||
|
||
id: int
|
||
asset_id: int
|
||
ip_address: str
|
||
tailscale_ip: Optional[str] = None
|
||
region: Optional[str] = None
|
||
os: Optional[str] = None
|
||
cpu_cores: int = 1
|
||
memory_gb: float = 1
|
||
disk_gb: int = 20
|
||
bandwidth_gb: Optional[int] = None
|
||
ssh_port: int = 22
|
||
panel_url: Optional[str] = None
|
||
ssh_user: Optional[str] = None
|
||
login_method: Optional[str] = "key"
|
||
purpose: Optional[str] = None
|
||
has_ssh_key: bool = False
|
||
has_password: bool = False
|
||
|
||
|
||
class DomainDetailRead(DomainDetailIn):
|
||
id: int
|
||
asset_id: int
|
||
|
||
|
||
class AIAccountRead(SQLModel):
|
||
"""AI 账号输出(不暴露 API Key 明文,仅返回 has_api_key)"""
|
||
|
||
id: int
|
||
asset_id: int
|
||
provider: str
|
||
plan: Optional[str] = None
|
||
balance: Optional[float] = None
|
||
currency: str = "USD"
|
||
monthly_usage: Optional[float] = None
|
||
monthly_limit: Optional[float] = None
|
||
last_synced_at: Optional[datetime] = None
|
||
has_api_key: bool = False
|
||
|
||
|
||
class AssetRead(AssetBase):
|
||
"""资产完整输出"""
|
||
|
||
id: int
|
||
created_at: datetime
|
||
updated_at: datetime
|
||
days_to_expiry: Optional[int] = None
|
||
provider_name: Optional[str] = None
|
||
vps_detail: Optional[VPSDetailRead] = None
|
||
domain_detail: Optional[DomainDetailRead] = None
|
||
ai_detail: Optional[AIAccountRead] = None
|