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 an...@apache.org on 2012/10/18 20:51:20 UTC
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/...
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