This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-cpconverter.git


The following commit(s) were added to refs/heads/master by this push:
     new cb03166  SLING-8573 - ACLs are missing from the converted content 
packages for regular users and groups
cb03166 is described below

commit cb03166805d884549b27a02ab71e1b51eeaa4aef
Author: Simo Tripodi <[email protected]>
AuthorDate: Thu Jul 11 16:44:43 2019 +0200

    SLING-8573 - ACLs are missing from the converted content packages for
    regular users and groups
    
    only detected system users will be filtered in the repoinit, all other
    udetected users will be stored in the related _rep_policy.xml file
---
 .../handlers/RepPolicyEntryHandler.java            | 88 +++++++++++++++++-----
 .../cpconverter/vltpkg/VaultPackageAssembler.java  | 12 +--
 .../handlers/RepPolicyEntryHandlerTest.java        | 75 +++++++++++++++---
 3 files changed, 140 insertions(+), 35 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandler.java
 
b/src/main/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandler.java
index 3015622..79995f4 100644
--- 
a/src/main/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandler.java
+++ 
b/src/main/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandler.java
@@ -19,13 +19,25 @@ package org.apache.sling.feature.cpconverter.handlers;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 
 import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.nio.file.Paths;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Stack;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.vault.fs.io.Archive;
 import org.apache.jackrabbit.vault.fs.io.Archive.Entry;
 import 
org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
@@ -37,6 +49,8 @@ import org.xml.sax.SAXException;
 
 public final class RepPolicyEntryHandler extends AbstractRegexEntryHandler {
 
+    private final SAXTransformerFactory saxTransformerFactory = 
(SAXTransformerFactory) TransformerFactory.newInstance();
+
     public RepPolicyEntryHandler() {
         super("/jcr_root(.*/)_rep_policy.xml");
     }
@@ -57,15 +71,27 @@ public final class RepPolicyEntryHandler extends 
AbstractRegexEntryHandler {
                                             + "' but it does not, currently");
         }
 
-        RepPolicyParser systemUserParser = new RepPolicyParser(resourcePath, 
converter.getAclManager());
-        boolean accepted = false;
+        Properties format = new Properties();
+        format.put(OutputKeys.INDENT, "yes");
+        format.put(OutputKeys.ENCODING, "utf-8");
+
+        TransformerHandler handler = 
saxTransformerFactory.newTransformerHandler();
+        handler.getTransformer().setOutputProperties(format);
+        StringWriter stringWriter = new StringWriter();
+        handler.setResult(new StreamResult(stringWriter));
+
+        RepPolicyParser systemUserParser = new RepPolicyParser(resourcePath, 
converter.getAclManager(), handler);
+        boolean hasRejectedAcls;
 
         try (InputStream input = archive.openInputStream(entry)) {
-            accepted = systemUserParser.parse(input);
+            hasRejectedAcls = systemUserParser.parse(input);
         }
 
-        if (!accepted) {
-            converter.getMainPackageAssembler().addEntry(path, archive, entry);
+        if (hasRejectedAcls) {
+            try (Reader reader = new StringReader(stringWriter.toString());
+                    OutputStreamWriter writer = new 
OutputStreamWriter(converter.getMainPackageAssembler().createEntry(path))) {
+                IOUtils.copy(reader, writer);
+            }
         }
     }
 
@@ -83,8 +109,6 @@ public final class RepPolicyEntryHandler extends 
AbstractRegexEntryHandler {
 
         private static final String REP_PRIVILEGES = "rep:privileges";
 
-        private static final String[] RESTRICTIONS = new String[] { 
"rep:glob", "rep:ntNames", "rep:prefixes", "rep:itemNames" };
-
         private static final Map<String, String> operations = new HashMap<>();
 
         static {
@@ -92,6 +116,8 @@ public final class RepPolicyEntryHandler extends 
AbstractRegexEntryHandler {
             operations.put(REP_DENY_ACE, "deny");
         }
 
+        private static final String[] RESTRICTIONS = new String[] { 
"rep:glob", "rep:ntNames", "rep:prefixes", "rep:itemNames" };
+
         private static final Pattern typeIndicatorPattern = 
Pattern.compile("\\{[^\\}]+\\}\\[(.+)\\]");
 
         private final Stack<Acl> acls = new Stack<>();
@@ -100,14 +126,26 @@ public final class RepPolicyEntryHandler extends 
AbstractRegexEntryHandler {
 
         private final AclManager aclManager;
 
+        private final TransformerHandler handler;
+
         private boolean onRepAclNode = false;
 
-        private boolean accepted = true;
+        // ACL processing result
+        private boolean hasRejectedNodes = false;
 
-        public RepPolicyParser(String path, AclManager aclManager) {
+        // just internal pointer for every iteration
+        private boolean processCurrentAcl = false;
+
+        public RepPolicyParser(String path, AclManager aclManager, 
TransformerHandler handler) {
             super(REP_ACL);
             this.path = path;
             this.aclManager = aclManager;
+            this.handler = handler;
+        }
+
+        @Override
+        public void startDocument() throws SAXException {
+            handler.startDocument();
         }
 
         @Override
@@ -124,41 +162,55 @@ public final class RepPolicyEntryHandler extends 
AbstractRegexEntryHandler {
 
                     Acl acl = new Acl(operation, privileges, Paths.get(path));
 
-                    if (aclManager.addAcl(principalName, acl)) {
+                    processCurrentAcl = aclManager.addAcl(principalName, acl);
+                    if (processCurrentAcl) {
                         acls.add(acl);
                     } else {
-                        accepted = false;
-                        onRepAclNode = false;
+                        hasRejectedNodes = true;
                     }
                 } else if (REP_RESTRICTIONS.equals(primaryType) && 
!acls.isEmpty()) {
-                    for (String restriction : RESTRICTIONS) {
-                        String path = 
extractValue(attributes.getValue(restriction));
+                    if (processCurrentAcl) {
+                        for (String restriction : RESTRICTIONS) {
+                            String path = 
extractValue(attributes.getValue(restriction));
 
-                        if (path != null && !path.isEmpty()) {
-                            acls.peek().addRestriction(restriction + ',' + 
path);
+                            if (path != null && !path.isEmpty()) {
+                                acls.peek().addRestriction(restriction + ',' + 
path);
+                            }
                         }
                     }
                 }
             } else {
                 super.startElement(uri, localName, qName, attributes);
             }
+
+            if (!onRepAclNode || !processCurrentAcl) {
+                handler.startElement(uri, localName, qName, attributes);
+            }
         }
 
         @Override
         public void endElement(String uri, String localName, String qName) 
throws SAXException {
-            if (onRepAclNode && !acls.isEmpty()) {
+            if (onRepAclNode && processCurrentAcl && !acls.isEmpty()) {
                 acls.pop();
+            } else {
+                processCurrentAcl = false;
+                handler.endElement(uri, localName, qName);
             }
         }
 
         @Override
+        public void endDocument() throws SAXException {
+            handler.endDocument();
+        }
+
+        @Override
         protected void onJcrRootElement(String uri, String localName, String 
qName, Attributes attributes) {
             onRepAclNode = true;
         }
 
         @Override
         protected Boolean getParsingResult() {
-            return accepted;
+            return hasRejectedNodes;
         }
 
         private static String extractValue(String expression) {
diff --git 
a/src/main/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssembler.java
 
b/src/main/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssembler.java
index 51d2107..7ec08de 100644
--- 
a/src/main/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssembler.java
+++ 
b/src/main/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssembler.java
@@ -155,15 +155,17 @@ public class VaultPackageAssembler implements 
EntryHandler {
     }
 
     public void addEntry(String path, InputStream input) throws IOException {
-        File target = new File(storingDirectory, path);
-
-        target.getParentFile().mkdirs();
-
-        try (OutputStream output = new FileOutputStream(target)) {
+        try (OutputStream output = createEntry(path)) {
             IOUtils.copy(input, output);
         }
     }
 
+    public OutputStream createEntry(String path) throws IOException {
+        File target = new File(storingDirectory, path);
+        target.getParentFile().mkdirs();
+        return new FileOutputStream(target);
+    }
+
     public File getEntry(String path) {
         if (!path.startsWith(ROOT_DIR)) {
             path = ROOT_DIR + path;
diff --git 
a/src/test/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandlerTest.java
 
b/src/test/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandlerTest.java
index 7bd8fc6..5545bb4 100644
--- 
a/src/test/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandlerTest.java
+++ 
b/src/test/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandlerTest.java
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.StringReader;
 import java.nio.file.Path;
@@ -89,7 +90,7 @@ public final class RepPolicyEntryHandlerTest {
                                                           
"acs-commons-package-replication-status-event-service",
                                                           
"acs-commons-ensure-service-user-service",
                                                           
"acs-commons-automatic-package-replicator-service",
-                                                          
"acs-commons-on-deploy-scripts-service");
+                                                          
"acs-commons-on-deploy-scripts-service").getRepoinitExtension();
         assertNotNull(repoinitExtension);
         assertEquals(ExtensionType.TEXT, repoinitExtension.getType());
 
@@ -130,10 +131,12 @@ public final class RepPolicyEntryHandlerTest {
 
     @Test
     public void notDeclaredSystemUsersWillNotHaveAclSettings() throws 
Exception {
-        Extension repoinitExtension = 
parseAndSetRepoinit("acs-commons-package-replication-status-event-service",
-                                                          
"acs-commons-ensure-service-user-service",
-                                                          
"acs-commons-automatic-package-replicator-service",
-                                                          
"acs-commons-on-deploy-scripts-service");
+        ParseResult result = 
parseAndSetRepoinit("acs-commons-package-replication-status-event-service",
+                                                 
"acs-commons-ensure-service-user-service",
+                                                 
"acs-commons-automatic-package-replicator-service",
+                                                 
"acs-commons-on-deploy-scripts-service");
+        Extension repoinitExtension = result.getRepoinitExtension();
+
         assertNotNull(repoinitExtension);
         assertEquals(ExtensionType.TEXT, repoinitExtension.getType());
 
@@ -162,11 +165,22 @@ public final class RepPolicyEntryHandlerTest {
         RepoInitParser repoInitParser = new RepoInitParserService();
         List<Operation> operations = repoInitParser.parse(new 
StringReader(actual));
         assertFalse(operations.isEmpty());
+
+        // acs-commons-ensure-oak-index-service and 
acs-commons-dispatcher-flush-service not recognized as system users
+        expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?><jcr:root 
xmlns:jcr=\"http://www.jcp.org/jcr/1.0\"; xmlns:rep=\"internal\" 
jcr:primaryType=\"rep:ACL\">\n" + 
+                "<allow0 jcr:primaryType=\"rep:GrantACE\" 
rep:principalName=\"acs-commons-ensure-oak-index-service\" 
rep:privileges=\"{Name}[jcr:read,rep:write,rep:indexDefinitionManagement]\">\n" 
+ 
+                "<rep:restrictions jcr:primaryType=\"rep:Restrictions\" 
rep:glob=\"{Name}[*/oak:index/*]\"/>\n" + 
+                "</allow0>\n" + 
+                "<allow1 jcr:primaryType=\"rep:GrantACE\" 
rep:principalName=\"acs-commons-dispatcher-flush-service\" 
rep:privileges=\"{Name}[jcr:read,crx:replicate,jcr:removeNode]\"/>\n" + 
+                "</jcr:root>\n";
+        actual = result.getExcludedAcls();
+        assertEquals(expected, actual);
     }
 
     @Test
     public void systemUserAclSetNotForUserPath() throws Exception {
-        Extension repoinitExtension = parseAndSetRepoinit(new 
SystemUser("acs-commons-package-replication-status-event-service", 
Paths.get("/this/is/a/completely/different/path")));
+        ParseResult result = parseAndSetRepoinit(new 
SystemUser("acs-commons-package-replication-status-event-service", 
Paths.get("/this/is/a/completely/different/path")));
+        Extension repoinitExtension = result.getRepoinitExtension();
         assertNotNull(repoinitExtension);
         assertEquals(ExtensionType.TEXT, repoinitExtension.getType());
 
@@ -182,15 +196,28 @@ public final class RepPolicyEntryHandlerTest {
         RepoInitParser repoInitParser = new RepoInitParserService();
         List<Operation> operations = repoInitParser.parse(new 
StringReader(actual));
         assertFalse(operations.isEmpty());
+
+        // acs-commons-package-replication-status-event-service only 
recognised as system user - ACLs in allow2
+        expected = "<?xml version=\"1.0\" encoding=\"utf-8\"?><jcr:root 
xmlns:jcr=\"http://www.jcp.org/jcr/1.0\"; xmlns:rep=\"internal\" 
jcr:primaryType=\"rep:ACL\">\n" + 
+                "<allow0 jcr:primaryType=\"rep:GrantACE\" 
rep:principalName=\"acs-commons-ensure-oak-index-service\" 
rep:privileges=\"{Name}[jcr:read,rep:write,rep:indexDefinitionManagement]\">\n" 
+ 
+                "<rep:restrictions jcr:primaryType=\"rep:Restrictions\" 
rep:glob=\"{Name}[*/oak:index/*]\"/>\n" + 
+                "</allow0>\n" + 
+                "<allow1 jcr:primaryType=\"rep:GrantACE\" 
rep:principalName=\"acs-commons-dispatcher-flush-service\" 
rep:privileges=\"{Name}[jcr:read,crx:replicate,jcr:removeNode]\"/>\n" + 
+                "<allow3 jcr:primaryType=\"rep:GrantACE\" 
rep:principalName=\"acs-commons-ensure-service-user-service\" 
rep:privileges=\"{Name}[jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl]\"/>\n"
 + 
+                "<allow4 jcr:primaryType=\"rep:GrantACE\" 
rep:principalName=\"acs-commons-automatic-package-replicator-service\" 
rep:privileges=\"{Name}[jcr:read]\"/>\n" + 
+                "<allow5 jcr:primaryType=\"rep:GrantACE\" 
rep:principalName=\"acs-commons-on-deploy-scripts-service\" 
rep:privileges=\"{Name}[jcr:read]\"/>\n" + 
+                "</jcr:root>\n";
+        actual = result.getExcludedAcls();
+        assertEquals(expected, actual);
     }
 
     @Test
     public void parseEmptyAcl() throws Exception {
-        Extension repoinitExtension = parseAndSetRepoinit(new String[] {});
+        Extension repoinitExtension = parseAndSetRepoinit(new String[] 
{}).getRepoinitExtension();
         assertNull(repoinitExtension);
     }
 
-    private Extension parseAndSetRepoinit(String...systemUsersNames) throws 
Exception {
+    private ParseResult parseAndSetRepoinit(String...systemUsersNames) throws 
Exception {
         Path alwaysTheSamePath = Paths.get("/asd/public");
 
         SystemUser[] systemUsers = new SystemUser[systemUsersNames.length];
@@ -201,11 +228,13 @@ public final class RepPolicyEntryHandlerTest {
         return parseAndSetRepoinit(systemUsers);
     }
 
-    private Extension parseAndSetRepoinit(SystemUser...systemUsers) throws 
Exception {
+    private ParseResult parseAndSetRepoinit(SystemUser...systemUsers) throws 
Exception {
         String path = "/jcr_root/asd/public/_rep_policy.xml";
         Archive archive = mock(Archive.class);
         Entry entry = mock(Entry.class);
         VaultPackageAssembler packageAssembler = 
mock(VaultPackageAssembler.class);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        when(packageAssembler.createEntry(anyString())).thenReturn(baos);
 
         
when(archive.openInputStream(entry)).thenReturn(getClass().getResourceAsStream(path.substring(1)));
 
@@ -215,8 +244,7 @@ public final class RepPolicyEntryHandlerTest {
         ContentPackage2FeatureModelConverter converter = 
spy(ContentPackage2FeatureModelConverter.class);
         when(converter.getFeaturesManager()).thenReturn(featuresManager);
         when(converter.getAclManager()).thenReturn(new DefaultAclManager());
-
-        handler.handle(path, archive, entry, converter);
+        when(converter.getMainPackageAssembler()).thenReturn(packageAssembler);
 
         if (systemUsers != null) {
             for (SystemUser systemUser : systemUsers) {
@@ -224,10 +252,33 @@ public final class RepPolicyEntryHandlerTest {
             }
         }
 
+        handler.handle(path, archive, entry, converter);
+
         when(packageAssembler.getEntry(anyString())).thenReturn(new 
File("itdoesnotexist"));
 
         
converter.getAclManager().addRepoinitExtension(Arrays.asList(packageAssembler), 
feature);
-        return 
feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT);
+        return new 
ParseResult(feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT),
 new String(baos.toByteArray()));
+    }
+
+    private static final class ParseResult {
+
+        private final Extension repoinitExtension;
+
+        private final String excludedAcls;
+
+        public ParseResult(Extension repoinitExtension, String excludedAcls) {
+            this.repoinitExtension = repoinitExtension;
+            this.excludedAcls = excludedAcls;
+        }
+
+        public Extension getRepoinitExtension() {
+            return repoinitExtension;
+        }
+
+        public String getExcludedAcls() {
+            return excludedAcls;
+        }
+
     }
 
 }

Reply via email to