b88c766dd6
Bug: nextcloudhost mit https://-Präfix in CSV/GUI führte zu Doppel-Schema (https://https://cloud.foo.de) und damit zu DNS-Fehler "host=https". - models.clean_host() entfernt http(s):// und Trailing-Slash; Account ruft das im __post_init__ für plesk-/kerio-/nextcloudhost auf. - NextcloudClient wickelt requests-Connection-Fehler in NextcloudError ein, damit die Log-Ausgabe lesbar bleibt statt HTTPSConnectionPool-Stacktrace. - README: Hostname-Eingabe als tolerant dokumentiert; pleskhost-Pflicht im manual-Modus klarer (POP3-Sammler braucht es trotzdem). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
76 lines
2.0 KiB
Python
76 lines
2.0 KiB
Python
from dataclasses import dataclass, field
|
|
from typing import List, Optional
|
|
|
|
|
|
def clean_host(s: str) -> str:
|
|
"""`https://cloud.foo.de/` → `cloud.foo.de`.
|
|
|
|
Akzeptiert die Eingaben unabhängig davon, ob der User Schema/Slash
|
|
mit eingetippt hat. Verhindert Doppel-Schemas wie
|
|
`https://https://cloud.foo.de` beim Bauen von URLs.
|
|
"""
|
|
s = (s or "").strip()
|
|
if "://" in s:
|
|
s = s.split("://", 1)[1]
|
|
return s.rstrip("/")
|
|
|
|
|
|
@dataclass
|
|
class Account:
|
|
name: str
|
|
vorname: str
|
|
emailadresse: str
|
|
pleskhost: str
|
|
keriohost: str
|
|
nextcloudhost: str
|
|
kerioemailkennwort: str
|
|
pleskemailkennwort: str
|
|
nextcloudgruppe: str = ""
|
|
nextcloudspeicher: Optional[int] = None # GB; None = unlimitiert
|
|
nextcloudkennwort: str = ""
|
|
|
|
def __post_init__(self):
|
|
self.pleskhost = clean_host(self.pleskhost)
|
|
self.keriohost = clean_host(self.keriohost)
|
|
self.nextcloudhost = clean_host(self.nextcloudhost)
|
|
self.emailadresse = (self.emailadresse or "").strip()
|
|
|
|
@property
|
|
def vollname(self) -> str:
|
|
return f"{self.vorname} {self.name}".strip()
|
|
|
|
@property
|
|
def nextcloud_username(self) -> str:
|
|
return derive_nc_username(self.vorname, self.name)
|
|
|
|
|
|
def derive_nc_username(vorname: str, name: str) -> str:
|
|
"""vorname.nachname, lowercase, Umlaute transliteriert, sichere Zeichen."""
|
|
s = f"{vorname.strip().lower()}.{name.strip().lower()}"
|
|
s = (s.replace("ä", "ae").replace("ö", "oe")
|
|
.replace("ü", "ue").replace("ß", "ss"))
|
|
out = []
|
|
for ch in s:
|
|
if ch.isalnum() or ch in "._-":
|
|
out.append(ch)
|
|
else:
|
|
out.append("-")
|
|
return "".join(out).strip("-.")
|
|
|
|
|
|
@dataclass
|
|
class StepResult:
|
|
service: str
|
|
status: str # "angelegt" | "übersprungen" | "Fehler"
|
|
detail: str = ""
|
|
|
|
|
|
@dataclass
|
|
class AccountResult:
|
|
account: Account
|
|
steps: List[StepResult] = field(default_factory=list)
|
|
|
|
@property
|
|
def has_errors(self) -> bool:
|
|
return any(s.status == "Fehler" for s in self.steps)
|