bulltrackers-module 1.0.557 → 1.0.559

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.
@@ -115,6 +115,7 @@ async function processAlertForPI(db, logger, piCid, alertType, computationMetada
115
115
  /**
116
116
  * Find all users who should receive alerts for a PI and alert type
117
117
  * Uses WatchlistMembershipData/{date} to find users, then reads watchlists from SignedInUsers/{cid}/watchlists
118
+ * Also checks for developer accounts with pretendSubscribedToAllAlerts flag enabled
118
119
  */
119
120
  async function findSubscriptionsForPI(db, logger, piCid, alertTypeId, computationDate, dependencies = {}) {
120
121
  const subscriptions = [];
@@ -135,6 +136,62 @@ async function findSubscriptionsForPI(db, logger, piCid, alertTypeId, computatio
135
136
  return subscriptions;
136
137
  }
137
138
 
139
+ // Check for developer accounts with pretendSubscribedToAllAlerts flag enabled
140
+ // This allows developers to test the alert system without manually configuring subscriptions
141
+ try {
142
+ const { getDevOverride, isDeveloperAccount } = require('../../generic-api/user-api/helpers/dev/dev_helpers');
143
+ const { getPIMasterList } = require('../../generic-api/user-api/helpers/core/user_status_helpers');
144
+ const config = dependencies.config || {};
145
+ const collectionRegistry = dependencies.collectionRegistry || null;
146
+
147
+ // Get all popular investors from master list for username lookup
148
+ const allInvestors = await getPIMasterList(db, collectionRegistry, logger);
149
+ const piUsername = allInvestors[String(piCid)]?.username || `PI-${piCid}`;
150
+
151
+ // Default alert config with all alert types enabled (for dev override)
152
+ const allAlertsEnabledConfig = {
153
+ increasedRisk: true,
154
+ volatilityChanges: true,
155
+ newSector: true,
156
+ increasedPositionSize: true,
157
+ newSocialPost: true,
158
+ newPositions: true
159
+ };
160
+
161
+ // Check all developer accounts
162
+ const devOverridesCollection = config.devOverridesCollection || 'dev_overrides';
163
+ const devOverridesSnapshot = await db.collection(devOverridesCollection).get();
164
+
165
+ for (const devOverrideDoc of devOverridesSnapshot.docs) {
166
+ const devUserCid = Number(devOverrideDoc.id);
167
+
168
+ // Verify this is actually a developer account (security check)
169
+ if (!isDeveloperAccount(devUserCid)) {
170
+ continue;
171
+ }
172
+
173
+ const devOverrideData = devOverrideDoc.data();
174
+
175
+ // Check if this developer has the pretendSubscribedToAllAlerts flag enabled
176
+ if (devOverrideData.enabled === true && devOverrideData.pretendSubscribedToAllAlerts === true) {
177
+ // Add this developer as a subscription for this PI and alert type
178
+ subscriptions.push({
179
+ userCid: devUserCid,
180
+ piCid: piCid,
181
+ piUsername: piUsername,
182
+ watchlistId: 'dev-override-all-alerts',
183
+ watchlistName: 'Dev Override - All Alerts',
184
+ alertConfig: allAlertsEnabledConfig
185
+ });
186
+
187
+ logger.log('INFO', `[findSubscriptionsForPI] DEV OVERRIDE: Added developer ${devUserCid} to subscriptions for PI ${piCid}, alert type ${alertTypeId}`);
188
+ }
189
+ }
190
+ } catch (error) {
191
+ // Don't fail the entire function if dev override check fails
192
+ logger.log('WARN', `[findSubscriptionsForPI] Error checking dev overrides: ${error.message}`);
193
+ }
194
+
138
195
  // Step 1: Load WatchlistMembershipData/{date} to find which users have this PI in their watchlist
139
196
  const piCidStr = String(piCid);
140
197
  let userCids = [];
@@ -41,6 +41,7 @@ async function getDevOverride(db, userCid, config, logger = null) {
41
41
  fakeCopiedPIs: [],
42
42
  pretendToBePI: false,
43
43
  impersonateCid: null, // CID to impersonate/view as
44
+ pretendSubscribedToAllAlerts: false, // Pretend to be subscribed to all alert types for all PIs
44
45
  createdAt: FieldValue.serverTimestamp(),
45
46
  lastUpdated: FieldValue.serverTimestamp()
46
47
  };
@@ -60,6 +61,7 @@ async function getDevOverride(db, userCid, config, logger = null) {
60
61
  fakeCopiedPIs: [],
61
62
  pretendToBePI: false,
62
63
  impersonateCid: null,
64
+ pretendSubscribedToAllAlerts: false,
63
65
  lastUpdated: null,
64
66
  wasAutoCreated: true
65
67
  };
@@ -73,6 +75,7 @@ async function getDevOverride(db, userCid, config, logger = null) {
73
75
  fakeCopiedPIs: data.fakeCopiedPIs || [],
74
76
  pretendToBePI: data.pretendToBePI === true,
75
77
  impersonateCid: data.impersonateCid ? Number(data.impersonateCid) : null,
78
+ pretendSubscribedToAllAlerts: data.pretendSubscribedToAllAlerts === true,
76
79
  lastUpdated: data.lastUpdated,
77
80
  wasAutoCreated: false
78
81
  };
@@ -157,7 +160,7 @@ async function hasUserCopiedWithDevOverride(db, userCid, piCid, config, logger)
157
160
  */
158
161
  async function setDevOverride(req, res, dependencies, config) {
159
162
  const { db, logger } = dependencies;
160
- const { userCid, enabled, fakeCopiedPIs, pretendToBePI, impersonateCid } = req.body;
163
+ const { userCid, enabled, fakeCopiedPIs, pretendToBePI, impersonateCid, pretendSubscribedToAllAlerts } = req.body;
161
164
 
162
165
  if (!userCid) {
163
166
  return res.status(400).json({ error: "Missing userCid" });
@@ -208,6 +211,7 @@ async function setDevOverride(req, res, dependencies, config) {
208
211
  fakeCopiedPIs: enabled !== undefined ? validatedPIs : (existingData.fakeCopiedPIs || []),
209
212
  pretendToBePI: pretendToBePI !== undefined ? (pretendToBePI === true) : (existingData.pretendToBePI || false),
210
213
  impersonateCid: impersonateCid !== undefined ? (impersonateCid ? Number(impersonateCid) : null) : (existingData.impersonateCid || null),
214
+ pretendSubscribedToAllAlerts: pretendSubscribedToAllAlerts !== undefined ? (pretendSubscribedToAllAlerts === true) : (existingData.pretendSubscribedToAllAlerts || false),
211
215
  lastUpdated: FieldValue.serverTimestamp()
212
216
  };
213
217
 
@@ -217,6 +221,7 @@ async function setDevOverride(req, res, dependencies, config) {
217
221
  `enabled=${overrideData.enabled}`,
218
222
  `pretendToBePI=${overrideData.pretendToBePI}`,
219
223
  `impersonateCid=${overrideData.impersonateCid || 'null'}`,
224
+ `pretendSubscribedToAllAlerts=${overrideData.pretendSubscribedToAllAlerts}`,
220
225
  `${validatedPIs.length} fake PIs`
221
226
  ];
222
227
  logger.log('SUCCESS', `[setDevOverride] Updated dev override for user ${userCid}: ${logParts.join(', ')}`);
@@ -270,6 +275,7 @@ async function getDevOverrideStatus(req, res, dependencies, config) {
270
275
  fakeCopiedPIs: devOverride.fakeCopiedPIs,
271
276
  pretendToBePI: devOverride.pretendToBePI || false,
272
277
  impersonateCid: devOverride.impersonateCid || null,
278
+ pretendSubscribedToAllAlerts: devOverride.pretendSubscribedToAllAlerts || false,
273
279
  lastUpdated: devOverride.lastUpdated,
274
280
  wasAutoCreated: devOverride.wasAutoCreated || false
275
281
  });
@@ -284,6 +290,9 @@ async function getDevOverrideStatus(req, res, dependencies, config) {
284
290
  * Get the effective CID to use for a developer account
285
291
  * Returns impersonateCid if set, otherwise returns the actual userCid
286
292
  * Only works for developer accounts
293
+ *
294
+ * Note: If pretendToBePI is false, impersonation will not be used for PI-related checks
295
+ * to prevent unintended impersonation when the user doesn't want to pretend to be a PI
287
296
  */
288
297
  async function getEffectiveCid(db, userCid, config, logger = null) {
289
298
  if (!isDeveloperAccount(userCid)) {
@@ -291,8 +300,20 @@ async function getEffectiveCid(db, userCid, config, logger = null) {
291
300
  }
292
301
 
293
302
  const devOverride = await getDevOverride(db, userCid, config, logger);
294
- // Only use impersonation if dev override is enabled
303
+ // Only use impersonation if dev override is enabled AND impersonateCid is set
304
+ // BUT: If pretendToBePI is explicitly false, don't use impersonation (user doesn't want to be treated as PI)
295
305
  if (devOverride && devOverride.enabled && devOverride.impersonateCid) {
306
+ // Check if user explicitly doesn't want to pretend to be a PI
307
+ // If pretendToBePI is false, don't use impersonation (respects user intent)
308
+ if (devOverride.pretendToBePI === false) {
309
+ if (logger && logger.log) {
310
+ logger.log('INFO', `[getEffectiveCid] DEV OVERRIDE: User ${userCid} has impersonateCid set but pretendToBePI=false, using actual CID ${userCid} instead`);
311
+ } else {
312
+ console.log(`[getEffectiveCid] DEV OVERRIDE: User ${userCid} has impersonateCid set but pretendToBePI=false, using actual CID ${userCid} instead`);
313
+ }
314
+ return Number(userCid);
315
+ }
316
+
296
317
  if (logger && logger.log) {
297
318
  logger.log('INFO', `[getEffectiveCid] DEV OVERRIDE: User ${userCid} impersonating CID ${devOverride.impersonateCid}`);
298
319
  } else {
@@ -96,8 +96,19 @@ async function getSignedInUserPIPersonalizedMetrics(req, res, dependencies, conf
96
96
  }
97
97
 
98
98
  try {
99
- const effectiveCid = await getEffectiveCid(db, userCid, config, logger);
100
99
  const devOverride = await getDevOverride(db, userCid, config, logger);
100
+
101
+ // For PI-related checks, respect pretendToBePI flag
102
+ // If pretendToBePI is false, use actual userCid even if impersonateCid is set
103
+ let effectiveCid;
104
+ if (devOverride && devOverride.enabled && devOverride.pretendToBePI === false) {
105
+ // User explicitly doesn't want to pretend to be a PI, use actual CID
106
+ effectiveCid = Number(userCid);
107
+ } else {
108
+ // Use normal effective CID logic (may use impersonateCid if set)
109
+ effectiveCid = await getEffectiveCid(db, userCid, config, logger);
110
+ }
111
+
101
112
  const isImpersonating = devOverride && devOverride.enabled && devOverride.impersonateCid && effectiveCid !== Number(userCid);
102
113
 
103
114
  // Check if user is a PI
@@ -128,8 +128,19 @@ async function checkIfUserIsPopularInvestor(req, res, dependencies, config) {
128
128
 
129
129
  try {
130
130
  // Check for dev override impersonation
131
- const effectiveCid = await getEffectiveCid(db, userCid, config, logger);
132
131
  const devOverride = await getDevOverride(db, userCid, config, logger);
132
+
133
+ // For PI-related checks, respect pretendToBePI flag
134
+ // If pretendToBePI is false, use actual userCid even if impersonateCid is set
135
+ let effectiveCid;
136
+ if (devOverride && devOverride.enabled && devOverride.pretendToBePI === false) {
137
+ // User explicitly doesn't want to pretend to be a PI, use actual CID
138
+ effectiveCid = Number(userCid);
139
+ } else {
140
+ // Use normal effective CID logic (may use impersonateCid if set)
141
+ effectiveCid = await getEffectiveCid(db, userCid, config, logger);
142
+ }
143
+
133
144
  const isImpersonating = devOverride && devOverride.enabled && devOverride.impersonateCid && effectiveCid !== Number(userCid);
134
145
 
135
146
  // Use effective CID (impersonated or actual) to check PI status
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.557",
3
+ "version": "1.0.559",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [