feat: Mandant/Reseller ohne E-Mail anlegbar (Temp-Passwort statt Einladung)
Security Audit / Python Dependency Audit (push) Has been cancelled
Security Audit / Node.js Dependency Audit (push) Has been cancelled

- admin_email bzw. reseller email optional; ohne E-Mail wird interne Login-
  Kennung (<name>@<slug>.local) + einmaliges Temp-Passwort erzeugt, Account
  sofort aktiv, kein Mailversand
- TenantOut/ResellerOut: initial_password (einmalig) ergänzt
- LoginRequest.email: str statt EmailStr (Kennung muss kein zustellbares
  Postfach sein; .local-Domains sind sonst nicht einloggbar)
- Frontend: E-Mail-Felder optional, CredDialog zeigt Login + Temp-Passwort einmalig
- Test: Anlage ohne E-Mail + Login mit generierten Zugangsdaten; 173/173 grün

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 01:34:23 +02:00
co-authored by Claude Opus 4.8
parent 898a81f499
commit 98cb2f867a
9 changed files with 215 additions and 56 deletions
+20
View File
@@ -79,6 +79,26 @@ async def test_reseller_creates_and_sees_only_own_company(client: AsyncClient, d
assert rid_a != rid_b
@pytest.mark.asyncio(loop_scope="session")
async def test_create_company_without_email_returns_temp_password(client: AsyncClient, db_session):
await _make_user(db_session, email="res-noemail@p.de", role="RESELLER")
h = await _login(client, "res-noemail@p.de")
r = await client.post("/api/v1/reseller/companies", json={
"name": "Delta GmbH", "admin_first_name": "De", "admin_last_name": "Lta",
}, headers=h)
assert r.status_code == 201, r.text
body = r.json()
assert body["initial_password"], "Temp-Passwort muss zurückgegeben werden"
assert body["admin_email"], "Login-Kennung muss erzeugt werden"
# Mit den generierten Zugangsdaten kann sich der Admin sofort einloggen
ok = await client.post("/api/v1/auth/login", json={
"email": body["admin_email"], "password": body["initial_password"],
})
assert ok.status_code == 200, ok.text
@pytest.mark.asyncio(loop_scope="session")
async def test_reseller_cannot_access_admin_endpoints(client: AsyncClient, db_session):
await _make_user(db_session, email="res-c@p.de", role="RESELLER")