jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1399780 [1/2] - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/security/ oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/ oak-core/src/main/java/org/apache/jackrabbit/oak/security/...
Date Thu, 18 Oct 2012 18:51:20 GMT
Author: angela
Date: Thu Oct 18 18:51:18 2012
New Revision: 1399780

URL: http://svn.apache.org/viewvc?rev=1399780&view=rev
Log:
OAK-50 : Implement User Management (WIP)

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableProperties.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CredentialsImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/JcrAuthorizableProperties.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
      - copied, changed from r1399538, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/OakAuthorizableProperties.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java
      - copied, changed from r1399538, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/UserManagerCallback.java
      - copied, changed from r1399538, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/UserProviderCallback.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserProviderTest.java
      - copied, changed from r1399538, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserProviderImplTest.java
Removed:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/UserProviderCallback.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/MembershipProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserProvider.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserProviderImplTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalManagerImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableBaseProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/ImpersonationImpl.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/security/user/UserImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidator.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidatorProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConfiguration.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/UserUtility.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/DefaultLoginModuleTest.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java Thu Oct 18 18:51:18 2012
@@ -101,7 +101,7 @@ public class SecurityProviderImpl implem
     @Override
     public UserConfiguration getUserConfiguration() {
         ConfigurationParameters options = configuration.getConfigValue(PARAM_USER_OPTIONS, new ConfigurationParameters());
-        return new UserConfigurationImpl(options);
+        return new UserConfigurationImpl(options, this);
     }
 
     @Nonnull

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java Thu Oct 18 18:51:18 2012
@@ -30,22 +30,25 @@ import java.util.Map;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
 import javax.jcr.SimpleCredentials;
 
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
 import org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
 import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenInfo;
 import org.apache.jackrabbit.oak.spi.security.authentication.token.TokenProvider;
-import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
 import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
-import org.apache.jackrabbit.oak.spi.security.user.UserProvider;
 import org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtility;
 import org.apache.jackrabbit.oak.util.NodeUtil;
 import org.apache.jackrabbit.util.ISO8601;
@@ -96,7 +99,7 @@ public class TokenProviderImpl implement
     private static final char DELIM = '_';
 
     private final Root root;
-    private final UserProvider userProvider;
+    private final UserManager userManager;
     private final IdentifierManager identifierManager;
     private final long tokenExpiration;
 
@@ -107,7 +110,7 @@ public class TokenProviderImpl implement
     public TokenProviderImpl(Root root, long tokenExpiration, UserConfiguration userConfiguration) {
         this.root = root;
         this.tokenExpiration = tokenExpiration;
-        this.userProvider = userConfiguration.getUserProvider(root);
+        this.userManager = userConfiguration.getUserManager(root, NamePathMapper.DEFAULT);
         this.identifierManager = new IdentifierManager(root);
     }
 
@@ -146,9 +149,9 @@ public class TokenProviderImpl implement
     @Override
     public TokenInfo createToken(String userId, Map<String, ?> attributes) {
         try {
-            Tree userTree = userProvider.getAuthorizable(userId, AuthorizableType.USER);
-            if (userTree != null) {
-                NodeUtil userNode = new NodeUtil(userTree);
+            Authorizable user = userManager.getAuthorizable(userId);
+            if (user != null && !user.isGroup()) {
+                NodeUtil userNode = new NodeUtil(root.getTree(user.getPath()));
                 NodeUtil tokenParent = userNode.getChild(TOKENS_NODE_NAME);
                 if (tokenParent == null) {
                     tokenParent = userNode.addChild(TOKENS_NODE_NAME, TOKENS_NT_NAME);
@@ -190,6 +193,8 @@ public class TokenProviderImpl implement
             log.debug("Failed to create login token ", e.getMessage());
         } catch (CommitFailedException e) {
             log.debug("Failed to create login token ", e.getMessage());
+        } catch (RepositoryException e) {
+            log.debug("Failed to create login token ", e.getMessage());
         }
 
         return null;
@@ -298,23 +303,18 @@ public class TokenProviderImpl implement
     }
 
     @CheckForNull
-    private Tree getUserTree(Tree tokenTree) {
-        if (tokenTree != null) {
-            return tokenTree.getParent().getParent();
-        } else {
-            return null;
-        }
-    }
-
-    @CheckForNull
     private String getUserId(Tree tokenTree) {
         if (tokenTree != null) {
-            Tree userTree = tokenTree.getParent().getParent();
-            if (userTree != null && !userProvider.isDisabled(userTree)) {
-                return userProvider.getAuthorizableId(userTree);
+            try {
+                String userPath = Text.getRelativeParent(tokenTree.getPath(), 2);
+                Authorizable authorizable = userManager.getAuthorizableByPath(userPath);
+                if (authorizable != null && !authorizable.isGroup() && !((User) authorizable).isDisabled()) {
+                    return authorizable.getID();
+                }
+            } catch (RepositoryException e) {
+                log.debug("Cannot determine userID from token: ", e.getMessage());
             }
         }
-
         return null;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java Thu Oct 18 18:51:18 2012
@@ -116,7 +116,7 @@ public final class LoginModuleImpl exten
             return false;
         }
 
-        Authentication authentication = new UserAuthentication(userId, getUserProvider(), getPrincipalProvider());
+        Authentication authentication = new UserAuthentication(userId, getUserManager(), getPrincipalProvider());
         boolean success = authentication.authenticate(credentials);
         if (success) {
             principals = getPrincipals(userId);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java Thu Oct 18 18:51:18 2012
@@ -24,14 +24,15 @@ import javax.jcr.SimpleCredentials;
 import javax.security.auth.Subject;
 import javax.security.auth.login.LoginException;
 
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.api.AuthInfo;
-import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.security.user.CredentialsImpl;
 import org.apache.jackrabbit.oak.spi.security.authentication.Authentication;
 import org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
-import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
 import org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtility;
-import org.apache.jackrabbit.oak.spi.security.user.UserProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,7 +45,7 @@ import org.slf4j.LoggerFactory;
  *
  * <ul>
  *     <li>{@link SimpleCredentials}: Authentication succeeds if userID and
- *     password match the information exposed by the {@link UserProvider}.</li>
+ *     password match the information exposed by the {@link UserManager}.</li>
  *     <li>{@link ImpersonationCredentials}: Authentication succeeds if the
  *     subject to be authenticated is allowed to impersonate the user identified
  *     by the userID.</li>
@@ -61,41 +62,52 @@ class UserAuthentication implements Auth
     private static final Logger log = LoggerFactory.getLogger(UserAuthentication.class);
 
     private final String userId;
-    private final UserProvider userProvider;
+    private final UserManager userManager;
     private final PrincipalProvider principalProvider;
 
-    UserAuthentication(String userId, UserProvider userProvider, PrincipalProvider principalProvider) {
+    UserAuthentication(String userId, UserManager userManager, PrincipalProvider principalProvider) {
         this.userId = userId;
-        this.userProvider = userProvider;
+        this.userManager = userManager;
         this.principalProvider = principalProvider;
     }
 
     @Override
     public boolean authenticate(Credentials credentials) throws LoginException {
-        if (userId == null || userProvider == null) {
+        if (userId == null || userManager == null) {
             return false;
         }
 
-        Tree userTree = userProvider.getAuthorizable(userId, AuthorizableType.USER);
-        if (userTree == null) {
-            throw new LoginException("Unknown user " + userId);
-        }
-        if (userProvider.isDisabled(userTree)) {
-            throw new LoginException("User with ID " + userId + " has been disabled.");
-        }
-
         boolean success;
-        if (credentials instanceof SimpleCredentials) {
-            SimpleCredentials creds = (SimpleCredentials) credentials;
-            success = PasswordUtility.isSame(userProvider.getPasswordHash(userTree), creds.getPassword());
-            checkSuccess(success, "UserId/Password mismatch.");
-        } else if (credentials instanceof ImpersonationCredentials) {
-            AuthInfo info = ((ImpersonationCredentials) credentials).getImpersonatorInfo();
-            success = impersonate(info, userTree);
-            checkSuccess(success, "Impersonation not allowed.");
-        } else {
-            // guest login is allowed if an anonymous user exists in the content (see get user above)
-            success = (credentials instanceof GuestCredentials);
+        try {
+            Authorizable authorizable = userManager.getAuthorizable(userId);
+            if (authorizable == null || authorizable.isGroup()) {
+                throw new LoginException("Unknown user " + userId);
+            }
+
+            User user = (User) authorizable;
+            if (user.isDisabled()) {
+                throw new LoginException("User with ID " + userId + " has been disabled: "+ user.getDisabledReason());
+            }
+
+            if (credentials instanceof SimpleCredentials) {
+                SimpleCredentials creds = (SimpleCredentials) credentials;
+                Credentials userCreds = user.getCredentials();
+                if (userCreds instanceof CredentialsImpl) {
+                    success = PasswordUtility.isSame(((CredentialsImpl) userCreds).getPasswordHash(), creds.getPassword());
+                } else {
+                    success = false;
+                }
+                checkSuccess(success, "UserId/Password mismatch.");
+            } else if (credentials instanceof ImpersonationCredentials) {
+                AuthInfo info = ((ImpersonationCredentials) credentials).getImpersonatorInfo();
+                success = impersonate(info, user);
+                checkSuccess(success, "Impersonation not allowed.");
+            } else {
+                // guest login is allowed if an anonymous user exists in the content (see get user above)
+                success = (credentials instanceof GuestCredentials);
+            }
+        } catch (RepositoryException e) {
+            throw new LoginException(e.getMessage());
         }
         return success;
     }
@@ -107,10 +119,10 @@ class UserAuthentication implements Auth
         }
     }
 
-    private boolean impersonate(AuthInfo info, Tree userTree) {
+    private boolean impersonate(AuthInfo info, User user) {
         Subject subject = new Subject(true, info.getPrincipals(), Collections.emptySet(), Collections.emptySet());
         try {
-            return userProvider.getImpersonation(userTree, principalProvider).allows(subject);
+            return user.getImpersonation().allows(subject);
         } catch (RepositoryException e) {
             log.debug("Error while validating impersonation", e.getMessage());
         }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalManagerImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalManagerImpl.java Thu Oct 18 18:51:18 2012
@@ -35,18 +35,6 @@ public class PrincipalManagerImpl implem
         this.principalProvider = principalProvider;
     }
 
-    /**
-     * Returns the underlying principal provider implementation. Note, that
-     * in contrast to Jackrabbit 2.x the principal provider is associated with
-     * the editing session. Thus exposing the lower level interface will not
-     * expose information that wasn't accessible by other means.
-     *
-     * @return the principal provider.
-     */
-    public PrincipalProvider getPrincipalProvider() {
-        return principalProvider;
-    }
-
     //---------------------------------------------------< PrincipalManager >---
     @Override
     public boolean hasPrincipal(String principalName) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java Thu Oct 18 18:51:18 2012
@@ -19,34 +19,29 @@ package org.apache.jackrabbit.oak.securi
 import java.security.Principal;
 import java.security.acl.Group;
 import java.util.Collections;
-import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
-import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterators;
-import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.api.Root;
-import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.namepath.PathMapper;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
-import org.apache.jackrabbit.oak.spi.security.principal.TreeBasedPrincipal;
-import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
-import org.apache.jackrabbit.oak.spi.security.user.MembershipProvider;
 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.UserProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * The {@code PrincipalProviderImpl} is a principal provider implementation
  * that operates on principal information read from user information exposed by
- * the configured {@link UserProvider} and {@link MembershipProvider}.
+ * the configured {@link UserManager}.
  */
 public class PrincipalProviderImpl implements PrincipalProvider {
 
@@ -55,186 +50,114 @@ public class PrincipalProviderImpl imple
      */
     private static final Logger log = LoggerFactory.getLogger(PrincipalProviderImpl.class);
 
-    private final UserProvider userProvider;
-    private final MembershipProvider membershipProvider;
-    private final PathMapper pathMapper;
+    private final UserManager userManager;
 
     public PrincipalProviderImpl(Root root,
                                  UserConfiguration userConfiguration,
-                                 PathMapper pathMapper) {
-        this.userProvider = userConfiguration.getUserProvider(root);
-        this.membershipProvider = userConfiguration.getMembershipProvider(root);
-        this.pathMapper = pathMapper;
+                                 NamePathMapper namePathMapper) {
+        this.userManager = userConfiguration.getUserManager(root, namePathMapper);
     }
 
     //--------------------------------------------------< PrincipalProvider >---
     @Override
     public Principal getPrincipal(final String principalName) {
-        Tree tree = userProvider.getAuthorizableByPrincipal(new Principal() {
+        Authorizable authorizable = getAuthorizable(new Principal() {
             @Override
             public String getName() {
                 return principalName;
             }
         });
-
-        if (tree != null) {
-            return (isGroup(tree)) ? new TreeBasedGroup(tree) : new TreeBasedPrincipal(tree, pathMapper);
-        } else {
-            return (EveryonePrincipal.NAME.equals(principalName)) ? EveryonePrincipal.getInstance() : null;
+        if (authorizable != null) {
+            try {
+                return authorizable.getPrincipal();
+            } catch (RepositoryException e) {
+                log.debug(e.getMessage());
+            }
         }
+
+        // no such principal or error while accessing principal from user/group
+        return (EveryonePrincipal.NAME.equals(principalName)) ? EveryonePrincipal.getInstance() : null;
     }
 
     @Override
     public Set<Group> getGroupMembership(Principal principal) {
-        Tree authTree = userProvider.getAuthorizableByPrincipal(principal);
-        if (authTree == null) {
+        Authorizable authorizable = getAuthorizable(principal);
+        if (authorizable == null) {
             return Collections.emptySet();
         } else {
-            return getGroupMembership(authTree);
+            return getGroupMembership(authorizable);
         }
     }
 
     @Override
     public Set<? extends Principal> getPrincipals(String userID) {
-        Set<Principal> principals;
-        Tree userTree = userProvider.getAuthorizable(userID, AuthorizableType.USER);
-        if (userTree != null) {
-            principals = new HashSet<Principal>();
-            Principal userPrincipal;
-            if (userProvider.isAdminUser(userTree)) {
-                userPrincipal = new AdminPrincipalImpl(userTree, pathMapper);
-            } else {
-                userPrincipal = new TreeBasedPrincipal(userTree, pathMapper);
+        Set<Principal> principals = new HashSet<Principal>();
+        try {
+            Authorizable authorizable = userManager.getAuthorizable(userID);
+            if (authorizable != null && !authorizable.isGroup()) {
+                principals.add(authorizable.getPrincipal());
+                principals.addAll(getGroupMembership(authorizable));
             }
-            principals.add(userPrincipal);
-            principals.addAll(getGroupMembership(userPrincipal));
-
-        } else {
-            principals = Collections.emptySet();
+        } catch (RepositoryException e) {
+            log.debug(e.getMessage());
         }
         return principals;
     }
 
     @Override
     public Iterator<? extends Principal> findPrincipals(String nameHint, int searchType) {
-        String[] propNames = new String[] {UserConstants.REP_PRINCIPAL_NAME};
-        String ntName;
-        switch (searchType) {
-            case PrincipalManager.SEARCH_TYPE_GROUP:
-                ntName = UserConstants.NT_REP_GROUP;
-                break;
-            case PrincipalManager.SEARCH_TYPE_NOT_GROUP:
-                ntName = UserConstants.NT_REP_USER;
-                break;
-            default:
-                ntName = UserConstants.NT_REP_AUTHORIZABLE;
-        }
-
-        Iterator<Tree> authorizables = userProvider.findAuthorizables(propNames,
-                nameHint, new String[] {ntName}, false, Long.MAX_VALUE,
-                AuthorizableType.AUTHORIZABLE);
-
+        try {
+        Iterator<Authorizable> authorizables = userManager.findAuthorizables(UserConstants.REP_PRINCIPAL_NAME, nameHint, UserManager.SEARCH_TYPE_AUTHORIZABLE);
         return Iterators.transform(
                 Iterators.filter(authorizables, Predicates.<Object>notNull()),
                 new AuthorizableToPrincipal());
+        } catch (RepositoryException e) {
+            log.debug(e.getMessage());
+            return Iterators.emptyIterator();
+        }
     }
 
     //------------------------------------------------------------< private >---
-
-    private Set<Group> getGroupMembership(Tree authorizableTree) {
-        Iterator<String> groupPaths = membershipProvider.getMembership(authorizableTree, true);
-        Set<Group> groups = new HashSet<Group>();
-        groups.add(EveryonePrincipal.getInstance());
-
-        while (groupPaths.hasNext()) {
-            String path = groupPaths.next();
-            Tree groupTree = userProvider.getAuthorizableByPath(path);
-            if (groupTree != null) {
-                groups.add(new TreeBasedGroup(groupTree));
-            }
+    private Authorizable getAuthorizable(Principal principal) {
+        try {
+            return userManager.getAuthorizable(principal);
+        } catch (RepositoryException e) {
+            log.debug("Error while retrieving principal: ", e.getMessage());
+            return null;
         }
-        return groups;
     }
 
-    private boolean isGroup(Tree authorizableTree) {
-        return userProvider.isAuthorizableType(authorizableTree, AuthorizableType.GROUP);
-    }
-
-    //--------------------------------------------------------------------------
-    /**
-     * Tree-based principal implementation that marks the principal as group.
-     */
-    private final class TreeBasedGroup extends TreeBasedPrincipal implements Group {
-
-        private TreeBasedGroup(Tree groupTree) {
-            super(groupTree, pathMapper);
-        }
-
-        @Nonnull
-        private Tree getTree(String oakPath) {
-            Tree tree = userProvider.getAuthorizableByPath(oakPath);
-            if (tree == null) {
-                throw new IllegalStateException("Path " + oakPath + " cannot be resolved to an existing authorizable.");
+    private Set<Group> getGroupMembership(Authorizable authorizable) {
+        Set<java.security.acl.Group> groupPrincipals = new HashSet<Group>();
+        groupPrincipals.add(EveryonePrincipal.getInstance());
+        try {
+            Iterator<org.apache.jackrabbit.api.security.user.Group> groups = authorizable.memberOf();
+            while (groups.hasNext()) {
+                Principal grPrincipal = groups.next().getPrincipal();
+                if (grPrincipal instanceof Group) {
+                    groupPrincipals.add((Group) grPrincipal);
+                }
             }
-            return tree;
-        }
-
-        @Override
-        public boolean addMember(Principal principal) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public boolean removeMember(Principal principal) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public boolean isMember(Principal principal) {
-            Tree groupTree = getTree(getOakPath());
-            return membershipProvider.isMember(groupTree, userProvider.getAuthorizableByPrincipal(principal), true);
-        }
-
-        @Override
-        public Enumeration<? extends Principal> members() {
-            Tree groupTree = getTree(getOakPath());
-            Iterator<String> declaredMemberPaths = membershipProvider.getMembers(groupTree, AuthorizableType.AUTHORIZABLE, false);
-            Iterator<? extends Principal> members = Iterators.transform(
-                    Iterators.filter(declaredMemberPaths, Predicates.<Object>notNull()),
-                    new PathToPrincipal());
-            return Iterators.asEnumeration(Iterators.filter(members, Predicates.notNull()));
+        } catch (RepositoryException e) {
+            log.debug(e.getMessage());
         }
+        return groupPrincipals;
     }
 
-    /**
-     * Function to covert an authorizable tree to a principal.
-     */
-    private final class AuthorizableToPrincipal implements Function<Tree, TreeBasedPrincipal> {
-        @Override
-        public TreeBasedPrincipal apply(Tree tree) {
-            if (userProvider.isAuthorizableType(tree, AuthorizableType.GROUP)) {
-                return new TreeBasedGroup(tree);
-            } else {
-                return new TreeBasedPrincipal(tree, pathMapper);
-            }
-        }
-    }
+    //--------------------------------------------------------------------------
 
     /**
-     * Function to convert a oak-path to a principal.
+     * Function to covert an authorizable tree to a principal.
      */
-    private final class PathToPrincipal implements Function<String, Principal> {
+    private final class AuthorizableToPrincipal implements Function<Authorizable, Principal> {
         @Override
-        public Principal apply(String oakPath) {
-            Tree tree = userProvider.getAuthorizableByPath(oakPath);
-            if (tree != null) {
-                if (isGroup(tree)) {
-                    return new TreeBasedGroup(tree);
-                } else {
-                    return new TreeBasedPrincipal(tree, pathMapper);
-                }
+        public Principal apply(Authorizable authorizable) {
+            try {
+                return authorizable.getPrincipal();
+            } catch (RepositoryException e) {
+                log.debug(e.getMessage());
+                return null;
             }
-            return null;
         }
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableBaseProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableBaseProvider.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableBaseProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableBaseProvider.java Thu Oct 18 18:51:18 2012
@@ -41,7 +41,7 @@ abstract class AuthorizableBaseProvider 
 
     Tree getByID(String authorizableId, AuthorizableType authorizableType) {
         Tree tree = identifierManager.getTree(getContentID(authorizableId));
-        if (UserUtility.isAuthorizableTree(tree, authorizableType)) {
+        if (UserUtility.isType(tree, authorizableType)) {
             return tree;
         } else {
             return null;
@@ -50,7 +50,7 @@ abstract class AuthorizableBaseProvider 
 
     Tree getByPath(String authorizableOakPath) {
         Tree tree = root.getTree(authorizableOakPath);
-        if (UserUtility.isAuthorizableTree(tree, AuthorizableType.AUTHORIZABLE)) {
+        if (UserUtility.isType(tree, AuthorizableType.AUTHORIZABLE)) {
             return tree;
         } else {
             return null;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java Thu Oct 18 18:51:18 2012
@@ -16,19 +16,13 @@
  */
 package org.apache.jackrabbit.oak.security.user;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
-import java.util.List;
-
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.PropertyDefinition;
 
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
@@ -37,13 +31,12 @@ import org.apache.jackrabbit.commons.ite
 import org.apache.jackrabbit.oak.api.Tree;
 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.MembershipProvider;
 import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
-import org.apache.jackrabbit.oak.spi.security.user.UserProvider;
-import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.jackrabbit.oak.api.Type.STRING;
+
 /**
  * AuthorizableImpl...
  */
@@ -56,7 +49,9 @@ abstract class AuthorizableImpl implemen
 
     private final String id;
     private final UserManagerImpl userManager;
+
     private Node node;
+    private AuthorizableProperties properties;
     private int hashCode;
 
     AuthorizableImpl(String id, Tree tree, UserManagerImpl userManager) throws RepositoryException {
@@ -124,20 +119,7 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public Iterator<String> getPropertyNames(String relPath) throws RepositoryException {
-        Node node = getNode();
-        Node n = node.getNode(relPath);
-        if (Text.isDescendantOrEqual(node.getPath(), n.getPath())) {
-            List<String> l = new ArrayList<String>();
-            for (PropertyIterator it = n.getProperties(); it.hasNext();) {
-                Property prop = it.nextProperty();
-                if (isAuthorizableProperty(prop, false)) {
-                    l.add(prop.getName());
-                }
-            }
-            return l.iterator();
-        } else {
-            throw new IllegalArgumentException("Relative path " + relPath + " refers to items outside of scope of authorizable " + getID());
-        }
+        return getAuthorizableProperties().getNames(relPath);
     }
 
     /**
@@ -145,8 +127,7 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public boolean hasProperty(String relPath) throws RepositoryException {
-        Node node = getNode();
-        return node.hasProperty(relPath) && isAuthorizableProperty(node.getProperty(relPath), true);
+        return getAuthorizableProperties().hasProperty(relPath);
     }
 
     /**
@@ -154,19 +135,7 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public Value[] getProperty(String relPath) throws RepositoryException {
-        Node node = getNode();
-        Value[] values = null;
-        if (node.hasProperty(relPath)) {
-            Property prop = node.getProperty(relPath);
-            if (isAuthorizableProperty(prop, true)) {
-                if (prop.isMultiple()) {
-                    values = prop.getValues();
-                } else {
-                    values = new Value[]{prop.getValue()};
-                }
-            }
-        }
-        return values;
+        return getAuthorizableProperties().getProperty(relPath);
     }
 
     /**
@@ -174,20 +143,7 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public void setProperty(String relPath, Value value) throws RepositoryException {
-        String name = Text.getName(relPath);
-        String intermediate = (relPath.equals(name)) ? null : Text.getRelativeParent(relPath, 1);
-
-        Node n = getOrCreateTargetNode(intermediate);
-        // check if the property has already been created as multi valued
-        // property before -> in this case remove in order to avoid
-        // ValueFormatException.
-        if (n.hasProperty(name)) {
-            Property p = n.getProperty(name);
-            if (p.isMultiple()) {
-                p.remove();
-            }
-        }
-        n.setProperty(name, value);
+        getAuthorizableProperties().setProperty(relPath, value);
     }
 
     /**
@@ -195,20 +151,7 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public void setProperty(String relPath, Value[] values) throws RepositoryException {
-        String name = Text.getName(relPath);
-        String intermediate = (relPath.equals(name)) ? null : Text.getRelativeParent(relPath, 1);
-
-        Node n = getOrCreateTargetNode(intermediate);
-        // check if the property has already been created as single valued
-        // property before -> in this case remove in order to avoid
-        // ValueFormatException.
-        if (n.hasProperty(name)) {
-            Property p = n.getProperty(name);
-            if (!p.isMultiple()) {
-                p.remove();
-            }
-        }
-        n.setProperty(name, values);
+        getAuthorizableProperties().setProperty(relPath, values);
     }
 
     /**
@@ -216,16 +159,7 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public boolean removeProperty(String relPath) throws RepositoryException {
-        Node node = getNode();
-        if (node.hasProperty(relPath)) {
-            Property p = node.getProperty(relPath);
-            if (isAuthorizableProperty(p, true)) {
-                p.remove();
-                return true;
-            }
-        }
-        // no such property or wasn't a property of this authorizable.
-        return false;
+        return getAuthorizableProperties().removeProperty(relPath);
     }
 
     /**
@@ -233,7 +167,12 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public String getPath() throws RepositoryException {
-        return getNode().getPath();
+        Node n = getNode();
+        if (n != null) {
+            return n.getPath();
+        } else {
+            return userManager.getNamePathMapper().getJcrPath(getTree().getPath());
+        }
     }
 
     //-------------------------------------------------------------< Object >---
@@ -243,17 +182,18 @@ abstract class AuthorizableImpl implemen
     @Override
     public int hashCode() {
         if (hashCode == 0) {
-            try {
-                Node node = getNode();
+            // FIXME: add proper hash-code generation taking repo/workspace/tree-identifier into account
+//            try {
+//                Node node = getNode();
                 StringBuilder sb = new StringBuilder();
                 sb.append(isGroup() ? "group:" : "user:");
-                sb.append(node.getSession().getWorkspace().getName());
+                //sb.append(node.getSession().getWorkspace().getName());
                 sb.append(':');
                 sb.append(id);
                 hashCode = sb.toString().hashCode();
-            } catch (RepositoryException e) {
-                log.warn("Error while calculating hash code.",e.getMessage());
-            }
+//            } catch (RepositoryException e) {
+//                log.warn("Error while calculating hash code.",e.getMessage());
+//            }
         }
         return hashCode;
     }
@@ -263,14 +203,13 @@ abstract class AuthorizableImpl implemen
      */
     @Override
     public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
         if (obj instanceof AuthorizableImpl) {
             AuthorizableImpl otherAuth = (AuthorizableImpl) obj;
-            try {
-                Node node = getNode();
-                return isGroup() == otherAuth.isGroup() && node.isSame(otherAuth.getNode());
-            } catch (RepositoryException e) {
-                // should not occur -> return false in this case.
-            }
+            // FIXME: make sure 2 authorizables are based on the same tree/node object
+            return isGroup() == otherAuth.isGroup() && id.equals(otherAuth.id);
         }
         return false;
     }
@@ -294,6 +233,17 @@ abstract class AuthorizableImpl implemen
         return tree;
     }
 
+    String getPrincipalName(Tree thisTree) throws RepositoryException {
+        String principalName;
+        if (thisTree.hasProperty(REP_PRINCIPAL_NAME)) {
+            return thisTree.getProperty(REP_PRINCIPAL_NAME).getValue(STRING);
+        } else {
+            String msg = "Authorizable without principal name " + id;
+            log.warn(msg);
+            throw new RepositoryException(msg);
+        }
+    }
+
     String getJcrName(String oakName) {
         return userManager.getNamePathMapper().getJcrName(oakName);
     }
@@ -330,94 +280,32 @@ abstract class AuthorizableImpl implemen
      * @throws RepositoryException If an error occurs.
      */
     boolean isEveryone() throws RepositoryException {
-        return isGroup() && EveryonePrincipal.NAME.equals(getUserProvider().getPrincipalName(getTree()));
+        return isGroup() && EveryonePrincipal.NAME.equals(getPrincipalName(getTree()));
     }
 
     /**
      * @return The node associated with this authorizable instance.
      * @throws javax.jcr.RepositoryException
      */
-    @Nonnull
+    @CheckForNull
     private Node getNode() throws RepositoryException {
         if (node == null) {
-            node = userManager.getAuthorizableNode(getTree().getPath());
+            node = userManager.getAuthorizableNode(id);
         }
         return node;
     }
 
     /**
-     * Returns true if the given property of the authorizable node is one of the
-     * non-protected properties defined by the rep:Authorizable node type or a
-     * some other descendant of the authorizable node.
+     * Retrieve authorizable properties for property related operations.
      *
-     * @param prop Property to be tested.
-     * @param verifyAncestor If true the property is tested to be a descendant
-     * of the node of this authorizable; otherwise it is expected that this
-     * test has been executed by the caller.
-     * @return {@code true} if the given property is defined
-     * by the rep:authorizable node type or one of it's sub-node types;
-     * {@code false} otherwise.
-     * @throws RepositoryException If the property definition cannot be retrieved.
-     */
-    private boolean isAuthorizableProperty(Property prop, boolean verifyAncestor) throws RepositoryException {
-        Node node = getNode();
-        if (verifyAncestor && !Text.isDescendant(node.getPath(), prop.getPath())) {
-            log.debug("Attempt to access property outside of authorizable scope.");
-            return false;
-        }
-
-        PropertyDefinition def = prop.getDefinition();
-        if (def.isProtected()) {
-            return false;
-        } else if (node.isSame(prop.getParent())) {
-            NodeType declaringNt = prop.getDefinition().getDeclaringNodeType();
-            return declaringNt.isNodeType(getJcrName(NT_REP_AUTHORIZABLE));
-        } else {
-            // another non-protected property somewhere in the subtree of this
-            // authorizable node -> is a property that can be set using #setProperty.
-            return true;
-        }
-    }
-
-    /**
-     * Retrieves the node at {@code relPath} relative to node associated with
-     * this authorizable. If no such node exist it and any missing intermediate
-     * nodes are created.
-     *
-     * @param relPath A relative path.
-     * @return The corresponding node.
-     * @throws RepositoryException If an error occurs or if {@code relPath} refers
-     * to a node that is outside of the scope of this authorizable.
+     * @return
+     * @throws RepositoryException
      */
-    @Nonnull
-    private Node getOrCreateTargetNode(String relPath) throws RepositoryException {
-        Node n;
-        Node node = getNode();
-        if (relPath != null) {
-            String userPath = node.getPath();
-            if (node.hasNode(relPath)) {
-                n = node.getNode(relPath);
-                if (!Text.isDescendantOrEqual(userPath, n.getPath())) {
-                    throw new RepositoryException("Relative path " + relPath + " outside of scope of " + this);
-                }
-            } else {
-                n = node;
-                for (String segment : Text.explode(relPath, '/')) {
-                    if (n.hasNode(segment)) {
-                        n = n.getNode(segment);
-                    } else {
-                        if (Text.isDescendantOrEqual(userPath, n.getPath())) {
-                            n = n.addNode(segment);
-                        } else {
-                            throw new RepositoryException("Relative path " + relPath + " outside of scope of " + this);
-                        }
-                    }
-                }
-            }
-        } else {
-            n = node;
+    private AuthorizableProperties getAuthorizableProperties() throws RepositoryException {
+        if (properties == null) {
+            properties = userManager.getAuthorizableProperties(id);
         }
-        return n;
+        return properties;
     }
 
     /**

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableProperties.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableProperties.java?rev=1399780&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableProperties.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableProperties.java Thu Oct 18 18:51:18 2012
@@ -0,0 +1,40 @@
+/*
+ * 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.Iterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+/**
+ * AuthorizableProperty... TODO
+ */
+public interface AuthorizableProperties {
+
+    Iterator<String> getNames(String relPath) throws RepositoryException;
+
+    boolean hasProperty(String relPath) throws RepositoryException;
+
+    Value[] getProperty(String relPath) throws RepositoryException;
+
+    void setProperty(String relPath, Value value) throws RepositoryException;
+
+    void setProperty(String relPath, Value[] values) throws RepositoryException;
+
+    boolean removeProperty(String relPath) throws RepositoryException;
+
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CredentialsImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CredentialsImpl.java?rev=1399780&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CredentialsImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/CredentialsImpl.java Thu Oct 18 18:51:18 2012
@@ -0,0 +1,41 @@
+/*
+ * 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 javax.jcr.Credentials;
+
+/**
+ * CredentialsImpl... TODO
+ */
+public class CredentialsImpl implements Credentials {
+
+    private final String userId;
+    private final String pwHash;
+
+    CredentialsImpl(String userId, String pwHash) {
+        this.userId = userId;
+        this.pwHash = pwHash;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public String getPasswordHash() {
+        return pwHash;
+    }
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java Thu Oct 18 18:51:18 2012
@@ -31,8 +31,8 @@ import org.apache.jackrabbit.commons.ite
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.oak.spi.security.principal.TreeBasedPrincipal;
-import org.apache.jackrabbit.oak.spi.security.user.MembershipProvider;
 import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
+import org.apache.jackrabbit.oak.spi.security.user.util.UserUtility;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,7 +52,7 @@ class GroupImpl extends AuthorizableImpl
 
     @Override
     void checkValidTree(Tree tree) throws RepositoryException {
-        if (tree == null || !getUserProvider().isAuthorizableType(tree, AuthorizableType.GROUP)) {
+        if (tree == null || !UserUtility.isType(tree, AuthorizableType.GROUP)) {
             throw new IllegalArgumentException("Invalid group node: node type rep:Group expected.");
         }
     }
@@ -72,7 +72,7 @@ class GroupImpl extends AuthorizableImpl
     @Override
     public Principal getPrincipal() throws RepositoryException {
         Tree groupTree = getTree();
-        return new GroupPrincipal(getUserProvider().getPrincipalName(groupTree), groupTree);
+        return new GroupPrincipal(getPrincipalName(groupTree), groupTree);
     }
 
     //--------------------------------------------------------------< Group >---

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/ImpersonationImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/ImpersonationImpl.java?rev=1399780&r1=1399779&r2=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/ImpersonationImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/ImpersonationImpl.java Thu Oct 18 18:51:18 2012
@@ -24,16 +24,16 @@ import javax.jcr.RepositoryException;
 import javax.security.auth.Subject;
 
 import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
+import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Impersonation;
+import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.spi.security.principal.AdminPrincipal;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalIteratorAdapter;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
-import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
 import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
-import org.apache.jackrabbit.oak.spi.security.user.UserProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -49,14 +49,12 @@ class ImpersonationImpl implements Imper
      */
     private static final Logger log = LoggerFactory.getLogger(ImpersonationImpl.class);
 
-    private final String userId;
-    private final UserProvider userProvider;
+    private final UserImpl user;
     private final PrincipalProvider principalProvider;
 
-    ImpersonationImpl(String userId, UserProvider userProvider, PrincipalProvider principalProvider) {
-        this.userId = userId;
-        this.userProvider = userProvider;
-        this.principalProvider = principalProvider;
+    ImpersonationImpl(UserImpl user) throws RepositoryException {
+        this.user = user;
+        this.principalProvider = user.getUserManager().getPrincipalProvider();
     }
 
     //------------------------------------------------------< Impersonation >---
@@ -105,7 +103,7 @@ class ImpersonationImpl implements Imper
         }
 
         // make sure user does not impersonate himself
-        Tree userTree = getUserTree();
+        Tree userTree = user.getTree();
         PropertyState prop = userTree.getProperty(REP_PRINCIPAL_NAME);
         if (prop != null && prop.getValue(Type.STRING).equals(principalName)) {
             log.warn("Cannot grant impersonation to oneself.");
@@ -134,7 +132,7 @@ class ImpersonationImpl implements Imper
     public boolean revokeImpersonation(Principal principal) throws RepositoryException {
         String pName = principal.getName();
 
-        Tree userTree = getUserTree();
+        Tree userTree = user.getTree();
         Set<String> impersonators = getImpersonatorNames(userTree);
         if (impersonators.remove(pName)) {
             updateImpersonatorNames(userTree, impersonators);
@@ -173,7 +171,7 @@ class ImpersonationImpl implements Imper
 
     //------------------------------------------------------------< private >---
     private Set<String> getImpersonatorNames() throws RepositoryException {
-        return getImpersonatorNames(getUserTree());
+        return getImpersonatorNames(user.getTree());
     }
 
     private Set<String> getImpersonatorNames(Tree userTree) {
@@ -195,22 +193,19 @@ class ImpersonationImpl implements Imper
         }
     }
 
-    private Tree getUserTree() throws RepositoryException {
-        Tree userTree = userProvider.getAuthorizable(userId, AuthorizableType.USER);
-        if (userTree == null) {
-            throw new RepositoryException("UserId " + userId + " cannot be resolved to user.");
-        }
-        return userTree;
-    }
-
     private boolean isAdmin(Principal principal) {
         if (principal instanceof AdminPrincipal) {
             return true;
         } else if (principal instanceof Group) {
             return false;
         } else {
-            Tree authorizableTree = userProvider.getAuthorizableByPrincipal(principal);
-            return authorizableTree != null && userProvider.isAdminUser(authorizableTree);
+            try {
+                Authorizable authorizable = user.getUserManager().getAuthorizable(principal);
+                return authorizable != null && !authorizable.isGroup() && ((User) authorizable).isAdmin();
+            } catch (RepositoryException e) {
+                log.debug(e.getMessage());
+                return false;
+            }
         }
     }
 }

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/JcrAuthorizableProperties.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/JcrAuthorizableProperties.java?rev=1399780&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/JcrAuthorizableProperties.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/JcrAuthorizableProperties.java Thu Oct 18 18:51:18 2012
@@ -0,0 +1,243 @@
+/*
+ * 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.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
+
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JcrAuthorizableProperty... TODO
+ */
+class JcrAuthorizableProperties implements AuthorizableProperties, UserConstants {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(JcrAuthorizableProperties.class);
+
+    private final Node authorizableNode;
+    private final NamePathMapper namePathMapper;
+
+    JcrAuthorizableProperties(Node authorizableNode, NamePathMapper namePathMapper) {
+        this.authorizableNode = authorizableNode;
+        this.namePathMapper = namePathMapper;
+    }
+
+    @Override
+    public Iterator<String> getNames(String relPath) throws RepositoryException {
+        Node node = getNode();
+        Node n = node.getNode(relPath);
+        if (Text.isDescendantOrEqual(node.getPath(), n.getPath())) {
+            List<String> l = new ArrayList<String>();
+            for (PropertyIterator it = n.getProperties(); it.hasNext();) {
+                Property prop = it.nextProperty();
+                if (isAuthorizableProperty(prop, false)) {
+                    l.add(prop.getName());
+                }
+            }
+            return l.iterator();
+        } else {
+            throw new IllegalArgumentException("Relative path " + relPath + " refers to items outside of scope of authorizable.");
+        }
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#hasProperty(String)
+     */
+    @Override
+    public boolean hasProperty(String relPath) throws RepositoryException {
+        Node node = getNode();
+        return node.hasProperty(relPath) && isAuthorizableProperty(node.getProperty(relPath), true);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#getProperty(String)
+     */
+    @Override
+    public Value[] getProperty(String relPath) throws RepositoryException {
+        Node node = getNode();
+        Value[] values = null;
+        if (node.hasProperty(relPath)) {
+            Property prop = node.getProperty(relPath);
+            if (isAuthorizableProperty(prop, true)) {
+                if (prop.isMultiple()) {
+                    values = prop.getValues();
+                } else {
+                    values = new Value[]{prop.getValue()};
+                }
+            }
+        }
+        return values;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#setProperty(String, javax.jcr.Value)
+     */
+    @Override
+    public void setProperty(String relPath, Value value) throws RepositoryException {
+        String name = Text.getName(relPath);
+        String intermediate = (relPath.equals(name)) ? null : Text.getRelativeParent(relPath, 1);
+
+        Node n = getOrCreateTargetNode(intermediate);
+        // check if the property has already been created as multi valued
+        // property before -> in this case remove in order to avoid
+        // ValueFormatException.
+        if (n.hasProperty(name)) {
+            Property p = n.getProperty(name);
+            if (p.isMultiple()) {
+                p.remove();
+            }
+        }
+        n.setProperty(name, value);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#setProperty(String, javax.jcr.Value[])
+     */
+    @Override
+    public void setProperty(String relPath, Value[] values) throws RepositoryException {
+        String name = Text.getName(relPath);
+        String intermediate = (relPath.equals(name)) ? null : Text.getRelativeParent(relPath, 1);
+
+        Node n = getOrCreateTargetNode(intermediate);
+        // check if the property has already been created as single valued
+        // property before -> in this case remove in order to avoid
+        // ValueFormatException.
+        if (n.hasProperty(name)) {
+            Property p = n.getProperty(name);
+            if (!p.isMultiple()) {
+                p.remove();
+            }
+        }
+        n.setProperty(name, values);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#removeProperty(String)
+     */
+    @Override
+    public boolean removeProperty(String relPath) throws RepositoryException {
+        Node node = getNode();
+        if (node.hasProperty(relPath)) {
+            Property p = node.getProperty(relPath);
+            if (isAuthorizableProperty(p, true)) {
+                p.remove();
+                return true;
+            }
+        }
+        // no such property or wasn't a property of this authorizable.
+        return false;
+    }
+
+    private Node getNode() {
+        return authorizableNode;
+    }
+
+    private String getJcrName(String oakName) {
+        return namePathMapper.getJcrName(oakName);
+    }
+
+    /**
+     * Returns true if the given property of the authorizable node is one of the
+     * non-protected properties defined by the rep:Authorizable node type or a
+     * some other descendant of the authorizable node.
+     *
+     * @param prop Property to be tested.
+     * @param verifyAncestor If true the property is tested to be a descendant
+     * of the node of this authorizable; otherwise it is expected that this
+     * test has been executed by the caller.
+     * @return {@code true} if the given property is defined
+     * by the rep:authorizable node type or one of it's sub-node types;
+     * {@code false} otherwise.
+     * @throws RepositoryException If the property definition cannot be retrieved.
+     */
+    private boolean isAuthorizableProperty(Property prop, boolean verifyAncestor) throws RepositoryException {
+        Node node = getNode();
+        if (verifyAncestor && !Text.isDescendant(node.getPath(), prop.getPath())) {
+            log.debug("Attempt to access property outside of authorizable scope.");
+            return false;
+        }
+
+        PropertyDefinition def = prop.getDefinition();
+        if (def.isProtected()) {
+            return false;
+        } else if (node.isSame(prop.getParent())) {
+            NodeType declaringNt = prop.getDefinition().getDeclaringNodeType();
+            return declaringNt.isNodeType(getJcrName(NT_REP_AUTHORIZABLE));
+        } else {
+            // another non-protected property somewhere in the subtree of this
+            // authorizable node -> is a property that can be set using #setProperty.
+            return true;
+        }
+    }
+
+    /**
+     * Retrieves the node at {@code relPath} relative to node associated with
+     * this authorizable. If no such node exist it and any missing intermediate
+     * nodes are created.
+     *
+     * @param relPath A relative path.
+     * @return The corresponding node.
+     * @throws RepositoryException If an error occurs or if {@code relPath} refers
+     * to a node that is outside of the scope of this authorizable.
+     */
+    @Nonnull
+    private Node getOrCreateTargetNode(String relPath) throws RepositoryException {
+        Node n;
+        Node node = getNode();
+        if (relPath != null) {
+            String userPath = node.getPath();
+            if (node.hasNode(relPath)) {
+                n = node.getNode(relPath);
+                if (!Text.isDescendantOrEqual(userPath, n.getPath())) {
+                    throw new RepositoryException("Relative path " + relPath + " outside of scope of " + this);
+                }
+            } else {
+                n = node;
+                for (String segment : Text.explode(relPath, '/')) {
+                    if (n.hasNode(segment)) {
+                        n = n.getNode(segment);
+                    } else {
+                        if (Text.isDescendantOrEqual(userPath, n.getPath())) {
+                            n = n.addNode(segment);
+                        } else {
+                            throw new RepositoryException("Relative path " + relPath + " outside of scope of " + this);
+                        }
+                    }
+                }
+            }
+        } else {
+            n = node;
+        }
+        return n;
+    }
+}
\ No newline at end of file

Copied: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java (from r1399538, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java&p1=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java&r1=1399538&r2=1399780&rev=1399780&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java Thu Oct 18 18:51:18 2012
@@ -20,6 +20,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.jcr.PropertyType;
 
@@ -35,7 +36,6 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
 import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
-import org.apache.jackrabbit.oak.spi.security.user.MembershipProvider;
 import org.apache.jackrabbit.oak.spi.security.user.util.UserUtility;
 import org.apache.jackrabbit.oak.spi.state.PropertyBuilder;
 import org.apache.jackrabbit.oak.util.NodeUtil;
@@ -80,13 +80,13 @@ import static org.apache.jackrabbit.oak.
  * parameter is modified later on, existing membership information is not
  * modified or converted to the new structure.
  */
-public class MembershipProviderImpl extends AuthorizableBaseProvider implements MembershipProvider {
+class MembershipProvider extends AuthorizableBaseProvider {
 
-    private static final Logger log = LoggerFactory.getLogger(MembershipProviderImpl.class);
+    private static final Logger log = LoggerFactory.getLogger(MembershipProvider.class);
 
     private final int splitSize;
 
-    MembershipProviderImpl(Root root, ConfigurationParameters config) {
+    MembershipProvider(Root root, ConfigurationParameters config) {
         super(root, config);
 
         int splitValue = config.getConfigValue(PARAM_GROUP_MEMBERSHIP_SPLIT_SIZE, 0);
@@ -97,14 +97,8 @@ public class MembershipProviderImpl exte
         this.splitSize = splitValue;
     }
 
-    //--------------------------------------------------< MembershipProvider>---
-    @Override
-    public Iterator<String> getMembership(String authorizableId, boolean includeInherited) {
-        return getMembership(getByID(authorizableId, AuthorizableType.AUTHORIZABLE), includeInherited);
-    }
-
-    @Override
-    public Iterator<String> getMembership(Tree authorizableTree, boolean includeInherited) {
+    @Nonnull
+    Iterator<String> getMembership(Tree authorizableTree, boolean includeInherited) {
         Set<String> groupPaths = new HashSet<String>();
         Set<String> refPaths = identifierManager.getReferences(true, authorizableTree, null, NT_REP_GROUP, NT_REP_MEMBERS);
         for (String propPath : refPaths) {
@@ -124,18 +118,8 @@ public class MembershipProviderImpl exte
         }
     }
 
-    @Override
-    public Iterator<String> getMembers(String groupId, AuthorizableType authorizableType, boolean includeInherited) {
-        Tree groupTree = getByID(groupId, AuthorizableType.GROUP);
-        if (groupTree == null) {
-            return Iterators.emptyIterator();
-        } else {
-            return getMembers(groupTree, authorizableType, includeInherited);
-        }
-    }
-
-    @Override
-    public Iterator<String> getMembers(Tree groupTree, AuthorizableType authorizableType, boolean includeInherited) {
+    @Nonnull
+    Iterator<String> getMembers(Tree groupTree, AuthorizableType authorizableType, boolean includeInherited) {
         Iterable memberPaths = Collections.emptySet();
         if (useMemberNode(groupTree)) {
             Tree membersTree = groupTree.getChild(REP_MEMBERS);
@@ -163,8 +147,7 @@ public class MembershipProviderImpl exte
         }
     }
 
-    @Override
-    public boolean isMember(Tree groupTree, Tree authorizableTree, boolean includeInherited) {
+    boolean isMember(Tree groupTree, Tree authorizableTree, boolean includeInherited) {
         if (includeInherited) {
             Iterator<String> groupPaths = getMembership(authorizableTree, true);
             String path = groupTree.getPath();
@@ -198,8 +181,7 @@ public class MembershipProviderImpl exte
         return false;
     }
 
-    @Override
-    public boolean addMember(Tree groupTree, Tree newMemberTree) {
+    boolean addMember(Tree groupTree, Tree newMemberTree) {
         if (useMemberNode(groupTree)) {
             NodeUtil groupNode = new NodeUtil(groupTree);
             NodeUtil membersNode = groupNode.getOrAddChild(REP_MEMBERS, NT_REP_MEMBERS);
@@ -221,8 +203,7 @@ public class MembershipProviderImpl exte
         return true;
     }
 
-    @Override
-    public boolean removeMember(Tree groupTree, Tree memberTree) {
+    boolean removeMember(Tree groupTree, Tree memberTree) {
         if (useMemberNode(groupTree)) {
             Tree membersTree = groupTree.getChild(REP_MEMBERS);
             if (membersTree != null) {
@@ -291,7 +272,7 @@ public class MembershipProviderImpl exte
 
             private Iterator<String> inherited(String authorizablePath) {
                 Tree group = getByPath(authorizablePath);
-                if (UserUtility.isAuthorizableTree(group, AuthorizableType.GROUP)) {
+                if (UserUtility.isType(group, AuthorizableType.GROUP)) {
                     return getMembers(group, authorizableType, true);
                 } else {
                     return Iterators.emptyIterator();
@@ -321,7 +302,7 @@ public class MembershipProviderImpl exte
 
             private Iterator<String> inherited(String authorizablePath) {
                 Tree group = getByPath(authorizablePath);
-                if (UserUtility.isAuthorizableTree(group, AuthorizableType.GROUP)) {
+                if (UserUtility.isType(group, AuthorizableType.GROUP)) {
                     return getMembership(group, true);
                 } else {
                     return Iterators.emptyIterator();

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/OakAuthorizableProperties.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/OakAuthorizableProperties.java?rev=1399780&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/OakAuthorizableProperties.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/OakAuthorizableProperties.java Thu Oct 18 18:51:18 2012
@@ -0,0 +1,263 @@
+/*
+ * 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.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.api.TreeLocation;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
+import org.apache.jackrabbit.oak.util.NodeUtil;
+import org.apache.jackrabbit.util.Text;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * OakAuthorizableProperty... TODO
+ */
+public class OakAuthorizableProperties implements AuthorizableProperties {
+
+    /**
+     * logger instance
+     */
+    private static final Logger log = LoggerFactory.getLogger(OakAuthorizableProperties.class);
+
+    private final UserProvider userProvider;
+    private final String id;
+    private final NamePathMapper namePathMapper;
+
+    OakAuthorizableProperties(UserProvider userProvider, String id, NamePathMapper namePathMapper) {
+        this.userProvider = userProvider;
+        this.id = id;
+        this.namePathMapper = namePathMapper;
+    }
+
+    @Override
+    public Iterator<String> getNames(String relPath) throws RepositoryException {
+        Tree tree = getTree();
+        Tree n = tree.getLocation().getChild(relPath).getTree();
+        if (n != null && Text.isDescendantOrEqual(tree.getPath(), n.getPath())) {
+            List<String> l = new ArrayList<String>();
+            for (PropertyState property : n.getProperties()) {
+                if (isAuthorizableProperty(tree, property)) {
+                    l.add(property.getName());
+                }
+            }
+            return l.iterator();
+        } else {
+            throw new IllegalArgumentException("Relative path " + relPath + " refers to items outside of scope of authorizable.");
+        }
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#hasProperty(String)
+     */
+    @Override
+    public boolean hasProperty(String relPath) throws RepositoryException {
+        Tree tree = getTree();
+        TreeLocation propertyLocation = getPropertyLocation(tree, relPath);
+        return propertyLocation.getProperty() != null && isAuthorizableProperty(tree, propertyLocation, true);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#getProperty(String)
+     */
+    @Override
+    public Value[] getProperty(String relPath) throws RepositoryException {
+        Tree tree = getTree();
+        Value[] values = null;
+        TreeLocation propertyLocation = getPropertyLocation(tree, relPath);
+        PropertyState property = propertyLocation.getProperty();
+        if (property != null) {
+            if (isAuthorizableProperty(tree, propertyLocation, true)) {
+                if (property.isArray()) {
+                    List<Value> vs = ValueFactoryImpl.createValues(property, namePathMapper);
+                    values = vs.toArray(new Value[vs.size()]);
+                } else {
+                    values = new Value[]{ValueFactoryImpl.createValue(property, namePathMapper)};
+                }
+            }
+        }
+        return values;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#setProperty(String, javax.jcr.Value)
+     */
+    @Override
+    public void setProperty(String relPath, Value value) throws RepositoryException {
+        String name = Text.getName(relPath);
+        String intermediate = (relPath.equals(name)) ? null : Text.getRelativeParent(relPath, 1);
+
+        Tree n = getOrCreateTargetTree(intermediate);
+        // check if the property has already been created as multi valued
+        // property before -> in this case remove in order to avoid
+        // ValueFormatException.
+        if (n.hasProperty(name)) {
+            PropertyState p = n.getProperty(name);
+            if (p.isArray()) {
+                n.removeProperty(name);
+            }
+        }
+        n.setProperty(name, value);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#setProperty(String, javax.jcr.Value[])
+     */
+    @Override
+    public void setProperty(String relPath, Value[] values) throws RepositoryException {
+        String name = Text.getName(relPath);
+        String intermediate = (relPath.equals(name)) ? null : Text.getRelativeParent(relPath, 1);
+
+        Tree n = getOrCreateTargetTree(intermediate);
+        // check if the property has already been created as single valued
+        // property before -> in this case remove in order to avoid
+        // ValueFormatException.
+        if (n.hasProperty(name)) {
+            PropertyState p = n.getProperty(name);
+            if (!p.isArray()) {
+                n.removeProperty(name);
+            }
+        }
+        n.setProperty(name, values);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.api.security.user.Authorizable#removeProperty(String)
+     */
+    @Override
+    public boolean removeProperty(String relPath) throws RepositoryException {
+        Tree node = getTree();
+        TreeLocation propertyLocation = node.getLocation().getChild(relPath);
+        PropertyState property = propertyLocation.getProperty();
+        if (property != null) {
+            if (isAuthorizableProperty(node, propertyLocation, true)) {
+                Tree parent = propertyLocation.getParent().getTree();
+                parent.removeProperty(property.getName());
+                return true;
+            }
+        }
+        // no such property or wasn't a property of this authorizable.
+        return false;
+    }
+
+    private Tree getTree() {
+        return userProvider.getAuthorizable(id);
+    }
+
+    private String getJcrName(String oakName) {
+        return namePathMapper.getJcrName(oakName);
+    }
+
+    /**
+     * Returns true if the given property of the authorizable node is one of the
+     * non-protected properties defined by the rep:Authorizable node type or a
+     * some other descendant of the authorizable node.
+     *
+     * @param authorizableTree The tree of the target authorizable.
+     * @param propertyLocation Location to be tested.
+     * @param verifyAncestor If true the property is tested to be a descendant
+     * of the node of this authorizable; otherwise it is expected that this
+     * test has been executed by the caller.
+     * @return {@code true} if the given property is defined
+     * by the rep:authorizable node type or one of it's sub-node types;
+     * {@code false} otherwise.
+     * @throws RepositoryException If the property definition cannot be retrieved.
+     */
+    private boolean isAuthorizableProperty(Tree authorizableTree, TreeLocation propertyLocation, boolean verifyAncestor) throws RepositoryException {
+        if (verifyAncestor && !Text.isDescendant(authorizableTree.getPath(), propertyLocation.getPath())) {
+                log.debug("Attempt to access property outside of authorizable scope.");
+                return false;
+            }
+        return isAuthorizableProperty(authorizableTree, propertyLocation.getProperty());
+
+
+    }
+
+    private boolean isAuthorizableProperty(Tree authorizableTree, PropertyState property) throws RepositoryException {
+
+        // TODO: check protection and declaring nt of the property
+        return true;
+//        PropertyDefinition def = prop.getDefinition();
+//        if (def.isProtected()) {
+//            return false;
+//        } else if (node.isSame(prop.getParent())) {
+//            NodeType declaringNt = prop.getDefinition().getDeclaringNodeType();
+//            return declaringNt.isNodeType(getJcrName(NT_REP_AUTHORIZABLE));
+//        } else {
+//            // another non-protected property somewhere in the subtree of this
+//            // authorizable node -> is a property that can be set using #setProperty.
+//            return true;
+//        }
+    }
+
+    /**
+     * Retrieves the node at {@code relPath} relative to node associated with
+     * this authorizable. If no such node exist it and any missing intermediate
+     * nodes are created.
+     *
+     * @param relPath A relative path.
+     * @return The corresponding node.
+     * @throws RepositoryException If an error occurs or if {@code relPath} refers
+     * to a node that is outside of the scope of this authorizable.
+     */
+    @Nonnull
+    private Tree getOrCreateTargetTree(String relPath) throws RepositoryException {
+        Tree n;
+        Tree node = getTree();
+        if (relPath != null) {
+            String userPath = node.getPath();
+            n = node.getLocation().getChild(relPath).getTree();
+            if (n != null) {
+                if (!Text.isDescendantOrEqual(userPath, n.getPath())) {
+                    throw new RepositoryException("Relative path " + relPath + " outside of scope of " + this);
+                }
+            } else {
+                n = node;
+                for (String segment : Text.explode(relPath, '/')) {
+                    if (n.hasChild(segment)) {
+                        n = n.getChild(segment);
+                    } else {
+                        if (Text.isDescendantOrEqual(userPath, n.getPath())) {
+                            NodeUtil util = new NodeUtil(n, namePathMapper);
+                            n = util.addChild(segment, JcrConstants.NT_UNSTRUCTURED).getTree();
+                        } else {
+                            throw new RepositoryException("Relative path " + relPath + " outside of scope of " + this);
+                        }
+                    }
+                }
+            }
+        } else {
+            n = node;
+        }
+        return n;
+    }
+
+    @Nonnull
+    private TreeLocation getPropertyLocation(Tree tree, String relativePath) {
+        return tree.getLocation().getChild(relativePath);
+    }
+}
\ No newline at end of file



Mime
View raw message