Verify integration points: OC webhook events (order.processed/new member), Cloudron user payload
This commit is contained in:
1 parent
451fb561bc
commit
7b84025e60
2 files changed
+28
-10
No files matched your search
@@ -77,8 +77,11 @@ endpoints:
|
||||
**Scaffold** — the three handlers are stubbed with the correct integration
|
||||
points. Remaining work before production:
|
||||
|
||||
- [ ] Verify Open Collective webhook event names + payload shape
|
||||
- [ ] Verify Cloudron user-creation API payload (role/group assignment)
|
||||
- [x] Verify Open Collective webhook event names + payload shape
|
||||
→ `order.processed` (every payment), `new member` (first only), `firstPayment` flag
|
||||
- [x] Verify Cloudron user-creation API payload (role/group assignment)
|
||||
→ `POST /api/v1/users` with `{username, email, displayName, role, active}`
|
||||
- [ ] Add a persistent store (SQLite/Postgres) for email→key mapping
|
||||
- [ ] Add HMAC signature verification for the OC webhook
|
||||
- [ ] Wire the OIDC addon for admin access
|
||||
- [ ] Verify LiteLLM key/generate + key/list payload shapes against live gateway
|
||||
+23
-8
@@ -48,24 +48,34 @@ def cloudron_headers() -> dict:
|
||||
|
||||
|
||||
async def cloudron_create_user(email: str, name: str) -> str:
|
||||
"""Create (or return existing) Cloudron user, assigned to the chat app."""
|
||||
"""Create (or return existing) Cloudron user, assigned to the chat app.
|
||||
|
||||
Verified user shape (from live API):
|
||||
{id, username, email, fallbackEmail, displayName, role, active, groupIds}
|
||||
Roles: "owner", "admin", "user".
|
||||
"""
|
||||
async with httpx.AsyncClient() as client:
|
||||
# Check if user exists
|
||||
r = await client.get(
|
||||
f"{CLOUDRON_API}/api/v1/users",
|
||||
headers=cloudron_headers(),
|
||||
params={"email": email},
|
||||
)
|
||||
r.raise_for_status()
|
||||
users = r.json().get("users", [])
|
||||
if users:
|
||||
return users[0]["id"]
|
||||
for u in r.json().get("users", []):
|
||||
if u.get("email") == email:
|
||||
return u["id"]
|
||||
|
||||
# Create user
|
||||
# Create user (role "user" = regular member)
|
||||
r = await client.post(
|
||||
f"{CLOUDRON_API}/api/v1/users",
|
||||
headers=cloudron_headers(),
|
||||
json={"email": email, "displayName": name, "role": "user"},
|
||||
json={
|
||||
"username": email.split("@")[0],
|
||||
"email": email,
|
||||
"displayName": name,
|
||||
"role": "user",
|
||||
"active": True,
|
||||
},
|
||||
)
|
||||
r.raise_for_status()
|
||||
return r.json()["id"]
|
||||
@@ -143,7 +153,12 @@ async def opencollective_webhook(request: Request):
|
||||
|
||||
logger.info("Open Collective event: %s for %s", event_type, email)
|
||||
|
||||
if event_type in ("collective.member.created", "collective.transaction.created"):
|
||||
# Open Collective webhook events (verified):
|
||||
# - "order.processed" → fires on EVERY payment (incl. monthly recurring)
|
||||
# - "new member" → fires on FIRST contribution only
|
||||
# - payload has "firstPayment" boolean to distinguish new vs recurring
|
||||
# - "collective.transaction.created" is DEPRECATED (being removed)
|
||||
if event_type in ("order.processed", "new.member", "collective.member.created"):
|
||||
# New or renewed member → ensure active
|
||||
tier = (data.get("tier") or {}).get("slug", DEFAULT_TIER)
|
||||
budget = TIER_BUDGETS.get(tier, TIER_BUDGETS[DEFAULT_TIER])
|
||||
|
||||
Reference in new issue
Block a user