Admin: member search + drilldown card (identity, chain, credits, line, purchases, payouts, campaigns) with username/sponsor/wallet/credits/delete actions; sortable + filterable admin tables; Earn tab zero-credit button wording
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
+32
@@ -201,6 +201,23 @@ const J = {
|
||||
if (p.memberId) return { error: 'That position is already registered on-chain and cannot be unlinked.' };
|
||||
delete this.db.positions[a]; this.save(); return { ok: true };
|
||||
},
|
||||
// admin only: point the account at a different main wallet (or none); the caller re-reads the member id
|
||||
async adminSetAddress(e, a) {
|
||||
const acct = this.db.byEmail[e]; if (!acct) return { error: 'No such account.' };
|
||||
if (a) {
|
||||
if (this.db.byAddress[a] && this.db.byAddress[a] !== e) return { error: 'That wallet is the main wallet of another account.' };
|
||||
if (this.db.positions[a]) return { error: 'That wallet is a linked position on ' + (this.db.positions[a].email === e ? 'this' : 'another') + ' account.' };
|
||||
}
|
||||
if (acct.address) delete this.db.byAddress[acct.address];
|
||||
acct.address = a || null; if (a) this.db.byAddress[a] = e; this.save(); return { ok: true, account: pub(acct) };
|
||||
},
|
||||
async positionByAddress(a) { const p = this.db.positions[a]; return p ? { address: a, email: p.email, memberId: p.memberId } : null; },
|
||||
async removeAccount(e) {
|
||||
const acct = this.db.byEmail[e]; if (!acct) return { error: 'No such account.' };
|
||||
if (acct.address) delete this.db.byAddress[acct.address]; if (acct.code) delete this.db.byCode[acct.code];
|
||||
for (const [a, p] of Object.entries(this.db.positions)) if (p.email === e) delete this.db.positions[a];
|
||||
delete this.db.byEmail[e]; this.save(); return { ok: true };
|
||||
},
|
||||
};
|
||||
|
||||
// ---- MySQL mode ----
|
||||
@@ -350,6 +367,18 @@ const D = {
|
||||
if (r.member_id) return { error: 'That position is already registered on-chain and cannot be unlinked.' };
|
||||
await db.q('DELETE FROM positions WHERE address=?', [a]); return { ok: true };
|
||||
},
|
||||
async adminSetAddress(e, a) {
|
||||
if (a) {
|
||||
const o = (await db.q('SELECT email FROM accounts WHERE address=?', [a]))[0]; if (o && o.email !== e) return { error: 'That wallet is the main wallet of another account.' };
|
||||
const pos = (await db.q('SELECT email FROM positions WHERE address=?', [a]))[0]; if (pos) return { error: 'That wallet is a linked position on ' + (pos.email === e ? 'this' : 'another') + ' account.' };
|
||||
}
|
||||
await db.q('UPDATE accounts SET address=? WHERE email=?', [a || null, e]); return { ok: true, account: await this.byEmail(e) };
|
||||
},
|
||||
async positionByAddress(a) { const r = (await db.q('SELECT * FROM positions WHERE address=?', [a]))[0]; return r ? { address: r.address, email: r.email, memberId: r.member_id || 0 } : null; },
|
||||
async removeAccount(e) {
|
||||
await db.q('DELETE FROM positions WHERE email=?', [e]);
|
||||
const r = await db.q('DELETE FROM accounts WHERE email=?', [e]); return r.affectedRows ? { ok: true } : { error: 'No such account.' };
|
||||
},
|
||||
};
|
||||
|
||||
const impl = () => db.enabled() ? D : J;
|
||||
@@ -446,6 +475,9 @@ module.exports = { init, signup, login, ensure, byEmail, byAddress, byCode, byUs
|
||||
setWallOffers: (e, j) => impl().setWallOffers(String(e || '').toLowerCase(), j),
|
||||
setProfile: (e, a, bio, socials) => impl().setProfile(String(e || '').toLowerCase(), a, bio, socials),
|
||||
touchSeen: e => impl().touchSeen(String(e || '').toLowerCase()),
|
||||
adminSetAddress: (e, a) => impl().adminSetAddress(String(e || '').toLowerCase(), a ? normAddr(a) : null),
|
||||
positionByAddress: a => impl().positionByAddress(normAddr(a)),
|
||||
removeAccount: e => impl().removeAccount(String(e || '').toLowerCase()),
|
||||
setChatAvailable: (e, v) => impl().setChatAvailable(String(e || '').toLowerCase(), v),
|
||||
getMutes: e => impl().getMutes(String(e || '').toLowerCase()),
|
||||
setMute: (o, t, m) => impl().setMute(String(o || '').toLowerCase(), String(t || '').toLowerCase(), m),
|
||||
|
||||
Reference in New Issue
Block a user