Fallback unattributed joins under #1 instead of root
Members were activating with sponsorId 0 (their own root) whenever their sponsor couldn't be resolved — dead pre-wipe links (dkain) or no link at all — so their purchases rolled to admin instead of building the tree. Default an unresolvable sponsor to the configured catch position (siteConfig.defaultSponsorId, default 1) in both the buy path (/api/sponsor) and the free-activation path (/api/me), guarded so #1 itself is never self-sponsored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -428,7 +428,10 @@ const server = http.createServer(async (req, res) => {
|
|||||||
const s = await auth.fromRequest(req);
|
const s = await auth.fromRequest(req);
|
||||||
const acct = s && s.email ? await accounts.byEmail(s.email) : null;
|
const acct = s && s.email ? await accounts.byEmail(s.email) : null;
|
||||||
const tok = (acct && acct.sponsorRef) || parseCookies(req)['iap.sponsor'] || '';
|
const tok = (acct && acct.sponsorRef) || parseCookies(req)['iap.sponsor'] || '';
|
||||||
const sponsorId = await resolveSponsorToken(tok);
|
let sponsorId = await resolveSponsorToken(tok);
|
||||||
|
// orphan fallback: an unresolvable/absent sponsor (dead link, no link) lands
|
||||||
|
// the new member under the configured catch position (#1) instead of root
|
||||||
|
if (!sponsorId && (!acct || acct.memberId !== (Number(siteConfig().defaultSponsorId) || 1))) sponsorId = Number(siteConfig().defaultSponsorId) || 1;
|
||||||
let name = null, avatarUrl = null;
|
let name = null, avatarUrl = null;
|
||||||
if (tok) {
|
if (tok) {
|
||||||
const t = tok.toLowerCase();
|
const t = tok.toLowerCase();
|
||||||
@@ -552,7 +555,9 @@ const server = http.createServer(async (req, res) => {
|
|||||||
if (!s) return json(res, 200, { signedIn: false });
|
if (!s) return json(res, 200, { signedIn: false });
|
||||||
const memberId = await auth.refreshMemberId(s);
|
const memberId = await auth.refreshMemberId(s);
|
||||||
const acct = (s.email && await accounts.byEmail(s.email)) || (s.address && await accounts.byAddress(s.address)) || null;
|
const acct = (s.email && await accounts.byEmail(s.email)) || (s.address && await accounts.byAddress(s.address)) || null;
|
||||||
const sponsorId = await resolveSponsorToken((acct && acct.sponsorRef) || parseCookies(req)['iap.sponsor']);
|
let sponsorId = await resolveSponsorToken((acct && acct.sponsorRef) || parseCookies(req)['iap.sponsor']);
|
||||||
|
const _defSpon = Number(siteConfig().defaultSponsorId) || 1;
|
||||||
|
if (!sponsorId && memberId !== _defSpon) sponsorId = _defSpon; // orphan fallback → #1 (never self-sponsor)
|
||||||
if (memberId && acct && acct.memberId !== memberId) accounts.setMemberId(acct.email, memberId).catch(() => {});
|
if (memberId && acct && acct.memberId !== memberId) accounts.setMemberId(acct.email, memberId).catch(() => {});
|
||||||
const out = { signedIn: true, email: s.email || (acct && acct.email) || null,
|
const out = { signedIn: true, email: s.email || (acct && acct.email) || null,
|
||||||
address: s.address || (acct && acct.address) || null, memberId,
|
address: s.address || (acct && acct.address) || null, memberId,
|
||||||
|
|||||||
Reference in New Issue
Block a user