Skip to content

Commit

Permalink
Enforce replication metadata on segment pages by default
Browse files Browse the repository at this point in the history
This closes #15
  • Loading branch information
kwin committed May 13, 2024
1 parent 82d4537 commit 25b2356
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 6 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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 `<regex>[<primary-type or sling:resourceType>]`. 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 `<regex>[<primary-type or sling:resourceType>]`. 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 `<regex>[<primary-type or sling:resourceType>]`. 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
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="cq:Page">
<jcr:content
cq:lastModified="{Date}2024-05-13T13:00:57.908+02:00"
cq:lastModifiedBy="admin"
jcr:primaryType="cq:PageContent"
jcr:title="new segment"
sling:resourceType="cq/contexthub/components/segment-page"
segmentBoost="{Long}0"
segmentName="new-segment">
<traits
jcr:primaryType="nt:unstructured"
sling:resourceType="cq/contexthub/components/traits/logic/operator-and">
<andpar
jcr:primaryType="nt:unstructured"
sling:resourceType="foundation/components/parsys"/>
</traits>
</jcr:content>
</jcr:root>
10 changes: 10 additions & 0 deletions src/it/project1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
<validRoots>/,/libs,/apps,/etc,/var,/tmp,/conf,/content,/content/campaigns/,/content/cq:tags/,/content/dam,/content/experience-fragments/,/content/projects/,/content/screens/,/etc/packages</validRoots>
</options>
</jackrabbit-filter>
<jackrabbit-nodetypes>
<options>
<cnds>tccl:aem.cnd</cnds>
</options>
</jackrabbit-nodetypes>
</validatorsSettings>
</configuration>
<dependencies>
Expand All @@ -57,6 +62,11 @@
<artifactId>aem-replication-metadata-validator</artifactId>
<version>@project.version@</version>
</dependency>
<dependency>
<groupId>biz.netcentric.aem</groupId>
<artifactId>aem-nodetypes</artifactId>
<version>2023.10.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
Expand Down
5 changes: 4 additions & 1 deletion src/it/project1/verify.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -128,7 +129,7 @@ private Optional<NodeMetadata> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Pattern, String> DEFAULT_INCLUDED_NODE_PATH_PATTERNS_AND_TYPES = createDefaultIncludeMap();
private static final String RESOURCE_TYPE_SEGMENT_PAGE = "cq/contexthub/components/segment-page";

private static Map<Pattern, String> createDefaultIncludeMap() {
Map<Pattern, String> map = new HashMap<>();
Expand All @@ -52,8 +53,10 @@ private static Map<Pattern, String> 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);
}

Expand Down

0 comments on commit 25b2356

Please sign in to comment.