@getjones/test-infra 5.2.11 → 5.2.12
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/package.json +1 -1
- package/src/common/commonFlows/records/records.js +12 -3
- package/src/saas/internal-api/auth/api/auth.service.js +35 -1
- package/src/saas/internal-api/requirements/consts/consts.js +3 -1
- package/src/saas/internal-api/users/models/notification.settings.model.js +2 -1
- package/src/saas/internal-api/users/utils/util.js +2 -1
package/package.json
CHANGED
|
@@ -20,6 +20,8 @@ const recordTypes = require('../../../common/consts/recordTypes');
|
|
|
20
20
|
const policyNames = require('../../../defaults/index').polices;
|
|
21
21
|
const { ExtractionRequestModel } = require('../../../saas/internal-api/requirements/models/extraction.request.model');
|
|
22
22
|
const { TabExtractionRequestModel } = require('../../../saas/internal-api/requirements/models/tab.extraction.request.model');
|
|
23
|
+
const { DEFAULT_LEASE_PATH } = require('../../../saas/internal-api/requirements/consts/consts');
|
|
24
|
+
const { RELATED_DOC_TYPES } = require('../../../saas/internal-api/uploadFiles/consts');
|
|
23
25
|
const { WAIVER_REASONS, EXPIRY_TYPES } = compliance.models.waive;
|
|
24
26
|
|
|
25
27
|
const makeRecordNotResponsive = async function(recordId, context) {
|
|
@@ -392,18 +394,25 @@ const requestRequirementsExtraction = async (recordId, context, { leaseFilePath,
|
|
|
392
394
|
};
|
|
393
395
|
|
|
394
396
|
const requestTabRequirementsExtraction = async (tabId, context,
|
|
395
|
-
{ leaseFilePath, requirementName, notes, docType } = {}, { expectError, readContext = context } = {}) => {
|
|
397
|
+
{ leaseFilePath = DEFAULT_LEASE_PATH, requirementName, notes, docType = RELATED_DOC_TYPES.SERVICE_AGREEMENT } = {}, { expectError, readContext = context } = {}) => {
|
|
396
398
|
const stagedDocument = await uploadFile.services.stageDocumentToTempBucket(tabId, context, { filePath: leaseFilePath });
|
|
397
399
|
const tabExtractionRequestModel = new TabExtractionRequestModel({ ... stagedDocument, requirementName, docType, notes });
|
|
400
|
+
const existingLeases = expectError ? [] : await requirements.lease.services.getLeasesByTabId(tabId, readContext, { openOnly: false });
|
|
401
|
+
const existingLeaseIds = new Set(existingLeases.map(({ leaseId }) => leaseId));
|
|
398
402
|
const requestResponse = await requirements.lease.services.requestTabLeaseExtraction(tabId, tabExtractionRequestModel, context, { expectError });
|
|
399
403
|
|
|
400
404
|
if (expectError) {
|
|
401
405
|
return { requestResponse, stagedDocument };
|
|
402
406
|
}
|
|
403
407
|
|
|
404
|
-
const
|
|
408
|
+
const openLeases = await requirements.lease.services.getLeasesByTabId(tabId, readContext);
|
|
409
|
+
const createdLease = openLeases.find(({ leaseId }) => !existingLeaseIds.has(leaseId));
|
|
405
410
|
|
|
406
|
-
|
|
411
|
+
if (!createdLease) {
|
|
412
|
+
throw Error(`No new tab-level lease found for tab: ${tabId}`);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return createdLease.leaseId;
|
|
407
416
|
};
|
|
408
417
|
|
|
409
418
|
const cancelOpenTabRequests = async (tabId, icsContext) => {
|
|
@@ -4,6 +4,18 @@ const { credentials } = getEnv();
|
|
|
4
4
|
const httpResponseStatusCodes = require('../../../../common/httpResponseStatusCodes.json');
|
|
5
5
|
|
|
6
6
|
const authApi = require('./auth.api');
|
|
7
|
+
const timeUtils = require('../../../../common/utils/timeUtils');
|
|
8
|
+
|
|
9
|
+
const RETRYABLE_LOGIN_STATUSES = [
|
|
10
|
+
httpResponseStatusCodes.BAD_GATEWAY,
|
|
11
|
+
httpResponseStatusCodes.SERVICE_UNAVAILABLE,
|
|
12
|
+
httpResponseStatusCodes.GATEWAY_TIMEOUT
|
|
13
|
+
];
|
|
14
|
+
const MAX_LOGIN_ATTEMPTS = 3;
|
|
15
|
+
const LOGIN_RETRY_DELAY_SECONDS = 1;
|
|
16
|
+
|
|
17
|
+
// Parallel callers for the same user share one login request
|
|
18
|
+
const pendingLogins = new Map();
|
|
7
19
|
|
|
8
20
|
const getAuthCookie = async (email, password) => {
|
|
9
21
|
const systemUser = getSystemUserIdentity(email);
|
|
@@ -12,9 +24,31 @@ const getAuthCookie = async (email, password) => {
|
|
|
12
24
|
return systemUser.cookie;
|
|
13
25
|
}
|
|
14
26
|
|
|
15
|
-
|
|
27
|
+
if (!pendingLogins.has(email)) {
|
|
28
|
+
const login = loginAndCacheCookie(email, password).finally(() => pendingLogins.delete(email));
|
|
29
|
+
pendingLogins.set(email, login);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return pendingLogins.get(email);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const loginWithRetry = async (email, password) => {
|
|
36
|
+
for (let attempt = 1; ; attempt++) {
|
|
16
37
|
const response = await authApi.login(email, password);
|
|
17
38
|
|
|
39
|
+
if (!RETRYABLE_LOGIN_STATUSES.includes(response.status) || attempt === MAX_LOGIN_ATTEMPTS) {
|
|
40
|
+
return response;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.warn(`Login for ${email} failed with status ${response.status}, retrying`);
|
|
44
|
+
await timeUtils.waitFor(LOGIN_RETRY_DELAY_SECONDS).seconds;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const loginAndCacheCookie = async (email, password) => {
|
|
49
|
+
try {
|
|
50
|
+
const response = await loginWithRetry(email, password);
|
|
51
|
+
|
|
18
52
|
if (response.status !== httpResponseStatusCodes.OK) {
|
|
19
53
|
throw Error(`Error: ${JSON.stringify(response.data)}`);
|
|
20
54
|
}
|
|
@@ -12,9 +12,11 @@ const leaseExtractionStatus = {
|
|
|
12
12
|
closedReqSet: 'CLOSED_REQ_SET'
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const DEFAULT_LEASE_PATH = 'packages/test-infra/src/resources/lease/defaultLease.pdf';
|
|
16
|
+
|
|
15
17
|
const LEASE_TRIGGER_TYPES = {
|
|
16
18
|
record: 'RECORD',
|
|
17
19
|
tab: 'TAB'
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
module.exports = { REQUIREMENT_SHARING_LEVELS, leaseExtractionStatus, LEASE_TRIGGER_TYPES };
|
|
22
|
+
module.exports = { REQUIREMENT_SHARING_LEVELS, leaseExtractionStatus, LEASE_TRIGGER_TYPES, DEFAULT_LEASE_PATH };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
class NotificationSettingsModel {
|
|
2
|
-
constructor({ aboutToExpire = true, auditCompliant = true, auditNotCompliant = true, missingCoi = true, recordOverrideRequest = true, timedOverrideExpired = true } = {}) {
|
|
2
|
+
constructor({ aboutToExpire = true, auditCompliant = true, auditNotCompliant = true, missingCoi = true, recordOverrideRequest = true, timedOverrideExpired = true, weeklySummary = true } = {}) {
|
|
3
3
|
this.aboutToExpire = aboutToExpire;
|
|
4
4
|
this.auditCompliant = auditCompliant;
|
|
5
5
|
this.auditNotCompliant = auditNotCompliant;
|
|
6
6
|
this.missingCoi = missingCoi;
|
|
7
7
|
this.recordOverrideRequest = recordOverrideRequest;
|
|
8
8
|
this.timedOverrideExpired = timedOverrideExpired;
|
|
9
|
+
this.weeklySummary = weeklySummary;
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -13,7 +13,8 @@ const attributesConvertor = {
|
|
|
13
13
|
'COI is compliant.': 'auditCompliant',
|
|
14
14
|
'Unresponsive contact.': 'missingCoi',
|
|
15
15
|
'Record Override Request': 'recordOverrideRequest',
|
|
16
|
-
'Timed override expired — record is not compliant.': 'timedOverrideExpired'
|
|
16
|
+
'Timed override expired — record is not compliant.': 'timedOverrideExpired',
|
|
17
|
+
'Weekly summary': 'weeklySummary'
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
const getUserEncryptedData = async (email, role, context) => {
|