Author: stillalex
Date: Wed Jun 28 15:03:41 2017
New Revision: 1800179
URL: http://svn.apache.org/viewvc?rev=1800179&view=rev
Log:
OAK-3374 Concurrent Updates of Group's Membership Results in Conflict
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandler.java
(with props)
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandlerTest.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/CompositeAuthorizationTest.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/CompositeConfiguration.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/SecurityConfiguration.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/package-info.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java
Modified:
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/CompositeAuthorizationTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/CompositeAuthorizationTest.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/CompositeAuthorizationTest.java
(original)
+++
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/CompositeAuthorizationTest.java
Wed Jun 28 15:03:41 2017
@@ -41,6 +41,7 @@ import org.apache.jackrabbit.oak.securit
import
org.apache.jackrabbit.oak.security.authorization.composite.CompositeAuthorizationConfiguration;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
@@ -166,6 +167,12 @@ public class CompositeAuthorizationTest
return Collections.EMPTY_LIST;
}
+ @Nonnull
+ @Override
+ public List<ThreeWayConflictHandler> getConflictHandlers() {
+ return Collections.EMPTY_LIST;
+ }
+
@Nonnull
@Override
public List<ProtectedItemImporter> getProtectedItemImporters() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
Wed Jun 28 15:03:41 2017
@@ -79,6 +79,7 @@ import org.apache.jackrabbit.oak.plugins
import
org.apache.jackrabbit.oak.plugins.index.property.jmx.PropertyIndexAsyncReindex;
import
org.apache.jackrabbit.oak.plugins.index.property.jmx.PropertyIndexAsyncReindexMBean;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.spi.commit.CompositeConflictHandler;
import org.apache.jackrabbit.oak.spi.query.QueryEngineSettings;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
@@ -146,6 +147,8 @@ public class Oak {
private List<EditorProvider> editorProviders = newArrayList();
+ private CompositeConflictHandler conflictHandler;
+
private SecurityProvider securityProvider;
private ScheduledExecutorService scheduledExecutor;
@@ -484,6 +487,10 @@ public class Oak {
if (ri != RepositoryInitializer.DEFAULT) {
initializers.add(ri);
}
+
+ for (ThreeWayConflictHandler tch : sc.getConflictHandlers()) {
+ with(tch);
+ }
}
return this;
}
@@ -505,7 +512,18 @@ public class Oak {
public Oak with(@Nonnull ThreeWayConflictHandler conflictHandler) {
checkNotNull(conflictHandler);
withEditorHook();
- commitHooks.add(new ConflictHook(conflictHandler));
+
+ if (this.conflictHandler == null) {
+ if (conflictHandler instanceof CompositeConflictHandler) {
+ this.conflictHandler = (CompositeConflictHandler)
conflictHandler;
+ } else {
+ this.conflictHandler = new CompositeConflictHandler();
+ this.conflictHandler.addHandler(conflictHandler);
+ }
+ commitHooks.add(new ConflictHook(conflictHandler));
+ } else {
+ this.conflictHandler.addHandler(conflictHandler);
+ }
return this;
}
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandler.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandler.java?rev=1800179&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandler.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandler.java
Wed Jun 28 15:03:41 2017
@@ -0,0 +1,162 @@
+/*
+ * 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.jackrabbit.oak.security.user;
+
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.memory.PropertyBuilder;
+import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.collect.Sets;
+
+/**
+ * The {@code RepMembersConflictHandler} takes care of merging the {@code
rep:members} property
+ * during parallel updates.
+ *<p>
+ * The conflict handler deals with the following conflicts:
+ * <ul>
+ * <li>{@code addExistingProperty} : {@code Resolution.MERGED},</li>
+ * <li>{@code changeDeletedProperty}: {@code Resolution.THEIRS}, removing
the members property takes precedence.
+ * <li>{@code changeChangedProperty}: {@code Resolution.MERGED}, merge of
the 2 members sets into a single one
+ * <li>{@code deleteChangedProperty}: {@code Resolution.OURS} removing the
members property takes precedence.
+ * </ul>
+ */
+public class RepMembersConflictHandler implements ThreeWayConflictHandler {
+
+ @Nonnull
+ @Override
+ public Resolution addExistingProperty(@Nonnull NodeBuilder parent,
@Nonnull PropertyState ours,
+ @Nonnull PropertyState theirs) {
+ if (isRepMembersProperty(theirs)) {
+ mergeChange(parent, ours, theirs,Sets.newHashSet());
+ return Resolution.MERGED;
+ } else {
+ return Resolution.IGNORED;
+ }
+ }
+
+ @Override
+ @Nonnull
+ public Resolution changeDeletedProperty(@Nonnull NodeBuilder parent,
@Nonnull PropertyState ours,
+ @Nonnull PropertyState base) {
+ if (isRepMembersProperty(ours)) {
+ // removing the members property takes precedence
+ return Resolution.THEIRS;
+ } else {
+ return Resolution.IGNORED;
+ }
+ }
+
+ @Nonnull
+ @Override
+ public Resolution changeChangedProperty(@Nonnull NodeBuilder parent,
@Nonnull PropertyState ours,
+ @Nonnull PropertyState theirs, @Nonnull PropertyState base) {
+ if (isRepMembersProperty(theirs)) {
+ Set<String> baseMembers =
Sets.newHashSet(base.getValue(Type.STRINGS));
+ mergeChange(parent, ours, theirs, baseMembers);
+ return Resolution.MERGED;
+ } else {
+ return Resolution.IGNORED;
+ }
+ }
+
+ @Nonnull
+ @Override
+ public Resolution deleteDeletedProperty(@Nonnull NodeBuilder parent,
@Nonnull PropertyState base) {
+ // both are removing the members property, ignoring
+ return Resolution.IGNORED;
+ }
+
+ @Nonnull
+ @Override
+ public Resolution deleteChangedProperty(@Nonnull NodeBuilder parent,
@Nonnull PropertyState theirs,
+ @Nonnull PropertyState base) {
+ if (isRepMembersProperty(theirs)) {
+ // removing the members property takes precedence
+ return Resolution.OURS;
+ } else {
+ return Resolution.IGNORED;
+ }
+ }
+
+
+ @Nonnull
+ @Override
+ public Resolution addExistingNode(@Nonnull NodeBuilder parent, @Nonnull
String name, @Nonnull NodeState ours,
+ @Nonnull NodeState theirs) {
+ return Resolution.IGNORED;
+ }
+
+ @Nonnull
+ @Override
+ public Resolution changeDeletedNode(@Nonnull NodeBuilder parent, @Nonnull
String name, @Nonnull NodeState ours,
+ @Nonnull NodeState base) {
+ return Resolution.IGNORED;
+ }
+
+ @Nonnull
+ @Override
+ public Resolution deleteChangedNode(@Nonnull NodeBuilder parent, @Nonnull
String name, @Nonnull NodeState theirs,
+ @Nonnull NodeState base) {
+ return Resolution.IGNORED;
+ }
+
+ @Nonnull
+ @Override
+ public Resolution deleteDeletedNode(@Nonnull NodeBuilder parent, @Nonnull
String name, @Nonnull NodeState base) {
+ return Resolution.IGNORED;
+ }
+
+ //----------------------------< internal
>----------------------------------
+
+ private static void mergeChange(NodeBuilder parent, PropertyState ours,
PropertyState theirs, Set<String> base) {
+ PropertyBuilder<String> merged = PropertyBuilder.array(Type.STRING);
+ merged.setName(UserConstants.REP_MEMBERS);
+
+ Set<String> theirMembers =
Sets.newHashSet(theirs.getValue(Type.STRINGS));
+ Set<String> ourMembers = Sets.newHashSet(ours.getValue(Type.STRINGS));
+
+ // merge ours and theirs to a de-duplicated set
+ Set<String> combined = Sets.newHashSet(Sets.intersection(ourMembers,
theirMembers));
+ for (String m : Sets.difference(ourMembers, theirMembers)) {
+ if (!base.contains(m)) {
+ combined.add(m);
+ }
+ }
+ for (String m : Sets.difference(theirMembers, ourMembers)) {
+ if (!base.contains(m)) {
+ combined.add(m);
+ }
+ }
+ merged.addValues(combined);
+ parent.setProperty(merged.getPropertyState());
+ }
+
+ private static boolean isRepMembersProperty(PropertyState p) {
+ return UserConstants.REP_MEMBERS.equals(p.getName());
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java
Wed Jun 28 15:03:41 2017
@@ -37,6 +37,7 @@ import org.apache.jackrabbit.oak.api.Roo
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.security.user.autosave.AutoSaveEnabledManager;
import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
@@ -181,6 +182,12 @@ public class UserConfigurationImpl exten
}
@Nonnull
+ @Override
+ public List<ThreeWayConflictHandler> getConflictHandlers() {
+ return ImmutableList.of(new RepMembersConflictHandler());
+ }
+
+ @Nonnull
@Override
public List<ProtectedItemImporter> getProtectedItemImporters() {
return Collections.<ProtectedItemImporter>singletonList(new
UserImporter(getParameters()));
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/CompositeConfiguration.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/CompositeConfiguration.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/CompositeConfiguration.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/CompositeConfiguration.java
Wed Jun 28 15:03:41 2017
@@ -28,6 +28,7 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import aQute.bnd.annotation.ProviderType;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@@ -39,6 +40,7 @@ import org.apache.jackrabbit.oak.api.Tre
import org.apache.jackrabbit.oak.plugins.tree.TreeLocation;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
import org.apache.jackrabbit.oak.spi.lifecycle.CompositeInitializer;
import org.apache.jackrabbit.oak.spi.lifecycle.CompositeWorkspaceInitializer;
@@ -51,6 +53,7 @@ import org.osgi.framework.Constants;
* Abstract base implementation for {@link SecurityConfiguration}s that can
* combine different implementations.
*/
+@ProviderType
public abstract class CompositeConfiguration<T extends SecurityConfiguration>
implements SecurityConfiguration {
/**
@@ -213,6 +216,12 @@ public abstract class CompositeConfigura
}
@Nonnull
+ @Override
+ public List<ThreeWayConflictHandler> getConflictHandlers() {
+ return
ImmutableList.copyOf(Iterables.concat(Lists.transform(getConfigurations(),
securityConfiguration -> securityConfiguration.getConflictHandlers())));
+ }
+
+ @Nonnull
@Override
public List<ProtectedItemImporter> getProtectedItemImporters() {
return
ImmutableList.copyOf(Iterables.concat(Lists.transform(getConfigurations(), new
Function<T, List<? extends ProtectedItemImporter>>() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/SecurityConfiguration.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/SecurityConfiguration.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/SecurityConfiguration.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/SecurityConfiguration.java
Wed Jun 28 15:03:41 2017
@@ -23,8 +23,10 @@ import java.util.Set;
import javax.annotation.Nonnull;
+import aQute.bnd.annotation.ProviderType;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
+import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
import org.apache.jackrabbit.oak.spi.lifecycle.WorkspaceInitializer;
@@ -33,6 +35,7 @@ import org.apache.jackrabbit.oak.spi.xml
/**
* Base interface for all security related configurations.
*/
+@ProviderType
public interface SecurityConfiguration {
/**
@@ -99,6 +102,14 @@ public interface SecurityConfiguration {
@Nonnull MoveTracker
moveTracker);
/**
+ * Returns the list of conflict handlers available for this security
configuration.
+ *
+ * @return A list of {@link
org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler}.
+ */
+ @Nonnull
+ List<ThreeWayConflictHandler> getConflictHandlers();
+
+ /**
* @return The list of protected item importers defined by this
configuration.
*/
@Nonnull
@@ -153,6 +164,12 @@ public interface SecurityConfiguration {
return Collections.emptyList();
}
+ @Nonnull
+ @Override
+ public List<ThreeWayConflictHandler> getConflictHandlers() {
+ return Collections.emptyList();
+ }
+
@Nonnull
@Override
public List<ProtectedItemImporter> getProtectedItemImporters() {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
Wed Jun 28 15:03:41 2017
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.2.0")
+@Version("1.3.0")
package org.apache.jackrabbit.oak.spi.security.authentication;
import aQute.bnd.annotation.Version;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/token/package-info.java
Wed Jun 28 15:03:41 2017
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.4.1")
+@Version("1.5.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.authentication.token;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/package-info.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authorization/package-info.java
Wed Jun 28 15:03:41 2017
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0")
+@Version("1.1.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.authorization;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/package-info.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/package-info.java
Wed Jun 28 15:03:41 2017
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("2.1.0")
+@Version("2.2.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/principal/package-info.java
Wed Jun 28 15:03:41 2017
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.4.0")
+@Version("1.5.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.principal;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/privilege/package-info.java
Wed Jun 28 15:03:41 2017
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.1.0")
+@Version("1.2.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.privilege;
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/package-info.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/package-info.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/package-info.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/package-info.java
Wed Jun 28 15:03:41 2017
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("2.2.0")
+@Version("2.3.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.spi.security.user;
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandlerTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandlerTest.java?rev=1800179&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandlerTest.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandlerTest.java
Wed Jun 28 15:03:41 2017
@@ -0,0 +1,287 @@
+/*
+ * 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.jackrabbit.oak.security.user;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+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.AbstractSecurityTest;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.junit.Test;
+
+public class RepMembersConflictHandlerTest extends AbstractSecurityTest {
+
+ /**
+ * The id of the test group
+ */
+ private static final String GROUP_ID = "test-groupId";
+
+ private Group group;
+ private User[] users;
+
+ @Override
+ public void before() throws Exception {
+ super.before();
+ UserManager um = getUserManager(root);
+ // create a group to receive users
+ group = um.createGroup(GROUP_ID);
+ // create future members of the above group
+ User u1 = um.createUser("u1", "pass");
+ User u2 = um.createUser("u2", "pass");
+ User u3 = um.createUser("u3", "pass");
+ User u4 = um.createUser("u4", "pass");
+ User u5 = um.createUser("u5", "pass");
+ root.commit();
+ users = new User[] { u1, u2, u3, u4, u5 };
+ }
+
+ @Test
+ public void addExistingProperty() throws Exception {
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ add(ours, users[1].getID());
+ add(theirs, users[2].getID());
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[1]));
+ assertTrue(group.isDeclaredMember(users[2]));
+ }
+
+ /**
+ * Add-Add test
+ */
+ @Test
+ public void changeChangedPropertyAA() throws Exception {
+ add(root, users[0].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ add(ours, users[1].getID());
+ add(theirs, users[2].getID());
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertTrue(group.isDeclaredMember(users[1]));
+ assertTrue(group.isDeclaredMember(users[2]));
+ }
+
+ /**
+ * Remove-Remove test
+ */
+ @Test
+ public void changeChangedPropertyRR() throws Exception {
+ add(root, users[0].getID(), users[1].getID(), users[2].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ rm(ours, users[1].getID());
+ rm(theirs, users[2].getID());
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertFalse(group.isDeclaredMember(users[1]));
+ assertFalse(group.isDeclaredMember(users[2]));
+ }
+
+ /**
+ * Remove-Add with different ids test
+ */
+ @Test
+ public void changeChangedPropertyRA() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ rm(ours, users[1].getID());
+ add(theirs, users[2].getID());
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertFalse(group.isDeclaredMember(users[1]));
+ assertTrue(group.isDeclaredMember(users[2]));
+ }
+
+ /**
+ * Add-Remove with different ids test
+ */
+ @Test
+ public void changeChangedPropertyAR() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ add(ours, users[2].getID());
+ rm(theirs, users[1].getID());
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertFalse(group.isDeclaredMember(users[1]));
+ assertTrue(group.isDeclaredMember(users[2]));
+ }
+
+ /**
+ * Remove-Add same value test. value was already part of the group
+ */
+ @Test
+ public void changeChangedPropertyRA2() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ String id = users[1].getID();
+ rm(ours, id);
+ add(theirs, id);
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertFalse(group.isDeclaredMember(users[1]));
+ }
+
+ /**
+ * Add-Remove same value test. value was already part of the group
+ */
+ @Test
+ public void changeChangedPropertyAR2() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ String id = users[1].getID();
+ add(ours, id);
+ rm(theirs, id);
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertFalse(group.isDeclaredMember(users[1]));
+ }
+
+ /**
+ * Remove-Add same value test. value was not part of the group
+ */
+ @Test
+ public void changeChangedPropertyRA3() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ String id = users[2].getID();
+ // we are removing an item that does not yet exist, this should
+ // not overlap/conflict with the other session adding the same item
+ rm(ours, id);
+ add(theirs, id);
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertTrue(group.isDeclaredMember(users[1]));
+ assertTrue(group.isDeclaredMember(users[2]));
+ }
+
+ /**
+ * Add-Remove same value test. value was not part of the group
+ */
+ @Test
+ public void changeChangedPropertyAR3() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ String id = users[2].getID();
+ add(ours, id);
+ // we are removing an item that does not yet exist, this should
+ // not overlap/conflict with the other session adding the same item
+ rm(theirs, id);
+
+ root.refresh();
+ assertTrue(group.isDeclaredMember(users[0]));
+ assertTrue(group.isDeclaredMember(users[1]));
+ assertTrue(group.isDeclaredMember(users[2]));
+ }
+
+ /**
+ * Delete-Changed. Delete takes precedence
+ */
+ @Test
+ public void deleteChangedProperty() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ add(theirs, users[2].getID());
+ wipeGroup(ours);
+
+ root.refresh();
+ assertFalse(group.isDeclaredMember(users[0]));
+ assertFalse(group.isDeclaredMember(users[1]));
+ }
+
+ /**
+ * Changed-Deleted. Delete takes precedence
+ */
+ @Test
+ public void changeDeletedProperty() throws Exception {
+ add(root, users[0].getID(), users[1].getID());
+
+ Root ours = login(getAdminCredentials()).getLatestRoot();
+ Root theirs = login(getAdminCredentials()).getLatestRoot();
+
+ wipeGroup(theirs);
+ add(ours, users[2].getID());
+
+ root.refresh();
+ assertFalse(group.isDeclaredMember(users[0]));
+ assertFalse(group.isDeclaredMember(users[1]));
+ }
+
+ private void add(Root r, String... ids) throws Exception {
+ UserManager um = getUserManager(r);
+ Group g = (Group) um.getAuthorizable(GROUP_ID);
+ for (String id : ids) {
+ g.addMember(um.getAuthorizable(id));
+ }
+ r.commit();
+ }
+
+ private void rm(Root r, String... ids) throws Exception {
+ UserManager um = getUserManager(r);
+ Group g = (Group) um.getAuthorizable(GROUP_ID);
+ for (String id : ids) {
+ g.removeMember(um.getAuthorizable(id));
+ }
+ r.commit();
+ }
+
+ private void wipeGroup(Root r) throws Exception {
+ UserManager um = getUserManager(r);
+ Group g = (Group) um.getAuthorizable(GROUP_ID);
+ r.getTree(g.getPath()).removeProperty(UserConstants.REP_MEMBERS);
+ r.commit();
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RepMembersConflictHandlerTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java?rev=1800179&r1=1800178&r2=1800179&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/CompositeConfigurationTest.java
Wed Jun 28 15:03:41 2017
@@ -21,6 +21,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
+import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
import org.junit.Before;
import org.junit.Test;
@@ -193,7 +194,7 @@ public class CompositeConfigurationTest
}
@Test
- public void testGetProtectedItemImporter() {
+ public void testGetProtectedItemImporters() {
assertTrue(compositeConfiguration.getProtectedItemImporters().isEmpty());
addConfiguration(new SecurityConfiguration.Default());
@@ -210,4 +211,24 @@ public class CompositeConfigurationTest
assertEquals(1,
compositeConfiguration.getProtectedItemImporters().size());
}
+
+
+ @Test
+ public void testGetConflictHandlers() {
+ assertTrue(compositeConfiguration.getConflictHandlers().isEmpty());
+
+ addConfiguration(new SecurityConfiguration.Default());
+ assertTrue(compositeConfiguration.getConflictHandlers().isEmpty());
+
+ SecurityConfiguration withConflictHandler = new
SecurityConfiguration.Default() {
+ @Nonnull
+ @Override
+ public List<ThreeWayConflictHandler> getConflictHandlers() {
+ return
ImmutableList.of(Mockito.mock(ThreeWayConflictHandler.class));
+ }
+ };
+ addConfiguration(withConflictHandler);
+
+ assertEquals(1, compositeConfiguration.getConflictHandlers().size());
+ }
}
\ No newline at end of file