Add remote browser pages and website sync

Enable managed remote browser custom pages with login autofill and add website sync workflows so external admin surfaces can be handled inside SmartUp.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
liumangmang
2026-05-15 15:43:58 +08:00
parent a13a0070a5
commit 7adc7c00ab
43 changed files with 6615 additions and 641 deletions
+2 -2
View File
@@ -2,7 +2,7 @@ from datetime import datetime
from typing import Optional, List
from pydantic import BaseModel
ALLOWED_EVENTS = ["upstream_rate_changed", "upstream_unhealthy", "upstream_recovered"]
ALLOWED_EVENTS = ["upstream_rate_changed", "website_rate_changed", "upstream_unhealthy", "upstream_recovered"]
class WebhookCreate(BaseModel):
@@ -11,7 +11,7 @@ class WebhookCreate(BaseModel):
url: str
secret: str = ""
enabled: bool = True
events: List[str] = ["upstream_rate_changed"]
events: List[str] = ["upstream_rate_changed", "website_rate_changed"]
class WebhookUpdate(BaseModel):
+124
View File
@@ -0,0 +1,124 @@
from datetime import datetime
from typing import Any, Optional
from pydantic import BaseModel, Field
class TestResult(BaseModel):
success: bool
message: str
detail: Optional[str] = None
class WebsiteCreate(BaseModel):
name: str
site_type: str = "sub2api"
base_url: str
api_prefix: str = "/api/v1/admin"
auth_type: str = "api_key"
auth_config: dict[str, Any] = {}
groups_endpoint: str = "/groups"
group_update_endpoint: str = "/groups/{id}"
enabled: bool = True
auto_sync_enabled: bool = True
timeout_seconds: int = 30
class WebsiteUpdate(BaseModel):
name: Optional[str] = None
site_type: Optional[str] = None
base_url: Optional[str] = None
api_prefix: Optional[str] = None
auth_type: Optional[str] = None
auth_config: Optional[dict[str, Any]] = None
groups_endpoint: Optional[str] = None
group_update_endpoint: Optional[str] = None
enabled: Optional[bool] = None
auto_sync_enabled: Optional[bool] = None
timeout_seconds: Optional[int] = None
class WebsiteResponse(BaseModel):
id: int
name: str
site_type: str
base_url: str
api_prefix: str
auth_type: str
auth_config_masked: dict[str, Any]
groups_endpoint: str
group_update_endpoint: str
enabled: bool
auto_sync_enabled: bool
timeout_seconds: int
last_status: str
last_checked_at: Optional[datetime]
last_error: Optional[str]
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
class WebsiteGroupResponse(BaseModel):
id: str
name: str
rate_multiplier: Optional[str] = None
raw: dict[str, Any] = {}
class BindingSourceGroup(BaseModel):
upstream_id: int
group_id: str
upstream_name: str = ""
group_name: str = ""
class BindingCreate(BaseModel):
website_id: int
target_group_id: str
target_group_name: str = ""
source_groups: list[BindingSourceGroup] = Field(default_factory=list)
percent: float = Field(default=0, ge=0)
algorithm: str = "max_plus_percent"
enabled: bool = True
class BindingUpdate(BaseModel):
website_id: Optional[int] = None
target_group_id: Optional[str] = None
target_group_name: Optional[str] = None
source_groups: Optional[list[BindingSourceGroup]] = None
percent: Optional[float] = Field(default=None, ge=0)
algorithm: Optional[str] = None
enabled: Optional[bool] = None
class BindingResponse(BaseModel):
id: int
website_id: int
website_name: str
target_group_id: str
target_group_name: str
source_groups: list[BindingSourceGroup]
percent: float
algorithm: str
enabled: bool
created_at: datetime
updated_at: datetime
class WebsiteSyncLogResponse(BaseModel):
id: int
website_id: int
binding_id: Optional[int]
target_group_id: str
target_group_name: str
algorithm: str
percent: float
source_rates: list[dict[str, Any]]
old_rate: Optional[str]
new_rate: Optional[str]
status: str
message: str
created_at: datetime