abmp-npm 2.0.82 → 2.0.83

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.
@@ -119,6 +119,15 @@ const getTodayInAssociationTimeZone = (now = new Date()) => {
119
119
  }
120
120
  };
121
121
 
122
+ const isAssociationExpirationCurrent = (member, now) => {
123
+ const stored = member?.[ASSOCIATION_EXPIRATION_FIELD];
124
+ const expiration = stored instanceof Date ? stored : stored ? new Date(stored) : null;
125
+
126
+ if (!expiration || Number.isNaN(expiration.getTime())) return false;
127
+
128
+ return expiration.getTime() >= getTodayInAssociationTimeZone(now).getTime();
129
+ };
130
+
122
131
  module.exports = {
123
132
  parseExpirationToUtcDate,
124
133
  classifyAssociationExpiration,
@@ -126,6 +135,7 @@ module.exports = {
126
135
  summarizeExpirationOutcomes,
127
136
  memberNeedsAssociationExpirationBackfill,
128
137
  getTodayInAssociationTimeZone,
138
+ isAssociationExpirationCurrent,
129
139
  ASSOCIATION_EXPIRATION_FIELD,
130
140
  ASSOCIATION_TIME_ZONE,
131
141
  EXPIRATION_OUTCOMES,
@@ -4,6 +4,10 @@ const { COLLECTIONS, MEMBERS_FIELDS } = require('../public/consts.js');
4
4
  const { findMainAddress } = require('../public/Utils/sharedUtils.js');
5
5
  const { calculateDistance, shuffleArray } = require('../public/Utils/sharedUtils.js');
6
6
 
7
+ const {
8
+ getTodayInAssociationTimeZone,
9
+ ASSOCIATION_EXPIRATION_FIELD,
10
+ } = require('./association-expiry');
7
11
  const {
8
12
  GEO_HASH_PRECISION,
9
13
  MAX__MEMBERS_SEARCH_RESULTS,
@@ -34,6 +38,8 @@ function buildMembersSearchQuery(data) {
34
38
  .ne('action', 'drop')
35
39
  .ne('memberships.membertype', MEMBERSHIPS_TYPES.PAC_STAFF)
36
40
  .eq('isVisible', true);
41
+
42
+ query = query.ge(ASSOCIATION_EXPIRATION_FIELD, getTodayInAssociationTimeZone());
37
43
  let filterConfig = [
38
44
  {
39
45
  filterKey: 'practiceAreas',
package/backend/consts.js CHANGED
@@ -43,6 +43,10 @@ const LOGIN_EMAIL_SYNC_STATUS = {
43
43
  SKIPPED: 'skipped', // member has no wixMemberId, nothing to change
44
44
  };
45
45
 
46
+ const LOGIN_REFUSAL_REASONS = {
47
+ ASSOCIATION_MEMBERSHIP_EXPIRED: 'ASSOCIATION_MEMBERSHIP_EXPIRED',
48
+ };
49
+
46
50
  module.exports = {
47
51
  CONFIG_KEYS,
48
52
  MAX__MEMBERS_SEARCH_RESULTS,
@@ -55,4 +59,5 @@ module.exports = {
55
59
  SSO_TOKEN_AUTH_API_URL,
56
60
  BACKUP_API_URL,
57
61
  LOGIN_EMAIL_SYNC_STATUS,
62
+ LOGIN_REFUSAL_REASONS,
58
63
  };
@@ -1,4 +1,5 @@
1
1
  const { ADDRESS_STATUS_TYPES } = require('../../public/consts');
2
+ const { ASSOCIATION_EXPIRATION_FIELD } = require('../association-expiry');
2
3
  const { findMemberById, getMemberBySlug } = require('../members-data-methods');
3
4
  const { isValidArray, generateGeoHash } = require('../utils');
4
5
 
@@ -198,6 +199,7 @@ async function createCoreMemberData(inputMemberData, existingDbMember, currentPa
198
199
  memberships: inputMemberData.memberships,
199
200
  pageNumber: currentPageNumber,
200
201
  isVisible: inputMemberData.action !== MEMBER_ACTIONS.DROP,
202
+ [ASSOCIATION_EXPIRATION_FIELD]: inputMemberData[ASSOCIATION_EXPIRATION_FIELD] ?? null,
201
203
 
202
204
  // Handle Member emails
203
205
  ...getMemberEmails(),
@@ -1,5 +1,9 @@
1
1
  const { taskManager } = require('psdev-task-manager');
2
2
 
3
+ const {
4
+ resolveAssociationExpiration,
5
+ ASSOCIATION_EXPIRATION_FIELD,
6
+ } = require('../association-expiry');
3
7
  const { CONFIG_KEYS } = require('../consts');
4
8
  const { fetchPACMembers } = require('../pac-api-methods');
5
9
  const { TASKS_NAMES } = require('../tasks/consts');
@@ -126,9 +130,10 @@ async function synchronizeSinglePage(taskObject) {
126
130
  }
127
131
  return isUpdatedMember(member);
128
132
  });
129
- const toSyncMembersWithFilteredLicenses = toSyncMembers.map(member =>
130
- filterLicensesByAssociation(member, siteAssociation)
131
- );
133
+ const toSyncMembersWithFilteredLicenses = toSyncMembers.map(member => ({
134
+ ...filterLicensesByAssociation(member, siteAssociation),
135
+ [ASSOCIATION_EXPIRATION_FIELD]: resolveAssociationExpiration(member, siteAssociation),
136
+ }));
132
137
  if (toSyncMembers.length === 0) {
133
138
  return {
134
139
  success: true,
@@ -3,7 +3,8 @@ const { createHmac } = require('crypto');
3
3
  const axios = require('axios');
4
4
  const { decode } = require('jwt-js-decode');
5
5
 
6
- const { CONFIG_KEYS, SSO_TOKEN_AUTH_API_URL } = require('../consts');
6
+ const { isAssociationExpirationCurrent } = require('../association-expiry');
7
+ const { CONFIG_KEYS, SSO_TOKEN_AUTH_API_URL, LOGIN_REFUSAL_REASONS } = require('../consts');
7
8
  const { MEMBER_ACTIONS } = require('../daily-pull/consts');
8
9
  const { getCurrentMember } = require('../members-area-methods');
9
10
  const { getCMSMemberByWixMemberId, prepareMemberForSSOLogin } = require('../members-data-methods');
@@ -79,6 +80,13 @@ async function validateMemberToken(memberIdInput) {
79
80
  return invalidTokenResponse;
80
81
  }
81
82
 
83
+ if (!isAssociationExpirationCurrent(memberData)) {
84
+ console.log(
85
+ `[validateMemberToken] association membership expired for memberId ${memberData.memberId}`
86
+ );
87
+ return invalidTokenResponse;
88
+ }
89
+
82
90
  // Add computed properties
83
91
  memberData.addressDisplayOption = getAddressDisplayOptions(memberData);
84
92
  console.log('memberData', memberData);
@@ -134,7 +142,14 @@ const authenticateSSOToken = async ({ token }) => {
134
142
  if (isValidToken) {
135
143
  const jwt = decode(responseToken);
136
144
  const payload = jwt.payload;
137
- const memberData = await prepareMemberForSSOLogin(payload);
145
+ let memberData;
146
+ try {
147
+ memberData = await prepareMemberForSSOLogin(payload);
148
+ } catch (error) {
149
+ if (error.message !== LOGIN_REFUSAL_REASONS.ASSOCIATION_MEMBERSHIP_EXPIRED) throw error;
150
+ console.log('[authenticateSSOToken] refusing login, association membership expired');
151
+ return { type: 'error', memberId: '', sessionToken: '' };
152
+ }
138
153
  console.log('memberDataCollectionId', memberData._id);
139
154
  const sessionToken = await generateMemberSessionToken(memberData.email);
140
155
  const authObj = {
@@ -1,7 +1,8 @@
1
1
  const { COLLECTIONS } = require('../public/consts');
2
2
  const { isWixHostedImage, emailsMatch, normalizeEmail } = require('../public/Utils/sharedUtils');
3
3
 
4
- const { MEMBERSHIPS_TYPES } = require('./consts');
4
+ const { isAssociationExpirationCurrent } = require('./association-expiry');
5
+ const { MEMBERSHIPS_TYPES, LOGIN_REFUSAL_REASONS } = require('./consts');
5
6
  const { createSiteContact } = require('./contacts-methods');
6
7
  const { MEMBER_ACTIONS } = require('./daily-pull/consts');
7
8
  const { wixData } = require('./elevated-modules');
@@ -696,6 +697,12 @@ async function prepareMemberForSSOLogin(data) {
696
697
  if (!memberData) {
697
698
  throw new Error(`Member data not found for memberId ${memberId}`);
698
699
  }
700
+ if (!isAssociationExpirationCurrent(memberData)) {
701
+ console.log(
702
+ `[prepareMemberForSSOLogin] refusing login, association membership expired for memberId ${memberId}`
703
+ );
704
+ throw new Error(LOGIN_REFUSAL_REASONS.ASSOCIATION_MEMBERSHIP_EXPIRED);
705
+ }
699
706
  console.log('memberData', memberData);
700
707
  return await ensureWixMemberAndContactExist(memberData);
701
708
  } catch (error) {
@@ -1,4 +1,5 @@
1
1
  const { getMainAddress } = require('../../public/Utils/sharedUtils');
2
+ const { isAssociationExpirationCurrent } = require('../association-expiry');
2
3
  const { getMemberBySlug } = require('../members-data-methods');
3
4
  const {
4
5
  getMoreAddressesToDisplay,
@@ -113,6 +114,11 @@ const getMemberProfileData = async (slug, siteAssociation) => {
113
114
  return null;
114
115
  }
115
116
 
117
+ if (!isAssociationExpirationCurrent(member)) {
118
+ console.log(`[getMemberProfileData] Association membership expired for slug: ${slug}`);
119
+ return null;
120
+ }
121
+
116
122
  return transformMemberToProfileData(member, siteAssociation);
117
123
  } catch (error) {
118
124
  const errorMessage = `Error in getMemberProfileData for slug: ${slug} : ${error.message}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abmp-npm",
3
- "version": "2.0.82",
3
+ "version": "2.0.83",
4
4
  "main": "index.js",
5
5
  "files": [
6
6
  "index.js",