@getjones/test-infra 5.3.1 → 5.3.3

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 (27) hide show
  1. package/package.json +1 -1
  2. package/src/common/commonFlows/records/records.js +49 -2
  3. package/src/common/consts/accountSettings.js +0 -4
  4. package/src/common/consts/projectSettings.js +7 -0
  5. package/src/index.js +0 -2
  6. package/src/saas/internal-api/accountDirectory/api/accountDirectory.service.js +3 -9
  7. package/src/saas/internal-api/accountDirectory/models/accountDirectory.models.js +1 -3
  8. package/src/saas/internal-api/accounts/models/settings/update.settings.model.js +1 -3
  9. package/src/saas/internal-api/agreement/api/agreement.service.js +3 -3
  10. package/src/saas/internal-api/coi/consts/uploaderTypes.js +1 -1
  11. package/src/saas/internal-api/coi/index.js +0 -1
  12. package/src/saas/internal-api/coi/utils/utils.js +10 -11
  13. package/src/saas/internal-api/compliance/api/overrideGap/override.gap.api.js +25 -2
  14. package/src/saas/internal-api/compliance/api/overrideGap/override.gap.service.js +93 -2
  15. package/src/saas/internal-api/compliance/consts/overrideGapRequest/override.gap.request.js +6 -1
  16. package/src/saas/internal-api/compliance/models/overrideGapRequest/override.gap.request.model.js +16 -1
  17. package/src/saas/internal-api/dbEmails/consts/consts.js +5 -10
  18. package/src/saas/internal-api/dbEmails/utils/util.js +5 -0
  19. package/src/saas/internal-api/notificationCenter/consts.js +4 -1
  20. package/src/saas/internal-api/projects/models/settings/update.project.settings.model.js +8 -0
  21. package/src/saas/internal-api/thread-scheduler/runner.js +0 -3
  22. package/src/saas/internal-api/thread-scheduler/schedulerJobs.js +0 -1
  23. package/src/saas/internal-api/coi/consts/coiUploaderTypes.js +0 -9
  24. package/src/saas/internal-api/weeklyDigest/api/weekly.digest.api.js +0 -32
  25. package/src/saas/internal-api/weeklyDigest/api/weekly.digest.service.js +0 -69
  26. package/src/saas/internal-api/weeklyDigest/consts/weekly.digest.consts.js +0 -21
  27. package/src/saas/internal-api/weeklyDigest/index.js +0 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getjones/test-infra",
3
- "version": "5.3.1",
3
+ "version": "5.3.3",
4
4
  "description": "Providing internal and openapi interface",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -14,6 +14,7 @@ const coi = require('../../../saas/internal-api/coi');
14
14
  const usersAPI = require('../../../saas/internal-api/users/index');
15
15
  const auth = require('../../../saas/internal-api/auth/index');
16
16
  const accounts = require('../../../saas/internal-api/accounts');
17
+ const { getIcsCookie } = require('../../../saas/internal-api/auth/api/auth.service');
17
18
  const activationStatuses = require('../../../common/consts/activationStatuses');
18
19
  const recordTypes = require('../../../common/consts/recordTypes');
19
20
  const policyNames = require('../../../defaults/index').polices;
@@ -327,6 +328,45 @@ const rejectOverrideGapRequest = async (overrideGapRequestId, rejectReason, reco
327
328
  return compliance.services.overrideGap.rejectOverrideGapRequest(overrideGapRequestId, rejectReason, record.dateModified, context);
328
329
  };
329
330
 
331
+ const createPmOverrideRequest = async (recordId, policyName, attributeName, assigneeUserIds, context, {
332
+ requestReason = 'PM override request reason for integration tests exceeding minimum length of 35 characters.',
333
+ expiryType = EXPIRY_TYPES.NEVER,
334
+ expiryDate = null,
335
+ expectError
336
+ } = {}) => {
337
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
338
+ const auditorContractorId = compliance.services.overrideGap.getAuditorContractorIdFromGap(record, policyName, attributeName);
339
+ return compliance.services.overrideGap.createPmOverrideRequest(auditorContractorId, context, {
340
+ requestReason,
341
+ expiryType,
342
+ expiryDate,
343
+ assigneeUserIds,
344
+ recordDateModified: record.dateModified,
345
+ expectError
346
+ });
347
+ };
348
+
349
+ const editPmOverrideRequest = async (overrideGapRequestId, recordId, context, {
350
+ requestReason,
351
+ expiryType,
352
+ expiryDate = null,
353
+ assigneeUserIds,
354
+ expectError
355
+ } = {}) => {
356
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
357
+ return compliance.services.overrideGap.editPmOverrideRequest(overrideGapRequestId, context, {
358
+ requestReason,
359
+ expiryType,
360
+ expiryDate,
361
+ assigneeUserIds,
362
+ recordDateModified: record.dateModified,
363
+ expectError
364
+ });
365
+ };
366
+
367
+ const deletePmOverrideRequest = (overrideGapRequestId, context, { expectError } = {}) =>
368
+ compliance.services.overrideGap.deletePmOverrideRequest(overrideGapRequestId, context, { expectError });
369
+
330
370
  const uploadMultipleCoiFiles = async (recordId, coiFilePaths, uploadedBy, uploaderEmail, context, { uploaderContext, duplicateHandling } = {}) => {
331
371
  const recordResponse = await contractors.services.getContractorById(recordId, context);
332
372
  const recordDateModified = recordResponse.data.dateModified;
@@ -336,12 +376,16 @@ const uploadMultipleCoiFiles = async (recordId, coiFilePaths, uploadedBy, upload
336
376
  fileIds.push(await coi.utils.uploadFileToStorage(recordId, filePath));
337
377
  }
338
378
 
379
+ if (!uploaderContext) {
380
+ uploaderContext = await getIcsCookie();
381
+ }
382
+
339
383
  const submitResponse = fileIds && await coi.utils.submitCoiFilesUpload({
340
384
  recordId,
341
385
  fileIds,
342
- uploadedBy,
386
+ uploadedBy, // If provided, uploaderContext will be ignored
343
387
  uploaderEmail,
344
- uploaderContext,
388
+ uploaderContext, // Can be used instead of uploadedBy + uploaderEmail
345
389
  recordDateModified,
346
390
  duplicateHandling
347
391
  });
@@ -442,6 +486,9 @@ module.exports = {
442
486
  getActiveOverrides,
443
487
  createOverrideGapRequest,
444
488
  rejectOverrideGapRequest,
489
+ createPmOverrideRequest,
490
+ editPmOverrideRequest,
491
+ deletePmOverrideRequest,
445
492
  uploadMultipleCoiFiles,
446
493
  createTenantUser,
447
494
  deleteRecordByName,
@@ -7,10 +7,6 @@ module.exports = {
7
7
  on: { isAccountRequirementsEnabled: true },
8
8
  off: { isAccountRequirementsEnabled: false }
9
9
  },
10
- isWeeklyDigestEnabled: {
11
- on: { isWeeklyDigestEnabled: true },
12
- off: { isWeeklyDigestEnabled: false }
13
- },
14
10
  isPolicyVerificationEnabled: {
15
11
  on: { hasPolicyVerification: true },
16
12
  off: { hasPolicyVerification: false }
@@ -21,6 +21,13 @@ module.exports = {
21
21
  onForTenants: { overrideGapRequestSettings: { isOverrideGapRequestEnabledForVendors: false, isOverrideGapRequestEnabledForTenants: true, isOverrideGapRequestEnabledForGuests: false } },
22
22
  onForGuests: { overrideGapRequestSettings: { isOverrideGapRequestEnabledForVendors: false, isOverrideGapRequestEnabledForTenants: false, isOverrideGapRequestEnabledForGuests: true } }
23
23
  },
24
+ userOverrideRequest: {
25
+ onForAll: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: true, isUserOverrideRequestEnabledForTenants: true, isUserOverrideRequestEnabledForGuests: true } },
26
+ offForAll: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: false, isUserOverrideRequestEnabledForTenants: false, isUserOverrideRequestEnabledForGuests: false } },
27
+ onForVendors: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: true, isUserOverrideRequestEnabledForTenants: false, isUserOverrideRequestEnabledForGuests: false } },
28
+ onForTenants: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: false, isUserOverrideRequestEnabledForTenants: true, isUserOverrideRequestEnabledForGuests: false } },
29
+ onForGuests: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: false, isUserOverrideRequestEnabledForTenants: false, isUserOverrideRequestEnabledForGuests: true } }
30
+ },
24
31
  onboardingPhase: {
25
32
  on: { onboardingPhase: true },
26
33
  off: { onboardingPhase: false }
package/src/index.js CHANGED
@@ -48,7 +48,6 @@ const getInternalAPI = () => {
48
48
 
49
49
  const threadScheduler = require('./saas/internal-api/thread-scheduler/runner');
50
50
  const schedulerJobRun = require('./saas/internal-api/schedulerJobRun');
51
- const weeklyDigest = require('./saas/internal-api/weeklyDigest');
52
51
  const certificial = require('./saas/internal-api/certificial');
53
52
  const dbEmails = require('./saas/internal-api/dbEmails/index');
54
53
  const agreement = require('./saas/internal-api/agreement/index');
@@ -90,7 +89,6 @@ const getInternalAPI = () => {
90
89
  sampleCoi,
91
90
  threadScheduler,
92
91
  schedulerJobRun,
93
- weeklyDigest,
94
92
  certificial,
95
93
  dbEmails,
96
94
  emailCustomization,
@@ -289,7 +289,6 @@ const getAllRecords = async (accountId, context, {
289
289
  sortOrder,
290
290
  pageNum,
291
291
  rowsPerPage,
292
- digestScope,
293
292
  expectError
294
293
  } = {}) => {
295
294
  const model = new accountDirectoryModels.AllRecordsTableRequestModel({
@@ -305,8 +304,7 @@ const getAllRecords = async (accountId, context, {
305
304
  sortBy,
306
305
  sortOrder,
307
306
  pageNum,
308
- rowsPerPage,
309
- digestScope
307
+ rowsPerPage
310
308
  });
311
309
 
312
310
  const response = await accountDirectoryAPI.getAllRecords(model, context);
@@ -331,7 +329,6 @@ const selectAllRecords = async (accountId, context, {
331
329
  selectedTagIds,
332
330
  expiryDateFrom,
333
331
  expiryDateTo,
334
- digestScope,
335
332
  expectError
336
333
  } = {}) => {
337
334
  const model = new accountDirectoryModels.AllRecordsTableRequestModel({
@@ -343,8 +340,7 @@ const selectAllRecords = async (accountId, context, {
343
340
  selectedRequirementIds,
344
341
  selectedTagIds,
345
342
  expiryDateFrom,
346
- expiryDateTo,
347
- digestScope
343
+ expiryDateTo
348
344
  });
349
345
 
350
346
  const response = await accountDirectoryAPI.selectAllRecords(model, context);
@@ -401,7 +397,6 @@ const exportAllRecords = async (accountId, context, {
401
397
  expiryDateTo,
402
398
  sortBy,
403
399
  sortOrder,
404
- digestScope,
405
400
  expectError
406
401
  } = {}) => {
407
402
  const model = new accountDirectoryModels.AllRecordsTableRequestModel({
@@ -415,8 +410,7 @@ const exportAllRecords = async (accountId, context, {
415
410
  expiryDateFrom,
416
411
  expiryDateTo,
417
412
  sortBy,
418
- sortOrder,
419
- digestScope
413
+ sortOrder
420
414
  });
421
415
 
422
416
  const response = await accountDirectoryAPI.exportAllRecords(model, context);
@@ -80,8 +80,7 @@ class AllRecordsTableRequestModel {
80
80
  sortBy = ALL_RECORDS_TABLE_SORT_BY.COMPANY_NAME,
81
81
  sortOrder = 'ASC',
82
82
  pageNum = 1,
83
- rowsPerPage = ROWS_PER_PAGE.TEN,
84
- digestScope = undefined
83
+ rowsPerPage = ROWS_PER_PAGE.TEN
85
84
  } = {}) {
86
85
  this.accountId = accountId;
87
86
  this.searchTerm = searchTerm;
@@ -96,7 +95,6 @@ class AllRecordsTableRequestModel {
96
95
  this.sortOrder = sortOrder;
97
96
  this.pageNum = pageNum;
98
97
  this.rowsPerPage = rowsPerPage;
99
- this.digestScope = digestScope;
100
98
  }
101
99
  }
102
100
 
@@ -33,7 +33,6 @@ class UpdateAccountSettingsModel {
33
33
  inviteGapCadence = null,
34
34
  isAcord25SplitExtractionEnabled = false,
35
35
  isCertificialEnabled = false,
36
- isWeeklyDigestEnabled = false,
37
36
  sampleCoi = {}
38
37
  } = {}
39
38
  ) {
@@ -65,7 +64,6 @@ class UpdateAccountSettingsModel {
65
64
  this.isConfigurableRenewalCadenceEnabled = isConfigurableRenewalCadenceEnabled;
66
65
  this.isAcord25SplitExtractionEnabled = isAcord25SplitExtractionEnabled;
67
66
  this.isCertificialEnabled = isCertificialEnabled;
68
- this.isWeeklyDigestEnabled = isWeeklyDigestEnabled;
69
67
  this.gapsChat = { ... DEFAULT_GAPS_CHAT, ... gapsChat };
70
68
  this.supportAutomation = { ... DEFAULT_SUPPORT_AUTOMATION, ... supportAutomation };
71
69
  this.sampleCoi = { ... DEFAULT_SAMPLE_COI, ... sampleCoi };
@@ -99,7 +97,7 @@ const DEFAULT_GAPS_CHAT = {
99
97
  const DEFAULT_SUPPORT_AUTOMATION = {
100
98
  isSupportAutomationAutoReplyEnabled: false,
101
99
  isSupportAutomationTiersClassificationEnabled: false,
102
- isSupportAutomationNoActionNeededEnabled: true,
100
+ isSupportAutomationNoActionNeededEnabled: false,
103
101
  isSupportAutomationStandardAutoUploadEnabled: true,
104
102
  isSupportAutomationEnhancedAutoUploadEnabled: false
105
103
  };
@@ -56,19 +56,19 @@ const uploadAgreementByPM = async (
56
56
  context,
57
57
  { contractorDateModified } = {}
58
58
  ) => {
59
- const { data: { preSignedUrl, fileName: tempFileName } } = await getAgreementPreSignedUrl(recordId, context, { filePath });
59
+ const { data: { preSignedUrl, fileName: fullFilePath } } = await getAgreementPreSignedUrl(recordId, context, { filePath });
60
60
 
61
61
  const uploadResults = await uploadAgreementToTempBucket(preSignedUrl, filePath);
62
62
  validateResponse(uploadResults, recordId);
63
63
 
64
- const response = await uploadAgreementToS3(tempFileName, recordId);
64
+ const response = await uploadAgreementToS3(fullFilePath, recordId);
65
65
  validateResponse(response, recordId);
66
66
 
67
67
  const createAgreementModel = new CreateAgreementByPMModel({
68
68
  contractorId: recordId,
69
69
  contractorDateModified,
70
70
  uploaderId,
71
- signedContractName: response.data.fileName
71
+ signedContractName: fullFilePath
72
72
  });
73
73
 
74
74
  const createResponse = await createAgreement(createAgreementModel, context);
@@ -1,3 +1,3 @@
1
- const UPLOADER_TYPES = { ICS: 'ICS', PM: 'PM', AUDITOR: 'Auditor', VENDOR: 'Vendor', BOT: 'Bot' };
1
+ const UPLOADER_TYPES = { ICS: 'ICS', PM: 'PM', AUDITOR: 'Auditor', VENDOR: 'Vendor' };
2
2
 
3
3
  module.exports = UPLOADER_TYPES;
@@ -9,7 +9,6 @@ const utils = require('./utils/utils');
9
9
 
10
10
  const consts = {
11
11
  UPLOADER_TYPES: require('./consts/uploaderTypes'),
12
- COI_UPLOADER_TYPES: require('./consts/coiUploaderTypes'),
13
12
  HASHES: require('./consts/hashes'),
14
13
  DUPLICATE_HANDLING: require('./consts/duplicateHandling')
15
14
  };
@@ -27,9 +27,6 @@ const submitCoiFilesUpload = async ({
27
27
  recordDateModified,
28
28
  duplicateHandling
29
29
  }) => {
30
- // ICS is the default uploader, so without a session it falls back to the ICS cookie; other types go out unauthenticated
31
- const isUnauthenticatedUpload = !uploaderContext && uploadedBy !== UPLOADER_TYPES.ICS;
32
-
33
30
  const submitCoiModel = new SubmitCoiModel({
34
31
  recordId,
35
32
  fileIds,
@@ -40,12 +37,11 @@ const submitCoiFilesUpload = async ({
40
37
  duplicateHandling
41
38
  });
42
39
 
43
- if (isUnauthenticatedUpload) {
40
+ if (uploadedBy != UPLOADER_TYPES.ICS) { // Upload by user role
44
41
  return services.submitCoi(submitCoiModel);
45
42
  }
46
43
 
47
- const sessionContext = uploaderContext || await getIcsCookie();
48
- return services.submitCoiByUserContext(submitCoiModel, sessionContext);
44
+ return services.submitCoiByUserContext(submitCoiModel, uploaderContext); // Upload by user context
49
45
  };
50
46
 
51
47
  const uploadCoi = async (
@@ -54,13 +50,16 @@ const uploadCoi = async (
54
50
  uploadedBy,
55
51
  uploaderEmail,
56
52
  {
57
- markAsScaned,
53
+ markAsScaned, // Should be passed with context
58
54
  uploaderContext,
59
55
  duplicateHandling
60
56
  } = {}
61
57
  ) => {
62
- const icsContext = await getIcsCookie();
63
- const recordResponse = await getContractorById(recordId, icsContext); // Auditors can't read the record, same as combineLastTwoCOIs
58
+ if (!uploaderContext) {
59
+ uploaderContext = await getIcsCookie();
60
+ }
61
+
62
+ const recordResponse = await getContractorById(recordId, uploaderContext);
64
63
  const recordDateModified = recordResponse.data.dateModified;
65
64
  const fileId = await uploadFileToStorage(recordId, filePath);
66
65
 
@@ -76,8 +75,8 @@ const uploadCoi = async (
76
75
 
77
76
  const uploadedCoi = !!submitResponse.data.fileName && { id: fileId, name: submitResponse.data.fileName };
78
77
 
79
- if (uploadedCoi.name && markAsScaned) {
80
- await fileScanService.completeCoiScan(recordId, uploadedCoi.name, icsContext); // Only ICS may update the scan status
78
+ if (uploadedCoi.name && markAsScaned && uploaderContext) {
79
+ await fileScanService.completeCoiScan(recordId, uploadedCoi.name, uploaderContext);
81
80
  }
82
81
 
83
82
  return uploadedCoi;
@@ -13,7 +13,10 @@ const Endpoints = {
13
13
  updateOverrideExpiryDate: auditorContractorId => `${backendUrl}/saas/integration-tests/override/${auditorContractorId}/expiry-date`,
14
14
  getOverrideGapRequestById: overrideGapRequestId => `${backendUrl}/saas/gaps/override-gap-request/${overrideGapRequestId}`,
15
15
  createOverrideGapRequest: `${backendUrl}/secured/vendor-app/record/override-gap-request`,
16
- rejectOverrideGapRequest: `${backendUrl}/saas/gaps/override-gap-request/reject`
16
+ rejectOverrideGapRequest: `${backendUrl}/saas/gaps/override-gap-request/reject`,
17
+ createPmOverrideRequest: `${backendUrl}/saas/gaps/override-gap-request`,
18
+ pmOverrideRequestById: overrideGapRequestId => `${backendUrl}/saas/gaps/override-gap-request/${overrideGapRequestId}`,
19
+ eligibleOverrideAssignees: requestId => `${backendUrl}/saas/gaps/override-gap-request/assignees/${requestId}`
17
20
  };
18
21
 
19
22
  const waive = async (contractorId, waiveRequestModel, context) => {
@@ -70,6 +73,22 @@ const rejectOverrideGapRequest = (rejectModel, context) => {
70
73
  return requests.patchRequestHandler(Endpoints.rejectOverrideGapRequest, context, rejectModel);
71
74
  };
72
75
 
76
+ const createPmOverrideRequest = (pmOverrideRequestModel, context) => {
77
+ return requests.postRequestHandler(Endpoints.createPmOverrideRequest, pmOverrideRequestModel, context);
78
+ };
79
+
80
+ const editPmOverrideRequest = (overrideGapRequestId, pmOverrideRequestModel, context) => {
81
+ return requests.patchRequestHandler(Endpoints.pmOverrideRequestById(overrideGapRequestId), context, pmOverrideRequestModel);
82
+ };
83
+
84
+ const deletePmOverrideRequest = (overrideGapRequestId, context) => {
85
+ return requests.deleteRequestHandler(Endpoints.pmOverrideRequestById(overrideGapRequestId), context);
86
+ };
87
+
88
+ const getEligibleOverrideAssignees = (requestId, context) => {
89
+ return requests.getRequestHandler(Endpoints.eligibleOverrideAssignees(requestId), {}, context);
90
+ };
91
+
73
92
  module.exports = {
74
93
  waive,
75
94
  retract,
@@ -82,5 +101,9 @@ module.exports = {
82
101
  updateOverrideExpiryDate,
83
102
  getOverrideGapRequestById,
84
103
  createOverrideGapRequest,
85
- rejectOverrideGapRequest
104
+ rejectOverrideGapRequest,
105
+ createPmOverrideRequest,
106
+ editPmOverrideRequest,
107
+ deletePmOverrideRequest,
108
+ getEligibleOverrideAssignees
86
109
  };
@@ -10,7 +10,7 @@ const {
10
10
  WAIVER_REASONS,
11
11
  EXPIRY_TYPES
12
12
  } = require('../../models/waive/waive.model');
13
- const { OverrideGapRequestCreateModel, OverrideGapRequestRejectModel } = require('../../models/overrideGapRequest/override.gap.request.model');
13
+ const { OverrideGapRequestCreateModel, OverrideGapRequestRejectModel, PmOverrideRequestModel } = require('../../models/overrideGapRequest/override.gap.request.model');
14
14
  const { validateType } = require('../../../../../common/validations/typeValidations');
15
15
  const auditUtil = require('../../utils/auditUtil');
16
16
  const httpResponseStatusCodes = require('../../../../../common/httpResponseStatusCodes.json');
@@ -277,6 +277,93 @@ const updateOverrideExpiryDate = async (auditorContractorId, expiryDate, context
277
277
  return response;
278
278
  };
279
279
 
280
+ const createPmOverrideRequest = async (auditorContractorId, context, {
281
+ requestReason,
282
+ expiryType,
283
+ expiryDate = null,
284
+ assigneeUserIds,
285
+ recordDateModified,
286
+ expectError
287
+ } = {}) => {
288
+ const model = new PmOverrideRequestModel({
289
+ auditorContractorId,
290
+ requestReason,
291
+ expiryType,
292
+ expiryDate,
293
+ assigneeUserIds,
294
+ recordDateModified
295
+ });
296
+ validateType(model, PmOverrideRequestModel);
297
+ const response = await overrideGapApi.createPmOverrideRequest(model, context);
298
+
299
+ if (expectError) {
300
+ return response;
301
+ }
302
+
303
+ if (response.status !== httpResponseStatusCodes.CREATED) {
304
+ throw Error(`Failed to create PM override request. Status code: ${response.status}`);
305
+ }
306
+
307
+ return response.data;
308
+ };
309
+
310
+ const editPmOverrideRequest = async (overrideGapRequestId, context, {
311
+ requestReason,
312
+ expiryType,
313
+ expiryDate = null,
314
+ assigneeUserIds,
315
+ recordDateModified,
316
+ expectError
317
+ } = {}) => {
318
+ const model = new PmOverrideRequestModel({
319
+ requestReason,
320
+ expiryType,
321
+ expiryDate,
322
+ assigneeUserIds,
323
+ recordDateModified
324
+ });
325
+ validateType(model, PmOverrideRequestModel);
326
+ const response = await overrideGapApi.editPmOverrideRequest(overrideGapRequestId, model, context);
327
+
328
+ if (expectError) {
329
+ return response;
330
+ }
331
+
332
+ if (response.status !== httpResponseStatusCodes.NO_CONTENT) {
333
+ throw Error(`Failed to edit PM override request. Status code: ${response.status}`);
334
+ }
335
+
336
+ return response;
337
+ };
338
+
339
+ const deletePmOverrideRequest = async (overrideGapRequestId, context, { expectError } = {}) => {
340
+ const response = await overrideGapApi.deletePmOverrideRequest(overrideGapRequestId, context);
341
+
342
+ if (expectError) {
343
+ return response;
344
+ }
345
+
346
+ if (response.status !== httpResponseStatusCodes.NO_CONTENT) {
347
+ throw Error(`Failed to delete PM override request. Status code: ${response.status}`);
348
+ }
349
+
350
+ return response;
351
+ };
352
+
353
+ const getEligibleOverrideAssignees = async (requestId, context, { expectError } = {}) => {
354
+ const response = await overrideGapApi.getEligibleOverrideAssignees(requestId, context);
355
+
356
+ if (expectError) {
357
+ return response;
358
+ }
359
+
360
+ if (response.status !== httpResponseStatusCodes.OK) {
361
+ throw Error(`Failed to get eligible override assignees. Status code: ${response.status}`);
362
+ }
363
+
364
+ return response.data;
365
+ };
366
+
280
367
  module.exports = {
281
368
  waive,
282
369
  waiveAll,
@@ -296,5 +383,9 @@ module.exports = {
296
383
  getOverrideGapRequestById,
297
384
  rejectOverrideGapRequest,
298
385
  getAuditorContractorIdFromGap,
299
- updateOverrideExpiryDate
386
+ updateOverrideExpiryDate,
387
+ createPmOverrideRequest,
388
+ editPmOverrideRequest,
389
+ deletePmOverrideRequest,
390
+ getEligibleOverrideAssignees
300
391
  };
@@ -4,4 +4,9 @@ const OVERRIDE_GAP_REQUEST_STATUS = {
4
4
  REJECTED: 'REJECTED'
5
5
  };
6
6
 
7
- module.exports = { OVERRIDE_GAP_REQUEST_STATUS };
7
+ const OVERRIDE_REQUESTER_TYPE = {
8
+ HUB_USER: 'HUB_USER',
9
+ INVITER: 'INVITER'
10
+ };
11
+
12
+ module.exports = { OVERRIDE_GAP_REQUEST_STATUS, OVERRIDE_REQUESTER_TYPE };
@@ -13,4 +13,19 @@ class OverrideGapRequestRejectModel {
13
13
  this.recordDateModified = recordDateModified;
14
14
  }
15
15
  }
16
- module.exports = { OverrideGapRequestCreateModel, OverrideGapRequestRejectModel };
16
+
17
+ class PmOverrideRequestModel {
18
+ constructor({ auditorContractorId, requestReason, expiryType, expiryDate = null, assigneeUserIds, recordDateModified }) {
19
+ if (auditorContractorId !== undefined) {
20
+ this.auditorContractorId = auditorContractorId;
21
+ }
22
+
23
+ this.requestReason = requestReason;
24
+ this.expiryType = expiryType;
25
+ this.expiryDate = expiryDate;
26
+ this.assigneeUserIds = assigneeUserIds;
27
+ this.recordDateModified = recordDateModified;
28
+ }
29
+ }
30
+
31
+ module.exports = { OverrideGapRequestCreateModel, OverrideGapRequestRejectModel, PmOverrideRequestModel };
@@ -54,16 +54,11 @@ const EMAIL_SUBJECT = {
54
54
  overrideGapRequestPending: ({ vendorCompanyName }) => `${vendorCompanyName} asked for an exception`,
55
55
  overrideGapRequestRejected: ({ accountName }) => `${accountName} denied your exception request`,
56
56
  overrideGapRequestApproved: ({ accountName }) => `${accountName} approved your exception request`,
57
+ pmOverrideRequestAssigned: ({ requesterFullName, companyName }) => `${requesterFullName} asked you to override a gap for ${companyName}`,
58
+ pmOverrideRequestDenied: ({ rejecterFullName, companyName }) => `${rejecterFullName} Rejected your override request for ${companyName}`,
59
+ pmOverrideRequestApproved: ({ approverFullName, companyName }) => `${approverFullName} Approved your override request for ${companyName}`,
57
60
  timedOverrideExpired: ({ recordCompanyName, requesterName }) => `Override ended - ${recordCompanyName} in ${requesterName}`,
58
- allRecordsExport: 'Jones - All Records Export',
59
- weeklyDigest: ({ accountName }) => `Your Weekly updates for ${accountName}`
60
- };
61
-
62
- const EMAIL_LINK_REGEX = {
63
- mailActionButton: /(https:\/\/[a-zA-Z0-9.].*[a-zA-Z.]+\/CheckCustomersInviteLinkJSON\?data=[^"]+)/g,
64
- sampleCoiDownload: /\/sample-coi\/requirement\/([^/]+)\/download\?source=email/,
65
- allRecordsExportDownload: /href="(https?:\/\/[^"]+)"/,
66
- weeklyDigestViewAll: issue => new RegExp(`(https:\\/\\/[^"]+\\/all-records\\?digestIssue=${issue}[^"]*)`)
61
+ allRecordsExport: 'Jones - All Records Export'
67
62
  };
68
63
 
69
64
  const EMAIL_POLLING = {
@@ -71,4 +66,4 @@ const EMAIL_POLLING = {
71
66
  expectNoMail: { maxRetries: 3, pollIntervalSeconds: 1 }
72
67
  };
73
68
 
74
- module.exports = { DEFAULT_EMAIL_SENDER, EMAIL_TYPES, EMAIL_SUBJECT, EMAIL_LINK_REGEX, EMAIL_POLLING, tenantUserExtension };
69
+ module.exports = { DEFAULT_EMAIL_SENDER, EMAIL_TYPES, EMAIL_SUBJECT, EMAIL_POLLING, tenantUserExtension };
@@ -62,6 +62,10 @@ const getEmailTextInSubject = (recordCompanyName, emailType, isAfterUpdateRequir
62
62
  return isAfterUpdateRequirements ? `Updated Requirements - ${subject}` : subject;
63
63
  };
64
64
 
65
+ const getMailActionButtonUrlRegex = () => {
66
+ return /(https:\/\/[a-zA-Z0-9.].*[a-zA-Z.]+\/CheckCustomersInviteLinkJSON\?data=[^"]+)/g;
67
+ };
68
+
65
69
  const getEncryptedDataFromLink = (link, { removeLastTwoCharts } = {}) => {
66
70
  const encryptedData = link.split('data=').pop();
67
71
  return removeLastTwoCharts ? encryptedData.slice(0, -2) : encryptedData;
@@ -73,5 +77,6 @@ module.exports = {
73
77
  extractEmailFromNameAndEmailFormat,
74
78
  logRetrievedEmailInfo,
75
79
  getEmailTextInSubject,
80
+ getMailActionButtonUrlRegex,
76
81
  getEncryptedDataFromLink
77
82
  };
@@ -3,7 +3,10 @@ const NOTIFICATION_TYPES = {
3
3
  OVERRIDE_GAP_REQUEST_PENDING: 'NewOverrideGapRequest',
4
4
  RELATED_DOC_UPDATED: 'RelatedDocUpdated',
5
5
  GLOBAL_RECORD_RELATED_DOC_UPDATED: 'GlobalRecordRelatedDocUpdated',
6
- TIMED_OVERRIDE_EXPIRED: 'TimedOverrideExpired'
6
+ TIMED_OVERRIDE_EXPIRED: 'TimedOverrideExpired',
7
+ PM_OVERRIDE_REQUEST: 'NewPmOverrideRequest',
8
+ PM_OVERRIDE_REQUEST_APPROVED: 'PmOverrideRequestApproved',
9
+ PM_OVERRIDE_REQUEST_REJECTED: 'PmOverrideRequestRejected'
7
10
  };
8
11
 
9
12
  module.exports = { NOTIFICATION_TYPES };
@@ -9,6 +9,7 @@ class UpdateProjectSettingsModel {
9
9
  tenantSolution = false,
10
10
  autocompleteSettings = {},
11
11
  overrideGapRequestSettings = {},
12
+ userOverrideRequestSettings = {},
12
13
  relevantComplianceDocumentsSettings = {}
13
14
  } = {}
14
15
  ) {
@@ -20,6 +21,7 @@ class UpdateProjectSettingsModel {
20
21
  this.tenantSolution = tenantSolution;
21
22
  this.autocompleteSettings = { ... DEFAULT_AUTOCOMPLETE_ADD_VENDORS, ... autocompleteSettings };
22
23
  this.overrideGapRequestSettings = { ... DEFAULT_OVERRIDE_GAP_REQUEST, ... overrideGapRequestSettings };
24
+ this.userOverrideRequestSettings = { ... DEFAULT_USER_OVERRIDE_REQUEST, ... userOverrideRequestSettings };
23
25
  this.relevantComplianceDocumentsSettings = { ... DEFAULT_RELEVANT_COMPLIANCE_DOCUMENTS, ... relevantComplianceDocumentsSettings };
24
26
  }
25
27
  }
@@ -49,6 +51,12 @@ const DEFAULT_OVERRIDE_GAP_REQUEST = {
49
51
  isOverrideGapRequestEnabledForGuests: false
50
52
  };
51
53
 
54
+ const DEFAULT_USER_OVERRIDE_REQUEST = {
55
+ isUserOverrideRequestEnabledForVendors: false,
56
+ isUserOverrideRequestEnabledForTenants: false,
57
+ isUserOverrideRequestEnabledForGuests: false
58
+ };
59
+
52
60
  const DEFAULT_RELEVANT_COMPLIANCE_DOCUMENTS = {
53
61
  isRelevantComplianceDocumentsEnabledForVendors: false,
54
62
  isRelevantComplianceDocumentsEnabledForTenants: false,
@@ -66,9 +66,6 @@ module.exports = {
66
66
  requireScope(entityIds, schedulerJobs.CERTIFICIAL_MONITORING);
67
67
  return runSchedulerJob({ jobType: schedulerJobs.CERTIFICIAL_MONITORING, entityIds });
68
68
  },
69
- runJobForWeeklyDigest: function(entityIds) {
70
- return runSchedulerJob({ jobType: schedulerJobs.WEEKLY_DIGEST, entityIds });
71
- },
72
69
  runAllJobsNew: function(entityIds) {
73
70
  return runSchedulerJob({ jobType: schedulerJobs.ALL, entityIds });
74
71
  }
@@ -6,6 +6,5 @@ module.exports = {
6
6
  EXPIRE_TIMED_OVERRIDES: 'EXPIRE_TIMED_OVERRIDES',
7
7
  CERTIFICIAL_ENROLLMENT: 'CERTIFICIAL_ENROLLMENT',
8
8
  CERTIFICIAL_MONITORING: 'CERTIFICIAL_MONITORING',
9
- WEEKLY_DIGEST: 'WEEKLY_DIGEST',
10
9
  ALL: 'ALL'
11
10
  };
@@ -1,9 +0,0 @@
1
- const COI_UPLOADER_TYPES = {
2
- PM: 'pmUploadedCOI',
3
- ICS: 'ICSUploadedCOI',
4
- AUDITOR: 'AuditorUploadedCOI',
5
- VENDOR: 'vendorUploadedCOI',
6
- BOT: 'botUploadedCOI'
7
- };
8
-
9
- module.exports = COI_UPLOADER_TYPES;
@@ -1,32 +0,0 @@
1
- const requests = require('../../../../common/requests/cookieAuth/requests');
2
- const { backendUrl } = require('../../../../env').getEnv();
3
-
4
- const Endpoints = {
5
- snapshot: `${backendUrl}/saas/integration-tests/weekly-digest/snapshot`,
6
- accountSnapshot: accountId => `${backendUrl}/saas/integration-tests/weekly-digest/account/${accountId}/snapshot`,
7
- run: accountId => `${backendUrl}/saas/integration-tests/weekly-digest/account/${accountId}/run`,
8
- reportLog: `${backendUrl}/saas/integration-tests/weekly-digest/report-log`
9
- };
10
-
11
- const takeAccountSnapshot = (accountId, context) => {
12
- return requests.postRequestHandler(Endpoints.accountSnapshot(accountId), null, context);
13
- };
14
-
15
- const takeAccountsSnapshot = (accountIds, context) => {
16
- return requests.postRequestHandler(Endpoints.snapshot, { accountIds }, context);
17
- };
18
-
19
- const runWeeklyDigest = (accountId, body, context) => {
20
- return requests.postRequestHandler(Endpoints.run(accountId), body, context);
21
- };
22
-
23
- const getWeeklyDigestReports = (accountId, weekStart, context) => {
24
- return requests.getRequestHandler(Endpoints.reportLog, { accountId, weekStart }, context);
25
- };
26
-
27
- module.exports = {
28
- takeAccountSnapshot,
29
- takeAccountsSnapshot,
30
- runWeeklyDigest,
31
- getWeeklyDigestReports
32
- };
@@ -1,69 +0,0 @@
1
- const httpResponseStatusCodes = require('../../../../common/httpResponseStatusCodes.json');
2
- const timeUtils = require('../../../../common/utils/timeUtils');
3
-
4
- const authService = require('../../auth/api/auth.service');
5
- const weeklyDigestApi = require('./weekly.digest.api');
6
- const { REPORT_STATUS } = require('../consts/weekly.digest.consts');
7
-
8
- const takeAccountSnapshot = async accountId => {
9
- const response = await weeklyDigestApi.takeAccountSnapshot(accountId, await authService.getIcsCookie());
10
-
11
- if (response.status !== httpResponseStatusCodes.OK) {
12
- throw new Error(`Account snapshot failed for account ${accountId}. Status code: ${response.status}`);
13
- }
14
-
15
- return response.data.snapshotId;
16
- };
17
-
18
- const takeAccountsSnapshot = async accountIds => {
19
- const response = await weeklyDigestApi.takeAccountsSnapshot(accountIds, await authService.getIcsCookie());
20
-
21
- if (response.status !== httpResponseStatusCodes.OK) {
22
- throw new Error(`Accounts snapshot failed for accounts ${accountIds}. Status code: ${response.status}`);
23
- }
24
-
25
- return response.data.snapshotId;
26
- };
27
-
28
- // Runs synchronously for next Monday's week, after clearing the account's report-log rows for that week.
29
- const runWeeklyDigest = async (accountId, { previousRunId, currentRunId }) => {
30
- const body = { beforeSnapshotId: previousRunId, afterSnapshotId: currentRunId };
31
- const response = await weeklyDigestApi.runWeeklyDigest(accountId, body, await authService.getIcsCookie());
32
-
33
- if (response.status !== httpResponseStatusCodes.OK) {
34
- throw new Error(`Weekly digest run failed for account ${accountId}. Status code: ${response.status}`);
35
- }
36
-
37
- return response.data;
38
- };
39
-
40
- const getWeeklyDigestReports = async (accountId, weekStart) => {
41
- const response = await weeklyDigestApi.getWeeklyDigestReports(accountId, weekStart, await authService.getIcsCookie());
42
-
43
- if (response.status !== httpResponseStatusCodes.OK) {
44
- throw new Error(`Weekly digest reports failed for account ${accountId}. Status code: ${response.status}`);
45
- }
46
-
47
- return response.data;
48
- };
49
-
50
- // The scheduler endpoint returns before the job runs, so a real-job run has to poll the report log.
51
- const waitForWeeklyDigestReport = async (accountId, weekStart, userId, { expectedStatus = REPORT_STATUS.SENT, retries = 10 } = {}) => {
52
- let report;
53
-
54
- while (report?.reportData.status !== expectedStatus && retries-- > 0) {
55
- await timeUtils.waitFor(3).seconds;
56
- const reports = await getWeeklyDigestReports(accountId, weekStart);
57
- report = reports.find(row => row.userId === userId);
58
- }
59
-
60
- return report;
61
- };
62
-
63
- module.exports = {
64
- takeAccountSnapshot,
65
- takeAccountsSnapshot,
66
- runWeeklyDigest,
67
- getWeeklyDigestReports,
68
- waitForWeeklyDigestReport
69
- };
@@ -1,21 +0,0 @@
1
- const REPORT_STATUS = {
2
- IN_PROGRESS: 'IN_PROGRESS',
3
- SENT: 'SENT',
4
- NO_VISIBLE_REQUESTS: 'NO_VISIBLE_REQUESTS'
5
- };
6
-
7
- const NEW_ISSUE_TYPE = {
8
- EXPIRED_LAST_WEEK: 'EXPIRED_LAST_WEEK',
9
- BECAME_NOT_COMPLIANT: 'BECAME_NOT_COMPLIANT',
10
- EXPIRING_THIS_WEEK: 'EXPIRING_THIS_WEEK',
11
- BECAME_NOT_RESPONSIVE: 'BECAME_NOT_RESPONSIVE'
12
- };
13
-
14
- const ACTIVITY_TYPE = {
15
- TIMED_OVERRIDE_ENDING: 'TIMED_OVERRIDE_ENDING',
16
- EXCEPTION_REQUEST: 'EXCEPTION_REQUEST',
17
- MENTION: 'MENTION',
18
- RELATED_DOC: 'RELATED_DOC'
19
- };
20
-
21
- module.exports = { REPORT_STATUS, NEW_ISSUE_TYPE, ACTIVITY_TYPE };
@@ -1,4 +0,0 @@
1
- const services = require('./api/weekly.digest.service');
2
- const consts = require('./consts/weekly.digest.consts');
3
-
4
- module.exports = { services, consts };