Author: jsedding
Date: Tue Nov 1 11:35:24 2016
New Revision: 1767478
URL: http://svn.apache.org/viewvc?rev=1767478&view=rev
Log:
OAK-5043: Very old JR2 repositories may have invalid nodetypes for groupsPath
and usersPath
- add test and Editor implementation to fix the jcr:primaryType if needed
- only applies to RepositoryUpgrade, not RepositorySidegrade
Added:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/AuthorizableFolderEditor.java
(with props)
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AuthorizableFolderEditorTest.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java
Modified:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java?rev=1767478&r1=1767477&r2=1767478&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
(original)
+++
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
Tue Nov 1 11:35:24 2016
@@ -125,6 +125,7 @@ import org.apache.jackrabbit.oak.upgrade
import org.apache.jackrabbit.oak.upgrade.nodestate.report.LoggingReporter;
import org.apache.jackrabbit.oak.upgrade.nodestate.report.ReportingNodeState;
import org.apache.jackrabbit.oak.upgrade.nodestate.NodeStateCopier;
+import org.apache.jackrabbit.oak.upgrade.security.AuthorizableFolderEditor;
import org.apache.jackrabbit.oak.upgrade.security.GroupEditorProvider;
import org.apache.jackrabbit.oak.upgrade.security.RestrictionEditorProvider;
import org.apache.jackrabbit.oak.upgrade.version.VersionCopyConfiguration;
@@ -513,6 +514,9 @@ public class RepositoryUpgrade {
String groupsPath = userConf.getParameters().getConfigValue(
UserConstants.PARAM_GROUP_PATH,
UserConstants.DEFAULT_GROUP_PATH);
+ String usersPath = userConf.getParameters().getConfigValue(
+ UserConstants.PARAM_USER_PATH,
+ UserConstants.DEFAULT_USER_PATH);
// hooks specific to the upgrade, need to run first
hooks.add(new EditorHook(new CompositeEditorProvider(
@@ -520,7 +524,8 @@ public class RepositoryUpgrade {
new GroupEditorProvider(groupsPath),
// copy referenced version histories
new VersionableEditor.Provider(sourceRoot, workspaceName,
versionCopyConfiguration),
- new SameNameSiblingsEditor.Provider()
+ new SameNameSiblingsEditor.Provider(),
+ AuthorizableFolderEditor.provider(groupsPath, usersPath)
)));
// this editor works on the VersionableEditor output, so it can't
be
Added:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/AuthorizableFolderEditor.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/AuthorizableFolderEditor.java?rev=1767478&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/AuthorizableFolderEditor.java
(added)
+++
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/AuthorizableFolderEditor.java
Tue Nov 1 11:35:24 2016
@@ -0,0 +1,97 @@
+package org.apache.jackrabbit.oak.upgrade.security;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
+import org.apache.jackrabbit.oak.spi.commit.Editor;
+import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static
org.apache.jackrabbit.oak.spi.security.user.UserConstants.NT_REP_AUTHORIZABLE_FOLDER;
+
+/**
+ * There are occasions where in old JR2 repositories not all ancestors on
+ * the users path are of type {@code rep:AuthorizableFolder}, thus leading
+ * to exceptions after repository upgrade.
+ * <br/>
+ * In order to avoid such situations, this hook verifies that all nodes on
+ * the users and groups paths are of type {@code rep:AuthorizableFolder} and
+ * fixes the node-type if it is incorrect.
+ */
+public class AuthorizableFolderEditor extends DefaultEditor {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(AuthorizableFolderEditor.class);
+
+ private final NodeBuilder currentBuilder;
+
+ private final String groupsPath;
+
+ private final String usersPath;
+
+ private final String path;
+
+ public AuthorizableFolderEditor(final NodeBuilder builder, final String
path, final String groupsPath, final String usersPath) {
+ this.currentBuilder = builder;
+ this.groupsPath = groupsPath;
+ this.usersPath = usersPath;
+ this.path = path;
+ }
+
+ public static EditorProvider provider(final String groupsPath, final
String usersPath) {
+ return new EditorProvider() {
+ @Override
+ public Editor getRootEditor(final NodeState before,
+ final NodeState after,
+ final NodeBuilder builder,
+ final CommitInfo info) throws
CommitFailedException {
+ return new AuthorizableFolderEditor(builder, "/", groupsPath,
usersPath);
+ }
+ };
+ }
+
+ @Override
+ public void propertyAdded(final PropertyState after) throws
CommitFailedException {
+ propertyChanged(null, after);
+ }
+
+ @Override
+ public void propertyChanged(final PropertyState before, final
PropertyState after) throws CommitFailedException {
+ if (JCR_PRIMARYTYPE.equals(after.getName())) {
+ String nodeType = after.getValue(Type.STRING);
+ LOG.debug("Found {}/jcr:primaryType = {}", path, nodeType);
+ if (!nodeType.equals(NT_REP_AUTHORIZABLE_FOLDER) &&
expectAuthorizableFolder(path)) {
+ LOG.info("Changed {}/jcr:primaryType from {} to {}", path,
nodeType, NT_REP_AUTHORIZABLE_FOLDER);
+ currentBuilder.setProperty(JCR_PRIMARYTYPE,
NT_REP_AUTHORIZABLE_FOLDER, Type.NAME);
+ }
+ }
+ }
+
+ private boolean expectAuthorizableFolder(final String path) {
+ return !PathUtils.denotesRoot(path)
+ && (PathUtils.isAncestor(path, groupsPath) ||
path.equals(groupsPath)
+ || PathUtils.isAncestor(path, usersPath) ||
path.equals(usersPath));
+ }
+
+ @Override
+ public Editor childNodeAdded(final String name, final NodeState after)
throws CommitFailedException {
+ return childNodeChanged(name, null, after);
+ }
+
+ @Override
+ public Editor childNodeChanged(final String name, final NodeState before,
final NodeState after) throws CommitFailedException {
+ final String childPath = PathUtils.concat(path, name);
+ if (expectAuthorizableFolder(childPath)) {
+ LOG.debug("Found {} - descending", childPath);
+ return new AuthorizableFolderEditor(currentBuilder.child(name),
childPath, groupsPath, usersPath);
+ } else {
+ return null;
+ }
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/security/AuthorizableFolderEditor.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java?rev=1767478&r1=1767477&r2=1767478&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java
(original)
+++
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AbstractRepositoryUpgradeTest.java
Tue Nov 1 11:35:24 2016
@@ -160,24 +160,30 @@ public abstract class AbstractRepository
protected void assertExisting(final String... paths) throws
RepositoryException {
final Session session = createAdminSession();
try {
- for (final String path : paths) {
- final String relPath = path.substring(1);
- assertTrue("node " + path + " should exist",
session.getRootNode().hasNode(relPath));
- }
+ assertExisting(session, paths);
} finally {
session.logout();
}
}
+ protected void assertExisting(final Session session, final String...
paths) throws RepositoryException {
+ for (final String path : paths) {
+ assertTrue("node " + path + " should exist",
session.nodeExists(path));
+ }
+ }
+
protected void assertMissing(final String... paths) throws
RepositoryException {
final Session session = createAdminSession();
try {
- for (final String path : paths) {
- final String relPath = path.substring(1);
- assertFalse("node " + path + " should not exist",
session.getRootNode().hasNode(relPath));
- }
+ assertMissing(session, paths);
} finally {
session.logout();
}
}
+
+ protected void assertMissing(final Session session, final String... paths)
throws RepositoryException {
+ for (final String path : paths) {
+ assertFalse("node " + path + " should not exist",
session.nodeExists(path));
+ }
+ }
}
Added:
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AuthorizableFolderEditorTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AuthorizableFolderEditorTest.java?rev=1767478&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AuthorizableFolderEditorTest.java
(added)
+++
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AuthorizableFolderEditorTest.java
Tue Nov 1 11:35:24 2016
@@ -0,0 +1,111 @@
+package org.apache.jackrabbit.oak.upgrade;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Test;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import java.io.InputStream;
+
+import static org.junit.Assert.assertThat;
+
+public class AuthorizableFolderEditorTest extends
AbstractRepositoryUpgradeTest {
+
+ // this repository config sets the groupsPath and usersPath to match
+ // this tests expectations
+ private static final String REPOSITORY_XML_FILE =
"repository-groupmember.xml";
+
+ private static final String TEST_GROUP =
"AuthorizableFolderEditorTest-Group";
+
+ private static final String TEST_USER =
"AuthorizableFolderEditorTest-User";
+
+ private static final String HOME_PATH = "/home";
+
+ private static final String GROUPS_PATH = HOME_PATH + "/groups";
+
+ private static final String USERS_PATH = HOME_PATH + "/users";
+
+ private static final String CONTROL_PATH = HOME_PATH + "/control";
+
+ @Override
+ protected void createSourceContent(final Session session) throws Exception
{
+ UserManager userMgr = ((JackrabbitSession) session).getUserManager();
+ userMgr.autoSave(false);
+ Group group = userMgr.createGroup(TEST_GROUP);
+ User user = userMgr.createUser(TEST_USER, "secret");
+ group.addMember(user);
+ session.save();
+
+ // simulate the error, set node types to incorrect values
+ Node home = session.getNode("/home");
+ home.setPrimaryType(JcrConstants.NT_UNSTRUCTURED);
+ home.getNode("users").setPrimaryType(JcrConstants.NT_UNSTRUCTURED);
+ home.getNode("groups").setPrimaryType(JcrConstants.NT_UNSTRUCTURED);
+ home.addNode("control", JcrConstants.NT_UNSTRUCTURED);
+ session.save();
+ }
+
+ @Override
+ public InputStream getRepositoryConfig() {
+ return
getClass().getClassLoader().getResourceAsStream(REPOSITORY_XML_FILE);
+ }
+
+ @Test
+ public void verifyCorrectedNodeTypes() throws RepositoryException {
+ final Session session = createAdminSession();
+ assertExisting(session, HOME_PATH, USERS_PATH, GROUPS_PATH,
CONTROL_PATH);
+
+ assertThat(session.getNode(HOME_PATH),
hasNodeType(UserConstants.NT_REP_AUTHORIZABLE_FOLDER));
+ assertThat(session.getNode(USERS_PATH),
hasNodeType(UserConstants.NT_REP_AUTHORIZABLE_FOLDER));
+ assertThat(session.getNode(GROUPS_PATH),
hasNodeType(UserConstants.NT_REP_AUTHORIZABLE_FOLDER));
+ assertThat(session.getNode(CONTROL_PATH),
hasNodeType(JcrConstants.NT_UNSTRUCTURED));
+ }
+
+ private static Matcher<? super Node> hasNodeType(final String
expectedNodeType) {
+ return new TypeSafeMatcher<Node>() {
+
+ private String path;
+
+ @Override
+ protected boolean matchesSafely(final Node node) {
+ path = getPath(node);
+ return getNodeTypeName(node).equals(expectedNodeType);
+ }
+
+ @Override
+ public void describeTo(final Description description) {
+ description.appendText("the node " + path + " to be of type
").appendValue(expectedNodeType);
+ }
+
+ @Override
+ protected void describeMismatchSafely(final Node node, final
Description mismatchDescription) {
+ mismatchDescription.appendText(" was
").appendValue(getNodeTypeName(node));
+ }
+
+ private String getNodeTypeName(final Node node) {
+ try {
+ return node.getPrimaryNodeType().getName();
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String getPath(final Node node) {
+ try {
+ return node.getPath();
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-upgrade/src/test/java/org/apache/jackrabbit/oak/upgrade/AuthorizableFolderEditorTest.java
------------------------------------------------------------------------------
svn:eol-style = native