You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by pa...@apache.org on 2021/01/14 17:29:02 UTC
[sling-org-apache-sling-feature-cpconverter] branch master updated:
SLING-9953: ACEs on/below user nodes are ignored upon conversion (#51)
This is an automated email from the ASF dual-hosted git repository.
pauls 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 ea7983d SLING-9953: ACEs on/below user nodes are ignored upon conversion (#51)
ea7983d is described below
commit ea7983dd26b561b4fddb92b449610d8538d073ba
Author: Karl Pauls <pa...@apache.org>
AuthorDate: Thu Jan 14 18:28:52 2021 +0100
SLING-9953: ACEs on/below user nodes are ignored upon conversion (#51)
* SLING-9953: ACEs on/below user nodes are ignored upon conversion
Co-authored-by: angela <an...@adobe.com>
---
.../{SystemUser.java => AbstractUser.java} | 9 +-
.../cpconverter/accesscontrol/AclManager.java | 6 +-
.../accesscontrol/DefaultAclManager.java | 153 ++++++++++-------
.../accesscontrol/{AclManager.java => Group.java} | 31 ++--
.../cpconverter/accesscontrol/MixinParser.java | 9 +-
.../accesscontrol/PrimaryTypeParser.java | 11 +-
.../cpconverter/accesscontrol/SystemUser.java | 54 +-----
.../accesscontrol/{AclManager.java => User.java} | 31 ++--
.../features/DefaultFeaturesManager.java | 2 +-
.../handlers/AbstractUserEntryHandler.java | 54 ++++++
.../cpconverter/handlers/AbstractUserParser.java | 63 +++++++
.../cpconverter/handlers/GroupEntryHandler.java | 54 ++++++
.../handlers/SystemUsersEntryHandler.java | 95 ----------
.../cpconverter/handlers/UsersEntryHandler.java | 61 +++++++
.../cpconverter/shared/AbstractJcrNodeParser.java | 18 +-
.../vltpkg/RecollectorVaultPackageScanner.java | 4 +-
...sling.feature.cpconverter.handlers.EntryHandler | 2 +
.../cpconverter/accesscontrol/AclManagerTest.java | 159 ++++++++++++++++-
.../handlers/RepPolicyEntryHandlerTest.java | 191 +++++++++++++--------
.../feature/cpconverter/handlers/TestUtils.java | 9 +
...HandlerTest.java => UsersEntryHandlerTest.java} | 16 +-
.../handlers/jcr_root/home/groups/g/.content.xml | 20 +++
.../groups/g/HjDnfdMCjekaF4jhhUvO/.content.xml | 23 +++
.../groups/g/HjDnfdMCjekaF4jhhUvO/_rep_policy.xml | 32 ++++
.../groups/g/V084LLw1ypl2l9G0e28c/.content.xml | 22 +++
.../groups/g/V084LLw1ypl2l9G0e28c/_rep_policy.xml | 26 +++
.../jcr_root/home/groups/g/_rep_policy.xml | 25 +++
.../groups/g/ouStmkrzT9wCEhtMD9sT/.content.xml | 22 +++
.../g/ouStmkrzT9wCEhtMD9sT/profile/.content.xml | 21 +++
.../g/ouStmkrzT9wCEhtMD9sT/profile/_rep_policy.xml | 32 ++++
.../jcr_root/home/users/a/author/.content.xml | 23 +++
.../jcr_root/home/users/a/author/_rep_policy.xml | 25 +++
.../home/users/a/author/profile/.content.xml | 21 +++
.../users/system/services/random1/.content.xml | 22 +++
.../users/system/services/random2/.content.xml | 22 +++
.../users/system/services/random3/.content.xml | 22 +++
.../users/system/services/random4/.content.xml | 22 +++
37 files changed, 1046 insertions(+), 366 deletions(-)
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/SystemUser.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AbstractUser.java
similarity index 89%
copy from src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/SystemUser.java
copy to src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AbstractUser.java
index 6cce9f4..93c93c1 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/SystemUser.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AbstractUser.java
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Objects;
-public class SystemUser {
+abstract class AbstractUser {
private final String id;
@@ -33,7 +33,7 @@ public class SystemUser {
* @param path - the original repository path of the user in the content-package.
* @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
*/
- public SystemUser(@NotNull String id, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
+ protected AbstractUser(@NotNull String id, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
this.id = id;
this.path = path;
this.intermediatePath = intermediatePath;
@@ -70,13 +70,12 @@ public class SystemUser {
return false;
}
- SystemUser other = (SystemUser) obj;
+ AbstractUser other = (AbstractUser) obj;
return Objects.equals(id, other.getId()) && Objects.equals(path, other.getPath());
}
@Override
public String toString() {
- return "SystemUser [id=" + id + ", path=" + path + "]";
+ return getClass().getSimpleName() + " [id=" + id + ", path=" + path + "]";
}
-
}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java
index 1bc0664..0aa5eae 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java
@@ -28,7 +28,11 @@ import org.jetbrains.annotations.NotNull;
*/
public interface AclManager {
- boolean addSystemUser(SystemUser systemUser);
+ boolean addUser(@NotNull User user);
+
+ boolean addGroup(@NotNull Group group);
+
+ boolean addSystemUser(@NotNull SystemUser systemUser);
boolean addAcl(String systemUser, AccessControlEntry acl);
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/DefaultAclManager.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/DefaultAclManager.java
index 900923b..90c2277 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/DefaultAclManager.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/DefaultAclManager.java
@@ -34,30 +34,26 @@ import java.io.FileInputStream;
import java.util.Optional;
import java.util.Formatter;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Collection;
-import java.util.Map.Entry;
import java.util.Objects;
+import java.util.Map.Entry;
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
public final class DefaultAclManager implements AclManager {
private static final String CONTENT_XML_FILE_NAME = ".content.xml";
- private static final String DEFAULT_TYPE = "sling:Folder";
-
- private final Set<RepoPath> preProvidedSystemPaths = new HashSet<>();
-
- private final Set<RepoPath> preProvidedPaths = new HashSet<>();
-
private final Set<SystemUser> systemUsers = new LinkedHashSet<>();
+ private final Set<Group> groups = new LinkedHashSet<>();
+ private final Set<User> users = new LinkedHashSet<>();
private final Map<String, List<AccessControlEntry>> acls = new HashMap<>();
@@ -65,6 +61,15 @@ public final class DefaultAclManager implements AclManager {
private volatile PrivilegeDefinitions privilegeDefinitions;
+ @Override
+ public boolean addUser(@NotNull User user) {
+ return users.add(user);
+ }
+
+ public boolean addGroup(@NotNull Group group) {
+ return groups.add(group);
+ }
+
public boolean addSystemUser(@NotNull SystemUser systemUser) {
return systemUsers.add(systemUser);
}
@@ -77,17 +82,6 @@ public final class DefaultAclManager implements AclManager {
return false;
}
- private void addPath(@NotNull RepoPath path, @NotNull Set<RepoPath> paths) {
- if (preProvidedPaths.add(path)) {
- paths.add(path);
- }
-
- RepoPath parent = path.getParent();
- if (parent != null && parent.getSegmentCount() > 0) {
- addPath(parent, paths);
- }
- }
-
public void addRepoinitExtension(@NotNull List<VaultPackageAssembler> packageAssemblers, @NotNull FeaturesManager featureManager) {
try (Formatter formatter = new Formatter()) {
@@ -104,17 +98,38 @@ public final class DefaultAclManager implements AclManager {
for (SystemUser systemUser : systemUsers) {
// make sure all users are created first
formatter.format("create service user %s with path %s%n", systemUser.getId(), systemUser.getIntermediatePath());
+ if (aclIsBelow(systemUser.getPath())) {
+ throw new IllegalStateException("Detected policy on subpath of system-user: " + systemUser);
+ }
+ }
+
+ for (Group group : groups) {
+ if (aclStartsWith(group.getPath())) {
+ formatter.format("create group %s with path %s%n", group.getId(), group.getIntermediatePath());
+ }
+ if (aclIsBelow(group.getPath())) {
+ throw new IllegalStateException("Detected policy on subpath of group: " + group);
+ }
+ }
+
+ for (User user : users) {
+ if (aclStartsWith(user.getPath())) {
+ throw new IllegalStateException("Detected policy on user: " + user);
+ }
}
Set<RepoPath> paths = acls.entrySet().stream()
.filter(entry -> getSystemUser(entry.getKey()).isPresent())
.map(Entry::getValue)
.flatMap(Collection::stream)
- .map(AccessControlEntry::getRepositoryPath).collect(Collectors.toSet());
+ .map(AccessControlEntry::getRepositoryPath)
+ .collect(Collectors.toSet());
paths.stream()
.filter(path -> !paths.stream().anyMatch(other -> !other.equals(path) && other.startsWith(path)))
.filter(((Predicate<RepoPath>)RepoPath::isRepositoryPath).negate())
+ .filter(path -> Stream.of(systemUsers, users, groups).flatMap(Collection::stream)
+ .noneMatch(user -> user.getPath().startsWith(path)))
.map(path -> computePathWithTypes(path, packageAssemblers))
.filter(Objects::nonNull)
.forEach(
@@ -135,22 +150,46 @@ public final class DefaultAclManager implements AclManager {
}
}
+ private boolean aclStartsWith(RepoPath path) {
+ return acls.values().stream().flatMap(List::stream).anyMatch(acl -> acl.getRepositoryPath().startsWith(path));
+ }
+
+ private boolean aclIsBelow(RepoPath path) {
+ return acls.values().stream().flatMap(List::stream).anyMatch(acl -> acl.getRepositoryPath().startsWith(path) && !acl.getRepositoryPath().equals(path));
+ }
+
private void addStatements(@NotNull SystemUser systemUser,
@NotNull List<AccessControlEntry> authorizations,
@NotNull List<VaultPackageAssembler> packageAssemblers,
@NotNull Formatter formatter) {
- // clean the unneeded ACLs, see SLING-8561
- Iterator<AccessControlEntry> authorizationsIterator = authorizations.iterator();
- while (authorizationsIterator.hasNext()) {
- AccessControlEntry acl = authorizationsIterator.next();
+ if (authorizations.isEmpty()) {
+ return;
+ }
- if (acl.getRepositoryPath().startsWith(systemUser.getIntermediatePath())) {
- authorizationsIterator.remove();
+ Map<AccessControlEntry, String> entries = new LinkedHashMap<>();
+ authorizations.forEach(entry -> {
+ String path = getRepoInitPath(entry.getRepositoryPath(), systemUser);
+ if (path != null) {
+ entries.put(entry, path);
}
- }
- // finally add ACLs
+ });
+ if (!entries.isEmpty()) {
+ formatter.format("set ACL for %s%n", systemUser.getId());
+ entries.forEach((entry, path) -> {
+ formatter.format("%s %s on %s",
+ entry.getOperation(),
+ entry.getPrivileges(),
+ path);
+
+ if (!entry.getRestrictions().isEmpty()) {
+ formatter.format(" restriction(%s)",
+ String.join(",", entry.getRestrictions()));
+ }
- addAclStatement(formatter, systemUser, authorizations);
+ formatter.format("%n");
+ });
+ formatter.format("end%n");
+ }
}
private @NotNull Optional<SystemUser> getSystemUser(@NotNull String id) {
@@ -215,44 +254,40 @@ public final class DefaultAclManager implements AclManager {
return type ? new RepoPath(current).toString() : null;
}
- private static void addAclStatement(@NotNull Formatter formatter, @NotNull SystemUser systemUser, @NotNull List<AccessControlEntry> authorizations) {
- if (authorizations.isEmpty()) {
- return;
+ @Nullable
+ private String getRepoInitPath(@NotNull RepoPath path, @NotNull SystemUser systemUser) {
+ if (path.isRepositoryPath()) {
+ return ":repository";
+ } else if (isHomePath(path, systemUser.getPath())) {
+ return getHomePath(path, systemUser);
+ } else {
+ AbstractUser other = getOtherUser(path, Stream.of(systemUsers, groups).flatMap(Collection::stream));
+ if (other != null) {
+ return getHomePath(path, other);
+ }
+ // not a special path
+ return path.toString();
}
-
- writeAccessControl(authorizations, "set ACL for %s%n", systemUser, formatter);
}
- private static void writeAccessControl(@NotNull List<AccessControlEntry> accessControlEntries, @NotNull String statement, @NotNull SystemUser systemUser, @NotNull Formatter formatter) {
- formatter.format(statement, systemUser.getId());
- writeEntries(accessControlEntries, systemUser, formatter);
- formatter.format("end%n");
+ private static boolean isHomePath(@NotNull RepoPath path, @NotNull RepoPath systemUserPath) {
+ return path.startsWith(systemUserPath);
}
- private static void writeEntries(@NotNull List<AccessControlEntry> accessControlEntries, @NotNull SystemUser systemUser, @NotNull Formatter formatter) {
- for (AccessControlEntry entry : accessControlEntries) {
- formatter.format("%s %s on %s",
- entry.getOperation(),
- entry.getPrivileges(),
- getRepoInitPath(entry.getRepositoryPath(), systemUser));
-
- if (!entry.getRestrictions().isEmpty()) {
- formatter.format(" restriction(%s)",
- String.join(",", entry.getRestrictions()));
- }
+ @Nullable
+ private static AbstractUser getOtherUser(@NotNull RepoPath path, @NotNull Stream<? extends AbstractUser> abstractUsers) {
+ return abstractUsers.filter(au -> path.startsWith(au.getPath())).findFirst().orElse(null);
+ }
- formatter.format("%n");
- }
+ @NotNull
+ private static String getHomePath(@NotNull RepoPath path, @NotNull AbstractUser abstractUser) {
+ return getHomePath(path, abstractUser.getPath(), abstractUser.getId());
}
@NotNull
- private static String getRepoInitPath(@NotNull RepoPath path, @NotNull SystemUser systemUser) {
- // FIXME SLING-9953 : add special handing for path pointing to the system-user home or some other user/group home
- if (path.isRepositoryPath()) {
- return ":repository";
- } else {
- return path.toString();
- }
+ private static String getHomePath(@NotNull RepoPath path, @NotNull RepoPath userPath, @NotNull String id) {
+ String subpath = (path.equals(userPath) ? "" : path.toString().substring(userPath.toString().length()));
+ return "home("+id+")"+subpath;
}
private static void registerPrivileges(@NotNull PrivilegeDefinitions definitions, @NotNull Formatter formatter) {
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/Group.java
similarity index 54%
copy from src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java
copy to src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/Group.java
index 1bc0664..686fdd7 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/Group.java
@@ -16,28 +16,17 @@
*/
package org.apache.sling.feature.cpconverter.accesscontrol;
-import java.util.List;
-
-import org.apache.jackrabbit.vault.fs.spi.PrivilegeDefinitions;
-import org.apache.sling.feature.cpconverter.features.FeaturesManager;
-import org.apache.sling.feature.cpconverter.vltpkg.VaultPackageAssembler;
+import org.apache.sling.feature.cpconverter.shared.RepoPath;
import org.jetbrains.annotations.NotNull;
-/**
- * The Manager able to collect and build System Users and related ACL policies.
- */
-public interface AclManager {
-
- boolean addSystemUser(SystemUser systemUser);
-
- boolean addAcl(String systemUser, AccessControlEntry acl);
-
- void addRepoinitExtension(List<VaultPackageAssembler> packageAssemblers, FeaturesManager featureManager);
-
- void addNodetypeRegistrationSentence(String nodetypeRegistrationSentence);
-
- void addPrivilegeDefinitions(@NotNull PrivilegeDefinitions privilegeDefinitions);
-
- void reset();
+public class Group extends AbstractUser {
+ /**
+ * @param id - the authorizableId to use.
+ * @param path - the original repository path of the user in the content-package.
+ * @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
+ */
+ public Group(@NotNull String id, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
+ super(id, path, intermediatePath);
+ }
}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/MixinParser.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/MixinParser.java
index 5371fff..b447493 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/MixinParser.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/MixinParser.java
@@ -18,7 +18,6 @@ package org.apache.sling.feature.cpconverter.accesscontrol;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.feature.cpconverter.shared.AbstractJcrNodeParser;
-import org.jetbrains.annotations.NotNull;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@@ -26,15 +25,11 @@ final class MixinParser extends AbstractJcrNodeParser<String> {
private String mixins;
public MixinParser() {
- this("sling:Folder");
- }
- public MixinParser(@NotNull String primaryType) {
- super(primaryType);
+ super();
}
@Override
- protected void onJcrRootNode(String uri, String localName, String qName, Attributes attributes, String primaryType)
- throws SAXException {
+ protected void onJcrRootNode(String uri, String localName, String qName, Attributes attributes, String primaryType) {
mixins = attributes.getValue(JcrConstants.JCR_MIXINTYPES);
}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/PrimaryTypeParser.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/PrimaryTypeParser.java
index 27f769f..ffed8fc 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/PrimaryTypeParser.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/PrimaryTypeParser.java
@@ -17,20 +17,13 @@
package org.apache.sling.feature.cpconverter.accesscontrol;
import org.apache.sling.feature.cpconverter.shared.AbstractJcrNodeParser;
-import org.jetbrains.annotations.NotNull;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
final class PrimaryTypeParser extends AbstractJcrNodeParser<String> {
- private String detectedPrimaryType;
-
public PrimaryTypeParser() {
- this("sling:Folder");
- }
-
- public PrimaryTypeParser(@NotNull String primaryType) {
- super(primaryType);
+ super();
}
@Override
@@ -47,7 +40,7 @@ final class PrimaryTypeParser extends AbstractJcrNodeParser<String> {
@Override
protected String getParsingResult() {
- return detectedPrimaryType != null ? detectedPrimaryType : getPrimaryType();
+ return detectedPrimaryType;
}
}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/SystemUser.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/SystemUser.java
index 6cce9f4..e03eda1 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/SystemUser.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/SystemUser.java
@@ -19,14 +19,7 @@ package org.apache.sling.feature.cpconverter.accesscontrol;
import org.apache.sling.feature.cpconverter.shared.RepoPath;
import org.jetbrains.annotations.NotNull;
-import java.util.Objects;
-
-public class SystemUser {
-
- private final String id;
-
- private final RepoPath path;
- private final RepoPath intermediatePath;
+public class SystemUser extends AbstractUser {
/**
* @param id - the authorizableId to use.
@@ -34,49 +27,6 @@ public class SystemUser {
* @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
*/
public SystemUser(@NotNull String id, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
- this.id = id;
- this.path = path;
- this.intermediatePath = intermediatePath;
- }
-
- public @NotNull String getId() {
- return id;
- }
-
- public @NotNull RepoPath getPath() {
- return path;
- }
-
- public @NotNull RepoPath getIntermediatePath() {
- return intermediatePath;
+ super(id, path, intermediatePath);
}
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + Objects.hash(id);
- result = prime * result + Objects.hash(path);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
-
- SystemUser other = (SystemUser) obj;
- return Objects.equals(id, other.getId()) && Objects.equals(path, other.getPath());
- }
-
- @Override
- public String toString() {
- return "SystemUser [id=" + id + ", path=" + path + "]";
- }
-
}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/User.java
similarity index 54%
copy from src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java
copy to src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/User.java
index 1bc0664..cad22bb 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManager.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/accesscontrol/User.java
@@ -16,28 +16,17 @@
*/
package org.apache.sling.feature.cpconverter.accesscontrol;
-import java.util.List;
-
-import org.apache.jackrabbit.vault.fs.spi.PrivilegeDefinitions;
-import org.apache.sling.feature.cpconverter.features.FeaturesManager;
-import org.apache.sling.feature.cpconverter.vltpkg.VaultPackageAssembler;
+import org.apache.sling.feature.cpconverter.shared.RepoPath;
import org.jetbrains.annotations.NotNull;
-/**
- * The Manager able to collect and build System Users and related ACL policies.
- */
-public interface AclManager {
-
- boolean addSystemUser(SystemUser systemUser);
-
- boolean addAcl(String systemUser, AccessControlEntry acl);
-
- void addRepoinitExtension(List<VaultPackageAssembler> packageAssemblers, FeaturesManager featureManager);
-
- void addNodetypeRegistrationSentence(String nodetypeRegistrationSentence);
-
- void addPrivilegeDefinitions(@NotNull PrivilegeDefinitions privilegeDefinitions);
-
- void reset();
+public class User extends AbstractUser {
+ /**
+ * @param id - the authorizableId to use.
+ * @param path - the original repository path of the user in the content-package.
+ * @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
+ */
+ public User(@NotNull String id, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
+ super(id, path, intermediatePath);
+ }
}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java b/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java
index 86fa637..ab4ea25 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/features/DefaultFeaturesManager.java
@@ -88,7 +88,7 @@ public class DefaultFeaturesManager implements FeaturesManager {
private Feature targetFeature = null;
DefaultFeaturesManager() {
- this(null);
+ this(new File(""));
}
public DefaultFeaturesManager(@NotNull File tempDir) {
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractUserEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractUserEntryHandler.java
new file mode 100644
index 0000000..26e6a4d
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractUserEntryHandler.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.apache.jackrabbit.vault.fs.io.Archive;
+import org.apache.jackrabbit.vault.fs.io.Archive.Entry;
+import org.apache.jackrabbit.vault.util.PlatformNameFormat;
+import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
+import org.apache.sling.feature.cpconverter.shared.RepoPath;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.InputStream;
+import java.util.regex.Matcher;
+
+abstract class AbstractUserEntryHandler extends AbstractRegexEntryHandler {
+
+ AbstractUserEntryHandler(@NotNull String rexex) {
+ super(rexex);
+ }
+
+ @Override
+ public void handle(@NotNull String path, @NotNull Archive archive, @NotNull Entry entry, @NotNull ContentPackage2FeatureModelConverter converter)
+ throws Exception {
+ Matcher matcher = getPattern().matcher(path);
+ if (matcher.matches()) {
+ path = matcher.group(1);
+ }
+
+ RepoPath originalPath = new RepoPath(PlatformNameFormat.getRepositoryPath(path));
+ RepoPath intermediatePath = originalPath.getParent();
+
+ AbstractUserParser parser = createParser(converter, originalPath, intermediatePath);
+ try (InputStream input = archive.openInputStream(entry)) {
+ parser.parse(input);
+ }
+ }
+
+ abstract AbstractUserParser createParser(@NotNull ContentPackage2FeatureModelConverter converter, @NotNull RepoPath originalPath, @NotNull RepoPath intermediatePath);
+
+}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractUserParser.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractUserParser.java
new file mode 100644
index 0000000..3d360c5
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/AbstractUserParser.java
@@ -0,0 +1,63 @@
+/*
+ * 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 org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
+import org.apache.sling.feature.cpconverter.shared.AbstractJcrNodeParser;
+import org.apache.sling.feature.cpconverter.shared.RepoPath;
+import org.jetbrains.annotations.NotNull;
+import org.xml.sax.Attributes;
+
+abstract class AbstractUserParser extends AbstractJcrNodeParser<Void> {
+
+ private static final String REP_AUTHORIZABLE_ID = "rep:authorizableId";
+
+ final ContentPackage2FeatureModelConverter converter;
+
+ final RepoPath path;
+
+ final RepoPath intermediatePath;
+
+ /**
+ * @param converter - the converter to use.
+ * @param path - the original repository path of the user in the content-package.
+ * @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
+ * @param primaryTypes - the primary type of the user/group nodes to be parsed
+ */
+ protected AbstractUserParser(@NotNull ContentPackage2FeatureModelConverter converter, @NotNull RepoPath path, @NotNull RepoPath intermediatePath, @NotNull String... primaryTypes) {
+ super(primaryTypes);
+ this.converter = converter;
+ this.path = path;
+ this.intermediatePath = intermediatePath;
+ }
+
+ @Override
+ protected void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) {
+ String authorizableId = attributes.getValue(REP_AUTHORIZABLE_ID);
+ if (authorizableId != null && !authorizableId.isEmpty()) {
+ handleUser(authorizableId);
+ }
+ }
+
+ @Override
+ protected Void getParsingResult() {
+ return null;
+ }
+
+ abstract void handleUser(@NotNull String id);
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/GroupEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/GroupEntryHandler.java
new file mode 100644
index 0000000..afea198
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/GroupEntryHandler.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
+import org.apache.sling.feature.cpconverter.accesscontrol.Group;
+import org.apache.sling.feature.cpconverter.shared.RepoPath;
+import org.jetbrains.annotations.NotNull;
+
+public final class GroupEntryHandler extends AbstractUserEntryHandler {
+
+ public GroupEntryHandler() {
+ // FIXME: SLING-9969
+ super("/jcr_root(/home/groups.*/)\\.content.xml");
+ }
+
+ @Override
+ AbstractUserParser createParser(@NotNull ContentPackage2FeatureModelConverter converter, @NotNull RepoPath originalPath, @NotNull RepoPath intermediatePath) {
+ return new GroupParser(converter, originalPath, intermediatePath);
+ }
+
+ private static final class GroupParser extends AbstractUserParser {
+
+ private static final String REP_GROUP = "rep:Group";
+
+ /**
+ * @param converter - the converter to use.
+ * @param path - the original repository path of the user in the content-package.
+ * @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
+ */
+ public GroupParser(@NotNull ContentPackage2FeatureModelConverter converter, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
+ super(converter, path, intermediatePath, REP_GROUP);
+ }
+
+ @Override
+ void handleUser(@NotNull String id) {
+ converter.getAclManager().addGroup(new Group(id, path, intermediatePath));
+ }
+ }
+}
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
deleted file mode 100644
index 3785a2c..0000000
--- a/src/main/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandler.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 org.apache.jackrabbit.vault.util.PlatformNameFormat;
-import org.jetbrains.annotations.NotNull;
-import org.xml.sax.Attributes;
-
-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.accesscontrol.SystemUser;
-import org.apache.sling.feature.cpconverter.shared.AbstractJcrNodeParser;
-import org.apache.sling.feature.cpconverter.shared.RepoPath;
-
-import java.io.InputStream;
-import java.util.regex.Matcher;
-
-public final class SystemUsersEntryHandler extends AbstractRegexEntryHandler {
-
- public SystemUsersEntryHandler() {
- super("/jcr_root(/home/users/.*/)\\.content.xml");
- }
-
- @Override
- public void handle(@NotNull String path, @NotNull Archive archive, @NotNull Entry entry, @NotNull ContentPackage2FeatureModelConverter converter)
- throws Exception {
- Matcher matcher = getPattern().matcher(path);
- if (matcher.matches()) {
- path = matcher.group(1);
- }
-
- RepoPath originalPath = new RepoPath(PlatformNameFormat.getRepositoryPath(path));
- RepoPath intermediatePath = originalPath.getParent();
-
- SystemUserParser systemUserParser = new SystemUserParser(converter, originalPath, intermediatePath);
- try (InputStream input = archive.openInputStream(entry)) {
- systemUserParser.parse(input);
- }
- }
-
- private static final class SystemUserParser extends AbstractJcrNodeParser<Void> {
-
- private final static String REP_SYSTEM_USER = "rep:SystemUser";
-
- private final static String REP_AUTHORIZABLE_ID = "rep:authorizableId";
-
- private final ContentPackage2FeatureModelConverter converter;
-
- private final RepoPath path;
-
- private final RepoPath intermediatePath;
-
- /**
- * @param converter - the converter to use.
- * @param path - the original repository path of the user in the content-package.
- * @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
- */
- public SystemUserParser(@NotNull ContentPackage2FeatureModelConverter converter, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
- super(REP_SYSTEM_USER);
- this.converter = converter;
- this.path = path;
- this.intermediatePath = intermediatePath;
- }
-
- @Override
- protected void onJcrRootElement(String uri, String localName, String qName, Attributes attributes) {
- String authorizableId = attributes.getValue(REP_AUTHORIZABLE_ID);
- if (authorizableId != null && !authorizableId.isEmpty()) {
- converter.getAclManager().addSystemUser(new SystemUser(authorizableId, path, intermediatePath));
- }
- }
-
- @Override
- protected Void getParsingResult() {
- return null;
- }
-
- }
-
-}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/handlers/UsersEntryHandler.java b/src/main/java/org/apache/sling/feature/cpconverter/handlers/UsersEntryHandler.java
new file mode 100644
index 0000000..6773c4d
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/cpconverter/handlers/UsersEntryHandler.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
+import org.apache.sling.feature.cpconverter.accesscontrol.SystemUser;
+import org.apache.sling.feature.cpconverter.accesscontrol.User;
+import org.apache.sling.feature.cpconverter.shared.RepoPath;
+import org.jetbrains.annotations.NotNull;
+
+public final class UsersEntryHandler extends AbstractUserEntryHandler {
+
+ public UsersEntryHandler() {
+ // FIXME: SLING-9969
+ super("/jcr_root(/home/users/.*/)\\.content.xml");
+ }
+
+ @Override
+ AbstractUserParser createParser(@NotNull ContentPackage2FeatureModelConverter converter, @NotNull RepoPath originalPath, @NotNull RepoPath intermediatePath) {
+ return new SystemUserParser(converter, originalPath, intermediatePath);
+ }
+
+ private static final class SystemUserParser extends AbstractUserParser {
+
+ private static final String REP_SYSTEM_USER = "rep:SystemUser";
+ private static final String REP_USER = "rep:User";
+
+ /**
+ * @param converter - the converter to use.
+ * @param path - the original repository path of the user in the content-package.
+ * @param intermediatePath - the intermediate path the user should have - most likely the (direct) parent of the path.
+ */
+ public SystemUserParser(@NotNull ContentPackage2FeatureModelConverter converter, @NotNull RepoPath path, @NotNull RepoPath intermediatePath) {
+ super(converter, path, intermediatePath, REP_SYSTEM_USER, REP_USER);
+ }
+
+ @Override
+ void handleUser(@NotNull String id) {
+ if (REP_USER.equals(detectedPrimaryType)) {
+ converter.getAclManager().addUser(new User(id, path, intermediatePath));
+ } else{
+ converter.getAclManager().addSystemUser(new SystemUser(id, path, intermediatePath));
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/shared/AbstractJcrNodeParser.java b/src/main/java/org/apache/sling/feature/cpconverter/shared/AbstractJcrNodeParser.java
index 79caf44..c265f5f 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/shared/AbstractJcrNodeParser.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/shared/AbstractJcrNodeParser.java
@@ -19,10 +19,12 @@ package org.apache.sling.feature.cpconverter.shared;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import java.io.InputStream;
+import java.util.Set;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+import com.google.common.collect.ImmutableSet;
import org.jetbrains.annotations.NotNull;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@@ -34,10 +36,12 @@ public abstract class AbstractJcrNodeParser<O> extends DefaultHandler {
private static final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
- private final String primaryType;
+ private final Set<String> primaryTypes;
- public AbstractJcrNodeParser(@NotNull String primaryType) {
- this.primaryType = primaryType;
+ protected String detectedPrimaryType;
+
+ protected AbstractJcrNodeParser(@NotNull String... primaryTypes) {
+ this.primaryTypes = ImmutableSet.of(primaryTypes);
}
public O parse(InputStream input) throws Exception {
@@ -54,12 +58,9 @@ public abstract class AbstractJcrNodeParser<O> extends DefaultHandler {
}
}
- protected final @NotNull String getPrimaryType() {
- return primaryType;
- }
-
protected void onJcrRootNode(String uri, String localName, String qName, Attributes attributes, String primaryType) throws SAXException {
- if (this.primaryType.equals(primaryType)) {
+ if (this.primaryTypes.contains(primaryType)) {
+ detectedPrimaryType = primaryType;
onJcrRootElement(uri, localName, qName, attributes);
}
}
@@ -67,5 +68,4 @@ public abstract class AbstractJcrNodeParser<O> 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/vltpkg/RecollectorVaultPackageScanner.java b/src/main/java/org/apache/sling/feature/cpconverter/vltpkg/RecollectorVaultPackageScanner.java
index 8e9f290..ec25f3a 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/vltpkg/RecollectorVaultPackageScanner.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/vltpkg/RecollectorVaultPackageScanner.java
@@ -24,7 +24,7 @@ import org.apache.jackrabbit.vault.packaging.PackageId;
import org.apache.jackrabbit.vault.packaging.PackageManager;
import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
import org.apache.sling.feature.cpconverter.handlers.EntryHandler;
-import org.apache.sling.feature.cpconverter.handlers.SystemUsersEntryHandler;
+import org.apache.sling.feature.cpconverter.handlers.UsersEntryHandler;
import org.apache.sling.feature.cpconverter.handlers.VersionResolverContentPackageEntryHandler;
import org.jetbrains.annotations.NotNull;
@@ -41,7 +41,7 @@ public final class RecollectorVaultPackageScanner extends BaseVaultPackageScanne
super(packageManager, strictValidation);
this.converter = converter;
handlers = new EntryHandler[] {
- new SystemUsersEntryHandler(),
+ new UsersEntryHandler(),
new VersionResolverContentPackageEntryHandler(this, subContentPackages)
};
}
diff --git a/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.handlers.EntryHandler b/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.handlers.EntryHandler
index 1ab38fb..7a82e4e 100644
--- a/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.handlers.EntryHandler
+++ b/src/main/resources/META-INF/services/org.apache.sling.feature.cpconverter.handlers.EntryHandler
@@ -1,10 +1,12 @@
org.apache.sling.feature.cpconverter.handlers.BundleEntryHandler
org.apache.sling.feature.cpconverter.handlers.ConfigurationEntryHandler
org.apache.sling.feature.cpconverter.handlers.ContentPackageEntryHandler
+org.apache.sling.feature.cpconverter.handlers.GroupEntryHandler
org.apache.sling.feature.cpconverter.handlers.JsonConfigurationEntryHandler
org.apache.sling.feature.cpconverter.handlers.NodeTypesEntryHandler
org.apache.sling.feature.cpconverter.handlers.PrivilegesHandler
org.apache.sling.feature.cpconverter.handlers.PropertiesConfigurationEntryHandler
org.apache.sling.feature.cpconverter.handlers.RepPolicyEntryHandler
org.apache.sling.feature.cpconverter.handlers.RepRepoPolicyEntryHandler
+org.apache.sling.feature.cpconverter.handlers.UsersEntryHandler
org.apache.sling.feature.cpconverter.handlers.XmlConfigurationEntryHandler
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManagerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManagerTest.java
index 98c1863..52b66fa 100644
--- a/src/test/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManagerTest.java
+++ b/src/test/java/org/apache/sling/feature/cpconverter/accesscontrol/AclManagerTest.java
@@ -66,7 +66,6 @@ public class AclManagerTest {
.map(Path::toFile)
.forEach(File::delete);
}
-
@Test
public void makeSureAclsAreCreatedOnlyoutsideSytemUsersPaths() throws Exception {
aclManager.addSystemUser(new SystemUser("acs-commons-package-replication-status-event-service", new RepoPath("/home/users/system/foo"), new RepoPath("/home/users/system")));
@@ -93,14 +92,11 @@ public class AclManagerTest {
// acs-commons-on-deploy-scripts-service will be missed
String expected =
"create service user acs-commons-package-replication-status-event-service with path /home/users/system" + System.lineSeparator() +
- "create path /asd/not(nt:unstructured mixin rep:AccessControllable,mix:created)/system/user/path" + System.lineSeparator() +
- // see SLING-8561
- // "set ACL for acs-commons-package-replication-status-event-service\n" +
- // "allow jcr:read,crx:replicate,jcr:removeNode on /asd/public\n" +
- // "end\n" +
- "set ACL for acs-commons-package-replication-status-event-service" + System.lineSeparator() +
- "allow jcr:read,rep:write,rep:indexDefinitionManagement on /asd/not/system/user/path" + System.lineSeparator() +
- "end" + System.lineSeparator();
+ "create path /asd/not(nt:unstructured mixin rep:AccessControllable,mix:created)/system/user/path" + System.lineSeparator() +
+ "set ACL for acs-commons-package-replication-status-event-service" + System.lineSeparator() +
+ "allow jcr:read,rep:write,rep:indexDefinitionManagement on /asd/not/system/user/path" + System.lineSeparator() +
+ "allow jcr:read,crx:replicate,jcr:removeNode on /home/users/system" + System.lineSeparator() +
+ "end" + System.lineSeparator();
String actual = repoinitExtension.getText();
assertEquals(expected, actual);
@@ -201,6 +197,151 @@ public class AclManagerTest {
assertFalse(operations.isEmpty());
}
+ @Test
+ public void testGroupHandlingWithGroupUsed() {
+ aclManager.addSystemUser(new SystemUser("sys-usr", new RepoPath("/home/users/system/foo"), new RepoPath("/home/users/system")));
+
+ aclManager.addGroup(new Group("test", new RepoPath("/home/groups/test"), new RepoPath("/home/groups/test")));
+ aclManager.addAcl("sys-usr", newAcl(true, "jcr:read", "/home/groups/test"));
+ VaultPackageAssembler assembler = mock(VaultPackageAssembler.class);
+ when(assembler.getEntry(anyString())).thenReturn(new File(System.getProperty("java.io.tmpdir")));
+ Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null));
+
+ FeaturesManager fm = Mockito.spy(new DefaultFeaturesManager(tempDir.toFile()));
+ when(fm.getTargetFeature()).thenReturn(feature);
+
+ aclManager.addRepoinitExtension(Arrays.asList(assembler), fm);
+
+ Extension repoinitExtension = feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT);
+ assertNotNull(repoinitExtension);
+
+ String expected =
+ "create service user sys-usr with path /home/users/system" + System.lineSeparator() +
+ "create group test with path /home/groups/test" + System.lineSeparator() +
+ "set ACL for sys-usr" + System.lineSeparator() +
+ "allow jcr:read on home(test)" + System.lineSeparator() +
+ "end" + System.lineSeparator();
+
+ String actual = repoinitExtension.getText();
+ assertEquals(expected, actual);
+
+ }
+
+ @Test
+ public void testGroupHandlingWithGroupNotUsed() {
+ aclManager.addSystemUser(new SystemUser("sys-usr", new RepoPath("/home/users/system/foo"), new RepoPath("/home/users/system")));
+
+ aclManager.addGroup(new Group("test", new RepoPath("/home/groups/test"), new RepoPath("/home/groups/test")));
+ aclManager.addAcl("sys-usr", newAcl(true, "jcr:read", "/content/test"));
+ VaultPackageAssembler assembler = mock(VaultPackageAssembler.class);
+ when(assembler.getEntry(anyString())).thenReturn(new File(System.getProperty("java.io.tmpdir")));
+ Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null));
+
+ FeaturesManager fm = Mockito.spy(new DefaultFeaturesManager(tempDir.toFile()));
+ when(fm.getTargetFeature()).thenReturn(feature);
+
+ aclManager.addRepoinitExtension(Arrays.asList(assembler), fm);
+
+ Extension repoinitExtension = feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT);
+ assertNotNull(repoinitExtension);
+
+ String expected =
+ "create service user sys-usr with path /home/users/system" + System.lineSeparator() +
+ "set ACL for sys-usr" + System.lineSeparator() +
+ "allow jcr:read on /content/test" + System.lineSeparator() +
+ "end" + System.lineSeparator();
+
+ String actual = repoinitExtension.getText();
+ assertEquals(expected, actual);
+
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testGroupHandlingWithGroupMatchingSubPath() {
+ aclManager.addSystemUser(new SystemUser("sys-usr", new RepoPath("/home/users/system/foo"), new RepoPath("/home/users/system")));
+
+ aclManager.addGroup(new Group("test", new RepoPath("/home/groups/test"), new RepoPath("/home/groups/test")));
+ aclManager.addAcl("sys-usr", newAcl(true, "jcr:read", "/home/groups/test/foo"));
+ VaultPackageAssembler assembler = mock(VaultPackageAssembler.class);
+ when(assembler.getEntry(anyString())).thenReturn(new File(System.getProperty("java.io.tmpdir")));
+ Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null));
+
+ FeaturesManager fm = Mockito.spy(new DefaultFeaturesManager(tempDir.toFile()));
+ when(fm.getTargetFeature()).thenReturn(feature);
+ aclManager.addRepoinitExtension(Arrays.asList(assembler), fm);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testUserHandlingWithMatchingUser() {
+ aclManager.addSystemUser(new SystemUser("sys-usr", new RepoPath("/home/users/system/foo"), new RepoPath("/home/users/system")));
+
+ aclManager.addUser(new User("test", new RepoPath("/home/users/test"), new RepoPath("/home/users/test")));
+ aclManager.addAcl("sys-usr", newAcl(true, "jcr:read", "/home/users/test/foo"));
+ VaultPackageAssembler assembler = mock(VaultPackageAssembler.class);
+ when(assembler.getEntry(anyString())).thenReturn(new File(System.getProperty("java.io.tmpdir")));
+ Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null));
+
+ FeaturesManager fm = Mockito.spy(new DefaultFeaturesManager(tempDir.toFile()));
+ when(fm.getTargetFeature()).thenReturn(feature);
+ aclManager.addRepoinitExtension(Arrays.asList(assembler), fm);
+ }
+
+ @Test
+ public void testUserHandlingWithNonMatchingUser() {
+ aclManager.addSystemUser(new SystemUser("sys-usr", new RepoPath("/home/users/system/foo"), new RepoPath("/home/users/system")));
+
+ aclManager.addUser(new User("test", new RepoPath("/home/users/test"), new RepoPath("/home/users/test")));
+ aclManager.addAcl("sys-usr", newAcl(true, "jcr:read", "/content/test"));
+ VaultPackageAssembler assembler = mock(VaultPackageAssembler.class);
+ when(assembler.getEntry(anyString())).thenReturn(new File(System.getProperty("java.io.tmpdir")));
+ Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null));
+
+ FeaturesManager fm = Mockito.spy(new DefaultFeaturesManager(tempDir.toFile()));
+ when(fm.getTargetFeature()).thenReturn(feature);
+
+ aclManager.addRepoinitExtension(Arrays.asList(assembler), fm);
+
+ Extension repoinitExtension = feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT);
+ assertNotNull(repoinitExtension);
+
+ String expected =
+ "create service user sys-usr with path /home/users/system" + System.lineSeparator() +
+ "set ACL for sys-usr" + System.lineSeparator() +
+ "allow jcr:read on /content/test" + System.lineSeparator() +
+ "end" + System.lineSeparator();
+
+ String actual = repoinitExtension.getText();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testPathHandlingWithUser() {
+ aclManager.addSystemUser(new SystemUser("sys-usr", new RepoPath("/home/users/system/foo"), new RepoPath("/home/users/system")));
+
+ aclManager.addUser(new User("test", new RepoPath("/home/users/test"), new RepoPath("/home/users/test")));
+ aclManager.addAcl("sys-usr", newAcl(true, "jcr:read", "/home/users/test2"));
+ VaultPackageAssembler assembler = mock(VaultPackageAssembler.class);
+ when(assembler.getEntry(anyString())).thenReturn(new File(System.getProperty("java.io.tmpdir")));
+ Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null));
+
+ FeaturesManager fm = Mockito.spy(new DefaultFeaturesManager(tempDir.toFile()));
+ when(fm.getTargetFeature()).thenReturn(feature);
+
+ aclManager.addRepoinitExtension(Arrays.asList(assembler), fm);
+
+ Extension repoinitExtension = feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT);
+ assertNotNull(repoinitExtension);
+
+ String expected =
+ "create service user sys-usr with path /home/users/system" + System.lineSeparator() +
+ "set ACL for sys-usr" + System.lineSeparator() +
+ "allow jcr:read on /home/users/test2" + System.lineSeparator() +
+ "end" + System.lineSeparator();
+
+ String actual = repoinitExtension.getText();
+ assertEquals(expected, actual);
+ }
+
private static AccessControlEntry newAcl(boolean isAllow, String privileges, String path) {
return new AccessControlEntry(isAllow, privileges, new RepoPath(PlatformNameFormat.getRepositoryPath(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 a9bf8eb..e2d9889 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
@@ -23,8 +23,11 @@ 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.apache.sling.feature.cpconverter.accesscontrol.AclManager;
import org.apache.sling.feature.cpconverter.accesscontrol.DefaultAclManager;
+import org.apache.sling.feature.cpconverter.accesscontrol.Group;
import org.apache.sling.feature.cpconverter.accesscontrol.SystemUser;
+import org.apache.sling.feature.cpconverter.accesscontrol.User;
import org.apache.sling.feature.cpconverter.features.DefaultFeaturesManager;
import org.apache.sling.feature.cpconverter.features.FeaturesManager;
import org.apache.sling.feature.cpconverter.shared.RepoPath;
@@ -32,6 +35,7 @@ import org.apache.sling.feature.cpconverter.vltpkg.VaultPackageAssembler;
import org.apache.sling.repoinit.parser.RepoInitParser;
import org.apache.sling.repoinit.parser.impl.RepoInitParserService;
import org.apache.sling.repoinit.parser.operations.Operation;
+import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -96,31 +100,32 @@ public final class RepPolicyEntryHandlerTest {
// commented ACLs are due SLING-8561
String expected =
"create service user acs-commons-ensure-oak-index-service with path /home/users/system" + System.lineSeparator() +
- // "create path (sling:Folder) /asd\n" +
- // "create path (sling:Folder) /asd/public\n" +
- // "set ACL for acs-commons-ensure-oak-index-service\n" +
- // "allow jcr:read,rep:write,rep:indexDefinitionManagement on /asd/public restriction(rep:glob,*/oak:index/*)\n" +
- // "end\n" +
"create service user acs-commons-dispatcher-flush-service with path /home/users/system" + System.lineSeparator() +
- // "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 with path /home/users/system" + System.lineSeparator() +
- // "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 with path /home/users/system" + System.lineSeparator() +
- // "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 with path /home/users/system" + System.lineSeparator() +
- // "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 with path /home/users/system" + System.lineSeparator();
- // "set ACL for acs-commons-on-deploy-scripts-service\n" +
- // "allow jcr:read on /asd/public\n" +
- // "end\n";
+ "create service user acs-commons-on-deploy-scripts-service with path /home/users/system" + System.lineSeparator() +
+ "set ACL for acs-commons-automatic-package-replicator-service" + System.lineSeparator() +
+ "allow jcr:read on home(acs-commons-automatic-package-replicator-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-package-replication-status-event-service" + System.lineSeparator() +
+ "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on home(acs-commons-package-replication-status-event-service)" + System.lineSeparator() +
+ "deny jcr:write on home(acs-commons-package-replication-status-event-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-dispatcher-flush-service" + System.lineSeparator() +
+ "allow jcr:read,crx:replicate,jcr:removeNode on home(acs-commons-dispatcher-flush-service)" + System.lineSeparator() +
+ "deny jcr:write on home(acs-commons-dispatcher-flush-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-ensure-oak-index-service" + System.lineSeparator() +
+ "allow jcr:read,rep:write,rep:indexDefinitionManagement on home(acs-commons-ensure-oak-index-service) restriction(rep:glob,*/oak:index/*)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-on-deploy-scripts-service" + System.lineSeparator() +
+ "allow jcr:read on home(acs-commons-on-deploy-scripts-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-ensure-service-user-service" + System.lineSeparator() +
+ "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on home(acs-commons-ensure-service-user-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator();
+
String actual = repoinitExtension.getText();
assertEquals(expected, actual);
@@ -140,26 +145,24 @@ public final class RepPolicyEntryHandlerTest {
assertNotNull(repoinitExtension);
assertEquals(ExtensionType.TEXT, repoinitExtension.getType());
- // commented ACLs are due SLING-8561
String expected =
"create service user acs-commons-package-replication-status-event-service with path /home/users/system" + System.lineSeparator() +
- // "create path (sling:Folder) /asd\n" +
- // "create path (sling:Folder) /asd/public\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 with path /home/users/system" + System.lineSeparator() +
- // "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 with path /home/users/system" + System.lineSeparator() +
- // "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 with path /home/users/system" + System.lineSeparator();
- //"set ACL for acs-commons-on-deploy-scripts-service\n" +
- //"allow jcr:read on /asd/public\n" +
- //"end\n";
+ "create service user acs-commons-on-deploy-scripts-service with path /home/users/system" + System.lineSeparator() +
+ "set ACL for acs-commons-automatic-package-replicator-service" + System.lineSeparator() +
+ "allow jcr:read on home(acs-commons-automatic-package-replicator-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-package-replication-status-event-service" + System.lineSeparator() +
+ "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on home(acs-commons-package-replication-status-event-service)" + System.lineSeparator() +
+ "deny jcr:write on home(acs-commons-package-replication-status-event-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-on-deploy-scripts-service" + System.lineSeparator() +
+ "allow jcr:read on home(acs-commons-on-deploy-scripts-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator() +
+ "set ACL for acs-commons-ensure-service-user-service" + System.lineSeparator() +
+ "allow jcr:read,rep:write,jcr:readAccessControl,jcr:modifyAccessControl on home(acs-commons-ensure-service-user-service)" + System.lineSeparator() +
+ "end" + System.lineSeparator();
String actual = repoinitExtension.getText();
assertEquals(expected, actual);
@@ -223,6 +226,79 @@ public final class RepPolicyEntryHandlerTest {
assertNull(repoinitExtension);
}
+ @Test
+ public void policyAtAuthorizableFolder() throws Exception {
+ SystemUser s1 = new SystemUser("service1", new RepoPath("/home/users/system/services/random1"), new RepoPath("/home/users/system/services"));
+
+ AclManager aclManager = new DefaultAclManager();
+ aclManager.addSystemUser(s1);
+
+ ParseResult result = parseAndSetRepoInit("/jcr_root/home/groups/g/_rep_policy.xml", aclManager);
+ Extension repoinitExtension = result.getRepoinitExtension();
+ assertNotNull(repoinitExtension);
+ assertEquals(ExtensionType.TEXT, repoinitExtension.getType());
+
+ String expected =
+ "create service user service1 with path /home/users/system/services" + System.lineSeparator() +
+ "set ACL for service1" + System.lineSeparator() +
+ "allow jcr:read,rep:userManagement on /home/groups/g" + System.lineSeparator() +
+ "end" + System.lineSeparator();
+ assertEquals(expected, repoinitExtension.getText());
+ assertTrue(result.excludedAcls.isEmpty());
+ }
+
+ @Test
+ public void policyAtGroupNode() throws Exception {
+ SystemUser s1 = new SystemUser("service1", new RepoPath("/home/users/system/services/random1"), new RepoPath("/home/users/system/services"));
+ Group gr = new Group("testgroup", new RepoPath("/home/groups/g/HjDnfdMCjekaF4jhhUvO"), new RepoPath("/home/groups/g"));
+
+ AclManager aclManager = new DefaultAclManager();
+ aclManager.addSystemUser(s1);
+ aclManager.addGroup(gr);
+
+ ParseResult result = parseAndSetRepoInit("/jcr_root/home/groups/g/HjDnfdMCjekaF4jhhUvO/_rep_policy.xml", aclManager);
+ Extension repoinitExtension = result.getRepoinitExtension();
+ assertNotNull(repoinitExtension);
+ assertEquals(ExtensionType.TEXT, repoinitExtension.getType());
+
+ String expected =
+ "create service user service1 with path /home/users/system/services" + System.lineSeparator() +
+ "create group testgroup with path /home/groups/g" + System.lineSeparator() +
+ "set ACL for service1" + System.lineSeparator() +
+ "allow jcr:read on home(testgroup)" + System.lineSeparator() +
+ "end" + System.lineSeparator();
+ assertEquals(expected, repoinitExtension.getText());
+
+ String expectedExclusions = "<?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" +
+ " <allow1 jcr:primaryType=\"rep:GrantACE\" rep:principalName=\"testgroup\" rep:privileges=\"{Name}[jcr:read]\"/>\n" +
+ "</jcr:root>\n";
+ assertEquals(expectedExclusions, result.excludedAcls);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void policyAtGroupSubTree() throws Exception {
+ SystemUser s1 = new SystemUser("service1", new RepoPath("/home/users/system/services/random1"), new RepoPath("/home/users/system/services"));
+ Group gr = new Group("testgroup3", new RepoPath("/home/groups/g/ouStmkrzT9wCEhtMD9sT"), new RepoPath("/home/groups/g"));
+
+ AclManager aclManager = new DefaultAclManager();
+ aclManager.addSystemUser(s1);
+ aclManager.addGroup(gr);
+
+ parseAndSetRepoInit("/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/profile/_rep_policy.xml", aclManager);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void policyAtUserNode() throws Exception {
+ SystemUser s1 = new SystemUser("service1", new RepoPath("/home/users/system/services/random1"), new RepoPath("/home/users/system/services"));
+ User user = new User("author", new RepoPath("/home/users/a/author"), new RepoPath("/home/users/a"));
+
+ AclManager aclManager = new DefaultAclManager();
+ aclManager.addSystemUser(s1);
+ aclManager.addUser(user);
+
+ parseAndSetRepoInit("/jcr_root/home/users/a/author/_rep_policy.xml", aclManager);
+ }
+
private ParseResult parseAndSetRepoinit(String...systemUsersNames) throws Exception {
RepoPath alwaysTheSameOrgPath = new RepoPath("/home/users/system/asd");
RepoPath alwaysTheSameInterPath = new RepoPath("/home/users/system");
@@ -235,42 +311,25 @@ public final class RepPolicyEntryHandlerTest {
return parseAndSetRepoinit(systemUsers);
}
- private ParseResult parseAndSetRepoinit(SystemUser...systemUsers) throws Exception {
+ private ParseResult parseAndSetRepoinit(@NotNull SystemUser...systemUsers) throws Exception {
String path = "/jcr_root/home/users/system/asd/_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)));
-
- Feature feature = new Feature(new ArtifactId("org.apache.sling", "org.apache.sling.cp2fm", "0.0.1", null, null));
- FeaturesManager featuresManager = spy(DefaultFeaturesManager.class);
- when(featuresManager.getTargetFeature()).thenReturn(feature);
- ContentPackage2FeatureModelConverter converter = spy(ContentPackage2FeatureModelConverter.class);
- when(converter.getFeaturesManager()).thenReturn(featuresManager);
- when(converter.getAclManager()).thenReturn(new DefaultAclManager());
- when(converter.getMainPackageAssembler()).thenReturn(packageAssembler);
-
- if (systemUsers != null) {
- for (SystemUser systemUser : systemUsers) {
- converter.getAclManager().addSystemUser(systemUser);
- }
+ AclManager aclManager = new DefaultAclManager();
+ for (SystemUser systemUser : systemUsers) {
+ aclManager.addSystemUser(systemUser);
}
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ return new ParseResult(TestUtils.createRepoInitExtension(handler, aclManager, path, getClass().getResourceAsStream(path.substring(1)), baos), new String(baos.toByteArray()));
+ }
- handler.handle(path, archive, entry, converter);
-
- when(packageAssembler.getEntry(anyString())).thenReturn(new File("itdoesnotexist"));
-
- converter.getAclManager().addRepoinitExtension(Arrays.asList(packageAssembler), featuresManager);
- return new ParseResult(feature.getExtensions().getByName(Extension.EXTENSION_NAME_REPOINIT), new String(baos.toByteArray()));
+ @NotNull
+ private ParseResult parseAndSetRepoInit(@NotNull String path, @NotNull AclManager aclManager) throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ return new ParseResult(TestUtils.createRepoInitExtension(handler, aclManager, path, getClass().getResourceAsStream(path.substring(1)), baos), new String(baos.toByteArray()));
}
private static final class ParseResult {
private final Extension repoinitExtension;
-
private final String excludedAcls;
public ParseResult(Extension repoinitExtension, String excludedAcls) {
@@ -285,7 +344,5 @@ public final class RepPolicyEntryHandlerTest {
public String getExcludedAcls() {
return excludedAcls;
}
-
}
-
}
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/handlers/TestUtils.java b/src/test/java/org/apache/sling/feature/cpconverter/handlers/TestUtils.java
index 9e674e0..396766a 100644
--- a/src/test/java/org/apache/sling/feature/cpconverter/handlers/TestUtils.java
+++ b/src/test/java/org/apache/sling/feature/cpconverter/handlers/TestUtils.java
@@ -26,11 +26,13 @@ import org.apache.sling.feature.cpconverter.features.DefaultFeaturesManager;
import org.apache.sling.feature.cpconverter.features.FeaturesManager;
import org.apache.sling.feature.cpconverter.vltpkg.VaultPackageAssembler;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Arrays;
import static org.mockito.ArgumentMatchers.anyString;
@@ -45,9 +47,15 @@ class TestUtils {
private TestUtils() {}
static Extension createRepoInitExtension(@NotNull EntryHandler handler, @NotNull AclManager aclManager, @NotNull String path, @NotNull InputStream is) throws Exception {
+ return createRepoInitExtension(handler, aclManager, path, is, null);
+ }
+ static Extension createRepoInitExtension(@NotNull EntryHandler handler, @NotNull AclManager aclManager, @NotNull String path, @NotNull InputStream is, @Nullable OutputStream out) throws Exception {
Archive archive = mock(Archive.class);
Archive.Entry entry = mock(Archive.Entry.class);
VaultPackageAssembler packageAssembler = mock(VaultPackageAssembler.class);
+ if (out != null) {
+ when(packageAssembler.createEntry(anyString())).thenReturn(out);
+ }
when(archive.openInputStream(entry)).thenReturn(is);
@@ -57,6 +65,7 @@ class TestUtils {
ContentPackage2FeatureModelConverter converter = spy(ContentPackage2FeatureModelConverter.class);
when(converter.getFeaturesManager()).thenReturn(featuresManager);
when(converter.getAclManager()).thenReturn(aclManager);
+ when(converter.getMainPackageAssembler()).thenReturn(packageAssembler);
handler.handle(path, archive, entry, converter);
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/handlers/UsersEntryHandlerTest.java
similarity index 82%
rename from src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java
rename to src/test/java/org/apache/sling/feature/cpconverter/handlers/UsersEntryHandlerTest.java
index 3fe0523..b232330 100644
--- a/src/test/java/org/apache/sling/feature/cpconverter/handlers/SystemUsersEntryHandlerTest.java
+++ b/src/test/java/org/apache/sling/feature/cpconverter/handlers/UsersEntryHandlerTest.java
@@ -35,29 +35,29 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-public class SystemUsersEntryHandlerTest {
+public class UsersEntryHandlerTest {
- private SystemUsersEntryHandler systemUsersEntryHandler;
+ private UsersEntryHandler usersEntryHandler;
@Before
public void setUp() {
- systemUsersEntryHandler = new SystemUsersEntryHandler();
+ usersEntryHandler = new UsersEntryHandler();
}
@After
public void tearDown() {
- systemUsersEntryHandler = null;
+ usersEntryHandler = null;
}
@Test
public void doesNotMatch() {
- assertFalse(systemUsersEntryHandler.matches("/this/is/a/path/not/pointing/to/a/valid/configuration.asd"));
- assertFalse(systemUsersEntryHandler.matches("/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml"));
+ assertFalse(usersEntryHandler.matches("/this/is/a/path/not/pointing/to/a/valid/configuration.asd"));
+ assertFalse(usersEntryHandler.matches("/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml"));
}
@Test
public void matches() {
- assertTrue(systemUsersEntryHandler.matches("/jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml"));
+ assertTrue(usersEntryHandler.matches("/jcr_root/home/users/system/asd-share-commons/asd-index-definition-reader/.content.xml"));
}
@Test
@@ -102,6 +102,6 @@ public class SystemUsersEntryHandlerTest {
}
private Extension parseAndSetRepoinit(String path) throws Exception {
- return TestUtils.createRepoInitExtension(systemUsersEntryHandler, new DefaultAclManager(), path, getClass().getResourceAsStream(path.substring(1)));
+ return TestUtils.createRepoInitExtension(usersEntryHandler, new DefaultAclManager(), path, getClass().getResourceAsStream(path.substring(1)));
}
}
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/.content.xml
new file mode 100644
index 0000000..280f6f5
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/.content.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:AuthorizableFolder"
+ jcr:mixinTypes="[rep:AccessControllable]"/>
\ No newline at end of file
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/HjDnfdMCjekaF4jhhUvO/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/HjDnfdMCjekaF4jhhUvO/.content.xml
new file mode 100644
index 0000000..4d9e251
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/HjDnfdMCjekaF4jhhUvO/.content.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:Group"
+ jcr:mixinTypes="[rep:AccessControllable]"
+ jcr:uuid="9628ffae-cf05-3138-8185-2cb572d50d45"
+ rep:authorizableId="testgroup"
+ rep:principalName="testgroup"/>
\ No newline at end of file
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/HjDnfdMCjekaF4jhhUvO/_rep_policy.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/HjDnfdMCjekaF4jhhUvO/_rep_policy.xml
new file mode 100644
index 0000000..157f7f4
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/HjDnfdMCjekaF4jhhUvO/_rep_policy.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:ACL">
+ <!-- entry to be converted to repo-init statement if service1 is part of the same package -->
+ <allow
+ jcr:primaryType="rep:GrantACE"
+ rep:principalName="service1"
+ rep:privileges="{Name}[jcr:read]">
+ </allow>
+ <!-- entry not to be converted to repo-init statement -->
+ <allow1
+ jcr:primaryType="rep:GrantACE"
+ rep:principalName="testgroup"
+ rep:privileges="{Name}[jcr:read]">
+ </allow1>
+</jcr:root>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/V084LLw1ypl2l9G0e28c/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/V084LLw1ypl2l9G0e28c/.content.xml
new file mode 100644
index 0000000..307f81b
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/V084LLw1ypl2l9G0e28c/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:Group"
+ jcr:uuid="62a34b2f-0897-32be-909e-a9ae27b85688"
+ rep:authorizableId="testgroup2"
+ rep:principalName="testgroup2"/>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/V084LLw1ypl2l9G0e28c/_rep_policy.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/V084LLw1ypl2l9G0e28c/_rep_policy.xml
new file mode 100644
index 0000000..942b0a3
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/V084LLw1ypl2l9G0e28c/_rep_policy.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:ACL">
+ <!-- entry not to be converted to repo-init statement -->
+ <allow1
+ jcr:primaryType="rep:GrantACE"
+ rep:principalName="testgroup2"
+ rep:privileges="{Name}[jcr:read]">
+ </allow1>
+</jcr:root>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/_rep_policy.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/_rep_policy.xml
new file mode 100644
index 0000000..e912df1
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/_rep_policy.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:ACL">
+ <allow
+ jcr:primaryType="rep:GrantACE"
+ rep:principalName="service1"
+ rep:privileges="{Name}[jcr:read,rep:userManagement]">
+ </allow>
+</jcr:root>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/.content.xml
new file mode 100644
index 0000000..5802f67
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:Group"
+ jcr:uuid="dff511f7-fa75-3922-b0f4-7194f7ad4267"
+ rep:authorizableId="testgroup3"
+ rep:principalName="testgroup3"/>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/profile/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/profile/.content.xml
new file mode 100644
index 0000000..494e2aa
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/profile/.content.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:mixinTypes="[rep:AccessControllable]"
+ jcr:primaryType="nt:unstructured"
+ aboutMe="test group"/>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/profile/_rep_policy.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/profile/_rep_policy.xml
new file mode 100644
index 0000000..1f5a54b
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/groups/g/ouStmkrzT9wCEhtMD9sT/profile/_rep_policy.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:ACL">
+ <!-- entry to be converted to repo-init statement if service1 is part of the same package -->
+ <allow
+ jcr:primaryType="rep:GrantACE"
+ rep:principalName="service1"
+ rep:privileges="{Name}[jcr:read]">
+ </allow>
+ <!-- entry not to be converted to repo-init statement -->
+ <allow1
+ jcr:primaryType="rep:GrantACE"
+ rep:principalName="testgroup3"
+ rep:privileges="{Name}[jcr:all]">
+ </allow1>
+</jcr:root>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/.content.xml
new file mode 100644
index 0000000..4f64da2
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/.content.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:mixinTypes="[rep:AccessControllable]"
+ jcr:primaryType="rep:User"
+ jcr:uuid="02bd92fa-a38a-3a6c-80ea-75e59937a1ef"
+ rep:authorizableId="author"
+ rep:principalName="author"/>
\ No newline at end of file
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/_rep_policy.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/_rep_policy.xml
new file mode 100644
index 0000000..b56cca7
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/_rep_policy.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:ACL">
+ <allow
+ jcr:primaryType="rep:GrantACE"
+ rep:principalName="service1"
+ rep:privileges="{Name}[jcr:read]">
+ </allow>
+</jcr:root>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/profile/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/profile/.content.xml
new file mode 100644
index 0000000..494e2aa
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/a/author/profile/.content.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:mixinTypes="[rep:AccessControllable]"
+ jcr:primaryType="nt:unstructured"
+ aboutMe="test group"/>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random1/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random1/.content.xml
new file mode 100644
index 0000000..5b113ba
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random1/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:SystemUser"
+ jcr:uuid="0a39b2bb-8594-3d80-a4fe-3464cfb7038b"
+ rep:authorizableId="service1"
+ rep:principalName="service1"/>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random2/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random2/.content.xml
new file mode 100644
index 0000000..c58ca5c
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random2/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:SystemUser"
+ jcr:uuid="fb3ed345-63d5-37d1-bead-97d5d64feeca"
+ rep:authorizableId="service2"
+ rep:principalName="service2"/>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random3/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random3/.content.xml
new file mode 100644
index 0000000..9c02a82
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random3/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:SystemUser"
+ jcr:uuid="ec2fbc3d-e9f6-3b3f-94f1-90ff5d05605f"
+ rep:authorizableId="service3"
+ rep:principalName="service3"/>
diff --git a/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random4/.content.xml b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random4/.content.xml
new file mode 100644
index 0000000..327ffdf
--- /dev/null
+++ b/src/test/resources/org/apache/sling/feature/cpconverter/handlers/jcr_root/home/users/system/services/random4/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:primaryType="rep:SystemUser"
+ jcr:uuid="342acedc-ac4a-3044-93d0-3288d39668af"
+ rep:authorizableId="service3"
+ rep:principalName="service3"/>