@xuda.io/account_module 1.2.2297 → 1.2.2298

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.mjs +32 -2
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -1925,8 +1925,18 @@ export const ops_reinstate_account = async function (req = {}) {
1925
1925
  export const ops_list_terminations = async function (req = {}) {
1926
1926
  try {
1927
1927
  if (!_ops_is_super(req)) return { code: -403, data: 'superuser only' };
1928
- const ret = await db_module.find_couch_query('xuda_accounts', { selector: { docType: 'account', $or: [{ account_suspension_status: 1 }, { account_termination_status: 1 }] }, limit: 9999 }, true);
1929
- const rows = (ret.docs || []).map((a) => ({
1928
+ // Suspended OR terminated. CouchDB Mango uses one index per query, so it
1929
+ // cannot serve an $or across two different fields and would full-scan every
1930
+ // account (logs "documents examined is high"). Query each branch separately
1931
+ // (each hits its own [docType, account_*_status] index) and merge, deduping
1932
+ // accounts flagged as both.
1933
+ const [susp_ret, term_ret] = await Promise.all([
1934
+ db_module.find_couch_query('xuda_accounts', { selector: { docType: 'account', account_suspension_status: 1 }, limit: 9999 }, true),
1935
+ db_module.find_couch_query('xuda_accounts', { selector: { docType: 'account', account_termination_status: 1 }, limit: 9999 }, true),
1936
+ ]);
1937
+ const by_id = new Map();
1938
+ for (const a of [...(susp_ret?.docs || []), ...(term_ret?.docs || [])]) by_id.set(a._id, a);
1939
+ const rows = [...by_id.values()].map((a) => ({
1930
1940
  account_uid: a._id,
1931
1941
  email: a.account_info?.email,
1932
1942
  name: `${a.account_info?.first_name || ''} ${a.account_info?.last_name || ''}`.trim(),
@@ -7574,6 +7584,26 @@ const _nl_one = async (db, docType) => {
7574
7584
  }
7575
7585
  })();
7576
7586
 
7587
+ // The abuse-review queue (the flagged-accounts list, see ~line 1014) selects on
7588
+ // `abuse_signals.flagged` with no index, so Couch full-scans xuda_accounts and
7589
+ // logs "No matching index found". xuda_accounts lives locally on dev + master;
7590
+ // ensure the index at module load, idempotent, on those content-home nodes only.
7591
+ (async () => {
7592
+ const host = process.env.XUDA_HOSTNAME;
7593
+ if (host !== 'dev.xuda.ai' && host !== 'master.xuda.ai') return;
7594
+ try {
7595
+ const ret = await db_module.create_couch_index('xuda_accounts', {
7596
+ index: { fields: ['abuse_signals.flagged'] },
7597
+ name: 'idx_abuse_signals_flagged',
7598
+ ddoc: 'idx_abuse_signals_flagged',
7599
+ type: 'json',
7600
+ });
7601
+ if (ret?.error) console.error('[abuse] xuda_accounts abuse_signals.flagged index create failed:', ret.error);
7602
+ } catch (err) {
7603
+ console.error('[abuse] xuda_accounts abuse_signals.flagged index init failed:', err?.message || err);
7604
+ }
7605
+ })();
7606
+
7577
7607
  const _nl_fashion_url = (p) => {
7578
7608
  const rel = p.custom_url || (p.slug ? '/' + p.slug : '');
7579
7609
  return `https://xuda.fashion${rel}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/account_module",
3
- "version": "1.2.2297",
3
+ "version": "1.2.2298",
4
4
  "description": "Xuda Account Server Module",
5
5
  "main": "index.mjs",
6
6
  "dependencies": {