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
commit 8e6b9097328d9fe5d9c62beae0460e02a8d4269c Author: stripodi <[email protected]> AuthorDate: Wed Apr 24 15:51:45 2019 +0200 SLING-8371 - [cp2fm] map rep:ACL JCR nodes to repoinit Feature extension initial implementation old System User refactored in order to use the new ACL Manager --- .../ContentPackage2FeatureModelConverter.java | 31 ++-- .../apache/sling/feature/cpconverter/acl/Acl.java | 59 ++++++++ .../sling/feature/cpconverter/acl/AclManager.java | 84 +++++++++++ .../feature/cpconverter/acl/package-info.java | 21 +++ .../handlers/AbstractJcrNodeParser.java | 6 +- .../handlers/RepPolicyEntryHandler.java | 143 ++++++++++++++++++ .../handlers/SystemUsersEntryHandler.java | 9 +- .../handlers/XmlConfigurationEntryHandler.java | 13 +- ...ache.sling.feature.cpconverter.spi.EntryHandler | 1 + .../handlers/RepPolicyEntryHandlerTest.java | 161 +++++++++++++++++++++ .../handlers/SystemUsersEntryHandlerTest.java | 5 +- .../vltpkg/VaultPackageAssemblerTest.java | 1 - .../handlers/jcr_root/asd/public/_rep_policy.xml | 38 ++++- 13 files changed, 532 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java b/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java index 9cf9b1e..378ac20 100644 --- a/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java +++ b/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java @@ -41,6 +41,7 @@ import org.apache.sling.feature.Extension; import org.apache.sling.feature.ExtensionType; import org.apache.sling.feature.Extensions; import org.apache.sling.feature.Feature; +import org.apache.sling.feature.cpconverter.acl.AclManager; import org.apache.sling.feature.cpconverter.spi.BundlesDeployer; import org.apache.sling.feature.cpconverter.spi.EntryHandler; import org.apache.sling.feature.cpconverter.vltpkg.VaultPackageAssembler; @@ -66,8 +67,6 @@ public class ContentPackage2FeatureModelConverter { private static final String DEFEAULT_VERSION = "0.0.0"; - private static final String REPOINIT = "repoinit"; - private final Logger logger = LoggerFactory.getLogger(getClass()); private final PackageManager packageManager = new PackageManagerImpl(); @@ -76,6 +75,8 @@ public class ContentPackage2FeatureModelConverter { private final Map<String, Feature> runModes = new HashMap<>(); + private final AclManager aclManager = new AclManager(); + private final RegexBasedResourceFilter filter = new RegexBasedResourceFilter(); private BundlesDeployer artifactDeployer; @@ -95,7 +96,7 @@ public class ContentPackage2FeatureModelConverter { private VaultPackageAssembler mainPackageAssembler = null; private String id; - + private String idOverride; public ContentPackage2FeatureModelConverter setStrictValidation(boolean strictValidation) { @@ -152,12 +153,15 @@ public class ContentPackage2FeatureModelConverter { this.id = id; return this; } - + public ContentPackage2FeatureModelConverter setIdOverride(String id) { this.idOverride = id; return this; } + public AclManager getAclManager() { + return aclManager; + } public Feature getRunMode(String runMode) { if (getTargetFeature() == null) { @@ -305,7 +309,9 @@ public class ContentPackage2FeatureModelConverter { // finally serialize the Feature Model(s) file(s) - seralize(targetFeature, null); + aclManager.addRepoinitExtension(getTargetFeature()); + + seralize(getTargetFeature(), null); if (!runModes.isEmpty()) { for (java.util.Map.Entry<String, Feature> runmodeEntry : runModes.entrySet()) { @@ -315,21 +321,6 @@ public class ContentPackage2FeatureModelConverter { } } - public void addRepoinitStatement(String format, Object...args) { - Extension repoInitExtension = getTargetFeature().getExtensions().getByName(REPOINIT); - if (repoInitExtension == null) { - repoInitExtension = new Extension(ExtensionType.TEXT, REPOINIT, true); - getTargetFeature().getExtensions().add(repoInitExtension); - } - - String statement = String.format(format, args); - if (repoInitExtension.getText() == null) { - repoInitExtension.setText(statement); - } else { - repoInitExtension.setText(repoInitExtension.getText() + '\n' + statement); - } - } - public void addConfiguration(String runMode, String pid, Dictionary<String, Object> configurationProperties) { if (!mergeConfigurations) { checkConfigurationExist(getTargetFeature(), pid); diff --git a/src/main/java/org/apache/sling/feature/cpconverter/acl/Acl.java b/src/main/java/org/apache/sling/feature/cpconverter/acl/Acl.java new file mode 100644 index 0000000..0f483ff --- /dev/null +++ b/src/main/java/org/apache/sling/feature/cpconverter/acl/Acl.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.sling.feature.cpconverter.acl; + +import java.util.Formatter; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Simple single ACL statement representation. + */ +public final class Acl { + + private final String operation; + + private final String privileges; + + private final String path; + + private final List<String> restrictions = new LinkedList<>(); + + protected Acl(String operation, String privileges, String path) { + this.operation = operation; + this.privileges = privileges; + this.path = path; + } + + public void addRestriction(String restriction) { + if (restriction != null && !restriction.isEmpty()) { + restrictions.add(restriction); + } + } + + protected void addAclStatement(Formatter formatter) { + formatter.format("%s %s on %s", operation, privileges, path); + + if (!restrictions.isEmpty()) { + formatter.format(" restriction(%s)", restrictions.stream().collect(Collectors.joining(","))); + } + + formatter.format("%n"); + } + +} diff --git a/src/main/java/org/apache/sling/feature/cpconverter/acl/AclManager.java b/src/main/java/org/apache/sling/feature/cpconverter/acl/AclManager.java new file mode 100644 index 0000000..54564c9 --- /dev/null +++ b/src/main/java/org/apache/sling/feature/cpconverter/acl/AclManager.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.sling.feature.cpconverter.acl; + +import java.util.Formatter; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.sling.feature.Extension; +import org.apache.sling.feature.ExtensionType; +import org.apache.sling.feature.Feature; + +/** + * The Manager able to collect and build System Users and related ACL policies. + */ +public final class AclManager { + + private final Set<String> systemUsers = new LinkedHashSet<>(); + + private final Map<String, List<Acl>> acls = new HashMap<>(); + + public boolean addSystemUser(String systemUser) { + if (systemUser != null && !systemUser.isEmpty()) { + return systemUsers.add(systemUser); + } + return false; + } + + public Acl addAcl(String systemUser, String operation, String privileges, String path) { + Acl acl = new Acl(operation, privileges, path); + acls.computeIfAbsent(systemUser, k -> new LinkedList<>()).add(acl); + return acl; + } + + public void addRepoinitExtension(Feature feature) { + if (systemUsers.isEmpty()) { + return; + } + + Extension repoInitExtension = new Extension(ExtensionType.TEXT, Extension.EXTENSION_NAME_REPOINIT, true); + + Formatter formatter = new Formatter(); + + for (String systemUser : systemUsers) { + formatter.format("create service user %s%n", systemUser); + + List<Acl> authorizations = acls.get(systemUser); + if (authorizations != null && !authorizations.isEmpty()) { + formatter.format("set ACL for %s%n", systemUser); + + for (Acl authorization : authorizations) { + authorization.addAclStatement(formatter); + } + + formatter.format("end%n"); + } + } + + String text = formatter.toString(); + formatter.close(); + repoInitExtension.setText(text); + + feature.getExtensions().add(repoInitExtension); + } + +} diff --git a/src/main/java/org/apache/sling/feature/cpconverter/acl/package-info.java b/src/main/java/org/apache/sling/feature/cpconverter/acl/package-info.java new file mode 100644 index 0000000..0ef4e34 --- /dev/null +++ b/src/main/java/org/apache/sling/feature/cpconverter/acl/package-info.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * Small utility set to handle System Users and related ACL policies. + */ +package org.apache.sling.feature.cpconverter.acl; diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractJcrNodeParser.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractJcrNodeParser.java index 12e3089..e346ff3 100644 --- a/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractJcrNodeParser.java +++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractJcrNodeParser.java @@ -27,7 +27,7 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; -abstract class AbstractJcrNodeParser extends DefaultHandler { +abstract class AbstractJcrNodeParser<O> extends DefaultHandler { private static final String JCR_ROOT = "jcr:root"; @@ -45,7 +45,7 @@ abstract class AbstractJcrNodeParser extends DefaultHandler { } @Override - public final void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { String primaryType = attributes.getValue(JCR_PRIMARYTYPE); if (JCR_ROOT.equals(qName) && this.primaryType.equals(primaryType)) { @@ -55,4 +55,6 @@ abstract class AbstractJcrNodeParser extends DefaultHandler { protected abstract void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) throws SAXException; + protected abstract O getParsingResult(); + } 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 new file mode 100644 index 0000000..6dad716 --- /dev/null +++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandler.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.sling.feature.cpconverter.handlers; + +import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; +import java.util.regex.Matcher; + +import org.apache.jackrabbit.vault.fs.io.Archive; +import org.apache.jackrabbit.vault.fs.io.Archive.Entry; +import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter; +import org.apache.sling.feature.cpconverter.acl.Acl; +import org.apache.sling.feature.cpconverter.acl.AclManager; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +public final class RepPolicyEntryHandler extends AbstractRegexEntryHandler { + + public RepPolicyEntryHandler() { + super("(jcr_root)?(/.+)/_rep_policy.xml"); + } + + @Override + public void handle(String path, Archive archive, Entry entry, ContentPackage2FeatureModelConverter converter) + throws Exception { + Matcher matcher = getPattern().matcher(path); + // we are pretty sure it matches, here + if (matcher.matches()) { + path = matcher.group(2); + } else { + throw new IllegalStateException("Something went terribly wrong: pattern '" + + getPattern().pattern() + + "' should have matched already with path '" + + path + + "' but it does not, currently"); + } + + RepPolicyParser systemUserParser = new RepPolicyParser(path, converter.getAclManager()); + try (InputStream input = archive.openInputStream(entry)) { + systemUserParser.parse(input); + } + } + + private static final class RepPolicyParser extends AbstractJcrNodeParser<Void> { + + private static final String REP_ACL = "rep:ACL"; + + private static final String REP_GRANT_ACE = "rep:GrantACE"; + + private static final String REP_DENY_ACE = "rep:DenyACE"; + + private static final String REP_RESTRICTIONS = "rep:Restrictions"; + + private static final String REP_PRINCIPAL_NAME = "rep:principalName"; + + private static final String REP_PRIVILEGES = "rep:privileges"; + + private static final String REP_GLOB = "rep:glob"; + + private static final Map<String, String> operations = new HashMap<>(); + + static { + operations.put(REP_GRANT_ACE, "allow"); + operations.put(REP_DENY_ACE, "deny"); + } + + private final Stack<Acl> acls = new Stack<>(); + + private final String path; + + private final AclManager aclManager; + + private boolean onRepAclNode = false; + + public RepPolicyParser(String path, AclManager aclManager) { + super(REP_ACL); + this.path = path; + this.aclManager = aclManager; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { + if (onRepAclNode) { + String primaryType = attributes.getValue(JCR_PRIMARYTYPE); + if (REP_GRANT_ACE.equals(primaryType) || REP_DENY_ACE.equals(primaryType)) { + String principalName = attributes.getValue(REP_PRINCIPAL_NAME); + + String operation = operations.get(primaryType); + + String privileges = attributes.getValue(REP_PRIVILEGES); + int beginIndex = privileges.indexOf('[') + 1; + int endIndex = privileges.indexOf(']'); + privileges = privileges.substring(beginIndex, endIndex); + + acls.add(aclManager.addAcl(principalName, operation, privileges, path)); + } else if (REP_RESTRICTIONS.equals(primaryType) && !acls.isEmpty()) { + String restriction = attributes.getValue(REP_GLOB); + acls.peek().addRestriction(restriction); + } + } else { + super.startElement(uri, localName, qName, attributes); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (onRepAclNode && !acls.isEmpty()) { + acls.pop(); + } + } + + @Override + protected void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) { + onRepAclNode = true; + } + + @Override + protected Void getParsingResult() { + return null; + } + + } + +} diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java index b451e8b..7fe64aa 100644 --- a/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java +++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java @@ -38,7 +38,7 @@ public final class SystemUsersEntryHandler extends AbstractRegexEntryHandler { } } - private static final class SystemUserParser extends AbstractJcrNodeParser { + private static final class SystemUserParser extends AbstractJcrNodeParser<Void> { private final static String REP_SYSTEM_USER = "rep:SystemUser"; @@ -55,10 +55,15 @@ public final class SystemUsersEntryHandler extends AbstractRegexEntryHandler { protected void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) { String authorizableId = attributes.getValue(REP_AUTHORIZABLE_ID); if (authorizableId != null && !authorizableId.isEmpty()) { - converter.addRepoinitStatement("create service user %s", authorizableId); + converter.getAclManager().addSystemUser(authorizableId); } } + @Override + protected Void getParsingResult() { + return null; + } + } } diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java index 5188b24..d1b1919 100644 --- a/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java +++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/XmlConfigurationEntryHandler.java @@ -34,19 +34,15 @@ public final class XmlConfigurationEntryHandler extends AbstractConfigurationEnt protected Dictionary<String, Object> parseConfiguration(String name, InputStream input) throws Exception { JcrConfigurationHandler configurationHandler = new JcrConfigurationHandler(); configurationHandler.parse(input); - return configurationHandler.getConfiguration(); + return configurationHandler.getParsingResult(); } - private static final class JcrConfigurationHandler extends AbstractJcrNodeParser { + private static final class JcrConfigurationHandler extends AbstractJcrNodeParser<Dictionary<String, Object>> { private static final String SLING_OSGICONFIG = "sling:OsgiConfig"; private final Dictionary<String, Object> configuration = new Hashtable<>(); - public Dictionary<String, Object> getConfiguration() { - return configuration; - } - public JcrConfigurationHandler() { super(SLING_OSGICONFIG); } @@ -75,6 +71,11 @@ public final class XmlConfigurationEntryHandler extends AbstractConfigurationEnt } } + @Override + protected Dictionary<String, Object> getParsingResult() { + return configuration; + } + } } diff --git a/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler b/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler index b4b9ec0..53e84b4 100644 --- a/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler +++ b/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.spi.EntryHandler @@ -3,5 +3,6 @@ org.apache.sling.feature.cpconverter.handlers.ConfigurationEntryHandler org.apache.sling.feature.cpconverter.handlers.ContentPackageEntryHandler org.apache.sling.feature.cpconverter.handlers.JsonConfigurationEntryHandler org.apache.sling.feature.cpconverter.handlers.PropertiesConfigurationEntryHandler +org.apache.sling.feature.cpconverter.handlers.RepPolicyEntryHandler org.apache.sling.feature.cpconverter.handlers.SystemUsersEntryHandler org.apache.sling.feature.cpconverter.handlers.XmlConfigurationEntryHandler 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 new file mode 100644 index 0000000..ecf5419 --- /dev/null +++ b/src/test/java/org/apache/sling/feature/cpconverter/handlers/RepPolicyEntryHandlerTest.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.sling.feature.cpconverter.handlers; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import org.apache.jackrabbit.vault.fs.io.Archive; +import org.apache.jackrabbit.vault.fs.io.Archive.Entry; +import org.apache.sling.feature.ArtifactId; +import org.apache.sling.feature.Extension; +import org.apache.sling.feature.ExtensionType; +import org.apache.sling.feature.Feature; +import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public final class RepPolicyEntryHandlerTest { + + private RepPolicyEntryHandler handler; + + @Before + public void setUp() { + handler = new RepPolicyEntryHandler(); + } + + @After + public void tearDown() { + handler = null; + } + + @Test + public void doesNotMatch() { + assertFalse(handler.matches("/this/is/a/path/not/pointing/to/a/valid/policy.xml")); + } + + @Test + public void matches() { + assertTrue(handler.matches("/home/users/system/asd-share-commons/asd-index-definition-reader/_rep_policy.xml")); + assertTrue(handler.matches("jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/_rep_policy.xml")); + } + + @Test + public void parseAcl() throws Exception { + Extension repoinitExtension = parseAndSetRepoinit("acs-commons-ensure-oak-index-service", + "acs-commons-dispatcher-flush-service", + "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"); + assertNotNull(repoinitExtension); + assertEquals(ExtensionType.TEXT, repoinitExtension.getType()); + + String expected = "create service user acs-commons-ensure-oak-index-service\n" + + "set ACL for acs-commons-ensure-oak-index-service\n" + + "allow jcr:read,rep:write,rep:indexDefinitionManagement on /asd/public restriction(*/oak:index/*)\n" + + "end\n" + + "create service user acs-commons-dispatcher-flush-service\n" + + "set ACL for acs-commons-dispatcher-flush-service\n" + + "allow jcr:read,crx:replicate,jcr:removeNode on /asd/public\n" + + "end\n" + + "create service user acs-commons-package-replication-status-event-service\n" + + "set ACL for acs-commons-package-replication-status-event-service\n" + + "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on /asd/public\n" + + "end\n" + + "create service user acs-commons-ensure-service-user-service\n" + + "set ACL for acs-commons-ensure-service-user-service\n" + + "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on /asd/public\n" + + "end\n" + + "create service user acs-commons-automatic-package-replicator-service\n" + + "set ACL for acs-commons-automatic-package-replicator-service\n" + + "allow jcr:read on /asd/public\n" + + "end\n" + + "create service user acs-commons-on-deploy-scripts-service\n" + + "set ACL for acs-commons-on-deploy-scripts-service\n" + + "allow jcr:read on /asd/public\n" + + "end\n"; + String actual = repoinitExtension.getText(); + assertEquals(expected, actual); + } + + @Test + public void notDeclaredSystemUsersWontHaveAclSettings() 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"); + assertNotNull(repoinitExtension); + assertEquals(ExtensionType.TEXT, repoinitExtension.getType()); + + String expected = "create service user acs-commons-package-replication-status-event-service\n" + + "set ACL for acs-commons-package-replication-status-event-service\n" + + "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on /asd/public\n" + + "end\n" + + "create service user acs-commons-ensure-service-user-service\n" + + "set ACL for acs-commons-ensure-service-user-service\n" + + "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on /asd/public\n" + + "end\n" + + "create service user acs-commons-automatic-package-replicator-service\n" + + "set ACL for acs-commons-automatic-package-replicator-service\n" + + "allow jcr:read on /asd/public\n" + + "end\n" + + "create service user acs-commons-on-deploy-scripts-service\n" + + "set ACL for acs-commons-on-deploy-scripts-service\n" + + "allow jcr:read on /asd/public\n" + + "end\n"; + String actual = repoinitExtension.getText(); + assertEquals(expected, actual); + } + + @Test + public void parseEmptyAcl() throws Exception { + Extension repoinitExtension = parseAndSetRepoinit(); + assertNull(repoinitExtension); + } + + private Extension parseAndSetRepoinit(String...systemUsers) throws Exception { + String path = "jcr_root/asd/public/_rep_policy.xml"; + Archive archive = mock(Archive.class); + Entry entry = mock(Entry.class); + + when(archive.openInputStream(entry)).thenReturn(getClass().getResourceAsStream(path)); + + Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null)); + ContentPackage2FeatureModelConverter converter = spy(ContentPackage2FeatureModelConverter.class); + when(converter.getTargetFeature()).thenReturn(feature); + + handler.handle(path, archive, entry, converter); + + if (systemUsers != null) { + for (String systemUser : systemUsers) { + converter.getAclManager().addSystemUser(systemUser); + } + } + + converter.getAclManager().addRepoinitExtension(feature); + return feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT); + } + +} diff --git a/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java index 5126e0f..70270d0 100644 --- a/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java +++ b/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java @@ -67,7 +67,7 @@ public class SystemUsersEntryHandlerTest { assertNotNull(repoinitExtension); assertEquals(ExtensionType.TEXT, repoinitExtension.getType()); assertTrue(repoinitExtension.isRequired()); - assertEquals("create service user asd-share-commons-asd-index-definition-reader-service", repoinitExtension.getText()); + assertEquals("create service user asd-share-commons-asd-index-definition-reader-service\n", repoinitExtension.getText()); } @Test @@ -89,7 +89,8 @@ public class SystemUsersEntryHandlerTest { systemUsersEntryHandler.handle(path, archive, entry, converter); - return feature.getExtensions().getByName("repoinit"); + converter.getAclManager().addRepoinitExtension(feature); + return feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT); } } diff --git a/src/test/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssemblerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssemblerTest.java index d2aa3cc..011a516 100644 --- a/src/test/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssemblerTest.java +++ b/src/test/java/org/apache/sling/feature/cpconverter/vltpkg/VaultPackageAssemblerTest.java @@ -81,7 +81,6 @@ public class VaultPackageAssemblerTest { return Arrays.asList(new Object[][] { { "jcr_root/.content.xml", assembler }, { "jcr_root/asd/.content.xml", assembler }, - { "jcr_root/asd/public/_rep_policy.xml", assembler }, { "jcr_root/asd/public/license.txt", assembler } }); } diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/asd/public/_rep_policy.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/asd/public/_rep_policy.xml index 2b1119a..8b639bb 100644 --- a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/asd/public/_rep_policy.xml +++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/asd/public/_rep_policy.xml @@ -15,10 +15,34 @@ License for the specific language governing permissions and limitations under the License. --> -<jcr:root xmlns:crx="http://www.day.com/crx/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal" - jcr:primaryType="rep:ACL"> - <allow - jcr:primaryType="rep:GrantACE" - rep:principalName="everyone" - rep:privileges="{Name}[jcr:read]"/> -</jcr:root> \ No newline at end of file +<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal" + jcr:primaryType="rep:ACL"> + <allow0 + jcr:primaryType="rep:GrantACE" + rep:principalName="acs-commons-ensure-oak-index-service" + rep:privileges="{Name}[jcr:read,rep:write,rep:indexDefinitionManagement]"> + <rep:restrictions + jcr:primaryType="rep:Restrictions" + rep:glob="*/oak:index/*"/> + </allow0> + <allow1 + jcr:primaryType="rep:GrantACE" + rep:principalName="acs-commons-dispatcher-flush-service" + rep:privileges="{Name}[jcr:read,crx:replicate,jcr:removeNode]"/> + <allow2 + jcr:primaryType="rep:GrantACE" + rep:principalName="acs-commons-package-replication-status-event-service" + rep:privileges="{Name}[jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl]"/> + <allow3 + jcr:primaryType="rep:GrantACE" + rep:principalName="acs-commons-ensure-service-user-service" + rep:privileges="{Name}[jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl]"/> + <allow4 + jcr:primaryType="rep:GrantACE" + rep:principalName="acs-commons-automatic-package-replicator-service" + rep:privileges="{Name}[jcr:read]"/> + <allow5 + jcr:primaryType="rep:GrantACE" + rep:principalName="acs-commons-on-deploy-scripts-service" + rep:privileges="{Name}[jcr:read]"/> +</jcr:root>
