You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by tr...@apache.org on 2014/04/15 19:19:21 UTC
svn commit: r1587638 - in /jackrabbit/oak/branches/1.0:
oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/
oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/...
Author: tripod
Date: Tue Apr 15 17:19:20 2014
New Revision: 1587638
URL: http://svn.apache.org/r1587638
Log:
OAK-1711 Provide tools to manage externally synced users
Added:
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncResult.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncResultImpl.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncedIdentityImpl.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SynchronizationMBean.java
jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/add_user.sh (with props)
jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/del_user.sh (with props)
Modified:
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityProvider.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java
jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityProvider.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityProvider.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/ExternalIdentityProvider.java Tue Apr 15 17:19:20 2014
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.spi.security.authentication.external;
+import java.util.Iterator;
+
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.jcr.Credentials;
@@ -78,4 +80,20 @@ public interface ExternalIdentityProvide
*/
@CheckForNull
ExternalGroup getGroup(@Nonnull String name) throws ExternalIdentityException;
+
+ /**
+ * List all external users.
+ * @return an iterator over all external users
+ * @throws ExternalIdentityException if an error occurs.
+ */
+ @Nonnull
+ Iterator<ExternalUser> listUsers() throws ExternalIdentityException;
+
+ /**
+ * List all external groups.
+ * @return an iterator over all external groups
+ * @throws ExternalIdentityException if an error occurs.
+ */
+ @Nonnull
+ Iterator<ExternalGroup> listGroups() throws ExternalIdentityException;
}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncContext.java Tue Apr 15 17:19:20 2014
@@ -25,23 +25,61 @@ import javax.annotation.Nonnull;
public interface SyncContext {
/**
+ * Defines if synchronization keeps missing external identities on synchronization of authorizables. Default
+ * is {@code false}.
+ * @return {@code true} if keep missing.
+ */
+ boolean isKeepMissing();
+
+ /**
+ * See {@link #isKeepMissing()}
+ */
+ @Nonnull
+ SyncContext setKeepMissing(boolean keep);
+
+ /**
+ * Defines if synchronization of users always will perform, i.e. ignores the last synced properties.
+ * @return {@code true} if forced syncing users
+ */
+ boolean isForceUserSync();
+
+ /**
+ * See {@link #isForceUserSync()}
+ */
+ @Nonnull
+ SyncContext setForceUserSync(boolean force);
+
+ /**
+ * Defines if synchronization of groups always will perform, i.e. ignores the last synced properties.
+ * @return {@code true} if forced syncing groups
+ */
+ boolean isForceGroupSync();
+
+ /**
+ * See {@link #isForceGroupSync()}
+ */
+ @Nonnull
+ SyncContext setForceGroupSync(boolean force);
+
+ /**
* Synchronizes an external identity with the repository based on the respective configuration.
*
* @param identity the identity to sync.
- * @return {@code true} if the given identity was synced; {@code false} for no change.
+ * @return the result of the operation
* @throws SyncException if an error occurrs
*/
- boolean sync(@Nonnull ExternalIdentity identity) throws SyncException;
+ SyncResult sync(@Nonnull ExternalIdentity identity) throws SyncException;
/**
* Synchronizes an authorizable with the corresponding external identity with the repository based on the respective
* configuration.
*
* @param id the id of the authorizable
- * @return {@code true} if the given identity was synced; {@code false} for no change.
+ * @return the result of the operation
* @throws SyncException if an error occurrs
*/
- boolean sync(@Nonnull String id) throws SyncException;
+ SyncResult sync(@Nonnull String id) throws SyncException;
+
/**
* Closes this context and releases any resources bound to it. Note that an implementation must not commit the
@@ -49,4 +87,5 @@ public interface SyncContext {
* application.
*/
void close();
+
}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncHandler.java Tue Apr 15 17:19:20 2014
@@ -16,17 +16,22 @@
*/
package org.apache.jackrabbit.oak.spi.security.authentication.external;
+import java.util.Iterator;
+
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.jcr.RepositoryException;
+import javax.jcr.ValueFactory;
import org.apache.jackrabbit.api.security.user.UserManager;
-import org.apache.jackrabbit.oak.api.Root;
+
+import com.google.common.base.Predicate;
/**
* SyncHandler is used to sync users and groups from an {@link ExternalIdentityProvider}.
* The synchronization performed within the scope of a {@link SyncContext} which is acquired during the
- * {@link #createContext(ExternalIdentityProvider, org.apache.jackrabbit.api.security.user.UserManager, org.apache.jackrabbit.oak.api.Root)} call.
+ * {@link #createContext(ExternalIdentityProvider, org.apache.jackrabbit.api.security.user.UserManager, javax.jcr.ValueFactory)} call.
*
* The exact configuration is managed by the sync handler instance. The system may contain several sync handler
* implementations with different configurations. those are managed by the {@link SyncManager}.
@@ -48,21 +53,31 @@ public interface SyncHandler {
*
* @param idp the external identity provider used for syncing
* @param userManager user manager for managing authorizables
- * @param root root of the current tree
+ * @param valueFactory the value factory to create values
* @return the sync context
* @throws SyncException if an error occurs
*/
@Nonnull
SyncContext createContext(@Nonnull ExternalIdentityProvider idp,
@Nonnull UserManager userManager,
- @Nonnull Root root) throws SyncException;
+ @Nonnull ValueFactory valueFactory) throws SyncException;
/**
* Tries to find the identity with the given authorizable id or name.
* @param userManager the user manager
* @param id the id or name of the authorizable
* @return a synced identity object or {@code null}
+ * @throws RepositoryException if an error occurs
*/
@CheckForNull
SyncedIdentity findIdentity(@Nonnull UserManager userManager, @Nonnull String id) throws RepositoryException;
+
+ /**
+ * Lists all externally synced identities.
+ * @param userManager the user manager
+ * @return an iterator over all authorizable that are externally synced.
+ * @throws RepositoryException if an error occurs
+ */
+ @Nonnull
+ Iterator<SyncedIdentity> listIdentities(@Nonnull UserManager userManager) throws RepositoryException;
}
\ No newline at end of file
Added: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncResult.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncResult.java?rev=1587638&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncResult.java (added)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/SyncResult.java Tue Apr 15 17:19:20 2014
@@ -0,0 +1,87 @@
+/*
+ * 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.spi.security.authentication.external;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+/**
+ * Defines the result of a sync operation
+ */
+public interface SyncResult {
+
+ /**
+ * The synchronized identity
+ * @return the identity
+ */
+ @CheckForNull
+ SyncedIdentity getIdentity();
+
+ /**
+ * The status of the sync operation
+ * @return the status
+ */
+ @Nonnull
+ Status getStatus();
+
+ /**
+ * Result codes for sync operation.
+ */
+ enum Status {
+
+ /**
+ * No update
+ */
+ NOP,
+
+ /**
+ * authorizable added
+ */
+ ADD,
+
+ /**
+ * authorizable updated
+ */
+ UPDATE,
+
+ /**
+ * authorizable deleted
+ */
+ DELETE,
+
+ /**
+ * nothing changed. no such authorizable found.
+ */
+ NO_SUCH_AUTHORIZABLE,
+
+ /**
+ * nothing changed. no such identity found.
+ */
+ NO_SUCH_IDENTITY,
+
+ /**
+ * nothing changed. corresponding identity missing
+ */
+ MISSING,
+
+ /**
+ * nothing changed. idp name not correct
+ */
+ FOREIGN
+ }
+
+}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/DefaultSyncHandler.java Tue Apr 15 17:19:20 2014
@@ -46,9 +46,7 @@ import org.apache.jackrabbit.api.securit
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.api.Root;
-import org.apache.jackrabbit.oak.namepath.NamePathMapper;
-import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
+import org.apache.jackrabbit.commons.iterator.AbstractLazyIterator;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
@@ -59,6 +57,7 @@ import org.apache.jackrabbit.oak.spi.sec
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncContext;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncedIdentity;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.slf4j.Logger;
@@ -133,9 +132,9 @@ public class DefaultSyncHandler implemen
*/
@Nonnull
@Override
- public SyncContext createContext(@Nonnull ExternalIdentityProvider idp, @Nonnull UserManager userManager, @Nonnull Root root)
- throws SyncException {
- return new ContextImpl(idp, userManager, root);
+ public SyncContext createContext(@Nonnull ExternalIdentityProvider idp, @Nonnull UserManager userManager,
+ @Nonnull ValueFactory valueFactory) throws SyncException {
+ return new ContextImpl(idp, userManager, valueFactory);
}
/**
@@ -144,17 +143,54 @@ public class DefaultSyncHandler implemen
@Override
public SyncedIdentity findIdentity(@Nonnull UserManager userManager, @Nonnull String id)
throws RepositoryException {
- Authorizable auth = userManager.getAuthorizable(id);
- if (auth == null) {
+ return createSyncedIdentity(userManager.getAuthorizable(id));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Iterator<SyncedIdentity> listIdentities(@Nonnull UserManager userManager) throws RepositoryException {
+ final Iterator<Authorizable> iter = userManager.findAuthorizables("jcr:primaryType", null);
+ return new AbstractLazyIterator<SyncedIdentity>() {
+
+ @Override
+ protected SyncedIdentity getNext() {
+ while (iter.hasNext()) {
+ try {
+ SyncedIdentity id = createSyncedIdentity(iter.next());
+ if (id != null) {
+ return id;
+ }
+ } catch (RepositoryException e) {
+ log.error("Error while fetching authorizables", e);
+ break;
+ }
+ }
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Creates a synced identity from the given authorizable.
+ * @param auth the authorizable
+ * @return the id
+ * @throws RepositoryException if an error occurrs
+ */
+ @CheckForNull
+ private static SyncedIdentityImpl createSyncedIdentity(@Nullable Authorizable auth) throws RepositoryException {
+ ExternalIdentityRef ref = auth == null ? null : getIdentityRef(auth);
+ if (ref == null) {
return null;
+ } else {
+ Value[] lmValues = auth.getProperty(REP_LAST_SYNCED);
+ long lastModified = -1;
+ if (lmValues != null && lmValues.length > 0) {
+ lastModified = lmValues[0].getLong();
+ }
+ return new SyncedIdentityImpl(auth.getID(), ref, auth.isGroup(), lastModified);
}
- ExternalIdentityRef ref = getIdentityRef(auth);
- Value[] lmValues = auth.getProperty(REP_LAST_SYNCED);
- long lastModified = -1;
- if (lmValues != null && lmValues.length > 0) {
- lastModified = lmValues[0].getLong();
- }
- return new SyncedIdentityImpl(id, ref, auth.isGroup(), lastModified);
}
/**
@@ -168,14 +204,20 @@ public class DefaultSyncHandler implemen
private final ValueFactory valueFactory;
+ private boolean keepMissing;
+
+ private boolean forceUserSync;
+
+ private boolean forceGroupSync;
+
// we use the same wall clock for the entire context
private final long now;
private final Value nowValue;
- private ContextImpl(ExternalIdentityProvider idp, UserManager userManager, Root root) {
+ private ContextImpl(ExternalIdentityProvider idp, UserManager userManager, ValueFactory valueFactory) {
this.idp = idp;
this.userManager = userManager;
- valueFactory = new ValueFactoryImpl(root, NamePathMapper.DEFAULT);
+ this.valueFactory = valueFactory;
// initialize 'now'
final Calendar nowCal = Calendar.getInstance();
@@ -195,16 +237,65 @@ public class DefaultSyncHandler implemen
* {@inheritDoc}
*/
@Override
- public boolean sync(@Nonnull ExternalIdentity identity) throws SyncException {
+ public boolean isKeepMissing() {
+ return keepMissing;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SyncContext setKeepMissing(boolean keepMissing) {
+ this.keepMissing = keepMissing;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isForceUserSync() {
+ return forceUserSync;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SyncContext setForceUserSync(boolean forceUserSync) {
+ this.forceUserSync = forceUserSync;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isForceGroupSync() {
+ return forceGroupSync;
+ }
+
+ public SyncContext setForceGroupSync(boolean forceGroupSync) {
+ this.forceGroupSync = forceGroupSync;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SyncResult sync(@Nonnull ExternalIdentity identity) throws SyncException {
try {
DebugTimer timer = new DebugTimer();
- boolean ret;
+ SyncResultImpl ret;
+ boolean created = false;
if (identity instanceof ExternalUser) {
User user = getAuthorizable(identity, User.class);
timer.mark("find");
if (user == null) {
user = createUser((ExternalUser) identity);
timer.mark("create");
+ created = true;
}
ret = syncUser((ExternalUser) identity, user);
timer.mark("sync");
@@ -214,6 +305,7 @@ public class DefaultSyncHandler implemen
if (group == null) {
group = createGroup((ExternalGroup) identity);
timer.mark("create");
+ created = true;
}
ret = syncGroup((ExternalGroup) identity, group);
timer.mark("sync");
@@ -223,6 +315,9 @@ public class DefaultSyncHandler implemen
if (log.isDebugEnabled()) {
log.debug("sync({}) -> {} {}", identity.getExternalId().getString(), identity.getId(), timer.getString());
}
+ if (created) {
+ ret.setStatus(SyncResult.Status.ADD);
+ }
return ret;
} catch (RepositoryException e) {
throw new SyncException(e);
@@ -233,19 +328,19 @@ public class DefaultSyncHandler implemen
* {@inheritDoc}
*/
@Override
- public boolean sync(@Nonnull String id) throws SyncException {
+ public SyncResult sync(@Nonnull String id) throws SyncException {
try {
DebugTimer timer = new DebugTimer();
- boolean ret = false;
+ SyncResultImpl ret;
// find authorizable
Authorizable auth = userManager.getAuthorizable(id);
if (auth == null) {
- return false;
+ return new SyncResultImpl(new SyncedIdentityImpl(id, null, false, -1), SyncResult.Status.NO_SUCH_AUTHORIZABLE);
}
// check if we need to deal with this authorizable
ExternalIdentityRef ref = getIdentityRef(auth);
if (ref == null || !idp.getName().equals(ref.getProviderName())) {
- return false;
+ return new SyncResultImpl(new SyncedIdentityImpl(id, null, false, -1), SyncResult.Status.FOREIGN);
}
if (auth instanceof Group) {
@@ -253,13 +348,18 @@ public class DefaultSyncHandler implemen
ExternalGroup external = idp.getGroup(id);
timer.mark("retrieve");
if (external == null) {
+ SyncedIdentityImpl syncId = createSyncedIdentity(auth);
if (group.getDeclaredMembers().hasNext()) {
log.info("won't remove local group with members: {}", id);
- } else {
+ ret = new SyncResultImpl(syncId, SyncResult.Status.NOP);
+ } else if (!keepMissing) {
auth.remove();
log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
timer.mark("remove");
- ret = true;
+ ret = new SyncResultImpl(syncId, SyncResult.Status.DELETE);
+ } else {
+ ret = new SyncResultImpl(syncId, SyncResult.Status.MISSING);
+ log.info("external identity missing for {}, but purge == false.", id);
}
} else {
ret = syncGroup(external, group);
@@ -269,10 +369,16 @@ public class DefaultSyncHandler implemen
ExternalUser external = idp.getUser(id);
timer.mark("retrieve");
if (external == null) {
- auth.remove();
- log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
- timer.mark("remove");
- ret = true;
+ SyncedIdentityImpl syncId = createSyncedIdentity(auth);
+ if (!keepMissing) {
+ auth.remove();
+ log.debug("removing authorizable '{}' that no longer exists on IDP {}", id, idp.getName());
+ timer.mark("remove");
+ ret = new SyncResultImpl(syncId, SyncResult.Status.DELETE);
+ } else {
+ ret = new SyncResultImpl(syncId, SyncResult.Status.MISSING);
+ log.info("external identity missing for {}, but purge == false.", id);
+ }
} else {
ret = syncUser(external, (User) auth);
timer.mark("sync");
@@ -357,11 +463,11 @@ public class DefaultSyncHandler implemen
}
- private boolean syncUser(@Nonnull ExternalUser external, @Nonnull User user) throws RepositoryException {
+ private SyncResultImpl syncUser(@Nonnull ExternalUser external, @Nonnull User user) throws RepositoryException {
// first check if user is expired
- // todo: add "forceSync" property for potential background sync
- if (!isExpired(user, config.user().getExpirationTime(), "Properties")) {
- return false;
+ if (!forceUserSync && !isExpired(user, config.user().getExpirationTime(), "Properties")) {
+ SyncedIdentityImpl syncId = createSyncedIdentity(user);
+ return new SyncResultImpl(syncId, SyncResult.Status.NOP);
}
// synchronize the properties
@@ -377,14 +483,15 @@ public class DefaultSyncHandler implemen
// finally "touch" the sync property
user.setProperty(REP_LAST_SYNCED, nowValue);
- return true;
+ SyncedIdentityImpl syncId = createSyncedIdentity(user);
+ return new SyncResultImpl(syncId, SyncResult.Status.UPDATE);
}
- private boolean syncGroup(ExternalGroup external, Group group) throws RepositoryException {
+ private SyncResultImpl syncGroup(ExternalGroup external, Group group) throws RepositoryException {
// first check if user is expired
- // todo: add "forceSync" property for potential background sync
- if (!isExpired(group, config.group().getExpirationTime(), "Properties")) {
- return false;
+ if (!forceGroupSync && !isExpired(group, config.group().getExpirationTime(), "Properties")) {
+ SyncedIdentityImpl syncId = createSyncedIdentity(group);
+ return new SyncResultImpl(syncId, SyncResult.Status.NOP);
}
// synchronize the properties
@@ -395,7 +502,8 @@ public class DefaultSyncHandler implemen
// finally "touch" the sync property
group.setProperty(REP_LAST_SYNCED, nowValue);
- return true;
+ SyncedIdentityImpl syncId = createSyncedIdentity(group);
+ return new SyncResultImpl(syncId, SyncResult.Status.UPDATE);
}
/**
@@ -694,42 +802,4 @@ public class DefaultSyncHandler implemen
return result.length() == 0 ? null : result.toString();
}
- private static class SyncedIdentityImpl implements SyncedIdentity {
-
- private final String id;
-
- private final ExternalIdentityRef ref;
-
- private final boolean isGroup;
-
- private final long lastSynced;
-
- private SyncedIdentityImpl(String id, ExternalIdentityRef ref, boolean isGroup, long lastSynced) {
- this.id = id;
- this.ref = ref;
- this.isGroup = isGroup;
- this.lastSynced = lastSynced;
- }
-
- @Nonnull
- @Override
- public String getId() {
- return id;
- }
-
- @Override
- public ExternalIdentityRef getExternalIdRef() {
- return ref;
- }
-
- @Override
- public boolean isGroup() {
- return false;
- }
-
- @Override
- public long lastSynced() {
- return lastSynced;
- }
- }
}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java Tue Apr 15 17:19:20 2014
@@ -33,6 +33,8 @@ import org.apache.jackrabbit.api.securit
import org.apache.jackrabbit.oak.api.AuthInfo;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.AbstractLoginModule;
import org.apache.jackrabbit.oak.spi.security.authentication.AuthInfoImpl;
@@ -300,7 +302,7 @@ public class ExternalLoginModule extends
SyncContext context = null;
try {
DebugTimer timer = new DebugTimer();
- context = syncHandler.createContext(idp, userManager, root);
+ context = syncHandler.createContext(idp, userManager, new ValueFactoryImpl(root, NamePathMapper.DEFAULT));
context.sync(user);
timer.mark("sync");
root.commit();
@@ -337,7 +339,7 @@ public class ExternalLoginModule extends
throw new SyncException("Cannot synchronize user. userManager == null");
}
DebugTimer timer = new DebugTimer();
- context = syncHandler.createContext(idp, userManager, root);
+ context = syncHandler.createContext(idp, userManager, new ValueFactoryImpl(root, NamePathMapper.DEFAULT));
context.sync(id);
timer.mark("sync");
root.commit();
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModuleFactory.java Tue Apr 15 17:19:20 2014
@@ -16,17 +16,35 @@
*/
package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
-import java.util.Map;
+import java.util.Hashtable;
+import javax.jcr.Repository;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
import javax.security.auth.spi.LoginModule;
import org.apache.felix.jaas.LoginModuleFactory;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
+import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncManager;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.jmx.SyncMBeanImpl;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.jmx.SynchronizationMBean;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
/**
* Implements a LoginModuleFactory that creates {@link ExternalLoginModule}s and allows to configure login modules
@@ -41,6 +59,11 @@ import org.apache.jackrabbit.oak.spi.sec
@Service
public class ExternalLoginModuleFactory implements LoginModuleFactory {
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(ExternalLoginModuleFactory.class);
+
@Property(
intValue = 50,
label = "JAAS Ranking",
@@ -79,18 +102,62 @@ public class ExternalLoginModuleFactory
)
public static final String PARAM_SYNC_HANDLER_NAME = ExternalLoginModule.PARAM_SYNC_HANDLER_NAME;
+ @Reference
+ SyncManager syncManager;
+
+ @Reference
+ ExternalIdentityProviderManager idpManager;
+
+ @Reference
+ SecurityProvider securityProvider;
+
+ @Reference
+ Repository repository;
+
/**
* default configuration for the login modules
*/
private ConfigurationParameters osgiConfig;
/**
+ * whiteboard registration handle of the manager mbean
+ */
+ private Registration mbeanRegistration;
+
+ /**
* Activates the LoginModuleFactory service
- * @param properties the OSGi config
+ * @param context the component context
*/
@Activate
- protected void activate(Map<String, Object> properties) {
- osgiConfig = ConfigurationParameters.of(properties);
+ private void activate(ComponentContext context) {
+ //noinspection unchecked
+ osgiConfig = ConfigurationParameters.of(context.getProperties());
+ String idpName = osgiConfig.getConfigValue(PARAM_IDP_NAME, "");
+ String sncName = osgiConfig.getConfigValue(PARAM_SYNC_HANDLER_NAME, "");
+
+ Whiteboard whiteboard = new OsgiWhiteboard(context.getBundleContext());
+ try {
+ SyncMBeanImpl bean = new SyncMBeanImpl(repository, syncManager, sncName, idpManager, idpName);
+ Hashtable<String, String> table = new Hashtable<String, String>();
+ table.put("type", "UserManagement");
+ table.put("name", "External Identity Synchronization Management");
+ table.put("handler", ObjectName.quote(sncName));
+ table.put("idp", ObjectName.quote(idpName));
+ mbeanRegistration = whiteboard.register(SynchronizationMBean.class, bean, ImmutableMap.of(
+ "jmx.objectname",
+ new ObjectName("org.apache.jackrabbit.oak", table))
+ );
+ } catch (MalformedObjectNameException e) {
+ log.error("Unable to register SynchronizationMBean.", e);
+ }
+ }
+
+ @Deactivate
+ private void deactivate() {
+ if (mbeanRegistration != null) {
+ mbeanRegistration.unregister();
+ mbeanRegistration = null;
+ }
}
/**
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncManagerImpl.java Tue Apr 15 17:19:20 2014
@@ -17,17 +17,11 @@
package org.apache.jackrabbit.oak.spi.security.authentication.external.impl;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
import javax.annotation.Nonnull;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.oak.osgi.OsgiWhiteboard;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
Added: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncResultImpl.java?rev=1587638&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncResultImpl.java (added)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncResultImpl.java Tue Apr 15 17:19:20 2014
@@ -0,0 +1,46 @@
+/*
+ * 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.spi.security.authentication.external.impl;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
+
+/**
+* {@code SyncResultImpl}...
+*/
+public class SyncResultImpl implements SyncResult {
+
+ private final SyncedIdentityImpl id;
+
+ private Status status = Status.NOP;
+
+ public SyncResultImpl(SyncedIdentityImpl id, Status status) {
+ this.id = id;
+ this.status = status;
+ }
+
+ public SyncedIdentityImpl getIdentity() {
+ return id;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncedIdentityImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncedIdentityImpl.java?rev=1587638&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncedIdentityImpl.java (added)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/SyncedIdentityImpl.java Tue Apr 15 17:19:20 2014
@@ -0,0 +1,64 @@
+/*
+ * 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.spi.security.authentication.external.impl;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncedIdentity;
+
+/**
+* {@code SyncedIdentityImpl}...
+*/
+public class SyncedIdentityImpl implements SyncedIdentity {
+
+ private final String id;
+
+ private final ExternalIdentityRef ref;
+
+ private final boolean isGroup;
+
+ private final long lastSynced;
+
+ public SyncedIdentityImpl(String id, ExternalIdentityRef ref, boolean isGroup, long lastSynced) {
+ this.id = id;
+ this.ref = ref;
+ this.isGroup = isGroup;
+ this.lastSynced = lastSynced;
+ }
+
+ @Nonnull
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public ExternalIdentityRef getExternalIdRef() {
+ return ref;
+ }
+
+ @Override
+ public boolean isGroup() {
+ return isGroup;
+ }
+
+ @Override
+ public long lastSynced() {
+ return lastSynced;
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java?rev=1587638&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java (added)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SyncMBeanImpl.java Tue Apr 15 17:19:20 2014
@@ -0,0 +1,449 @@
+/*
+ * 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.spi.security.authentication.external.impl.jmx;
+
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.json.JsonUtil;
+import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProviderManager;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncContext;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncException;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncManager;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncedIdentity;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncResultImpl;
+import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.SyncedIdentityImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@code SyncMBeanImpl}...
+ */
+public class SyncMBeanImpl implements SynchronizationMBean {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(SyncMBeanImpl.class);
+
+ private final Repository repository;
+
+ private final SyncManager syncManager;
+
+ private final String syncName;
+
+ private final ExternalIdentityProviderManager idpManager;
+
+ private final String idpName;
+
+ public SyncMBeanImpl(Repository repository, SyncManager syncManager, String syncName,
+ ExternalIdentityProviderManager idpManager, String idpName) {
+ this.repository = repository;
+ this.syncManager = syncManager;
+ this.syncName = syncName;
+ this.idpManager = idpManager;
+ this.idpName = idpName;
+ }
+
+ @Nonnull
+ private Delegatee getDelegatee() {
+ SyncHandler handler = syncManager.getSyncHandler(syncName);
+ if (handler == null) {
+ log.error("No sync manager available for name {}.", syncName);
+ throw new IllegalArgumentException("No sync manager available for name " + syncName);
+ }
+ ExternalIdentityProvider idp = idpManager.getProvider(idpName);
+ if (idp == null) {
+ log.error("No idp available for name", idpName);
+ throw new IllegalArgumentException("No idp manager available for name " + idpName);
+ }
+ try {
+ return new Delegatee(handler, idp);
+ } catch (SyncException e) {
+ throw new IllegalArgumentException("Unable to create delegatee", e);
+ }
+ }
+
+ private class Delegatee {
+
+ private SyncHandler handler;
+
+ private ExternalIdentityProvider idp;
+
+ private SyncContext context;
+
+ private UserManager userMgr;
+
+ private Session systemSession;
+
+ private Delegatee(SyncHandler handler, ExternalIdentityProvider idp) throws SyncException {
+ this.handler = handler;
+ this.idp = idp;
+ try {
+ systemSession = Subject.doAs(SystemSubject.INSTANCE, new PrivilegedExceptionAction<Session>() {
+ @Override
+ public Session run() throws LoginException, RepositoryException {
+ if (repository instanceof JackrabbitRepository) {
+ // this is to bypass GuestCredentials injection in the "AbstractSlingRepository2"
+ return ((JackrabbitRepository) repository).login(null, null, null);
+ } else {
+ return repository.login(null, null);
+ }
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new SyncException(e);
+ }
+ try {
+ context = handler.createContext(idp, userMgr = ((JackrabbitSession) systemSession).getUserManager(), systemSession.getValueFactory());
+ } catch (Exception e) {
+ systemSession.logout();
+ throw new SyncException(e);
+ }
+
+ log.info("Created delegatee for SyncMBean with session: {} {}", systemSession, systemSession.getUserID());
+ }
+
+ private void close() {
+ if (context != null) {
+ context.close();
+ context = null;
+ }
+ if (systemSession != null) {
+ systemSession.logout();
+ }
+ }
+
+ /**
+ * @see SynchronizationMBean#syncUsers(String[], boolean)
+ */
+ @Nonnull
+ public String[] syncUsers(@Nonnull String[] userIds, boolean purge) {
+ context.setKeepMissing(!purge)
+ .setForceGroupSync(true)
+ .setForceUserSync(true);
+ List<String> result = new ArrayList<String>();
+ for (String userId: userIds) {
+ try {
+ SyncResult r = context.sync(userId);
+ systemSession.save();
+ result.add(getJSONString(r));
+ } catch (SyncException e) {
+ log.warn("Error while syncing user {}", userId, e);
+ } catch (RepositoryException e) {
+ log.warn("Error while syncing user {}", userId, e);
+ }
+ }
+ return result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * @see SynchronizationMBean#syncAllUsers(boolean)
+ */
+ @Nonnull
+ public String[] syncAllUsers(boolean purge) {
+ try {
+ List<String> list = new ArrayList<String>();
+ context.setKeepMissing(!purge)
+ .setForceGroupSync(true)
+ .setForceUserSync(true);
+ Iterator<SyncedIdentity> iter = handler.listIdentities(userMgr);
+ while (iter.hasNext()) {
+ SyncedIdentity id = iter.next();
+ if (isMyIDP(id)) {
+ try {
+ SyncResult r = context.sync(id.getId());
+ systemSession.save();
+ list.add(getJSONString(r));
+ } catch (SyncException e) {
+ list.add(getJSONString(id, e));
+ } catch (RepositoryException e) {
+ list.add(getJSONString(id, e));
+ }
+ }
+ }
+ return list.toArray(new String[list.size()]);
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Error retrieving users for syncing", e);
+ }
+ }
+
+ /**
+ * @see SynchronizationMBean#syncExternalUsers(String[])
+ */
+ @Nonnull
+ public String[] syncExternalUsers(@Nonnull String[] externalIds) {
+ List<String> list = new ArrayList<String>();
+ context.setForceGroupSync(true).setForceUserSync(true);
+ for (String externalId: externalIds) {
+ ExternalIdentityRef ref = ExternalIdentityRef.fromString(externalId);
+ try {
+ ExternalIdentity id = idp.getIdentity(ref);
+ if (id != null) {
+ SyncResult r = context.sync(id);
+ systemSession.save();
+ list.add(getJSONString(r));
+ } else {
+ SyncResult r = new SyncResultImpl(
+ new SyncedIdentityImpl("", ref, false, -1),
+ SyncResult.Status.NO_SUCH_IDENTITY
+ );
+ list.add(getJSONString(r));
+ }
+ } catch (ExternalIdentityException e) {
+ log.warn("error while fetching the external identity {}", externalId, e);
+ list.add(getJSONString(ref, e));
+ } catch (SyncException e) {
+ list.add(getJSONString(ref, e));
+ } catch (RepositoryException e) {
+ list.add(getJSONString(ref, e));
+ }
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * @see SynchronizationMBean#syncAllExternalUsers()
+ */
+ @Nonnull
+ public String[] syncAllExternalUsers() {
+ List<String> list = new ArrayList<String>();
+ context.setForceGroupSync(true).setForceUserSync(true);
+ try {
+ Iterator<ExternalUser> iter = idp.listUsers();
+ while (iter.hasNext()) {
+ ExternalUser user = iter.next();
+ try {
+ SyncResult r = context.sync(user);
+ systemSession.save();
+ list.add(getJSONString(r));
+ } catch (SyncException e) {
+ list.add(getJSONString(user.getExternalId(), e));
+ } catch (RepositoryException e) {
+ list.add(getJSONString(user.getExternalId(), e));
+ }
+ }
+ return list.toArray(new String[list.size()]);
+ } catch (ExternalIdentityException e) {
+ throw new IllegalArgumentException("Unable to retrieve external users", e);
+ }
+ }
+
+ /**
+ * @see SynchronizationMBean#listOrphanedUsers()
+ */
+ @Nonnull
+ public String[] listOrphanedUsers() {
+ List<String> list = new ArrayList<String>();
+ try {
+ Iterator<SyncedIdentity> iter = handler.listIdentities(userMgr);
+ while (iter.hasNext()) {
+ SyncedIdentity id = iter.next();
+ if (isMyIDP(id)) {
+ ExternalIdentity extId = idp.getIdentity(id.getExternalIdRef());
+ if (extId == null) {
+ list.add(id.getId());
+ }
+ }
+ }
+ } catch (RepositoryException e) {
+ log.error("Error while listing orphaned users", e);
+ } catch (ExternalIdentityException e) {
+ log.error("Error while fetching external identity", e);
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * @see SynchronizationMBean#purgeOrphanedUsers()
+ */
+ @Nonnull
+ public String[] purgeOrphanedUsers() {
+ context.setKeepMissing(false);
+ List<String> result = new ArrayList<String>();
+ for (String userId: listOrphanedUsers()) {
+ try {
+ SyncResult r = context.sync(userId);
+ systemSession.save();
+ result.add(getJSONString(r));
+ } catch (SyncException e) {
+ log.warn("Error while syncing user {}", userId, e);
+ } catch (RepositoryException e) {
+ log.warn("Error while syncing user {}", userId, e);
+ }
+ }
+ return result.toArray(new String[result.size()]);
+ }
+
+ private boolean isMyIDP(SyncedIdentity id) {
+ String idpName = id.getExternalIdRef() == null
+ ? null
+ : id.getExternalIdRef().getProviderName();
+ return (idpName == null || idpName.length() ==0 || idpName.equals(idp.getName()));
+ }
+ }
+
+ private static String getJSONString(SyncResult r) {
+ String op = "";
+ switch (r.getStatus()) {
+ case NOP:
+ op = "nop";
+ break;
+ case ADD:
+ op = "add";
+ break;
+ case UPDATE:
+ op = "upd";
+ break;
+ case DELETE:
+ op = "del";
+ break;
+ case NO_SUCH_AUTHORIZABLE:
+ op = "nsa";
+ break;
+ case NO_SUCH_IDENTITY:
+ op = "nsi";
+ break;
+ case MISSING:
+ op = "mis";
+ break;
+ case FOREIGN:
+ op = "for";
+ break;
+ }
+ String uid = JsonUtil.getJsonString(r.getIdentity().getId());
+ String eid = r.getIdentity().getExternalIdRef() == null
+ ? "\"\""
+ : JsonUtil.getJsonString(r.getIdentity().getExternalIdRef().getString());
+ return String.format("{op:\"%s\",uid:%s,eid:%s}", op, uid, eid);
+ }
+
+ private static String getJSONString(SyncedIdentity id, Exception e) {
+ String uid = JsonUtil.getJsonString(id.getId());
+ String eid = id.getExternalIdRef() == null
+ ? "\"\""
+ : JsonUtil.getJsonString(id.getExternalIdRef().getString());
+ String msg = JsonUtil.getJsonString(e.toString());
+ return String.format("{op:\"ERR\",uid:%s,eid:%s,msg:%s}", uid, eid, msg);
+ }
+
+ private static String getJSONString(ExternalIdentityRef ref, Exception e) {
+ String eid = JsonUtil.getJsonString(ref.getString());
+ String msg = JsonUtil.getJsonString(e.toString());
+ return String.format("{op:\"ERR\",uid:\"\",eid:%s,msg:%s}", eid, msg);
+ }
+
+ //---------------------------------------------------------------------------------------< SynchronizationMBean >---
+ @Nonnull
+ @Override
+ public String getSyncHandlerName() {
+ return syncName;
+ }
+
+ @Nonnull
+ @Override
+ public String getIDPName() {
+ return idpName;
+ }
+
+ @Nonnull
+ @Override
+ public String[] syncUsers(@Nonnull String[] userIds, boolean purge) {
+ Delegatee delegatee = getDelegatee();
+ try {
+ return delegatee.syncUsers(userIds, purge);
+ } finally {
+ delegatee.close();
+ }
+ }
+
+ @Nonnull
+ @Override
+ public String[] syncAllUsers(boolean purge) {
+ Delegatee delegatee = getDelegatee();
+ try {
+ return delegatee.syncAllUsers(purge);
+ } finally {
+ delegatee.close();
+ }
+ }
+
+ @Nonnull
+ @Override
+ public String[] syncExternalUsers(@Nonnull String[] externalIds) {
+ Delegatee delegatee = getDelegatee();
+ try {
+ return delegatee.syncExternalUsers(externalIds);
+ } finally {
+ delegatee.close();
+ }
+ }
+
+ @Nonnull
+ @Override
+ public String[] syncAllExternalUsers() {
+ Delegatee delegatee = getDelegatee();
+ try {
+ return delegatee.syncAllExternalUsers();
+ } finally {
+ delegatee.close();
+ }
+ }
+
+ @Nonnull
+ @Override
+ public String[] listOrphanedUsers() {
+ Delegatee delegatee = getDelegatee();
+ try {
+ return delegatee.listOrphanedUsers();
+ } finally {
+ delegatee.close();
+ }
+ }
+
+ @Nonnull
+ @Override
+ public String[] purgeOrphanedUsers() {
+ Delegatee delegatee = getDelegatee();
+ try {
+ return delegatee.purgeOrphanedUsers();
+ } finally {
+ delegatee.close();
+ }
+ }
+}
\ No newline at end of file
Added: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SynchronizationMBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SynchronizationMBean.java?rev=1587638&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SynchronizationMBean.java (added)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/jmx/SynchronizationMBean.java Tue Apr 15 17:19:20 2014
@@ -0,0 +1,119 @@
+/*
+ * 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.spi.security.authentication.external.impl.jmx;
+
+import javax.annotation.Nonnull;
+
+import aQute.bnd.annotation.ProviderType;
+
+/**
+ * Provides utilities to manage synchronized external identities.
+ * The operations return a single or array of messages of the operations performed. for simplicity the messages are
+ * JSON serialized strings:
+ * <xmp>
+ * {
+ * "op": "upd",
+ * "uid": "bob",
+ * "eid": "cn=bob,o=apache"
+ * }
+ * </xmp>
+ *
+ * With the following operations:
+ * <ul>
+ * <li>nop: nothing changed</li>
+ * <li>upd: entry updated</li>
+ * <li>add: entry added</li>
+ * <li>del: entry deleted</li>
+ * <li>err: operation failed. in this case, the 'msg' property will contain a reason</li>
+ * </ul>
+ *
+ * Note that this interface is not exported via OSGi as it is not intended to use outside of JMX (yet).
+ */
+@ProviderType
+public interface SynchronizationMBean {
+
+ /**
+ * Returns the name of the {@link org.apache.jackrabbit.oak.spi.security.authentication.external.SyncHandler}
+ * that this MBean operates on.
+ *
+ * @return the name of the sync handler.
+ */
+ @Nonnull
+ String getSyncHandlerName();
+
+ /**
+ * Returns the name of the {@link org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider}
+ * that this MBean operates on.
+ *
+ * @return the name of the IDP.
+ */
+ @Nonnull
+ String getIDPName();
+
+ /**
+ * Synchronizes the local users with the given user ids.
+ * @param userIds the user ids
+ * @param purge if {@code true} users that don't exist in the IDP are deleted.
+ * @return result messages.
+ */
+ @Nonnull
+ String[] syncUsers(@Nonnull String[] userIds, boolean purge);
+
+ /**
+ * Synchronizes all local users with the given user ids. Note that this can be an expensive operation since all
+ * potential users need to be examined.
+ *
+ * @param purge if {@code true} users that don't exist in the IDP are deleted.
+ * @return result messages.
+ */
+ @Nonnull
+ String[] syncAllUsers(boolean purge);
+
+ /**
+ * Synchronizes the external users with the given external ids.
+ * @param externalIds the external id
+ * @return result messages.
+ */
+ @Nonnull
+ String[] syncExternalUsers(@Nonnull String[] externalIds);
+
+ /**
+ * Synchronizes all the external users, i.e. basically imports the entire IDP. Note that this can be an expensive
+ * operation.
+ *
+ * @return result messages.
+ */
+ @Nonnull
+ String[] syncAllExternalUsers();
+
+ /**
+ * Returns a list of orphaned users, i.e. users that don't exist anymore on the IDP. Note that this can be an
+ * expensive operation since all potential users need to be examined.
+ * @return a list of the user ids of orphaned users.
+ */
+ @Nonnull
+ String[] listOrphanedUsers();
+
+ /**
+ * Purges all orphaned users. this is similar to invoke {@link #syncUsers(String[], boolean)} with the list of
+ * orphaned users. Note tha this can eb an expensive operation since all potential users need to be examined.
+ *
+ * @return result messages.
+ */
+ @Nonnull
+ String[] purgeOrphanedUsers();
+}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/package-info.java Tue Apr 15 17:19:20 2014
@@ -14,8 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("0.17")
-@Export(optional = "provide:=true")
+@Version("1.0")
+@Export
package org.apache.jackrabbit.oak.spi.security.authentication.external;
import aQute.bnd.annotation.Version;
Modified: jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-external/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/external/TestIdentityProvider.java Tue Apr 15 17:19:20 2014
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.spi.se
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -28,8 +29,8 @@ import javax.security.auth.login.LoginEx
public class TestIdentityProvider implements ExternalIdentityProvider {
- private final Map<String, TestGroup> externalGroups = new HashMap<String, TestGroup>();
- private final Map<String, TestUser> externalUsers = new HashMap<String, TestUser>();
+ private final Map<String, ExternalGroup> externalGroups = new HashMap<String, ExternalGroup>();
+ private final Map<String, ExternalUser> externalUsers = new HashMap<String, ExternalUser>();
public TestIdentityProvider() {
@@ -96,6 +97,16 @@ public class TestIdentityProvider implem
return externalGroups.get(name);
}
+ @Override
+ public Iterator<ExternalUser> listUsers() throws ExternalIdentityException {
+ return externalUsers.values().iterator();
+ }
+
+ @Override
+ public Iterator<ExternalGroup> listGroups() throws ExternalIdentityException {
+ return externalGroups.values().iterator();
+ }
+
private static class TestIdentity implements ExternalIdentity {
private final String userId;
Modified: jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapIdentityProvider.java Tue Apr 15 17:19:20 2014
@@ -18,6 +18,9 @@ package org.apache.jackrabbit.oak.securi
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
@@ -53,6 +56,7 @@ import org.apache.felix.scr.annotations.
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.commons.iterator.AbstractLazyIterator;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
@@ -287,6 +291,82 @@ public class LdapIdentityProvider implem
}
}
+ @Override
+ public Iterator<ExternalUser> listUsers() throws ExternalIdentityException {
+ DebugTimer timer = new DebugTimer();
+ LdapConnection connection = connect();
+ timer.mark("connect");
+ try {
+ final List<Entry> entries = getEntries(connection, config.getUserConfig());
+ timer.mark("lookup");
+ if (log.isDebugEnabled()) {
+ log.debug("listUsers() {}", timer.getString());
+ }
+ return new AbstractLazyIterator<ExternalUser>() {
+
+ private final Iterator<Entry> iter = entries.iterator();
+
+ @Override
+ protected ExternalUser getNext() {
+ while (iter.hasNext()) {
+ try {
+ return createUser(iter.next(), null);
+ } catch (LdapInvalidAttributeValueException e) {
+ log.warn("Error while creating external user object", e);
+ }
+ }
+ return null;
+ }
+ };
+ } catch (LdapException e) {
+ log.error("Error during ldap lookup. " + timer.getString(), e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } catch (CursorException e) {
+ log.error("Error during ldap lookup. " + timer.getString(), e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } finally {
+ disconnect(connection);
+ }
+ }
+
+ @Override
+ public Iterator<ExternalGroup> listGroups() throws ExternalIdentityException {
+ DebugTimer timer = new DebugTimer();
+ LdapConnection connection = connect();
+ timer.mark("connect");
+ try {
+ final List<Entry> entries = getEntries(connection, config.getGroupConfig());
+ timer.mark("lookup");
+ if (log.isDebugEnabled()) {
+ log.debug("listGroups() {}", timer.getString());
+ }
+ return new AbstractLazyIterator<ExternalGroup>() {
+
+ private final Iterator<Entry> iter = entries.iterator();
+
+ @Override
+ protected ExternalGroup getNext() {
+ while (iter.hasNext()) {
+ try {
+ return createGroup(iter.next(), null);
+ } catch (LdapInvalidAttributeValueException e) {
+ log.warn("Error while creating external user object", e);
+ }
+ }
+ return null;
+ }
+ };
+ } catch (LdapException e) {
+ log.error("Error during ldap lookup. " + timer.getString(), e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } catch (CursorException e) {
+ log.error("Error during ldap lookup. " + timer.getString(), e);
+ throw new ExternalIdentityException("Error during ldap lookup.", e);
+ } finally {
+ disconnect(connection);
+ }
+ }
+
private Entry getEntry(LdapConnection connection, LdapProviderConfig.Identity idConfig, String id)
throws CursorException, LdapException {
String searchFilter = idConfig.getSearchFilter(id);
@@ -329,6 +409,65 @@ public class LdapIdentityProvider implem
return null;
}
+ /**
+ * currently fetch all entries so that we can close the connection afterwards. maybe switch to an iterator approach
+ * later.
+ */
+ private List<Entry> getEntries(LdapConnection connection, LdapProviderConfig.Identity idConfig)
+ throws CursorException, LdapException {
+ StringBuilder filter = new StringBuilder();
+ int num = 0;
+ for (String objectClass: idConfig.getObjectClasses()) {
+ num++;
+ filter.append("(objectclass=")
+ .append(LdapProviderConfig.encodeFilterValue(objectClass))
+ .append(')');
+ }
+ String extraFilter = idConfig.getExtraFilter();
+ if (extraFilter != null && extraFilter.length() > 0) {
+ num++;
+ filter.append(extraFilter);
+ }
+ String searchFilter = num > 1
+ ? "(&" + filter + ")"
+ : filter.toString();
+
+ // Create the SearchRequest object
+ SearchRequest req = new SearchRequestImpl();
+ req.setScope(SearchScope.SUBTREE);
+ req.addAttributes(SchemaConstants.ALL_USER_ATTRIBUTES);
+ req.setTimeLimit((int) config.getSearchTimeout());
+ req.setBase(new Dn(idConfig.getBaseDN()));
+ req.setFilter(searchFilter);
+
+ // Process the request
+ List<Entry> result = new LinkedList<Entry>();
+ SearchCursor searchCursor = null;
+ try {
+ searchCursor = connection.search(req);
+ while (searchCursor.next()) {
+ Response response = searchCursor.get();
+
+ // process the SearchResultEntry
+ if (response instanceof SearchResultEntry) {
+ Entry resultEntry = ((SearchResultEntry) response).getEntry();
+ result.add(resultEntry);
+ if (log.isDebugEnabled()) {
+ log.debug("search below {} with {} found {}", idConfig.getBaseDN(), searchFilter, resultEntry.getDn());
+ }
+ }
+ }
+ } finally {
+ if (searchCursor != null) {
+ searchCursor.close();
+ }
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("search below {} with {} found {} entries.", idConfig.getBaseDN(), searchFilter, result.size());
+ }
+ return result;
+ }
+
private ExternalUser createUser(Entry e, String id)
throws LdapInvalidAttributeValueException {
ExternalIdentityRef ref = new ExternalIdentityRef(e.getDn().getName(), this.getName());
Modified: jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java?rev=1587638&r1=1587637&r2=1587638&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java (original)
+++ jackrabbit/oak/branches/1.0/oak-auth-ldap/src/main/java/org/apache/jackrabbit/oak/security/authentication/ldap/impl/LdapProviderConfig.java Tue Apr 15 17:19:20 2014
@@ -862,7 +862,7 @@ public class LdapProviderConfig {
* @param value Right hand side of "attrId=value" assertion occurring in an LDAP search filter.
* @return Escaped version of <code>value</code>
*/
- private static String encodeFilterValue(String value) {
+ public static String encodeFilterValue(String value) {
StringBuilder sb = null;
for (int i = 0; i < value.length(); i++) {
char ch = value.charAt(i);
Added: jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/add_user.sh
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/add_user.sh?rev=1587638&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/add_user.sh (added)
+++ jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/add_user.sh Tue Apr 15 17:19:20 2014
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# 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.
+#
+if [ -z "$1" ]; then
+ echo "usage: $0 userid"
+ exit
+fi
+ldapadd -h localhost -p 10389 -D uid=admin,ou=system -w secret <<EOF
+dn: cn=Test User $1,ou=people,o=sevenSeas,dc=com
+objectclass: top
+objectclass: inetOrgPerson
+objectclass: person
+objectclass: organizationalPerson
+cn: Test User $1
+sn: User $1
+description: User to test stuff
+givenname: Test
+mail: $10@mail.com
+uid: $1
+userpassword:: e3NoYX1uVTRlSTcxYmNuQkdxZU8wdDl0WHZZMXU1b1E9
+EOF
Propchange: jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/add_user.sh
------------------------------------------------------------------------------
svn:executable = *
Added: jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/del_user.sh
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/del_user.sh?rev=1587638&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/del_user.sh (added)
+++ jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/del_user.sh Tue Apr 15 17:19:20 2014
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# 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.
+#
+if [ -z "$1" ]; then
+ echo "usage: $0 userid"
+ exit
+fi
+ldapdelete -v -h localhost -p 10389 -D uid=admin,ou=system -w secret "cn=Test User $1,ou=people,o=sevenSeas,dc=com"
Propchange: jackrabbit/oak/branches/1.0/oak-auth-ldap/src/test/scripts/del_user.sh
------------------------------------------------------------------------------
svn:executable = *