chore(home): mirror from kalinamall (9883e6a) with papatramp URLs
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
"""Effective Windows domain admin credentials (host → DB → env)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.config import get_settings
|
||||
from app.models.host import Host
|
||||
from app.models.ui_settings import UI_SETTINGS_ROW_ID, UiSettings
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class WinAdminConfig:
|
||||
user: str
|
||||
password: str
|
||||
source: str # host | env | db
|
||||
|
||||
@property
|
||||
def configured(self) -> bool:
|
||||
return bool(self.user.strip() and self.password.strip())
|
||||
|
||||
|
||||
def normalize_win_admin_user(user: str) -> str:
|
||||
"""DOMAIN\\user — один обратный слэш; убрать лишнее экранирование из env/UI."""
|
||||
text = user.strip()
|
||||
if not text:
|
||||
return ""
|
||||
text = text.replace("\\\\", "\\")
|
||||
if "\\" not in text and "@" not in text and "/" not in text:
|
||||
# NETBIOS\user без слэша — не трогаем (оператор допишет в UI)
|
||||
return text
|
||||
return text
|
||||
|
||||
|
||||
def _win_admin_from_env() -> WinAdminConfig:
|
||||
settings = get_settings()
|
||||
return WinAdminConfig(
|
||||
user=normalize_win_admin_user(settings.sac_win_admin_user),
|
||||
password=settings.sac_win_admin_password,
|
||||
source="env",
|
||||
)
|
||||
|
||||
|
||||
def get_effective_win_admin_config(db: Session | None = None) -> WinAdminConfig:
|
||||
if db is None:
|
||||
from app.database import SessionLocal
|
||||
|
||||
session = SessionLocal()
|
||||
try:
|
||||
return get_effective_win_admin_config(session)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
row = db.get(UiSettings, UI_SETTINGS_ROW_ID)
|
||||
env_cfg = _win_admin_from_env()
|
||||
if row is None:
|
||||
return env_cfg
|
||||
|
||||
user = normalize_win_admin_user((row.win_admin_user or "").strip() or env_cfg.user)
|
||||
password = (row.win_admin_password or "") or env_cfg.password
|
||||
has_db_values = bool((row.win_admin_user or "").strip() or (row.win_admin_password or "").strip())
|
||||
return WinAdminConfig(
|
||||
user=user,
|
||||
password=password,
|
||||
source="db" if has_db_values else env_cfg.source,
|
||||
)
|
||||
|
||||
|
||||
def upsert_win_admin_settings(
|
||||
db: Session,
|
||||
*,
|
||||
user: str | None = None,
|
||||
password: str | None = None,
|
||||
) -> WinAdminConfig:
|
||||
row = db.get(UiSettings, UI_SETTINGS_ROW_ID)
|
||||
env_cfg = _win_admin_from_env()
|
||||
if row is None:
|
||||
row = UiSettings(
|
||||
id=UI_SETTINGS_ROW_ID,
|
||||
show_sidebar_system_stats=True,
|
||||
win_admin_user=env_cfg.user or None,
|
||||
win_admin_password=env_cfg.password or None,
|
||||
)
|
||||
db.add(row)
|
||||
|
||||
if user is not None and user.strip():
|
||||
row.win_admin_user = normalize_win_admin_user(user)
|
||||
if password is not None and password.strip():
|
||||
row.win_admin_password = password
|
||||
|
||||
db.commit()
|
||||
db.refresh(row)
|
||||
return get_effective_win_admin_config(db)
|
||||
|
||||
|
||||
def get_effective_win_admin_for_host(db: Session, host: Host) -> WinAdminConfig:
|
||||
"""Prefer per-host mgmt_* when both user and password are set; else global Settings/env."""
|
||||
host_user = normalize_win_admin_user((host.mgmt_user or "").strip())
|
||||
host_password = (host.mgmt_password or "").strip()
|
||||
if host_user and host_password:
|
||||
return WinAdminConfig(user=host_user, password=host_password, source="host")
|
||||
|
||||
global_cfg = get_effective_win_admin_config(db)
|
||||
# Allow host to override only the username, still using global password (rare).
|
||||
if host_user and global_cfg.password.strip():
|
||||
return WinAdminConfig(user=host_user, password=global_cfg.password, source="host")
|
||||
return global_cfg
|
||||
Reference in New Issue
Block a user