diff --git a/README.md b/README.md index 971c74e..c31e3c0 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ case-insensitive. Beispiel: [`example.csv`](./example.csv). | `Vorname` | ja | Vorname | | `Name` | ja | Nachname | | `emailadresse` | ja | volle Mailadresse, ist Login bei Plesk + Kerio | -| `pleskhost` | ja | Hostname Plesk-Mailserver (auch POP3-Server für Kerio-Sammler) | +| `pleskhost` | ja | Hostname Plesk-Mailserver – **auch im `manual`-Modus Pflicht**, weil Kerio davon per POP3 abholt | | `keriohost` | ja | Hostname Kerio Connect (Admin-API auf Port 4040, Webmail auf 443) | | `nextcloudhost` | ja | Nextcloud-Hostname | | `kerioemailkennwort` | ja | Passwort für den Kerio-User | @@ -110,6 +110,11 @@ case-insensitive. Beispiel: [`example.csv`](./example.csv). > (`vorname.nachname`, lowercase, ä→ae, ö→oe, ü→ue, ß→ss). Die Emailadresse > aus der CSV wird im Nextcloud-Profil als E-Mail eingetragen. +> **Hostnamen-Eingabe ist tolerant**: `cloud.foo.de`, `https://cloud.foo.de` +> und `https://cloud.foo.de/` werden alle akzeptiert – Schema (`http(s)://`) +> und Trailing-Slash werden automatisch gestrippt, sodass beim URL-Bau +> kein doppeltes `https://https://…` entsteht. + --- ## Aufruf diff --git a/clients/nextcloud.py b/clients/nextcloud.py index cc5d545..460636a 100644 --- a/clients/nextcloud.py +++ b/clients/nextcloud.py @@ -31,8 +31,17 @@ class NextcloudClient: raise NextcloudError(f"Nextcloud {op}: ungültige Antwort: {r.text[:300]}") return data.get("ocs", {}) + def _request(self, method: str, url: str, op: str, **kw): + try: + return self.session.request(method, url, timeout=30, **kw) + except requests.RequestException as e: + raise NextcloudError( + f"Nextcloud {op} – Verbindung zu {url} fehlgeschlagen: {e}" + ) from e + def user_exists(self, userid: str) -> bool: - r = self.session.get(f"{self.base}/ocs/v2.php/cloud/users/{userid}") + r = self._request("GET", f"{self.base}/ocs/v2.php/cloud/users/{userid}", + op="user-lookup") ocs = self._meta(r, "user-lookup") sc = ocs.get("meta", {}).get("statuscode") return sc in (100, 200) @@ -40,10 +49,8 @@ class NextcloudClient: def ensure_group(self, group: str) -> None: if not group: return - r = self.session.post( - f"{self.base}/ocs/v2.php/cloud/groups", - data={"groupid": group}, - ) + r = self._request("POST", f"{self.base}/ocs/v2.php/cloud/groups", + op="group-create", data={"groupid": group}) ocs = self._meta(r, "group-create") sc = ocs.get("meta", {}).get("statuscode") # 100/200 = ok, 102 = exists already @@ -66,10 +73,8 @@ class NextcloudClient: body.append(("groups[]", group)) body.append(("quota", f"{quota_gb} GB" if quota_gb else "none")) - r = self.session.post( - f"{self.base}/ocs/v2.php/cloud/users", - data=body, - ) + r = self._request("POST", f"{self.base}/ocs/v2.php/cloud/users", + op="user-create", data=body) ocs = self._meta(r, "user-create") sc = ocs.get("meta", {}).get("statuscode") if sc not in (100, 200): diff --git a/models.py b/models.py index d3586ad..258d86e 100644 --- a/models.py +++ b/models.py @@ -2,6 +2,19 @@ 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 @@ -16,6 +29,12 @@ class Account: 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()