Files
duffyduck b88c766dd6 fix: Hostnamen normalisieren (Schema/Slash strippen) + freundlichere Nextcloud-Fehler
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>
2026-05-12 13:05:51 +02:00

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)