Skip to content

Commit

Permalink
OAK-8124: Sidegrade operation doesn't run security-related commit hooks
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/oak/trunk@1855570 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
trekawek committed Mar 15, 2019
1 parent eb5a4d6 commit 0fdc82e
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@
import org.apache.jackrabbit.oak.plugins.migration.report.LoggingReporter;
import org.apache.jackrabbit.oak.plugins.migration.report.ReportingNodeState;
import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
import org.apache.jackrabbit.oak.security.internal.SecurityProviderBuilder;
import org.apache.jackrabbit.oak.segment.SegmentNodeState;
import org.apache.jackrabbit.oak.segment.file.FileStore;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.state.ApplyDiff;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
Expand Down Expand Up @@ -407,6 +410,8 @@ private NodeState copyDiffToTarget(NodeState before, NodeState after, NodeState

private void migrateWithoutCheckpoints() throws CommitFailedException, RepositoryException {
final List<CommitHook> hooks = new ArrayList<>();
final String workspaceName = getWorkspaceName();

if (customCommitHooks != null) {
hooks.addAll(customCommitHooks);
}
Expand All @@ -423,7 +428,12 @@ private void migrateWithoutCheckpoints() throws CommitFailedException, Repositor
if (!versionCopyConfiguration.skipOrphanedVersionsCopy()) {
copyVersionStorage(targetRoot, getVersionStorage(sourceRoot), versionStorage, versionCopyConfiguration);
}
hooks.add(new EditorHook(new VersionableEditor.Provider(sourceRoot, getWorkspaceName(), versionCopyConfiguration)));
hooks.add(new EditorHook(new VersionableEditor.Provider(sourceRoot, workspaceName, versionCopyConfiguration)));
}

SecurityProvider security = SecurityProviderBuilder.newBuilder().build();
for (SecurityConfiguration securityConfig : security.getConfigurations()) {
hooks.addAll(securityConfig.getCommitHooks(workspaceName));
}
// type validation, reference and indexing hooks
hooks.add(new EditorHook(new CompositeEditorProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,75 +16,207 @@
*/
package org.apache.jackrabbit.oak.upgrade;

import static org.apache.jackrabbit.oak.segment.file.FileStoreBuilder.fileStoreBuilder;

import java.io.File;
import java.io.IOException;

import javax.jcr.Credentials;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;

import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.apache.jackrabbit.oak.Oak;
import org.apache.jackrabbit.oak.jcr.Jcr;
import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
import org.apache.jackrabbit.oak.segment.SegmentNodeStore;
import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
import org.apache.jackrabbit.oak.segment.file.FileStore;
import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.security.internal.SecurityProviderBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class IncludeExcludeSidegradeTest {

public static final Credentials CREDENTIALS = new SimpleCredentials("admin", "admin".toCharArray());

private NodeStore sourceNodeStore;

public class IncludeExcludeSidegradeTest extends IncludeExcludeUpgradeTest {
private NodeStore targetNodeStore;

private RepositoryImpl targetRepository;

private Session targetSession;

@Before
public synchronized void upgradeRepository() throws Exception {
if (targetNodeStore == null) {
File directory = getTestDirectory();
File source = new File(directory, "source");
source.mkdirs();
FileStore fileStore = fileStoreBuilder(source).build();
SegmentNodeStore segmentNodeStore = SegmentNodeStoreBuilders.builder(fileStore).build();
RepositoryImpl repository = (RepositoryImpl) new Jcr(new Oak(segmentNodeStore)).createRepository();
Session session = repository.login(CREDENTIALS);
try {
createSourceContent(session);
} finally {
session.save();
session.logout();
repository.shutdown();
fileStore.close();
}
final NodeStore target = getTargetNodeStore();
doUpgradeRepository(source, target);
targetNodeStore = target;
}
public void prepareNodeStores() throws RepositoryException {
sourceNodeStore = new MemoryNodeStore();
withSession(sourceNodeStore, s -> {
createCommonContent(s);
createSourceContent(s);
});

targetNodeStore = new MemoryNodeStore();
withSession(targetNodeStore, s -> {
createCommonContent(s);
});

performSidegrade();

targetRepository = getRepository(targetNodeStore);
targetSession = targetRepository.login(CREDENTIALS);
}

@Override
protected void doUpgradeRepository(File source, NodeStore target) throws RepositoryException, IOException {
FileStore fileStore;
try {
fileStore = fileStoreBuilder(source).build();
} catch (InvalidFileStoreVersionException e) {
throw new IllegalStateException(e);
public void cleanup() {
targetRepository.shutdown();
}

@Test
public void shouldHaveIncludedPaths() throws RepositoryException {
assertExists(
"/content/foo/en",
"/content/assets/foo/2015/02",
"/content/assets/foo/2015/01",
"/content/assets/foo/2014"
);
}

@Test
public void shouldLackPathsThatWereNotIncluded() throws RepositoryException {
assertMissing(
"/content/foo/de",
"/content/foo/fr",
"/content/foo/it"
);
}

@Test
public void shouldLackExcludedPaths() throws RepositoryException {
assertMissing(
"/content/assets/foo/2013",
"/content/assets/foo/2012",
"/content/assets/foo/2011",
"/content/assets/foo/2010"
);
}

@Test
public void testPermissions() throws RepositoryException {
Session aliceSession = targetRepository.login(new SimpleCredentials("alice", "bar".toCharArray()));
Session bobSession = targetRepository.login(new SimpleCredentials("bob", "bar".toCharArray()));

assertExists(aliceSession,
"/content/assets/foo/2015/02",
"/content/assets/foo/2015/01",
"/content/assets/foo/2014"
);

assertMissing(aliceSession,
"/content/foo/en"
);

assertExists(bobSession,
"/content/foo/en"
);

assertMissing(bobSession,
"/content/assets/foo/2015/02",
"/content/assets/foo/2015/01",
"/content/assets/foo/2014"
);
}

private void createCommonContent(JackrabbitSession session) throws RepositoryException {
UserManager um = session.getUserManager();
um.createUser("alice", "bar");
um.createUser("bob", "bar");
session.save();
}

private void createSourceContent(JackrabbitSession session) throws RepositoryException {
for (String p : Arrays.asList(
"/content/foo/de",
"/content/foo/en",
"/content/foo/fr",
"/content/foo/it",
"/content/assets/foo",
"/content/assets/foo/2015",
"/content/assets/foo/2015/02",
"/content/assets/foo/2015/01",
"/content/assets/foo/2014",
"/content/assets/foo/2013",
"/content/assets/foo/2012",
"/content/assets/foo/2011",
"/content/assets/foo/2010/12")) {
JcrUtils.getOrCreateByPath(p, JcrConstants.NT_FOLDER, JcrConstants.NT_FOLDER, session, false);
}
SegmentNodeStore segmentNodeStore = SegmentNodeStoreBuilders.builder(fileStore).build();

AccessControlUtils.denyAllToEveryone(session, "/content/foo/en");
AccessControlUtils.allow(session.getNode("/content/foo/en"), "bob", "jcr:read");

AccessControlUtils.denyAllToEveryone(session,"/content/assets/foo");
AccessControlUtils.allow(session.getNode("/content/assets/foo"), "alice", "jcr:read");
}

private void performSidegrade() throws RepositoryException {
RepositorySidegrade sidegrade = new RepositorySidegrade(sourceNodeStore, targetNodeStore);
sidegrade.setIncludes(
"/content/foo/en",
"/content/assets/foo",
"/content/other"
);
sidegrade.setExcludes(
"/content/assets/foo/2013",
"/content/assets/foo/2012",
"/content/assets/foo/2011",
"/content/assets/foo/2010"
);
sidegrade.copy();
}

private static RepositoryImpl getRepository(NodeStore nodeStore) {
return (RepositoryImpl) new Jcr(new Oak(nodeStore).with(SecurityProviderBuilder.newBuilder().build())).createRepository();
}

private static void withSession(NodeStore nodeStore, SessionConsumer sessionConsumer) throws RepositoryException {
RepositoryImpl repository = getRepository(nodeStore);
Session session = repository.login(CREDENTIALS);
try {
final RepositorySidegrade sidegrade = new RepositorySidegrade(segmentNodeStore, target);
sidegrade.setIncludes(
"/content/foo/en",
"/content/assets/foo",
"/content/other"
);
sidegrade.setExcludes(
"/content/assets/foo/2013",
"/content/assets/foo/2012",
"/content/assets/foo/2011",
"/content/assets/foo/2010"
);
sidegrade.copy();
sessionConsumer.accept((JackrabbitSession) session);
session.save();
} finally {
fileStore.close();
session.logout();
repository.shutdown();
}
}

private void assertExists(String... paths) throws RepositoryException {
assertExists(targetSession, paths);

}

private void assertExists(Session session, String... paths) throws RepositoryException {
for (String path : paths) {
assertTrue("node " + path + " should exist", session.nodeExists(path));
}
}

private void assertMissing(String... paths) throws RepositoryException {
assertMissing(targetSession, paths);
}

private void assertMissing(Session session, String... paths) throws RepositoryException {
for (String path : paths) {
assertFalse("node " + path + " should not exist", session.nodeExists(path));
}
}

private interface SessionConsumer {
void accept(JackrabbitSession session) throws RepositoryException;
}

}

0 comments on commit 0fdc82e

Please sign in to comment.