-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BDI/BGE: Update FLS to check only populated fields for DI & target objects #4155
Changes from 8 commits
0bbec29
74ea7de
eefb9c7
88e7121
c9e0ae3
5e6c546
280831c
955dd72
e0c0021
271efbc
cd1348b
80d28e7
6faa986
b9d0732
eef472b
2b6048f
ab143c8
019123b
35312f8
66b6569
b3e05db
7d5d2a1
15fd82e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,10 +78,14 @@ global with sharing class BDI_DataImportService { | |
* @return DataImportBatch__c | ||
*/ | ||
private static DataImportBatch__c loadBatch(Id batchId) { | ||
|
||
List<DataImportBatch__c> dataImportBatches = BDI_DataImportBatch_SEL.selectByIds(new Set<Id>{ batchId }); | ||
if (dataImportBatches.size() == 1) { | ||
return dataImportBatches[0]; | ||
DataImportBatch__c currentBatch = dataImportBatches[0]; | ||
if (!String.isBlank(currentBatch.Active_Fields__c)) { | ||
relevantDataImportFields = BGE_BatchGiftEntry_UTIL.getDataImportFields(batchId, false); | ||
batchFromBGE = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Want to avoid references to "BGE" if we can describe this property more generically ... "batchDefinesActiveFieldList" or somethign |
||
} | ||
return currentBatch; | ||
} else { | ||
throw(new BDIException(String.format(Label.bdiInvalidBatchId, new List<String>{ batchId }))); | ||
} | ||
|
@@ -489,12 +493,26 @@ global with sharing class BDI_DataImportService { | |
this.listDI = dataImports; | ||
this.diSettings = dataImportSettings; | ||
|
||
// list of populated data import fields | ||
Set<String> populatedDataImportFieldsSet = new Set<String>(); | ||
|
||
// first set a clean state for each DI | ||
for (DataImport__c dataImport : dataImports) { | ||
dataImport.Status__c = null; | ||
dataImport.ImportedDate__c = null; | ||
dataImport.ApexJobId__c = null; | ||
dataImport.FailureInformation__c = null; | ||
|
||
// collect populated DI fields to use for later mapping | ||
if (batchFromBGE != true) { | ||
Map<String, Object> populatedFieldsMap = dataImport.getPopulatedFieldsAsMap(); | ||
List<String> populatedFields = new List<String>(populatedFieldsMap.keySet()); | ||
populatedDataImportFieldsSet.addAll(populatedFields); | ||
} | ||
} | ||
|
||
if (batchFromBGE != true && populatedDataImportFieldsSet != null && populatedDataImportFieldsSet.size() > 0) { | ||
relevantDataImportFields = new List<String>(populatedDataImportFieldsSet); | ||
} | ||
|
||
// do any performance optimizations to avoid unnecessary code | ||
|
@@ -674,6 +692,28 @@ global with sharing class BDI_DataImportService { | |
} | ||
} | ||
|
||
/******************************************************************************************************* | ||
* @description flag to let us know if we came from BGE | ||
*/ | ||
global static Boolean batchFromBGE { get; set; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. avoid global! |
||
|
||
/******************************************************************************************************* | ||
* @description list of the fields in the Data Import object that we care about for FLS checks because | ||
* they are present in the Batch we are processing | ||
* This list gets set in the loadBatch method. | ||
* If no batch is loaded, we use the full list of all DI fields listStrDataImportFields | ||
*/ | ||
global static List<String> relevantDataImportFields { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. avoid global! |
||
get { | ||
if (relevantDataImportFields == null || relevantDataImportFields.isEmpty()) { | ||
return listStrDataImportFields; | ||
} else { | ||
return relevantDataImportFields; | ||
} | ||
} | ||
set; | ||
} | ||
|
||
/******************************************************************************************************* | ||
* @description list of all the fields in the Data Import object | ||
*/ | ||
|
@@ -940,7 +980,7 @@ global with sharing class BDI_DataImportService { | |
} | ||
|
||
// get our mapping of household custom fields | ||
Map<String, String> mapDIFieldToHHField = mapFieldsForDIObject('Household', 'Account', listStrDataImportFields); | ||
Map<String, String> mapDIFieldToHHField = mapFieldsForDIObject('Household', 'Account', relevantDataImportFields); | ||
|
||
// bail out if no custom fields | ||
if (mapDIFieldToHHField.size() == 0) { | ||
|
@@ -1491,7 +1531,7 @@ global with sharing class BDI_DataImportService { | |
get { | ||
if (mapDIFieldToA1Field == null) { | ||
mapDIFieldToA1Field = BDI_DataImportService.mapFieldsForDIObject( | ||
'Account1', 'Account', BDI_DataImportService.listStrDataImportFields | ||
'Account1', 'Account', BDI_DataImportService.relevantDataImportFields | ||
); | ||
} | ||
return mapDIFieldToA1Field; | ||
|
@@ -1507,7 +1547,7 @@ global with sharing class BDI_DataImportService { | |
if (mapDIFieldToA2Field == null) { | ||
mapDIFieldToA2Field = | ||
BDI_DataImportService.mapFieldsForDIObject( | ||
'Account2', 'Account', BDI_DataImportService.listStrDataImportFields | ||
'Account2', 'Account', BDI_DataImportService.relevantDataImportFields | ||
); | ||
} | ||
return mapDIFieldToA2Field; | ||
|
@@ -1563,7 +1603,8 @@ global with sharing class BDI_DataImportService { | |
} | ||
|
||
Map<String, String> mapDIFieldToAddrField = | ||
mapFieldsForDIObject('Address', UTIL_Namespace.StrTokenNSPrefix('Address__c'), listStrDataImportFields); | ||
mapFieldsForDIObject('Address', UTIL_Namespace.StrTokenNSPrefix('Address__c'), relevantDataImportFields); | ||
|
||
List<Address__c> addressesToInsert = new List<Address__c>(); | ||
List<DataImport__c> dataImportsToInsert = new List<DataImport__c>(); | ||
Map<String, Address__c> mapHHAddrKeyToAddrNew = new Map<String, Address__c>(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,108 @@ | |
*/ | ||
public with sharing class BGE_BatchGiftEntry_UTIL { | ||
|
||
/******************************************************************************************************* | ||
* @description returns a list of DataImport__c fields the Batch Gift Entry UI needs in SOQL | ||
* @param batchId the batch for which to get all fields for soql | ||
* @return List<String> list of DataImport__c field api names | ||
*/ | ||
public static List<String> getDataImportFields(Id batchId) { | ||
return getDataImportFields(batchId, true); | ||
} | ||
|
||
/******************************************************************************************************* | ||
* @description returns a list of DataImport__c fields the Batch Gift Entry UI needs in SOQL | ||
* @param batchId the batch for which to get all fields for soql | ||
* @param includeRelationshipFields whether to include relationship fields in the returned list | ||
* @return List<String> list of DataImport__c field api names | ||
*/ | ||
public static List<String> getDataImportFields(Id batchId, Boolean includeRelationshipFields) { | ||
|
||
List<String> fields = getCoreDataImportFields(includeRelationshipFields); | ||
fields.addAll(getActiveFieldNamesFromBatch(batchId)); | ||
|
||
return fields; | ||
} | ||
|
||
/******************************************************************************************************* | ||
* @description Returns the subset of DataImport__c fields that are part of every batch | ||
* @param includeRelationshipFields whether to include relationship fields in the returned list | ||
* @return list of DataImport__c field api names | ||
*/ | ||
private static List<String> getCoreDataImportFields(Boolean includeRelationshipFields) { | ||
List<String> fields = new List<String> { | ||
'Id', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any reason that Donation_Amount__c, Donation_Date__c, and NPSP_Data_Import_Batch__c aren't included in this list? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, these get added in by the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nm let's leave this alone |
||
'Account1Imported__c', | ||
'Contact1Imported__c', | ||
'Donation_Donor__c', | ||
'DonationImported__c', | ||
'DonationImportStatus__c', | ||
'FailureInformation__c', | ||
'NPSP_Data_Import_Batch__c', | ||
'PaymentImported__c', | ||
'PaymentImportStatus__c', | ||
'Status__c' | ||
}; | ||
|
||
if (includeRelationshipFields) { | ||
fields.addAll(new List<String> { | ||
'Account1Imported__r.Name', | ||
'Contact1Imported__r.Name', | ||
'DonationImported__r.Name', | ||
'PaymentImported__r.Name' | ||
}); | ||
} | ||
|
||
// Maybe create new method in UTIL_Namespace for lists | ||
List<String> namespacedFields = new List<String>(); | ||
for(String fieldName : fields) { | ||
namespacedFields.add(UTIL_Namespace.StrAllNSPrefix(fieldName)); | ||
} | ||
|
||
return namespacedFields; | ||
} | ||
|
||
/******************************************************************************************************* | ||
* @description parses Active_Fields__c for the list of user-defined fields included in the batch config | ||
* @param batchId: ID of the NPSP_Data_Import_Batch__c | ||
* @return list of field api names | ||
*/ | ||
public static List<String> getActiveFieldNamesFromBatch(Id batchId) { | ||
DataImportBatch__c batch = [SELECT Active_Fields__c FROM DataImportBatch__c WHERE Id = :batchId]; | ||
String activeFieldsJSON = batch.Active_Fields__c; | ||
List<String> activeFieldNames = new List<String>(); | ||
|
||
if (activeFieldsJSON != null) { | ||
List<BGE_ConfigurationWizard_CTRL.BGEField> activeFields = | ||
(List<BGE_ConfigurationWizard_CTRL.BGEField>)JSON.deserialize( | ||
activeFieldsJSON, | ||
List<BGE_ConfigurationWizard_CTRL.BGEField>.class | ||
); | ||
for (BGE_ConfigurationWizard_CTRL.BGEField field : activeFields) { | ||
activeFieldNames.add(field.name); | ||
if (field.type == 'reference') { | ||
DescribeFieldResult lookupDFR = UTIL_Describe.getFieldDescribe( | ||
UTIL_Namespace.StrTokenNSPrefix('DataImport__c'), | ||
field.name.toLowerCase() | ||
); | ||
String referencedObjectName = lookupDFR.getReferenceTo()[0].getDescribe().name; | ||
activeFieldNames.add(field.name.substringBefore('__c') + '__r.' + UTIL_Describe.getNameField(referencedObjectName)); | ||
} | ||
} | ||
} | ||
|
||
return activeFieldNames; | ||
} | ||
|
||
/******************************************************************************************************* | ||
* @description checks for read, create, and edit FLS for a given field | ||
* @param dfr DescribeFieldResult of the field to check | ||
* @return Boolean | ||
*/ | ||
public static Boolean canUpdateField(DescribeFieldResult dfr) { | ||
return dfr.isCreateable() && dfr.isUpdateable(); | ||
} | ||
|
||
/******************************************************************************************************* | ||
* @description Returns the relevant Batch fields for soql | ||
* @return list of field API names | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was the thing that made me the most uncomfortable about the original PR, but I am thinking we may be able to avoid it - applications calling BDI (like BGE) should ideally not be defining BDI behaviors, else we could build up all these conditionals and exceptions built in for each application that's calling into it. HOWEVER, I think we may be able to avoid this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ptewson-sfdo - Would moving this logic (along with other the field collection/map building) from the BGE util to the BDI_DataImportService class make sense? The one thing that immediately sticks out to me is that the
getActiveFieldNamesFromBatch
method fromBGE_BatchGiftEntry_UTIL
relies on theBGE_ConfigurationWizard_CTRL.BGEField
class. If the above is acceptable, would movingBGEField
into its own file make sense so we don't rely on the config wizard controller in BDI here as well?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We believe we can pull the call to BGE_BatchGiftEntry_UTIL.getDataImportFields(batchId, false) entirely - these fields would only be used for FLS when the help text maps to a target object field and then the check would be on the target field. None of these fields have default mappings or map logically to target fields and would not be checked anyway, and we can remove an unneeded dependency on BGE by pulling this out.