fix(membership): guard against missing/invalid role_in_org in membership docs

list_org_members and _membership_from_doc used bracket access on role_in_org
which raises KeyError if the field is absent (old docs or direct DB inserts).
Also handles ValueError if the stored value doesn't match a valid OrgRole.
Falls back to OrgRole.MEMBER in both cases.

Fixes 500 on GET /organizations/{org_id}/members.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vadym Samoilenko 2026-05-01 14:35:09 +01:00
parent 997c1f622b
commit 8dee0b6ff5

View file

@ -13,11 +13,16 @@ def _now() -> datetime:
def _membership_from_doc(doc: dict) -> Membership:
raw_role = doc.get("role_in_org", "member")
try:
role = OrgRole(raw_role)
except ValueError:
role = OrgRole.MEMBER
return Membership(
id=str(doc["_id"]),
user_id=doc["user_id"],
organization_id=doc["organization_id"],
role_in_org=OrgRole(doc["role_in_org"]),
user_id=doc.get("user_id", ""),
organization_id=doc.get("organization_id", ""),
role_in_org=role,
created_at=doc.get("created_at"),
created_by=doc.get("created_by"),
)
@ -110,13 +115,18 @@ async def list_org_members(
details = []
async for doc in db.memberships.aggregate(pipeline):
u = doc["user_doc"]
raw_role = doc.get("role_in_org", "member")
try:
role = OrgRole(raw_role)
except ValueError:
role = OrgRole.MEMBER
details.append(
MemberDetail(
membership_id=str(doc["_id"]),
user_id=doc["user_id"],
user_id=doc.get("user_id", ""),
email=u.get("email", ""),
full_name=u.get("full_name", ""),
role_in_org=OrgRole(doc["role_in_org"]),
role_in_org=role,
created_at=doc.get("created_at"),
)
)