@plusscommunities/pluss-core-aws 2.0.25-auth.0 → 2.0.25-beta.0

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 (90) hide show
  1. package/aws/getDefaultEmailAddress.js +21 -21
  2. package/aws/getEmailService.js +16 -16
  3. package/aws/getEmailServiceInfo.js +26 -26
  4. package/aws/sendEmail.js +31 -31
  5. package/config.js +1 -1
  6. package/db/activity/publishActivity.js +22 -22
  7. package/db/analytics/checkActivityExists.js +15 -15
  8. package/db/analytics/logAnalyticsActivity.js +69 -37
  9. package/db/analytics/scheduleOldAggregation.js +14 -14
  10. package/db/auth/getSiteSetting.js +12 -12
  11. package/db/auth/getSiteUserTypes.js +16 -16
  12. package/db/auth/getUserAuth.js +13 -13
  13. package/db/automatedactions/getActionBySiteTrigger.js +9 -9
  14. package/db/common/deleteRef.js +21 -21
  15. package/db/common/editRef.js +36 -36
  16. package/db/common/getRef.js +23 -23
  17. package/db/common/getTableCount.js +18 -18
  18. package/db/common/indexQuery.js +17 -17
  19. package/db/common/indexQueryRecursive.js +20 -20
  20. package/db/common/scanRef.js +18 -18
  21. package/db/common/scanRefRecursive.js +20 -20
  22. package/db/common/updateAttribute.js +27 -27
  23. package/db/common/updateRef.js +20 -20
  24. package/db/linkedUsers/getLinkedBy.js +21 -21
  25. package/db/linkedUsers/getLinkedTo.js +21 -21
  26. package/db/notifications/deleteNotificationsByEntity.js +21 -21
  27. package/db/notifications/getNotificationSetting.js +14 -14
  28. package/db/notifications/publishNotifications.js +39 -39
  29. package/db/scheduledActions/deleteActionQueue.js +1 -1
  30. package/db/scheduledActions/getActionQueueByEntityId.js +10 -10
  31. package/db/scheduledActions/getActionQueueByEntityKey.js +9 -9
  32. package/db/scheduledActions/getActionQueueById.js +9 -9
  33. package/db/scheduledActions/getActionQueueByTriggerAt.js +14 -14
  34. package/db/scheduledActions/updateActionQueue.js +29 -29
  35. package/db/strings/getString.js +20 -20
  36. package/db/strings/logUpdate.js +18 -18
  37. package/db/templates/getTemplateById.js +1 -1
  38. package/db/templates/getTemplatesList.js +10 -10
  39. package/db/templates/updateTemplate.js +9 -9
  40. package/db/users/getRole.js +1 -1
  41. package/db/users/getUser.js +9 -9
  42. package/db/users/getUserByEmail.js +17 -17
  43. package/helper/audience/filterByAudienceType.js +27 -27
  44. package/helper/audience/filterOnAudienceType.js +26 -26
  45. package/helper/audience/getAudience.js +187 -187
  46. package/helper/audience/getMatchingAudienceTypes.js +21 -21
  47. package/helper/audience/getMatchingAudienceTypesFromPreview.js +60 -60
  48. package/helper/audience/getMatchingTags.js +15 -15
  49. package/helper/audience/isValidAudience.js +20 -20
  50. package/helper/auth/checkTokenBlacklist.js +17 -17
  51. package/helper/auth/getApiKeyFromReq.js +2 -2
  52. package/helper/auth/getSessionUser.js +70 -85
  53. package/helper/auth/getSessionUserFromReq.js +2 -2
  54. package/helper/auth/getSessionUserFromReqAuthKey.js +11 -11
  55. package/helper/auth/validateApiKey.js +32 -32
  56. package/helper/auth/validateMasterAuth.js +174 -174
  57. package/helper/auth/validateSiteAccess.js +12 -12
  58. package/helper/auth/validateSiteSetting.js +7 -7
  59. package/helper/auth/validateUserLoggedIn.js +19 -19
  60. package/helper/createGuid.js +5 -5
  61. package/helper/generateJsonResponse.js +27 -27
  62. package/helper/getUserPreview.js +57 -57
  63. package/helper/getUserPreviewFromHeader.js +17 -17
  64. package/helper/getUserPreviewFromReq.js +17 -17
  65. package/helper/hqPublishing.js +45 -0
  66. package/helper/index.js +28 -28
  67. package/helper/notifySiteConfigs.js +132 -0
  68. package/helper/opengraph/getOpenGraph.js +12 -12
  69. package/helper/rates/checkRateLimit.js +38 -38
  70. package/helper/requestToSource.js +10 -10
  71. package/helper/sendEmail.js +120 -120
  72. package/helper/templates/replacePlaceHolders.js +29 -29
  73. package/helper/time/getLocalTimestamp.js +18 -18
  74. package/helper/time/getSiteTimezone.js +11 -11
  75. package/helper/triggerAutomatedAction.js +25 -25
  76. package/helper/userToUserPreview.js +23 -23
  77. package/helper/users/getUserTypesByPermission.js +24 -24
  78. package/helper/users/getUsersByPermission.js +20 -20
  79. package/notification/prepNotification.js +144 -144
  80. package/notification/sendNotifications.js +166 -166
  81. package/package.json +35 -40
  82. package/templates/supportTicketEmails.js +8 -8
  83. package/helper/auth/context/AuthenticationContext.js +0 -50
  84. package/helper/auth/context/AuthenticationStrategy.js +0 -20
  85. package/helper/auth/context/auth0/Strategy.js +0 -12
  86. package/helper/auth/context/auth0/functions/decodeAccessToken.js +0 -102
  87. package/helper/auth/context/auth0/functions/getSessionUser.js +0 -21
  88. package/helper/auth/context/boltonclarke/Strategy.js +0 -10
  89. package/helper/auth/context/cognito/Strategy.js +0 -12
  90. package/helper/auth/context/cognito/functions/getSessionUser.js +0 -76
@@ -3,66 +3,66 @@ const getUser = require("../db/users/getUser");
3
3
  const { getConfig } = require("../config");
4
4
 
5
5
  module.exports = async (id, includeType, includeSite, options) => {
6
- return new Promise((resolve, reject) => {
7
- const logId = log("getUserPreview", "Input", {
8
- id,
9
- includeType,
10
- includeSite,
11
- options,
12
- });
6
+ return new Promise((resolve, reject) => {
7
+ const logId = log("getUserPreview", "Input", {
8
+ id,
9
+ includeType,
10
+ includeSite,
11
+ options,
12
+ });
13
13
 
14
- if (!id) {
15
- log("getUserPreview", "NoId", "id is missing", logId);
16
- return resolve({
17
- id: null,
18
- userId: null,
19
- displayName: "Pluss",
20
- profilePic: null,
21
- type: null,
22
- site: getConfig().anySignUpSite,
23
- });
24
- }
14
+ if (!id) {
15
+ log("getUserPreview", "NoId", "id is missing", logId);
16
+ return resolve({
17
+ id: null,
18
+ userId: null,
19
+ displayName: "Pluss",
20
+ profilePic: null,
21
+ type: null,
22
+ site: getConfig().anySignUpSite,
23
+ });
24
+ }
25
25
 
26
- getUser(id)
27
- .then((user) => {
28
- const returnObj = {
29
- id,
30
- userId: id,
31
- displayName: user.displayName,
32
- profilePic: user.profilePic || null,
33
- };
26
+ getUser(id)
27
+ .then((user) => {
28
+ const returnObj = {
29
+ id,
30
+ userId: id,
31
+ displayName: user.displayName,
32
+ profilePic: user.profilePic || null,
33
+ };
34
34
 
35
- if (includeType || includeSite) {
36
- returnObj.Roles = user.Roles;
37
- if (!user.Roles) {
38
- returnObj.Roles = [
39
- {
40
- type: user.type,
41
- site: user.site,
42
- },
43
- ];
44
- }
45
- }
35
+ if (includeType || includeSite) {
36
+ returnObj.Roles = user.Roles;
37
+ if (!user.Roles) {
38
+ returnObj.Roles = [
39
+ {
40
+ type: user.type,
41
+ site: user.site,
42
+ },
43
+ ];
44
+ }
45
+ }
46
46
 
47
- if (includeType) {
48
- returnObj.type = user.type || null;
49
- }
50
- if (includeSite) {
51
- returnObj.site = user.site || null;
52
- }
53
- if (options) {
54
- if (options.includeEmail) {
55
- returnObj.email = user.email !== "empty" ? user.email : null;
56
- }
57
- }
58
- log("getUserPreview", "Result", returnObj, logId);
47
+ if (includeType) {
48
+ returnObj.type = user.type || null;
49
+ }
50
+ if (includeSite) {
51
+ returnObj.site = user.site || null;
52
+ }
53
+ if (options) {
54
+ if (options.includeEmail) {
55
+ returnObj.email = user.email !== "empty" ? user.email : null;
56
+ }
57
+ }
58
+ log("getUserPreview", "Result", returnObj, logId);
59
59
 
60
- resolve(returnObj);
61
- })
62
- .catch((error) => {
63
- log("getUserPreview", "Error", error, logId);
64
- console.log("failed to get user preview", id);
65
- reject(error);
66
- });
67
- });
60
+ resolve(returnObj);
61
+ })
62
+ .catch((error) => {
63
+ log("getUserPreview", "Error", error, logId);
64
+ console.log("failed to get user preview", id);
65
+ reject(error);
66
+ });
67
+ });
68
68
  };
@@ -3,21 +3,21 @@ const getSessionUser = require("./auth/getSessionUser");
3
3
  const getUserPreview = require("./getUserPreview");
4
4
 
5
5
  module.exports = async (authkey, includeType, inlcudeSite, options) => {
6
- return new Promise((resolve, reject) => {
7
- getSessionUser(authkey)
8
- .then((uid) => {
9
- getUserPreview(uid, includeType, inlcudeSite, options)
10
- .then((user) => {
11
- resolve(user);
12
- })
13
- .catch((error) => {
14
- log("getUserPreviewFromHeader", "Error:getUserPreview", error);
15
- reject(error);
16
- });
17
- })
18
- .catch((error) => {
19
- log("getUserPreviewFromHeader", "Error:getSessionUser", error);
20
- reject(error);
21
- });
22
- });
6
+ return new Promise((resolve, reject) => {
7
+ getSessionUser(authkey)
8
+ .then((uid) => {
9
+ getUserPreview(uid, includeType, inlcudeSite, options)
10
+ .then((user) => {
11
+ resolve(user);
12
+ })
13
+ .catch((error) => {
14
+ log("getUserPreviewFromHeader", "Error:getUserPreview", error);
15
+ reject(error);
16
+ });
17
+ })
18
+ .catch((error) => {
19
+ log("getUserPreviewFromHeader", "Error:getSessionUser", error);
20
+ reject(error);
21
+ });
22
+ });
23
23
  };
@@ -2,21 +2,21 @@ const getSessionUserFromReqAuthKey = require("./auth/getSessionUserFromReqAuthKe
2
2
  const getUserPreview = require("./getUserPreview");
3
3
 
4
4
  module.exports = async (req, includeType, inlcudeSite, options) => {
5
- return new Promise((resolve, reject) => {
6
- getSessionUserFromReqAuthKey(req)
7
- .then((uid) => {
8
- getUserPreview(uid, includeType, inlcudeSite, options)
9
- .then((user) => {
10
- resolve(user);
11
- })
12
- .catch((error) => {
13
- console.log("failed to get user preview", uid);
14
- reject(error);
15
- });
16
- })
17
- .catch((error) => {
18
- console.log("failed to get session user", authkey);
19
- reject(error);
20
- });
21
- });
5
+ return new Promise((resolve, reject) => {
6
+ getSessionUserFromReqAuthKey(req)
7
+ .then((uid) => {
8
+ getUserPreview(uid, includeType, inlcudeSite, options)
9
+ .then((user) => {
10
+ resolve(user);
11
+ })
12
+ .catch((error) => {
13
+ console.log("failed to get user preview", uid);
14
+ reject(error);
15
+ });
16
+ })
17
+ .catch((error) => {
18
+ console.log("failed to get session user", req);
19
+ reject(error);
20
+ });
21
+ });
22
22
  };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * PC-1441 Epic 1 — Cross-site Publishing Framework primitives (§13).
3
+ *
4
+ * Entity-agnostic helpers for HQ-published content lifecycle. Newsletter is the
5
+ * first entity to adopt this in July 2026 (Stories A–F under PC-1441); Q4+
6
+ * entities (Surveys, Information, Facilities, Services) plug in by depending on
7
+ * the same primitives — `HqSourceId` / `PublishedToSites` / `TemplateId` are
8
+ * universal field conventions, the helpers below don't reference any newsletter-
9
+ * specific table or shape.
10
+ *
11
+ * Story coverage:
12
+ * - **Story A (PC-1443)** — `isHqLocked` (lock guard for community-copy mutations).
13
+ * - **Story B (PC-1444)** — adds `findCopiesByHqSourceId`, `fanOutHqSource`,
14
+ * `propagateHqEdit`, `cascadeHqRetract`, and `incrementTemplateUseCount`
15
+ * (these will appear as additional exports here).
16
+ *
17
+ * If this file grows beyond ~200 lines or develops sub-themes, refactor to a
18
+ * `hqPublishing/` subdirectory with `index.js` re-exports.
19
+ */
20
+
21
+ /**
22
+ * Returns `true` when the entry is a community copy of an HQ-published post —
23
+ * i.e. its `HqSourceId` is **truthy**.
24
+ *
25
+ * **Falsy test (`Boolean(HqSourceId)`) — NOT `!== null`.** Legacy entries and
26
+ * locally-created entries have `HqSourceId` `undefined`; `undefined !== null`
27
+ * evaluates to `true`, which would wrongly lock every pre-feature post. The
28
+ * falsy check accepts `undefined`, `null`, and `""` as "not locked." See PC-1441
29
+ * scoping doc §3.2 AC2.3 + §6.1 + commit `1123c79` on `docs/enterprise-roadmap-scoping`.
30
+ *
31
+ * Universal — no role-based exception, including masters. HQ users edit the
32
+ * HQ-source row (where `!HqSourceId`, so the lock does not apply); the stream
33
+ * cascades to community copies. This is the API-side gate that pairs with the
34
+ * admin UI lock indicator (PC-1448) — defense-in-depth.
35
+ *
36
+ * @param {object|null|undefined} entry - Any object with an `HqSourceId` field
37
+ * (typically a row fetched from the entity's DB table).
38
+ * @returns {boolean} `true` if the entry is a locked community copy; `false`
39
+ * for legacy / locally-authored / HQ-source rows.
40
+ */
41
+ const isHqLocked = (entry) => Boolean(entry?.HqSourceId);
42
+
43
+ module.exports = {
44
+ isHqLocked,
45
+ };
package/helper/index.js CHANGED
@@ -3,28 +3,28 @@ const uuid = require("uuid");
3
3
  const { encode, decode } = require("html-entities");
4
4
 
5
5
  exports.thisOrDefault = (val, def) => {
6
- if (val) {
7
- return val;
8
- }
9
- return def;
6
+ if (val) {
7
+ return val;
8
+ }
9
+ return def;
10
10
  };
11
11
 
12
12
  exports.getRowId = (site, id) => {
13
- if (_.isEmpty(site)) {
14
- return id;
15
- }
16
- return `${site}_${id}`;
13
+ if (_.isEmpty(site)) {
14
+ return id;
15
+ }
16
+ return `${site}_${id}`;
17
17
  };
18
18
 
19
19
  exports.getMultiRowId = (cols) => {
20
- let result = "";
21
- cols.forEach((col) => {
22
- if (!_.isEmpty(result)) {
23
- result += "_";
24
- }
25
- result += col;
26
- });
27
- return result;
20
+ let result = "";
21
+ cols.forEach((col) => {
22
+ if (!_.isEmpty(result)) {
23
+ result += "_";
24
+ }
25
+ result += col;
26
+ });
27
+ return result;
28
28
  };
29
29
 
30
30
  // exports.getExtension = (filename) => {
@@ -36,7 +36,7 @@ exports.getMultiRowId = (cols) => {
36
36
  // };
37
37
 
38
38
  exports.getBody = (event) => {
39
- return typeof event.body === "string" ? JSON.parse(event.body) : event.body;
39
+ return typeof event.body === "string" ? JSON.parse(event.body) : event.body;
40
40
  };
41
41
 
42
42
  // exports.generatePassword = () => {
@@ -47,20 +47,20 @@ exports.getBody = (event) => {
47
47
  // };
48
48
 
49
49
  exports.log = (action, logKey, data, logId) => {
50
- if (!logId) {
51
- logId = this.generateLogId();
52
- }
53
- console.log(
54
- `[${action}]:[${logId}]:[${logKey}]`,
55
- typeof data === "string" || typeof data === "number"
56
- ? data
57
- : JSON.stringify(data)
58
- );
59
- return logId;
50
+ if (!logId) {
51
+ logId = this.generateLogId();
52
+ }
53
+ console.log(
54
+ `[${action}]:[${logId}]:[${logKey}]`,
55
+ typeof data === "string" || typeof data === "number"
56
+ ? data
57
+ : JSON.stringify(data),
58
+ );
59
+ return logId;
60
60
  };
61
61
 
62
62
  exports.generateLogId = () => {
63
- return uuid.v4().substring(30);
63
+ return uuid.v4().substring(30);
64
64
  };
65
65
 
66
66
  exports.encodeHtml = (html) => encode(html);
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Notify SiteConfigs Service of Operational Data Changes
3
+ *
4
+ * This helper provides a pre-filtering mechanism for auto-propagation.
5
+ * When operational data changes (sites, usertypes, interfaces, strings, jobTypes),
6
+ * this function:
7
+ *
8
+ * 1. Queries SourceSiteIdIndex to check if any templates use this site as source
9
+ * 2. If none found → early return (no Lambda invoke, 99% of cases)
10
+ * 3. If templates found → invokes siteConfigs Lambda to handle republishing
11
+ *
12
+ * This hybrid approach ensures:
13
+ * - No Lambda latency for most sites (pre-filter catches non-source sites)
14
+ * - Publishing logic stays encapsulated in siteConfigs service
15
+ * - Minimal cross-service coupling
16
+ *
17
+ * Usage:
18
+ * const notifySiteConfigs = require("@plusscommunities/pluss-core-aws/helper/notifySiteConfigs");
19
+ * await notifySiteConfigs(siteId, logId);
20
+ */
21
+
22
+ const AWS = require("aws-sdk");
23
+ const indexQuery = require("../db/common/indexQuery");
24
+ const { log } = require("./index");
25
+
26
+ const lambda = new AWS.Lambda();
27
+
28
+ const TABLE_NAME = "siteconfigs";
29
+
30
+ /**
31
+ * Check if a site has any templates using it as a source
32
+ * @param {string} siteId - The site ID to check
33
+ * @returns {Promise<Array>} Array of template IDs (empty if none)
34
+ */
35
+ const getTemplatesForSourceSite = async (siteId) => {
36
+ try {
37
+ const result = await indexQuery(TABLE_NAME, {
38
+ IndexName: "SourceSiteIdIndex",
39
+ KeyConditionExpression: "SourceSiteId = :sourceSiteId",
40
+ ExpressionAttributeValues: {
41
+ ":sourceSiteId": siteId,
42
+ },
43
+ ProjectionExpression: "Id", // Only need IDs for pre-filter
44
+ });
45
+ return (result.Items || []).map((item) => item.Id);
46
+ } catch (err) {
47
+ // Table or index might not exist in all deployments
48
+ log("notifySiteConfigs", "QueryError", { siteId, error: err.message });
49
+ return [];
50
+ }
51
+ };
52
+
53
+ /**
54
+ * Invoke the siteConfigs operationalDataChanged Lambda
55
+ * @param {string} siteId - The source site that changed
56
+ * @param {Array<string>} templateIds - List of template IDs to republish
57
+ * @param {string} logId - Log ID for tracing
58
+ */
59
+ const invokeSiteConfigsLambda = async (siteId, templateIds, logId) => {
60
+ // Build function name from environment
61
+ // Format: {client}-siteConfigs-{stage}-operationalDataChanged
62
+ const client = process.env.client || "dev";
63
+ const stage = process.env.stage || "dev";
64
+ const functionName = `${client}-siteConfigs-${stage}-operationalDataChanged`;
65
+
66
+ const payload = {
67
+ siteId,
68
+ templateIds,
69
+ logId,
70
+ source: "notifySiteConfigs",
71
+ };
72
+
73
+ log(
74
+ "notifySiteConfigs",
75
+ "InvokingLambda",
76
+ { functionName, siteId, templateCount: templateIds.length },
77
+ logId,
78
+ );
79
+
80
+ try {
81
+ await lambda
82
+ .invoke({
83
+ FunctionName: functionName,
84
+ InvocationType: "Event", // Async invocation
85
+ Payload: JSON.stringify(payload),
86
+ })
87
+ .promise();
88
+
89
+ log("notifySiteConfigs", "LambdaInvoked", { functionName, siteId }, logId);
90
+ } catch (err) {
91
+ log(
92
+ "notifySiteConfigs",
93
+ "LambdaError",
94
+ { functionName, siteId, error: err.message },
95
+ logId,
96
+ );
97
+ // Don't throw - this is a non-critical operation
98
+ }
99
+ };
100
+
101
+ /**
102
+ * Notify siteConfigs service that operational data has changed for a site.
103
+ * Performs pre-filtering to avoid unnecessary Lambda invocations.
104
+ *
105
+ * @param {string} siteId - The site ID where operational data changed
106
+ * @param {string} logId - Optional log ID for tracing
107
+ */
108
+ const notifySiteConfigs = async (siteId, logId) => {
109
+ if (!siteId) {
110
+ return;
111
+ }
112
+
113
+ // Pre-filter: Check if this site is a source for any templates
114
+ const templateIds = await getTemplatesForSourceSite(siteId);
115
+
116
+ if (templateIds.length === 0) {
117
+ // No Lambda invocation needed
118
+ return;
119
+ }
120
+
121
+ log(
122
+ "notifySiteConfigs",
123
+ "TemplatesFound",
124
+ { siteId, count: templateIds.length },
125
+ logId,
126
+ );
127
+
128
+ // Invoke siteConfigs Lambda to handle republishing
129
+ await invokeSiteConfigsLambda(siteId, templateIds, logId);
130
+ };
131
+
132
+ module.exports = notifySiteConfigs;
@@ -2,17 +2,17 @@ const axios = require("axios");
2
2
  const { getConfig } = require("../../config");
3
3
 
4
4
  module.exports = async (url) => {
5
- return new Promise(async (resolve, reject) => {
6
- const request = {
7
- method: "GET",
8
- url: `https://opengraph.io/api/1.1/site/${encodeURIComponent(url)}?app_id=${getConfig().thirdPartyAPIKeys.openGraph}`,
9
- };
5
+ return new Promise(async (resolve, reject) => {
6
+ const request = {
7
+ method: "GET",
8
+ url: `https://opengraph.io/api/1.1/site/${encodeURIComponent(url)}?app_id=${getConfig().thirdPartyAPIKeys.openGraph}`,
9
+ };
10
10
 
11
- try {
12
- const response = await axios(request);
13
- return resolve(response.data);
14
- } catch (e) {
15
- return reject(e);
16
- }
17
- });
11
+ try {
12
+ const response = await axios(request);
13
+ return resolve(response.data);
14
+ } catch (e) {
15
+ return reject(e);
16
+ }
17
+ });
18
18
  };
@@ -12,45 +12,45 @@ const updateRef = require("../../db/common/updateRef");
12
12
  * @returns {Boolean} true if this call is fine. false if the call should be restricted due to rate limits.
13
13
  */
14
14
  module.exports = async (rateLimitId, timeframe, limit, noSave) => {
15
- const logId = log("checkRateLimit", "Input", {
16
- rateLimitId,
17
- timeframe,
18
- limit,
19
- });
15
+ const logId = log("checkRateLimit", "Input", {
16
+ rateLimitId,
17
+ timeframe,
18
+ limit,
19
+ });
20
20
 
21
- // get rate limit item
22
- const item = await getRef("ratelimit", "Id", rateLimitId);
23
- const now = moment().valueOf();
24
- const minTime = now - timeframe;
21
+ // get rate limit item
22
+ const item = await getRef("ratelimit", "Id", rateLimitId);
23
+ const now = moment().valueOf();
24
+ const minTime = now - timeframe;
25
25
 
26
- const history = item && item.History ? item.History : [];
26
+ const history = item && item.History ? item.History : [];
27
27
 
28
- if (history) {
29
- // check history for entries to determine whether limit is surpassed
30
- const entriesInTimeLimit = history.filter((e) => e > minTime);
31
- log(
32
- "checkRateLimit",
33
- "entriesInTimeLimit",
34
- entriesInTimeLimit.length,
35
- logId
36
- );
37
- if (entriesInTimeLimit.length >= limit) {
38
- // Limit surpassed
39
- log("checkRateLimit", "Return", false, logId);
40
- return false;
41
- }
42
- }
28
+ if (history) {
29
+ // check history for entries to determine whether limit is surpassed
30
+ const entriesInTimeLimit = history.filter((e) => e > minTime);
31
+ log(
32
+ "checkRateLimit",
33
+ "entriesInTimeLimit",
34
+ entriesInTimeLimit.length,
35
+ logId,
36
+ );
37
+ if (entriesInTimeLimit.length >= limit) {
38
+ // Limit surpassed
39
+ log("checkRateLimit", "Return", false, logId);
40
+ return false;
41
+ }
42
+ }
43
43
 
44
- // check whether to save the current entry - used for when checking multiple timeframes such as X calls in a minute and X calls in a day
45
- if (!noSave) {
46
- history.push(now);
47
- updateRef("ratelimit", {
48
- Id: rateLimitId,
49
- LastSent: now,
50
- History: history,
51
- });
52
- }
53
- // Limit is fine
54
- log("checkRateLimit", "Return", true, logId);
55
- return true;
56
- };
44
+ // check whether to save the current entry - used for when checking multiple timeframes such as X calls in a minute and X calls in a day
45
+ if (!noSave) {
46
+ history.push(now);
47
+ updateRef("ratelimit", {
48
+ Id: rateLimitId,
49
+ LastSent: now,
50
+ History: history,
51
+ });
52
+ }
53
+ // Limit is fine
54
+ log("checkRateLimit", "Return", true, logId);
55
+ return true;
56
+ };
@@ -3,14 +3,14 @@ const _ = require("lodash");
3
3
 
4
4
  // sends a request to the Pluss Source API
5
5
  module.exports = (method, service, endpoint, query, data) => {
6
- return axios({
7
- method,
8
- url: `https://pluss60.pluss60-api.com/${service}-demo/${endpoint}${
9
- !_.isEmpty(query) ? query : ""
10
- }`,
11
- data,
12
- headers: {
13
- Authorization: "SmartCommunities",
14
- },
15
- });
6
+ return axios({
7
+ method,
8
+ url: `https://pluss60.pluss60-api.com/${service}-demo/${endpoint}${
9
+ !_.isEmpty(query) ? query : ""
10
+ }`,
11
+ data,
12
+ headers: {
13
+ Authorization: "SmartCommunities",
14
+ },
15
+ });
16
16
  };