diff --git a/README.md b/README.md index aa1c423..30df009 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,10 @@ This artifact provides a validator implementation for the [FileVault Validation The following repository locations are considered by default which must contain replication metadata indicating that the node is *published and not modified*: -1. [Editable templates][page-templates]' structure nodes (as found by `com.day.cq.wcm.core.impl.reference.PageTemplateReferenceProvider`, only outside `/libs` and `/apps`) -1. [Editable templates][page-templates]' policy nodes (as found by `com.day.cq.wcm.core.impl.reference.ContentPolicyReferenceProvider`), this includes both *policy mappings* (with resource type=`wcm/core/components/policies/mappings`) as well as *actual policies* (with resource type=`wcm/core/components/policy/policy`, only outside `/libs`). The latter are also found outside actual editable templates. +1. [Editable templates][page-templates]' structure nodes (as found by `com.day.cq.wcm.core.impl.reference.PageTemplateReferenceProvider`) +1. [Editable templates][page-templates]' policy nodes (as found by `com.day.cq.wcm.core.impl.reference.ContentPolicyReferenceProvider`), this includes both *policy mappings* (with resource type=`wcm/core/components/policies/mappings`) as well as *actual policies* (with resource type=`wcm/core/components/policy/policy`). The latter are also found outside actual editable templates. 1. Generic [Sling Context-Aware configurations][ca-configs] (as found by [`com.adobe.cq.wcm.core.components.internal.services.CaConfigReferenceProvider`](https://github.com/adobe/aem-core-wcm-components/blob/main/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/services/CaConfigReferenceProvider.java)) +1. [Segment Pages](segment-pages) (as found by `com.day.cq.personalization.impl.TargetedComponentReferenceProvider`) Those locations are given through the default value for `includedNodePathPatternsAndTypes`. This default set can be overridden through the settings outlined below to check for other nodes. @@ -37,7 +38,7 @@ The following options are supported apart from the default settings mentioned in Option | Mandatory | Description | Default Value | Since Version --- | --- | --- | --- | --- -`includedNodePathPatternsAndTypes` | no | Comma-separated list of items, where each item has the format `[]`. The given regular expression must match a given node path (fully) for the node to be checked for valid metadata. In addition the node must have the given primary type (or `sling:resourceType` in case the primary type is `nt:unstructured`). | `.*/settings/wcm/templates/[^/]*/structure[cq:Page], .*/settings/wcm/templates/[^/]*/policies[cq:Page], .*/settings/wcm/policies/.*[wcm/core/components/policy/policy], /(apps\|conf)/.*/(sling:configs\|settings/cloudconfigs)/.*[cq:Page])` | 1.0.0 +`includedNodePathPatternsAndTypes` | no | Comma-separated list of items, where each item has the format `[]`. The given regular expression must match a given node path (fully) for the node to be checked for valid metadata. In addition the node must have the given primary type (or `sling:resourceType` in case the primary type is `nt:unstructured` or `cq:PageContent`). | `.*/settings/wcm/templates/[^/]*/structure[cq:Page], .*/settings/wcm/templates/[^/]*/policies[cq:Page], .*/settings/wcm/policies/.*[wcm/core/components/policy/policy], /(apps\|conf)/.*/(sling:configs\|settings/cloudconfigs)/.*[cq:Page]), /(apps|conf)/.*/jcr:content[cq/contexthub/components/segment-page]` | 1.0.0 `excludedNodePathPatternsAndTypes` | no | Comma-separated list of items, where each item has the format `[]`. The given regular expression must match a given node path (fully) for the node to be checked for missing metadata. In addition the node must have the given primary type (or `sling:resourceType` in case the primary type is `nt:unstructured`). | `.*/settings/wcm/templates/[^/]*/initial[cq:Page]` | 1.3.0 `strictLastModificationDateCheck` | no | `true` means that nodes without a last modification property should always lead to validation errors. Otherwise they are handled in a lenient fashion like AEM behaves (i.e. assumption is that the modification date is -1 which is older than all replication dates). | `false` | 1.0.0 `agentNames` | no | Comma-separated list of replication/distribution agent names whose replication metadata should be checked. Only relevant for AEMaaCS where it should be set to `publish,preview` in case the [Preview tier][preview-tier] is used next to the regular publish service. | `publish` | 1.1.0 @@ -114,3 +115,4 @@ However this approach only works if the according packages are replicated from t [package-replication-status-updater]: https://adobe-consulting-services.github.io/acs-aem-commons/features/package-replication-status-updater/index.html [docview-xml]: https://jackrabbit.apache.org/filevault/docview.html [preview-tier]: https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/sites/authoring/fundamentals/previewing-content.html?lang=en +[segment-pages]: https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/sites/authoring/personalization/contexthub-segmentation diff --git a/src/it/project1/content-package/src/main/jcr_root/conf/example/my-segment/.content.xml b/src/it/project1/content-package/src/main/jcr_root/conf/example/my-segment/.content.xml new file mode 100644 index 0000000..c5af05a --- /dev/null +++ b/src/it/project1/content-package/src/main/jcr_root/conf/example/my-segment/.content.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/src/it/project1/pom.xml b/src/it/project1/pom.xml index 58748cd..dfc6c61 100644 --- a/src/it/project1/pom.xml +++ b/src/it/project1/pom.xml @@ -49,6 +49,11 @@ /,/libs,/apps,/etc,/var,/tmp,/conf,/content,/content/campaigns/,/content/cq:tags/,/content/dam,/content/experience-fragments/,/content/projects/,/content/screens/,/etc/packages + + + tccl:aem.cnd + + @@ -57,6 +62,11 @@ aem-replication-metadata-validator @project.version@ + + biz.netcentric.aem + aem-nodetypes + 2023.10.0 + diff --git a/src/it/project1/verify.groovy b/src/it/project1/verify.groovy index 867daa1..f8640e2 100644 --- a/src/it/project1/verify.groovy +++ b/src/it/project1/verify.groovy @@ -10,4 +10,7 @@ assert buildLog.contains("[ERROR] ValidationViolation: \"netcentric-aem-replicat assert buildLog.contains("[ERROR] ValidationViolation: \"netcentric-aem-replication-metadata: The replication date 2021-12-31T23:00:00Z for agent publish is older than the last modification date 2022-01-01T23:00:00Z\", filePath=jcr_root${File.separator}conf${File.separator}example${File.separator}settings${File.separator}wcm${File.separator}templates${File.separator}template1${File.separator}structure${File.separator}.content.xml, nodePath=/conf/example/settings/wcm/templates/template1/structure/jcr:content,") : 'template structure violation not found' assert buildLog.contains("[ERROR] ValidationViolation: \"netcentric-aem-replication-metadata: Last replication action not allowed for this path but is ACTIVATE\", filePath=jcr_root${File.separator}conf${File.separator}example${File.separator}settings${File.separator}wcm${File.separator}templates${File.separator}template1${File.separator}initial${File.separator}.content.xml, nodePath=/conf/example/settings/wcm/templates/template1/initial/jcr:content, line=12, column=19") : 'initial violation not found' assert buildLog.contains("[ERROR] ValidationViolation: \"netcentric-aem-replication-metadata: Last replication date not allowed for this path but is 2021-12-31T23:00:00Z\", filePath=jcr_root${File.separator}conf${File.separator}example${File.separator}settings${File.separator}wcm${File.separator}templates${File.separator}template1${File.separator}initial${File.separator}.content.xml, nodePath=/conf/example/settings/wcm/templates/template1/initial/jcr:content, line=12, column=19") : 'initial violation not found' -assert buildLog.contains('[ERROR] Failed to execute goal org.apache.jackrabbit:filevault-package-maven-plugin:1.3.0:validate-package (default-validate-package) on project content-package: Found 4 violation(s) (with severity=ERROR). Check above errors for details -> [Help 1]') : 'Incorrect number of validation issues found' +assert buildLog.contains("[ERROR] ValidationViolation: \"netcentric-aem-replication-metadata: No replication action set for agent publish: Replication property {http://www.day.com/jcr/cq/1.0}lastReplicationAction not found\", filePath=jcr_root${File.separator}conf${File.separator}example${File.separator}my-segment${File.separator}.content.xml, nodePath=/conf/example/my-segment/jcr:content, line=19, column=19") : 'violation for segment page not found' +assert buildLog.contains("[ERROR] ValidationViolation: \"netcentric-aem-replication-metadata: No replication date set for agent publish: Replication properties {http://www.day.com/jcr/cq/1.0}lastReplicated or {http://www.day.com/jcr/cq/1.0}lastPublished not found\", filePath=jcr_root${File.separator}conf${File.separator}example${File.separator}my-segment${File.separator}.content.xml, nodePath=/conf/example/my-segment/jcr:content, line=19, column=19") : 'violation for segment page not found' + +assert buildLog.contains('[ERROR] Failed to execute goal org.apache.jackrabbit:filevault-package-maven-plugin:1.3.0:validate-package (default-validate-package) on project content-package: Found 6 violation(s) (with severity=ERROR). Check above errors for details -> [Help 1]') : 'Incorrect number of validation issues found' diff --git a/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java b/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java index 4283bc6..848c97b 100644 --- a/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java +++ b/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidator.java @@ -52,6 +52,7 @@ public class AemReplicationMetadataValidator implements DocumentViewXmlValidator static final ValueFactory VALUE_FACTORY = ValueFactoryImpl.getInstance(); static final String CQ_NAMESPACE_URI = "http://www.day.com/jcr/cq/1.0"; // no constant defined in https://developer.adobe.com/experience-manager/reference-materials/6-5/javadoc/constant-values.html + private static final String NT_CQ_PAGE_CONTENT = "cq:PageContent"; private static final Name NAME_JCR_CONTENT = org.apache.jackrabbit.spi.commons.name.NameConstants.JCR_CONTENT; private static final Name NAME_SLING_RESOURCETYPE = NAME_FACTORY.create(JcrResourceConstants.SLING_NAMESPACE_URI, SlingConstants.PROPERTY_RESOURCE_TYPE); @@ -128,7 +129,7 @@ private Optional getNodeMetadata(@NotNull String nodePath, @NotNul private static boolean isRelevantNodeType(DocViewNode2 node, String type) { boolean isNodeRelevant = node.getPrimaryType().equals(Optional.of(type)); // if node type == nt:unstructured, evaluate sling:resourceType instead - if (!isNodeRelevant && (node.getPrimaryType().equals(Optional.of(JcrConstants.NT_UNSTRUCTURED)))) { + if (!isNodeRelevant && (node.getPrimaryType().equals(Optional.of(JcrConstants.NT_UNSTRUCTURED)) || node.getPrimaryType().equals(Optional.of(NT_CQ_PAGE_CONTENT)))) { isNodeRelevant = node.getPropertyValue(NAME_SLING_RESOURCETYPE).equals(Optional.of(type)); } return isNodeRelevant; diff --git a/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidatorFactory.java b/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidatorFactory.java index 1f6215e..117de19 100644 --- a/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidatorFactory.java +++ b/src/main/java/biz/netcentric/filevault/validator/AemReplicationMetadataValidatorFactory.java @@ -43,6 +43,7 @@ public class AemReplicationMetadataValidatorFactory implements ValidatorFactory private static final String OPTION_AGENT_NAMES = "agentNames"; private static final @NotNull Set<@NotNull String> DEFAULT_AGENT_NAMES = Collections.singleton(ReplicationMetadata.DEFAULT_AGENT_NAME); private static final @NotNull Map DEFAULT_INCLUDED_NODE_PATH_PATTERNS_AND_TYPES = createDefaultIncludeMap(); + private static final String RESOURCE_TYPE_SEGMENT_PAGE = "cq/contexthub/components/segment-page"; private static Map createDefaultIncludeMap() { Map map = new HashMap<>(); @@ -52,8 +53,10 @@ private static Map createDefaultIncludeMap() { map.put(Pattern.compile(".*/settings/wcm/templates/[^/]*/policies"), NameConstants.NT_PAGE); // mapped content policies (as found by com.day.cq.wcm.core.impl.reference.ContentPolicyReferenceProvider) map.put(Pattern.compile(".*/settings/wcm/policies/.*"), RESOURCE_TYPE_CONTENT_POLICY); - // and regular context-aware configuration (as found by https://github.com/adobe/aem-core-wcm-components/blob/main/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/services/CaConfigReferenceProvider.java) + // regular context-aware configuration (as found by https://github.com/adobe/aem-core-wcm-components/blob/main/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/services/CaConfigReferenceProvider.java) map.put(Pattern.compile("/(apps|conf)/.*/(sling:configs|settings/cloudconfigs)/.*"), NameConstants.NT_PAGE); + // segment pages (as found by com.day.cq.personalization.impl.TargetedComponentReferenceProvider) + map.put(Pattern.compile("/(apps|conf)/.*/jcr:content"), RESOURCE_TYPE_SEGMENT_PAGE); return Collections.unmodifiableMap(map); }