Newer Version Available
Advanced Policy Migration Example
| Available in: Salesforce Classic and Lightning Experience |
| Available in: Enterprise, Unlimited, and
Developer Editions Requires Salesforce Shield or Salesforce Event Monitoring add-on subscriptions. |
The sample legacy policy in this topic is similar to the legacy Lead Data Export policy but with two key differences. Rather than monitor only leads, this policy monitors several different object types. Also, rather than hard-code an export limit of 2,000 records, this policy defines different limits for different object types.
- Object_Type__c (Picklist)—The object type
- Limit_Value__c (Number(18,0))—The maximum number of records of this object type that a user is allowed to export
The legacy policy queries this custom metadata type to dynamically determine the export limit value for each object type.
1global class DataExportPolicyCondition implements TxnSecurity.PolicyCondition {
2
3 private Final Integer DEFAULT_LIMIT = 2000;
4
5 public boolean evaluate(TxnSecurity.Event e){
6 Integer numberOfRecords = Integer.valueOf(e.data.get('NumberOfRecords'));
7 String entityName = e.data.get('EntityName');
8
9 Integer limitValue = getLimitValue(entityName);
10
11 if (numberOfRecords > limitValue) {
12 return true;
13 }
14 return false;
15 }
16
17 /**
18 * Get the export limit for the given object type. If no such limit exists,
19 * or an exception occurs while trying to look up the limit, the default limit
20 * of 2000 records is returned.
21 **/
22 private Integer getLimitValue(String entityName) {
23
24 List<Transaction_Security_Limit__mdt> limits = new List<Transaction_Security_Limit__mdt>();
25
26 try {
27 limits = [SELECT Limit_Value__c FROM Transaction_Security_Limit__mdt WHERE Object_Type__c = :entityName];
28 } catch (Exception ex) {
29 // unable to determine the limit, log and return the default
30 System.debug('Error getting limit value\n: ' + ex.getMessage());
31 return DEFAULT_LIMIT;
32 }
33
34 if (limits.size() == 0) {
35 // no limit found, return the default
36 return DEFAULT_LIMIT;
37 }
38
39 return (Integer)(limits[0].Limit_Value__c);
40 }
41}In the enhanced policy, we can reuse most of the logic that queries the TransactionSecurityLimit__mdt custom metadata type. The main difference is the code for getting the name of the entities for which we want to query the export limit. In the legacy policy, we use the EntityName key value of the data Map. Its equivalent in the enhanced framework is QueriedEntities. But remember that the QueriedEntities field can contain more than one entity name, because the enhanced framework supports exports on all standard and custom objects. So we take the comma-separated list of queried entities and split it up into a List of entity names.
1global class DynamicExportEventCondition implements TxnSecurity.EventCondition {
2
3 private Final Integer DEFAULT_LIMIT = 2000;
4
5 public boolean evaluate(SObject event) {
6 switch on event{
7 when ApiEvent apiEvent {
8 return evaluate(apiEvent.QueriedEntities, apiEvent.RowsProcessed);
9 }
10 when ReportEvent reportEvent {
11 return evaluate(reportEvent.QueriedEntities, reportEvent.RowsProcessed);
12 }
13 when ListViewEvent listViewEvent {
14 return evaluate(listViewEvent.QueriedEntities, listViewEvent.RowsProcessed);
15 }
16 when null {
17 return false;
18 }
19 when else {
20 return false;
21 }
22 }
23 }
24
25 private boolean evaluate(String queriedEntities, Decimal rowsProcessed){
26 List<String> queriedEntitiesList = queriedEntities.split(',');
27 // for all of the entities being exported, check their limit
28 for (String queriedEntity : queriedEntitiesList) {
29 Integer limitValue = getLimitValue(queriedEntity);
30 if (rowsProcessed > limitValue) {
31 // if any of our entities are having their limit violated
32 // then return true to trigger the policy
33 return true;
34 }
35 }
36 return false;
37 }
38
39 /**
40 * Get the export limit for the given object type. If no such limit exists,
41 * or an exception occurs while trying to look up the limit, the default limit
42 * of 2000 records is returned.
43 **/
44 private Integer getLimitValue(String entityName) {
45
46 List<Transaction_Security_Limit__mdt> limits = new List<Transaction_Security_Limit__mdt>();
47
48 try {
49 limits = [SELECT Limit_Value__c FROM Transaction_Security_Limit__mdt WHERE Object_Type__c = :entityName];
50 } catch (Exception ex) {
51 // unable to determine the limit, return the default
52 System.debug('Error getting limit value\n: ' + ex.getMessage());
53 return DEFAULT_LIMIT;
54 }
55
56 if (limits.size() == 0) {
57 // no limit found, return the default
58 return DEFAULT_LIMIT;
59 }
60
61 return (Integer)(limits[0].Limit_Value__c);
62 }
63}