abmp-npm 1.1.75 → 1.1.77

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.
package/backend/consts.js CHANGED
@@ -1,6 +1,5 @@
1
1
  const PAC_API_URL = 'https://members.abmp.com/eweb/api/Wix';
2
2
  const SSO_TOKEN_AUTH_API_URL = 'https://members.professionalassistcorp.com/';
3
- const SSO_TOKEN_AUTH_API_KEY = 'testkey';
4
3
 
5
4
  /**
6
5
  * Valid configuration keys for getSiteConfigs function
@@ -41,5 +40,4 @@ module.exports = {
41
40
  COMPILED_FILTERS_FIELDS,
42
41
  MEMBERSHIPS_TYPES,
43
42
  SSO_TOKEN_AUTH_API_URL,
44
- SSO_TOKEN_AUTH_API_KEY,
45
43
  };
@@ -42,7 +42,7 @@ const ensureUniqueUrl = async ({ url, memberId, fullName }) => {
42
42
  excludeDropped: true,
43
43
  excludeSearchedMember: true,
44
44
  memberId,
45
- queryAllMatches: true,
45
+ normalizeSlugForComparison: true,
46
46
  });
47
47
  if (existingMember && existingMember.url) {
48
48
  console.log(
@@ -1,7 +1,7 @@
1
1
  const { taskManager, TASK_TYPE } = require('psdev-task-manager');
2
2
 
3
3
  const { COMPILED_FILTERS_FIELDS } = require('./consts');
4
- const { TASKS_NAMES } = require('./tasks');
4
+ const { TASKS_NAMES } = require('./tasks/consts');
5
5
 
6
6
  const scheduleCompileFiltersTask = field =>
7
7
  taskManager().schedule({
@@ -11,7 +11,8 @@ const wixData = {
11
11
  remove: auth.elevate(items.remove),
12
12
  get: auth.elevate(items.get),
13
13
  truncate: auth.elevate(items.truncate),
14
+ bulkSave: auth.elevate(items.bulkSave),
15
+ search: auth.elevate(items.search),
14
16
  //TODO: add other methods here as needed
15
17
  };
16
-
17
18
  module.exports = { wixData };
package/backend/index.js CHANGED
@@ -10,7 +10,7 @@ module.exports = {
10
10
  ...require('./members-data-methods'), //TODO: remove it once we finish NPM movement
11
11
  ...require('./cms-data-methods'), //TODO: remove it once we finish NPM movement
12
12
  ...require('./routers'),
13
- ...require('./sso-methods'),
13
+ ...require('./login'),
14
14
  ...require('./data-hooks'),
15
15
  ...require('./http-functions'),
16
16
  };
package/backend/jobs.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const { taskManager } = require('psdev-task-manager');
2
2
 
3
- const { TASKS, TASKS_NAMES } = require('./tasks');
3
+ const { TASKS_NAMES } = require('./tasks/consts');
4
+ const { TASKS } = require('./tasks/tasks-configs');
4
5
 
5
6
  async function runScheduledTasks() {
6
7
  try {
@@ -0,0 +1,7 @@
1
+ const { createLoginMethods } = require('./login-methods-factory');
2
+ const { validateMemberToken } = require('./sso-methods');
3
+
4
+ module.exports = {
5
+ createLoginMethods,
6
+ validateMemberToken,
7
+ };
@@ -0,0 +1,24 @@
1
+ const { loginQAMember } = require('./qa-login-methods');
2
+ const { authenticateSSOToken } = require('./sso-methods');
3
+
4
+ /**
5
+ * Creates login methods with injected generateSessionToken dependency
6
+ * @param {Function} generateSessionToken - The Velo generateSessionToken function to inject
7
+ * @returns {Object} Object containing loginQAMember and authenticateSSOToken methods
8
+ */
9
+ const createLoginMethods = generateSessionToken => {
10
+ //There is no generateSessionToken SDK version, and the signOn of @wix/identity returns 403 error regardless that the permissions are valid
11
+ //Therefore, as a workaround we need to inject the Velo version of generateSessionToken to the login methods.
12
+ const injectGenerateSessionTokenToMethod =
13
+ method =>
14
+ async (...args) =>
15
+ await method(...args, generateSessionToken);
16
+ return {
17
+ loginQAMember: injectGenerateSessionTokenToMethod(loginQAMember),
18
+ authenticateSSOToken: injectGenerateSessionTokenToMethod(authenticateSSOToken),
19
+ };
20
+ };
21
+
22
+ module.exports = {
23
+ createLoginMethods,
24
+ };
@@ -1,18 +1,24 @@
1
- const { authentication } = require('@wix/members');
2
-
3
- const { getMemberByEmail, getQAUsers } = require('./members-data-methods');
4
- const { getSecret } = require('./utils');
1
+ const { getMemberByEmail, getQAUsers } = require('../members-data-methods');
2
+ const { getSecret } = require('../utils');
5
3
 
6
4
  const validateQAUser = async userEmail => {
7
5
  const qaUsers = await getQAUsers();
8
- const matchingUser = qaUsers.find(user => user.email === userEmail);
9
- if (!matchingUser) {
6
+ const matchingUserEmail = qaUsers.find(user => user.email === userEmail)?.email;
7
+ if (!matchingUserEmail) {
10
8
  return { error: `Invalid user email: ${userEmail}` };
11
9
  }
12
- return { valid: true, user: matchingUser };
10
+ return { valid: true, email: matchingUserEmail };
13
11
  };
14
12
 
15
- const loginQAMember = async (userEmail, secret) => {
13
+ /**
14
+ * Login a QA user
15
+ * @param {Object} params - The parameters for the login
16
+ * @param {string} params.userEmail - The email of the user to login
17
+ * @param {string} params.secret - The secret of the user to login
18
+ * @param {Function} generateSessionToken - a dependency of the method, injected by the createLoginMethods function
19
+ * @returns {Promise<Object>} The result of the login
20
+ */
21
+ const loginQAMember = async ({ userEmail, secret }, generateSessionToken) => {
16
22
  try {
17
23
  const userValidation = await validateQAUser(userEmail);
18
24
  if (userValidation.error) {
@@ -24,8 +30,7 @@ const loginQAMember = async (userEmail, secret) => {
24
30
  return { success: false, error: 'Invalid secret' };
25
31
  }
26
32
 
27
- //TODO: this code still needs fixes, as there is no generateSessionToken method on
28
- const token = await authentication.generateSessionToken(userValidation.user, qaSecret);
33
+ const token = await generateSessionToken(userValidation.email, qaSecret);
29
34
 
30
35
  const result = await getMemberCMSId(userEmail);
31
36
  if (!result.success) {
@@ -1,20 +1,18 @@
1
1
  const { createHmac } = require('crypto');
2
2
 
3
- const { auth } = require('@wix/essentials');
4
- const { authentication } = require('@wix/identity'); //importing from @wix/identity because @wix/members authentication do not have generateSessionToken method
5
- const generateSessionToken = auth.elevate(authentication.signOn);
6
3
  const { decode } = require('jwt-js-decode');
7
4
 
8
- const { CONFIG_KEYS, SSO_TOKEN_AUTH_API_URL, SSO_TOKEN_AUTH_API_KEY } = require('./consts');
9
- const { MEMBER_ACTIONS } = require('./daily-pull');
10
- const { getCurrentMember } = require('./members-area-methods');
11
- const { getMemberByContactId, getSiteMemberId } = require('./members-data-methods');
5
+ const { CONFIG_KEYS, SSO_TOKEN_AUTH_API_URL } = require('../consts');
6
+ const { MEMBER_ACTIONS } = require('../daily-pull/consts');
7
+ const { getCurrentMember } = require('../members-area-methods');
8
+ const { getMemberByContactId, getSiteMemberId } = require('../members-data-methods');
12
9
  const {
13
10
  formatDateToMonthYear,
14
11
  getAddressDisplayOptions,
15
12
  isStudent,
16
13
  getSiteConfigs,
17
- } = require('./utils');
14
+ getSecret,
15
+ } = require('../utils');
18
16
 
19
17
  /**
20
18
  * Validates member token and retrieves member data
@@ -90,6 +88,7 @@ async function validateMemberToken(memberIdInput) {
90
88
  }
91
89
  }
92
90
  async function checkAndFetchSSO(token) {
91
+ const SSO_TOKEN_AUTH_API_KEY = await getSecret('SSO_TOKEN_AUTH_API_KEY');
93
92
  const signature = createHmac('sha256', SSO_TOKEN_AUTH_API_KEY).update(token).digest('hex');
94
93
  const professionalassistcorpUrl = `${SSO_TOKEN_AUTH_API_URL}/eweb/SSOToken.ashx?token=${token}&Partner=Wix&Signature=${signature}`;
95
94
  const options = {
@@ -109,16 +108,14 @@ async function checkAndFetchSSO(token) {
109
108
  }
110
109
  }
111
110
 
112
- function generateSessionTokenFunction(email) {
113
- return generateSessionToken({ email })
114
- .then(response => response.sessionToken)
115
- .catch(error => {
116
- console.error('Error in generateSessionTokenFunction', error);
117
- throw error;
118
- });
119
- }
120
-
121
- const authenticateSSOToken = async token => {
111
+ /**
112
+ * Authenticate an SSO token
113
+ * @param {Object} params - The parameters for the authentication
114
+ * @param {string} params.token - The token to authenticate
115
+ * @param {Function} generateSessionToken - a dependency of the method, injected by the createLoginMethods function
116
+ * @returns {Promise<Object>} The result of the authentication
117
+ */
118
+ const authenticateSSOToken = async ({ token }, generateSessionToken) => {
122
119
  const responseToken = await checkAndFetchSSO(token);
123
120
  const isValidToken = Boolean(
124
121
  responseToken && typeof responseToken === 'string' && responseToken?.trim()
@@ -138,7 +135,7 @@ const authenticateSSOToken = async token => {
138
135
  const payload = jwt.payload;
139
136
  const membersData = await getSiteMemberId(payload);
140
137
  console.log('membersDataCollectionId', membersData._id);
141
- const sessionToken = await generateSessionTokenFunction(membersData.email);
138
+ const sessionToken = await generateSessionToken(membersData.email);
142
139
  const authObj = {
143
140
  type: 'success',
144
141
  memberId: membersData._id,
@@ -10,6 +10,7 @@ const {
10
10
  normalizeUrlForComparison,
11
11
  queryAllItems,
12
12
  generateGeoHash,
13
+ searchAllItems,
13
14
  } = require('./utils');
14
15
 
15
16
  /**
@@ -108,7 +109,7 @@ async function findMemberById(memberId) {
108
109
  * @param {boolean} options.excludeDropped - Whether to exclude dropped members (default: true)
109
110
  * @param {boolean} options.excludeSearchedMember - Whether to exclude a specific member (default: false)
110
111
  * @param {string|number} [options.memberId] - Member ID to exclude when excludeSearchedMember is true (optional)
111
- * @param {boolean} [options.queryAllMatches=false] - Whether to query all matches or just the first one (default: false)
112
+ * @param {boolean} [options.normalizeSlugForComparison=false] - Whether to normalize the slug for comparison (default: false)
112
113
  * @returns {Promise<Object|null>} - Member data or null if not found
113
114
  */
114
115
  async function getMemberBySlug({
@@ -116,12 +117,12 @@ async function getMemberBySlug({
116
117
  excludeDropped = true,
117
118
  excludeSearchedMember = false,
118
119
  memberId = null,
119
- queryAllMatches = false,
120
+ normalizeSlugForComparison = false,
120
121
  }) {
121
122
  if (!slug) return null;
122
123
 
123
124
  try {
124
- let query = wixData.query(COLLECTIONS.MEMBERS_DATA).contains('url', slug);
125
+ let query = wixData.search(COLLECTIONS.MEMBERS_DATA).expression(slug);
125
126
 
126
127
  if (excludeDropped) {
127
128
  query = query.ne('action', 'drop');
@@ -130,17 +131,13 @@ async function getMemberBySlug({
130
131
  if (excludeSearchedMember && memberId) {
131
132
  query = query.ne('memberId', memberId);
132
133
  }
133
- let membersList;
134
- if (queryAllMatches) {
135
- query = query.limit(1000);
136
- membersList = await queryAllItems(query);
137
- } else {
138
- membersList = await query.find().then(res => res.items);
139
- }
134
+ query = query.limit(1000);
135
+ const searchResult = await searchAllItems(query);
136
+ const membersList = searchResult.items.filter(item => item.url && item.url.includes(slug)); //replacement for contains
140
137
  let matchingMembers = membersList.filter(
141
138
  item => item.url && item.url.toLowerCase() === slug.toLowerCase()
142
139
  );
143
- if (queryAllMatches) {
140
+ if (normalizeSlugForComparison) {
144
141
  matchingMembers = membersList
145
142
  .filter(
146
143
  //remove trailing "-1", "-2", etc.
@@ -152,7 +149,7 @@ async function getMemberBySlug({
152
149
  const queryResultMsg = `Multiple members found with same slug ${slug} membersIds are : [${matchingMembers
153
150
  .map(member => member.memberId)
154
151
  .join(', ')}]`;
155
- if (!queryAllMatches) {
152
+ if (!normalizeSlugForComparison) {
156
153
  throw new Error(queryResultMsg);
157
154
  } else {
158
155
  console.log(queryResultMsg);
@@ -1,8 +1,8 @@
1
+ const { MEMBER_ACTIONS } = require('../daily-pull/consts.js');
1
2
  const {
2
- MEMBER_ACTIONS,
3
3
  synchronizeSinglePage,
4
4
  syncMembersDataPerAction,
5
- } = require('../daily-pull');
5
+ } = require('../daily-pull/sync-to-cms-methods');
6
6
 
7
7
  const { TASKS_NAMES } = require('./consts');
8
8
  const {
package/backend/utils.js CHANGED
@@ -107,18 +107,28 @@ function getAddressesByStatus(addresses = [], addressDisplayOption = []) {
107
107
  })
108
108
  .filter(Boolean);
109
109
  }
110
- const queryAllItems = async query => {
111
- console.log('start query');
112
- let oldResults = await query.find();
110
+ const getAllItems = async querySearchResult => {
111
+ let oldResults = querySearchResult;
113
112
  console.log(`found items: ${oldResults.items.length}`);
114
113
  const allItems = oldResults.items;
115
114
  while (oldResults.hasNext()) {
116
115
  oldResults = await oldResults.next();
117
116
  allItems.push(...oldResults.items);
118
117
  }
119
- console.log(`all items: ${allItems.length}`);
118
+ console.log(`all items count : ${allItems.length}`);
120
119
  return allItems;
121
120
  };
121
+ const searchAllItems = async searchQuery => {
122
+ console.log('start search');
123
+ const searchResults = await searchQuery.run();
124
+ return getAllItems(searchResults);
125
+ };
126
+
127
+ const queryAllItems = async query => {
128
+ console.log('start query');
129
+ const queryResults = await query.find();
130
+ return getAllItems(queryResults);
131
+ };
122
132
  /**
123
133
  * Chunks large arrays into smaller chunks for processing
124
134
  * @param {Array} array - Array to chunk
@@ -154,7 +164,7 @@ const normalizeUrlForComparison = url => {
154
164
  };
155
165
 
156
166
  async function getSecret(secretKey) {
157
- return await elevatedGetSecretValue(secretKey).value;
167
+ return (await elevatedGetSecretValue(secretKey)).value;
158
168
  }
159
169
 
160
170
  async function getSiteBaseUrl() {
@@ -206,4 +216,5 @@ module.exports = {
206
216
  formatDateOnly,
207
217
  getAddressesByStatus,
208
218
  isPAC_STAFF,
219
+ searchAllItems,
209
220
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abmp-npm",
3
- "version": "1.1.75",
3
+ "version": "1.1.77",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "check-cycles": "madge --circular .",
@@ -7,7 +7,7 @@ async function loadingPageOnReady(authenticateSSOToken) {
7
7
  const renderingEnv = await rendering.env();
8
8
  //This calls needs to triggered on client side, otherwise PAC API will return 401 error
9
9
  if (renderingEnv === 'browser') {
10
- //Need to pass processSubmission to checkAndLogin so it will run as a web method not a public one.
10
+ //Need to pass authenticateSSOToken to checkAndLogin so it will run as a web method not a public one.
11
11
  await checkAndLogin(authenticateSSOToken).catch(error => {
12
12
  wixWindow.openLightbox(LIGHTBOX_NAMES.LOGIN_ERROR_ALERT);
13
13
  console.error(`Something went wrong while logging in: ${error}`);
package/pages/QAPage.js CHANGED
@@ -10,7 +10,7 @@ async function qaPageOnReady({ $w: _$w, loginQAMember }) {
10
10
  throw new Error('Missing required parameters: userEmail and/or secret');
11
11
  }
12
12
 
13
- const result = await loginQAMember(userEmail, secret);
13
+ const result = await loginQAMember({ userEmail, secret });
14
14
 
15
15
  if (!result.success || !result.token) {
16
16
  throw new Error(result.error || 'Login failed');
@@ -0,0 +1,13 @@
1
+ const { lightbox } = require('@wix/site-window');
2
+
3
+ async function saveAlertsOnReady({ $w: _$w }) {
4
+ const receivedData = await lightbox.getContext();
5
+ _$w('#closeButton').onClick(() => lightbox.close());
6
+ _$w('#cancelButton').onClick(() => lightbox.close());
7
+ _$w('#leaveButton').link = receivedData?.membersExternalPortalUrl;
8
+ _$w('#leaveButton').target = '_blank';
9
+ }
10
+
11
+ module.exports = {
12
+ saveAlertsOnReady,
13
+ };
@@ -0,0 +1,46 @@
1
+ const { lightbox } = require('@wix/site-window');
2
+
3
+ function selectBannerImagesOnReady({ $w: _$w }) {
4
+ _$w('#imageDataset').onReady(async () => {
5
+ const numOfItems = _$w('#imageDataset').getTotalCount();
6
+ const result = await _$w('#imageDataset').getItems(0, numOfItems);
7
+ const items = result.items;
8
+ console.log('Loaded items from dataset:', items);
9
+
10
+ _$w('#bannerImagesRepeater').data = items;
11
+ });
12
+
13
+ _$w('#bannerImagesRepeater').onItemReady(($item, itemData, index) => {
14
+ $item('#bannerImage').src = itemData.image; // image field
15
+ $item('#bannerSelected').checked = false;
16
+
17
+ // Only one checkbox can be selected
18
+ $item('#bannerSelected').onChange(() => {
19
+ if ($item('#bannerSelected').checked) {
20
+ _$w('#bannerImagesRepeater').forEachItem(($otherItem, _, otherIndex) => {
21
+ if (otherIndex !== index) {
22
+ $otherItem('#bannerSelected').checked = false;
23
+ }
24
+ });
25
+ }
26
+ });
27
+ });
28
+
29
+ _$w('#uploadSelectedImages').onClick(() => {
30
+ let selectedImage = null;
31
+
32
+ _$w('#bannerImagesRepeater').forEachItem(($item, itemData) => {
33
+ if ($item('#bannerSelected').checked) {
34
+ selectedImage = {
35
+ image: itemData.image,
36
+ title: itemData.title,
37
+ };
38
+ }
39
+ });
40
+ lightbox.close(selectedImage);
41
+ });
42
+ }
43
+
44
+ module.exports = {
45
+ selectBannerImagesOnReady,
46
+ };
@@ -0,0 +1,19 @@
1
+ const { lightbox } = require('@wix/site-window');
2
+
3
+ function deleteConfirmOnReady({ $w: _$w }) {
4
+ _$w('#delete').onClick(() => {
5
+ lightbox.close({
6
+ toDelete: true,
7
+ });
8
+ });
9
+
10
+ _$w('#cancel').onClick(() => {
11
+ lightbox.close({
12
+ toDelete: false,
13
+ });
14
+ });
15
+ }
16
+
17
+ module.exports = {
18
+ deleteConfirmOnReady,
19
+ };
package/pages/index.js CHANGED
@@ -5,4 +5,7 @@ module.exports = {
5
5
  ...require('./personalDetails.js'),
6
6
  ...require('./QAPage.js'),
7
7
  ...require('./LoadingPage.js'),
8
+ ...require('./SelectBannerImages.js'),
9
+ ...require('./deleteConfirm.js'),
10
+ ...require('./SaveAlerts.js'),
8
11
  };
package/public/consts.js CHANGED
@@ -12,7 +12,7 @@ const COLLECTIONS = {
12
12
  INTERESTS: 'interests',
13
13
  STATE_CITY_MAP: 'City',
14
14
  UPDATED_LOGIN_EMAILS: 'updatedLoginEmails',
15
- QA_Users: 'QA_Users', //Make QA users configurable per site
15
+ QA_USERS: 'QA_Users', //Make QA users configurable per site
16
16
  };
17
17
 
18
18
  /**
@@ -9,7 +9,7 @@ const checkAndLogin = async authenticateSSOToken => {
9
9
  const token = query['token']?.trim();
10
10
  try {
11
11
  if (token) {
12
- const authObj = await authenticateSSOToken(token);
12
+ const authObj = await authenticateSSOToken({ token });
13
13
  console.log('authObj', authObj);
14
14
  if (authObj.type == 'success') {
15
15
  console.log('success');