feat: Windows admin in Settings UI and WinRM host test (0.10.1)

Store domain admin in ui_settings (DB overrides env); qwinsta/logoff use effective config.
Host card: POST /hosts/{id}/actions/winrm-test via pywinrm.
This commit is contained in:
PTah
2026-06-20 00:01:17 +10:00
parent df4c93d243
commit 154ba3efc2
16 changed files with 602 additions and 14 deletions
+54
View File
@@ -37,6 +37,17 @@ from app.services.ui_settings import (
get_effective_ui_settings,
upsert_ui_settings,
)
from app.services.win_admin_settings import (
get_effective_win_admin_config,
upsert_win_admin_settings,
)
from app.services.winrm_connect import (
HostNotWindowsError,
HostTargetMissingError,
WinAdminNotConfiguredError,
resolve_windows_host_target,
test_winrm_connection,
)
router = APIRouter(prefix="/settings", tags=["settings"])
@@ -439,3 +450,46 @@ def update_ui_settings(
show_sidebar_system_stats=cfg.show_sidebar_system_stats,
source=cfg.source,
)
class WinAdminSettingsResponse(BaseModel):
configured: bool
user: str | None = None
password_hint: str | None = None
source: str = Field(description="env или db")
class WinAdminSettingsUpdate(BaseModel):
user: str | None = None
password: str | None = None
@router.get("/win-admin", response_model=WinAdminSettingsResponse)
def get_win_admin_settings(
db: Session = Depends(get_db),
_user=Depends(require_admin),
) -> WinAdminSettingsResponse:
cfg = get_effective_win_admin_config(db)
return WinAdminSettingsResponse(
configured=cfg.configured,
user=cfg.user or None,
password_hint=_mask_secret(cfg.password),
source=cfg.source,
)
@router.put("/win-admin", response_model=WinAdminSettingsResponse)
def update_win_admin_settings(
body: WinAdminSettingsUpdate,
db: Session = Depends(get_db),
_user=Depends(require_admin),
) -> WinAdminSettingsResponse:
if body.user is not None and not body.user.strip():
raise HTTPException(status_code=422, detail="user must not be empty")
cfg = upsert_win_admin_settings(db, user=body.user, password=body.password)
return WinAdminSettingsResponse(
configured=cfg.configured,
user=cfg.user or None,
password_hint=_mask_secret(cfg.password),
source=cfg.source,
)