Skip to content

Commit

Permalink
OAK-9366 : Monitoring for user management implementation
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/oak/trunk@1887201 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
anchela committed Mar 5, 2021
1 parent 36e386a commit cbacf77
Show file tree
Hide file tree
Showing 21 changed files with 638 additions and 54 deletions.
1 change: 1 addition & 0 deletions oak-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
<include>org.apache.jackrabbit.oak.security.principal</include>
<include>org.apache.jackrabbit.oak.security.privilege</include>
<include>org.apache.jackrabbit.oak.security.user.autosave</include>
<include>org.apache.jackrabbit.oak.security.user.monitor</include>
<include>org.apache.jackrabbit.oak.security.user.query</include>
<include>org.apache.jackrabbit.oak.security.user.whiteboard</include>
</includes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import javax.jcr.RepositoryException;
import javax.jcr.Value;

import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import org.apache.jackrabbit.api.security.user.Authorizable;
Expand All @@ -29,6 +30,7 @@
import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.security.user.monitor.UserMonitor;
import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
Expand All @@ -37,6 +39,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static org.apache.jackrabbit.oak.api.Type.STRING;

/**
Expand Down Expand Up @@ -82,13 +85,13 @@ public String getID() {
@NotNull
@Override
public Iterator<Group> declaredMemberOf() throws RepositoryException {
return getMembership(false);
return memberOfMonitored(false);
}

@NotNull
@Override
public Iterator<Group> memberOf() throws RepositoryException {
return getMembership(true);
return memberOfMonitored(true);
}

@Override
Expand Down Expand Up @@ -216,6 +219,11 @@ MembershipProvider getMembershipProvider() {
return userManager.getMembershipProvider();
}

@NotNull
UserMonitor getMonitor() {
return userManager.getMonitor();
}

/**
* Returns {@code true} if this authorizable represents the 'everyone' group.
*
Expand Down Expand Up @@ -249,6 +257,14 @@ private AuthorizableProperties getAuthorizableProperties() {
return properties;
}

@NotNull
private Iterator<Group> memberOfMonitored(boolean includeInherited) throws RepositoryException {
Stopwatch watch = Stopwatch.createStarted();
Iterator<Group> groups = getMembership(includeInherited);
getMonitor().doneMemberOf(watch.elapsed(NANOSECONDS), !includeInherited);
return groups;
}

/**
* Retrieve the group membership of this authorizable.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import javax.jcr.nodetype.ConstraintViolationException;

import com.google.common.base.Predicates;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
Expand All @@ -40,6 +41,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
* GroupImpl...
*/
Expand Down Expand Up @@ -75,13 +78,13 @@ public Principal getPrincipal() throws RepositoryException {
@NotNull
@Override
public Iterator<Authorizable> getDeclaredMembers() throws RepositoryException {
return getMembers(false);
return getMembersMonitored(false);
}

@NotNull
@Override
public Iterator<Authorizable> getMembers() throws RepositoryException {
return getMembers(true);
return getMembersMonitored(true);
}

@Override
Expand All @@ -96,6 +99,13 @@ public boolean isMember(@NotNull Authorizable authorizable) throws RepositoryExc

@Override
public boolean addMember(@NotNull Authorizable authorizable) throws RepositoryException {
Stopwatch watch = Stopwatch.createStarted();
boolean success = internalAddMember(authorizable);
getMonitor().doneUpdateMembers(watch.elapsed(NANOSECONDS), 1, (success) ? 0 : 1, false);
return success;
}

private boolean internalAddMember(@NotNull Authorizable authorizable) throws RepositoryException {
if (!isValidAuthorizableImpl(authorizable)) {
log.warn("Invalid Authorizable: {}", authorizable);
return false;
Expand Down Expand Up @@ -132,11 +142,18 @@ public boolean addMember(@NotNull Authorizable authorizable) throws RepositoryEx
@NotNull
@Override
public Set<String> addMembers(@NotNull String... memberIds) throws RepositoryException {
return updateMembers(false, memberIds);
return updateMembersMonitored(false, memberIds);
}

@Override
public boolean removeMember(@NotNull Authorizable authorizable) throws RepositoryException {
Stopwatch watch = Stopwatch.createStarted();
boolean success = internalRemoveMember(authorizable);
getMonitor().doneUpdateMembers(watch.elapsed(NANOSECONDS), 1, (success) ? 0 : 1, true);
return success;
}

private boolean internalRemoveMember(@NotNull Authorizable authorizable) throws RepositoryException {
if (!isValidAuthorizableImpl(authorizable)) {
log.warn("Invalid Authorizable: {}", authorizable);
return false;
Expand All @@ -162,10 +179,18 @@ public boolean removeMember(@NotNull Authorizable authorizable) throws Repositor
@NotNull
@Override
public Set<String> removeMembers(@NotNull String... memberIds) throws RepositoryException {
return updateMembers(true, memberIds);
return updateMembersMonitored(true, memberIds);
}

//--------------------------------------------------------------------------
@NotNull
private Iterator<Authorizable> getMembersMonitored(boolean includeInherited) throws RepositoryException {
Stopwatch watch = Stopwatch.createStarted();
Iterator<Authorizable> members = getMembers(includeInherited);
getMonitor().doneGetMembers(watch.elapsed(NANOSECONDS), !includeInherited);
return members;
}

/**
* Internal implementation of {@link #getDeclaredMembers()} and {@link #getMembers()}.
*
Expand Down Expand Up @@ -231,6 +256,14 @@ private boolean isMember(@NotNull Authorizable authorizable, boolean includeInhe
}
}

@NotNull
private Set<String> updateMembersMonitored(boolean isRemove, @NotNull String... memberIds) throws RepositoryException {
Stopwatch watch = Stopwatch.createStarted();
Set<String> failed = updateMembers(isRemove, memberIds);
getMonitor().doneUpdateMembers(watch.elapsed(NANOSECONDS), memberIds.length, failed.size(), isRemove);
return failed;
}

/**
* Internal method to add or remove members by ID.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory;
import org.apache.jackrabbit.oak.security.user.autosave.AutoSaveEnabledManager;
import org.apache.jackrabbit.oak.security.user.monitor.UserMonitor;
import org.apache.jackrabbit.oak.security.user.monitor.UserMonitorImpl;
import org.apache.jackrabbit.oak.spi.commit.MoveTracker;
import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler;
import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider;
Expand All @@ -48,6 +50,8 @@
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter;
import org.apache.jackrabbit.oak.stats.Monitor;
import org.apache.jackrabbit.oak.stats.StatisticsProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.service.component.annotations.Activate;
Expand Down Expand Up @@ -192,6 +196,8 @@ private void activate(Configuration configuration, Map<String, Object> propertie
setParameters(ConfigurationParameters.of(properties));
}

private UserMonitor monitor = UserMonitor.NOOP;

private BlobAccessProvider blobAccessProvider;

@Reference(cardinality = ReferenceCardinality.OPTIONAL,
Expand Down Expand Up @@ -254,12 +260,18 @@ public Context getContext() {
return UserContext.getInstance();
}

@Override
public @NotNull Iterable<Monitor<?>> getMonitors(@NotNull StatisticsProvider statisticsProvider) {
monitor = new UserMonitorImpl(statisticsProvider);
return Collections.singleton(monitor);
}

//--------------------------------------------------< UserConfiguration >---
@NotNull
@Override
public UserManager getUserManager(Root root, NamePathMapper namePathMapper) {
PartialValueFactory vf = new PartialValueFactory(namePathMapper, getBlobAccessProvider());
UserManager umgr = new UserManagerImpl(root, vf, getSecurityProvider());
UserManager umgr = new UserManagerImpl(root, vf, getSecurityProvider(), monitor);
if (getParameters().getConfigValue(UserConstants.PARAM_SUPPORT_AUTOSAVE, false)) {
return new AutoSaveEnabledManager(umgr, root);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.security.user;

import com.google.common.base.Stopwatch;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
Expand All @@ -37,13 +38,17 @@
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.security.user.autosave.AutoSaveEnabledManager;
import org.apache.jackrabbit.oak.security.user.monitor.UserMonitor;
import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.jackrabbit.oak.spi.security.user.util.UserUtil;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAware;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
import org.apache.jackrabbit.oak.spi.xml.NodeInfo;
import org.apache.jackrabbit.oak.spi.xml.PropInfo;
Expand Down Expand Up @@ -74,6 +79,7 @@

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static org.apache.jackrabbit.oak.api.Type.STRINGS;

/**
Expand Down Expand Up @@ -166,6 +172,8 @@ class UserImporter implements ProtectedPropertyImporter, ProtectedNodeImporter,
*/
private Map<String, Principal> principals = new HashMap<>();

private UserMonitor userMonitor = UserMonitor.NOOP;

UserImporter(ConfigurationParameters config) {
importBehavior = UserUtil.getImportBehavior(config);
}
Expand Down Expand Up @@ -202,6 +210,14 @@ public boolean init(@NotNull Session session, @NotNull Root root, @NotNull NameP
return false;
}

if (securityProvider instanceof WhiteboardAware) {
Whiteboard whiteboard = ((WhiteboardAware) securityProvider).getWhiteboard();
UserMonitor monitor = WhiteboardUtils.getService(whiteboard, UserMonitor.class);
if (monitor != null) {
userMonitor = monitor;
}
}

initialized = true;
return initialized;
}
Expand Down Expand Up @@ -622,16 +638,19 @@ void process() throws RepositoryException {

// handling non-existing members in case of best-effort
if (!nonExisting.isEmpty()) {
Stopwatch watch = Stopwatch.createStarted();
log.debug("ImportBehavior.BESTEFFORT: Found {} entries of rep:members pointing to non-existing authorizables. Adding to rep:members.", nonExisting.size());
Tree groupTree = root.getTree(gr.getPath());

MembershipProvider membershipProvider = userManager.getMembershipProvider();

long totalSize = nonExisting.size();
Set<String> memberContentIds = Sets.newHashSet(nonExisting.keySet());
Set<String> failedContentIds = membershipProvider.addMembers(groupTree, nonExisting);
memberContentIds.removeAll(failedContentIds);

userManager.onGroupUpdate(gr, false, true, memberContentIds, failedContentIds);
userMonitor.doneUpdateMembers(watch.elapsed(NANOSECONDS), totalSize, failedContentIds.size(), false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,6 @@
*/
package org.apache.jackrabbit.oak.security.user;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.util.Iterator;
import java.util.Set;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;

import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
Expand All @@ -40,6 +32,7 @@
import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory;
import org.apache.jackrabbit.oak.security.user.monitor.UserMonitor;
import org.apache.jackrabbit.oak.security.user.query.UserQueryManager;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
Expand All @@ -61,6 +54,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.util.Iterator;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;

/**
Expand All @@ -79,17 +80,20 @@ public class UserManagerImpl implements UserManager {
private final MembershipProvider membershipProvider;
private final ConfigurationParameters config;
private final AuthorizableActionProvider actionProvider;
private final UserMonitor monitor;

private UserQueryManager queryManager;
private ReadOnlyNodeTypeManager ntMgr;

public UserManagerImpl(@NotNull Root root,
@NotNull PartialValueFactory valueFactory,
@NotNull SecurityProvider securityProvider) {
@NotNull SecurityProvider securityProvider,
@NotNull UserMonitor monitor) {
this.root = root;
this.valueFactory = valueFactory;
this.namePathMapper = valueFactory.getNamePathMapper();
this.securityProvider = securityProvider;
this.monitor = monitor;

UserConfiguration uc = securityProvider.getConfiguration(UserConfiguration.class);
this.config = uc.getParameters();
Expand Down Expand Up @@ -448,6 +452,11 @@ PrincipalManager getPrincipalManager() {
return securityProvider.getConfiguration(PrincipalConfiguration.class).getPrincipalManager(root, namePathMapper);
}

@NotNull
UserMonitor getMonitor() {
return monitor;
}

@NotNull
ConfigurationParameters getConfig() {
return config;
Expand Down
Loading

0 comments on commit cbacf77

Please sign in to comment.