From ecec9ddaaa0d1c2dffa00cc137e63eba88633cc8 Mon Sep 17 00:00:00 2001 From: Kacper Magdziarz Date: Tue, 8 Jul 2025 07:39:07 +0200 Subject: [PATCH] [ACS-9736] Add deflating of audit values and intecepting them into audit record --- .../repo/audit/AuditComponentImpl.java | 44 +++++++------------ .../org/alfresco/repo/audit/AuditRecord.java | 14 ++++++ .../alfresco/repo/audit/AuditRecordUtils.java | 42 ++++++++++++++++++ 3 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 repository/src/main/java/org/alfresco/repo/audit/AuditRecordUtils.java diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java b/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java index 6af9af6475..121464bb43 100644 --- a/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java +++ b/repository/src/main/java/org/alfresco/repo/audit/AuditComponentImpl.java @@ -48,7 +48,6 @@ import org.alfresco.repo.audit.model.AuditModelRegistryImpl; import org.alfresco.repo.domain.audit.AuditDAO; import org.alfresco.repo.domain.propval.PropertyValueDAO; import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.RetryingTransactionHelper; @@ -73,8 +72,8 @@ public class AuditComponentImpl implements AuditComponent { private static final String INBOUND_LOGGER = "org.alfresco.repo.audit.inbound"; - private static Log logger = LogFactory.getLog(AuditComponentImpl.class); - private static Log loggerInbound = LogFactory.getLog(INBOUND_LOGGER); + private static final Log logger = LogFactory.getLog(AuditComponentImpl.class); + private static final Log loggerInbound = LogFactory.getLog(INBOUND_LOGGER); private AuditModelRegistryImpl auditModelRegistry; private PropertyValueDAO propertyValueDAO; @@ -221,7 +220,7 @@ public class AuditComponentImpl implements AuditComponent public int deleteAuditEntries(List auditEntryIds) { // Shortcut, if necessary - if (auditEntryIds.size() == 0) + if (auditEntryIds.isEmpty()) { return 0; } @@ -240,7 +239,7 @@ public class AuditComponentImpl implements AuditComponent { Long disabledPathsId = application.getDisabledPathsId(); Set disabledPaths = (Set) propertyValueDAO.getPropertyById(disabledPathsId); - return new HashSet(disabledPaths); + return new HashSet<>(disabledPaths); } catch (Throwable e) { @@ -315,7 +314,7 @@ public class AuditComponentImpl implements AuditComponent { PathMapper pathMapper = auditModelRegistry.getAuditPathMapper(); Set mappedPaths = pathMapper.getMappedPathsWithPartialMatch(path); - return loggerInbound.isDebugEnabled() || mappedPaths.size() > 0; + return loggerInbound.isDebugEnabled() || !mappedPaths.isEmpty(); } /** @@ -352,7 +351,7 @@ public class AuditComponentImpl implements AuditComponent // Check if there are any entries that match or supercede the given path String disablingPath = null; - ; + for (String disabledPath : disabledPaths) { if (path.startsWith(disabledPath)) @@ -579,7 +578,7 @@ public class AuditComponentImpl implements AuditComponent } // Build the key paths using the session root path - Map pathedValues = new HashMap(values.size() * 2); + Map pathedValues = new HashMap<>(values.size() * 2); for (Map.Entry entry : values.entrySet()) { String pathElement = entry.getKey(); @@ -602,13 +601,10 @@ public class AuditComponentImpl implements AuditComponent case TXN_NONE: case TXN_READ_ONLY: // New transaction - RetryingTransactionCallback> callback = new RetryingTransactionCallback>() { - public Map execute() throws Throwable - { - Map recordedAuditValues = recordAuditValuesImpl(mappedValues); - auditRecordReporter.reportAuditRecord(createAuditRecord(recordedAuditValues, true)); - return recordedAuditValues; - } + RetryingTransactionCallback> callback = () -> { + Map recordedAuditValues = recordAuditValuesImpl(mappedValues); + auditRecordReporter.reportAuditRecord(createAuditRecord(recordedAuditValues, true)); + return recordedAuditValues; }; RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper(); txnHelper.setForceWritable(true); @@ -628,7 +624,7 @@ public class AuditComponentImpl implements AuditComponent public Map recordAuditValuesImpl(Map mappedValues) { // Group the values by root path - Map> mappedValuesByRootKey = new HashMap>(); + Map> mappedValuesByRootKey = new HashMap<>(); for (Map.Entry entry : mappedValues.entrySet()) { String path = entry.getKey(); @@ -636,7 +632,7 @@ public class AuditComponentImpl implements AuditComponent Map rootKeyMappedValues = mappedValuesByRootKey.get(rootKey); if (rootKeyMappedValues == null) { - rootKeyMappedValues = new HashMap(7); + rootKeyMappedValues = new HashMap<>(7); mappedValuesByRootKey.put(rootKey, rootKeyMappedValues); } rootKeyMappedValues.put(path, entry.getValue()); @@ -704,7 +700,7 @@ public class AuditComponentImpl implements AuditComponent } // Check if there is anything to audit - if (values.size() == 0) + if (values.isEmpty()) { if (logger.isDebugEnabled()) { @@ -737,12 +733,7 @@ public class AuditComponentImpl implements AuditComponent Map auditData = generateData(generators); // Now extract values - Map extractedData = AuthenticationUtil.runAs(new RunAsWork>() { - public Map doWork() throws Exception - { - return extractData(application, values); - } - }, AuthenticationUtil.getSystemUserName()); + Map extractedData = AuthenticationUtil.runAs(() -> extractData(application, values), AuthenticationUtil.getSystemUserName()); // Combine extracted and generated values (extracted data takes precedence) auditData.putAll(extractedData); @@ -910,7 +901,7 @@ public class AuditComponentImpl implements AuditComponent */ private Map generateData(Map generators) { - Map newData = new HashMap(generators.size() + 5); + Map newData = new HashMap<>(generators.size() + 5); for (Map.Entry entry : generators.entrySet()) { String path = entry.getKey(); @@ -937,8 +928,7 @@ public class AuditComponentImpl implements AuditComponent private AuditRecord createAuditRecord(Map auditData, boolean inTransaction) { - AuditRecord.Builder builder = new AuditRecord.Builder(); - builder.setAuditData(auditData); + AuditRecord.Builder builder = AuditRecordUtils.generateAuditRecordBuilder(auditData); builder.setInTransaction(inTransaction); return builder.build(); } diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditRecord.java b/repository/src/main/java/org/alfresco/repo/audit/AuditRecord.java index 0982a9908b..fc4bb769b1 100644 --- a/repository/src/main/java/org/alfresco/repo/audit/AuditRecord.java +++ b/repository/src/main/java/org/alfresco/repo/audit/AuditRecord.java @@ -31,11 +31,13 @@ import java.util.Map; public class AuditRecord { private final boolean inTransaction; + private final String auditApplicationId; private final ZonedDateTime createdAt; private final Map auditData; public AuditRecord(Builder builder) { + this.auditApplicationId = builder.auditApplicationId; this.inTransaction = builder.inTransaction; this.auditData = builder.auditData; this.createdAt = ZonedDateTime.now(); @@ -46,6 +48,11 @@ public class AuditRecord return inTransaction; } + public String getAuditApplicationId() + { + return auditApplicationId; + } + public ZonedDateTime getCreatedAt() { return createdAt; @@ -63,9 +70,16 @@ public class AuditRecord public static class Builder { + private String auditApplicationId; private boolean inTransaction; private Map auditData; + public Builder setAuditApplicationId(String auditApplicationId) + { + this.auditApplicationId = auditApplicationId; + return this; + } + public Builder setInTransaction(boolean inTransaction) { this.inTransaction = inTransaction; diff --git a/repository/src/main/java/org/alfresco/repo/audit/AuditRecordUtils.java b/repository/src/main/java/org/alfresco/repo/audit/AuditRecordUtils.java new file mode 100644 index 0000000000..3dceefb202 --- /dev/null +++ b/repository/src/main/java/org/alfresco/repo/audit/AuditRecordUtils.java @@ -0,0 +1,42 @@ +package org.alfresco.repo.audit; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class AuditRecordUtils +{ + /** + * This method will generate {@link AuditRecord#builder()} from provided structured audit data. Provided data will be translated from `key - value` structure to json structure. Generated builder will be preloaded with {@link AuditRecord#auditApplicationId} and {@link AuditRecord#auditData} + * + * @param data + * represent `key - value` structured map that contains audit data. + * @return preloaded {@link AuditRecord#builder()}. + */ + @SuppressWarnings("unchecked") + public static AuditRecord.Builder generateAuditRecordBuilder(Map data) + { + var auditRecordBuilder = AuditRecord.builder(); + + var rootNode = new HashMap(); + data.forEach((k, v) -> { + var keys = k.split("/"); + auditRecordBuilder.setAuditApplicationId(keys[0]); + var current = rootNode; + for (int i = 1; i < keys.length - 1; i++) + { + if (!current.containsKey(keys[i]) || !(current.get(keys[i]) instanceof ObjectNode)) + { + current.put(keys[i], new HashMap()); + } + current = (HashMap) current.get(keys[i]); + } + current.put(keys[keys.length - 1], v.toString()); + }); + + auditRecordBuilder.setAuditData(rootNode); + return auditRecordBuilder; + } +}