Files
member-portal/sweep.sh
T
inference-bot a0d15e30d8 sweep: drop the legacy WEBHOOK_TOKEN fallback (cutover is complete)
ADMIN_TOKEN_LEGACY is "0" and verified: ADMIN_TOKEN returns 200 on /admin/*,
WEBHOOK_TOKEN returns 403. The fallback in sweep.sh would therefore turn
"ADMIN_TOKEN unset" into a confusing mid-run 403 rather than the clear abort
that already exists three lines below it. Same removal in the digest script.

Not a behaviour change in normal operation — ADMIN_TOKEN is set (len 64) and
already preferred — but it removes a foot-gun that could mask a broken
configuration, and leaves the code honest about which credential is live.
2026-10-28 13:53:25 +00:00

43 lines
1.5 KiB
Bash

#!/bin/sh
# Membership reconciliation sweep — run by the Cloudron scheduler addon.
#
# Calls the portal's own /admin/sweep endpoint (localhost), which reconciles
# the portal against the live Open Collective member list: provisions missing
# members, deactivates lapsed members, and syncs Loomio.
#
# The ADMIN_TOKEN env var is shared with the main app (scheduler runs in the
# same launch environment), so we use it to authenticate the call. Admin auth is
# a header, never a URL token (security fix 2026-10-27). The WEBHOOK_TOKEN
# fallback was removed when the cutover completed (ADMIN_TOKEN_LEGACY=0): the
# legacy token now gets 403 on /admin/*, so falling back to it would turn
# "ADMIN_TOKEN unset" into a confusing mid-run 403 instead of a clear abort.
#
# Uses Python (guaranteed present in the base image) rather than curl.
set -e
if [ -z "$ADMIN_TOKEN" ]; then
echo "sweep: ADMIN_TOKEN is not set; aborting" >&2
exit 1
fi
python3 - "$ADMIN_TOKEN" <<'PY'
import sys, urllib.request, urllib.error
token = sys.argv[1]
url = "http://127.0.0.1:8000/admin/sweep"
req = urllib.request.Request(url, method="POST", data=b"", headers={
"Content-Type": "application/json",
"X-Admin-Token": token,
})
try:
with urllib.request.urlopen(req, timeout=60) as resp:
print("sweep:", resp.read().decode())
except urllib.error.HTTPError as e:
print(f"sweep: HTTP {e.code}: {e.read().decode()}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"sweep: request failed: {e}", file=sys.stderr)
sys.exit(1)
PY