Move invite flow to client navigation

This commit is contained in:
2026-09-01 22:20:48 +12:00
parent 06d944c9d9
commit c6d449dc17
5 changed files with 214 additions and 513 deletions
+12 -2
View File
@@ -102,6 +102,12 @@ def _require_recipient_email(value: object) -> str:
)
def _optional_recipient_email(value: object) -> str | None:
if value is None or not str(value).strip():
return None
return _require_recipient_email(value)
def _auth_client_ip(request: Request) -> str:
direct_host = request.client.host if request.client else None
if request_trusts_forwarded_headers(direct_host):
@@ -1210,8 +1216,10 @@ async def create_profile_invite(payload: dict, current_user: dict = Depends(get_
label = str(label).strip() or None
if description is not None:
description = str(description).strip() or None
recipient_email = _require_recipient_email(recipient_email)
send_email = bool(payload.get("send_email"))
recipient_email = _optional_recipient_email(recipient_email)
if send_email and not recipient_email:
recipient_email = _require_recipient_email(recipient_email)
delivery_message = str(payload.get("message") or "").strip() or None
master_invite = _get_self_service_master_invite()
@@ -1300,8 +1308,10 @@ async def update_profile_invite(
label = str(label).strip() or None
if description is not None:
description = str(description).strip() or None
recipient_email = _require_recipient_email(recipient_email)
send_email = bool(payload.get("send_email"))
recipient_email = _optional_recipient_email(recipient_email)
if send_email and not recipient_email:
recipient_email = _require_recipient_email(recipient_email)
delivery_message = str(payload.get("message") or "").strip() or None
master_invite = _get_self_service_master_invite()
+22 -6
View File
@@ -1424,7 +1424,23 @@ class AuthFlowTests(TempDatabaseMixin, unittest.IsolatedAsyncioTestCase):
send_email.assert_awaited_once()
self.assertEqual(send_email.await_args.kwargs["recipient_email"], "local@example.com")
async def test_profile_invite_requires_recipient_email(self) -> None:
async def test_profile_manual_invite_does_not_require_recipient_email(self) -> None:
current_user = {
"username": "invite-owner",
"role": "user",
"invite_management_enabled": True,
"profile_id": None,
}
result = await auth_router.create_profile_invite(
{"label": "Family", "recipient_email": None, "send_email": False},
current_user,
)
self.assertEqual(result["status"], "ok")
self.assertIsNone(result["invite"]["recipient_email"])
self.assertIsNone(result["email"])
async def test_profile_email_delivery_requires_recipient_email(self) -> None:
current_user = {
"username": "invite-owner",
"role": "user",
@@ -1432,13 +1448,13 @@ class AuthFlowTests(TempDatabaseMixin, unittest.IsolatedAsyncioTestCase):
"profile_id": None,
}
with self.assertRaises(HTTPException) as context:
await auth_router.create_profile_invite({"label": "Missing email"}, current_user)
await auth_router.create_profile_invite(
{"label": "Missing email", "send_email": True},
current_user,
)
self.assertEqual(context.exception.status_code, 400)
self.assertEqual(
context.exception.detail,
"recipient_email is required and must be a valid email address.",
)
self.assertEqual(context.exception.detail, "recipient_email is required and must be a valid email address.")
class MediaReplacementTests(unittest.IsolatedAsyncioTestCase):