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 2020/09/30 15:04:14 UTC

svn commit: r1882156 - in /jackrabbit/oak/trunk/oak-core: ./ src/main/java/org/apache/jackrabbit/oak/security/user/ src/main/java/org/apache/jackrabbit/oak/security/user/autosave/ src/main/java/org/apache/jackrabbit/oak/security/user/query/

Author: angela
Date: Wed Sep 30 15:04:14 2020
New Revision: 1882156

URL: http://svn.apache.org/viewvc?rev=1882156&view=rev
Log:
OAK-9247 : Sonar findings and minor improvements in o.a.j.oak.security.user

Modified:
    jackrabbit/oak/trunk/oak-core/pom.xml
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableIterator.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/MembershipProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/PasswordHistoryException.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserContext.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/autosave/AuthorizableWrapper.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/QueryUtil.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/UserQueryManager.java

Modified: jackrabbit/oak/trunk/oak-core/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/pom.xml?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-core/pom.xml Wed Sep 30 15:04:14 2020
@@ -183,6 +183,7 @@
                                     <include>org.apache.jackrabbit.oak.security.authorization.permission</include>
                                     <include>org.apache.jackrabbit.oak.security.authorization.restriction</include>
                                     <include>org.apache.jackrabbit.oak.security.internal</include>
+                                    <include>org.apache.jackrabbit.oak.security.user</include>
                                 </includes>
                                 <excludes>
                                     <exclude>*Test</exclude>
@@ -198,7 +199,6 @@
                             <rule>
                                 <element>PACKAGE</element>
                                 <includes>
-                                    <include>org.apache.jackrabbit.oak.security.user</include>
                                     <include>org.apache.jackrabbit.oak.security.authentication.token</include>
                                 </includes>
                                 <excludes>

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java Wed Sep 30 15:04:14 2020
@@ -16,15 +16,8 @@
  */
 package org.apache.jackrabbit.oak.security.user;
 
-import java.security.Principal;
-import java.util.Enumeration;
-import java.util.Iterator;
-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.GroupPrincipal;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.UserManager;
@@ -35,6 +28,11 @@ import org.jetbrains.annotations.NotNull
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.RepositoryException;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Iterator;
+
 /**
  * Base class for {@code Group} principals.
  */
@@ -95,19 +93,16 @@ abstract class AbstractGroupPrincipal ex
             throw new IllegalStateException(msg, e);
         }
 
-        Iterator<Principal> principals = Iterators.transform(members, new Function<Authorizable, Principal>() {
-            @Override
-            public Principal apply(Authorizable authorizable) {
-                if (authorizable == null) {
-                    return null;
-                }
-                try {
-                    return authorizable.getPrincipal();
-                } catch (RepositoryException e) {
-                    String msg = "Internal error while retrieving principal: " + e.getMessage();
-                    log.error(msg);
-                    throw new IllegalStateException(msg, e);
-                }
+        Iterator<Principal> principals = Iterators.transform(members, authorizable -> {
+            if (authorizable == null) {
+                return null;
+            }
+            try {
+                return authorizable.getPrincipal();
+            } catch (RepositoryException e) {
+                String msg = "Internal error while retrieving principal: " + e.getMessage();
+                log.error(msg);
+                throw new IllegalStateException(msg, e);
             }
         });
         return Iterators.asEnumeration(Iterators.filter(principals, Predicates.<Object>notNull()));

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableIterator.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableIterator.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableIterator.java Wed Sep 30 15:04:14 2020
@@ -16,19 +16,20 @@
  */
 package org.apache.jackrabbit.oak.security.user;
 
-import java.util.Iterator;
-import javax.jcr.RangeIterator;
-import javax.jcr.RepositoryException;
-
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterators;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
+import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.RangeIterator;
+import javax.jcr.RepositoryException;
+import java.util.Iterator;
+import java.util.function.Predicate;
+
 /**
  * AuthorizableIterator...
  */
@@ -97,7 +98,7 @@ final class AuthorizableIterator impleme
         public Authorizable apply(String oakPath) {
             try {
                 Authorizable a = userManager.getAuthorizableByOakPath(oakPath);
-                if (predicate.apply(a)) {
+                if (predicate.test(a)) {
                     return a;
                 }
             } catch (RepositoryException e) {
@@ -111,12 +112,12 @@ final class AuthorizableIterator impleme
 
         private final AuthorizableType authorizableType;
 
-        AuthorizableTypePredicate(AuthorizableType authorizableType) {
+        AuthorizableTypePredicate(@NotNull AuthorizableType authorizableType) {
             this.authorizableType = authorizableType;
         }
 
         @Override
-        public boolean apply(Authorizable authorizable) {
+        public boolean test(Authorizable authorizable) {
             return authorizableType.isType(authorizable);
         }
     }

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=1882156&r1=1882155&r2=1882156&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 Wed Sep 30 15:04:14 2020
@@ -261,39 +261,11 @@ class GroupImpl extends AuthorizableImpl
             if (Strings.isNullOrEmpty(memberId)) {
                 throw new ConstraintViolationException("MemberId must not be null or empty.");
             }
-            if (getID().equals(memberId)) {
-                String msg = "Attempt to add or remove a group as member of itself (" + getID() + ").";
-                log.debug(msg);
-                continue;
+            if (isValidMemberId(memberId, importBehavior)) {
+                // memberId can be processed -> remove from failedIds and generate contentID
+                failedIds.remove(memberId);
+                updateMap.put(mp.getContentID(memberId), memberId);
             }
-
-            if (ImportBehavior.BESTEFFORT != importBehavior) {
-                Authorizable member = getUserManager().getAuthorizable(memberId);
-                String msg = null;
-                if (member == null) {
-                    msg = "Attempt to add or remove a non-existing member '" + memberId + "' with ImportBehavior = " + ImportBehavior.nameFromValue(importBehavior);
-                } else if (member.isGroup()) {
-                    if (((AuthorizableImpl) member).isEveryone()) {
-                        log.debug("Attempt to add everyone group as member.");
-                        continue;
-                    } else if (isCyclicMembership((Group) member)) {
-                        msg = "Cyclic group membership detected for group " + getID() + " and member " + member.getID();
-                    }
-                }
-                if (msg != null) {
-                    if (ImportBehavior.ABORT == importBehavior) {
-                        throw new ConstraintViolationException(msg);
-                    } else {
-                        // ImportBehavior.IGNORE is default in UserUtil.getImportBehavior
-                        log.debug(msg);
-                        continue;
-                    }
-                }
-            }
-
-            // memberId can be processed -> remove from failedIds and generate contentID
-            failedIds.remove(memberId);
-            updateMap.put(mp.getContentID(memberId), memberId);
         }
 
         Set<String> processedIds = Sets.newHashSet(updateMap.values());
@@ -312,6 +284,38 @@ class GroupImpl extends AuthorizableImpl
         return failedIds;
     }
 
+    private boolean isValidMemberId(@NotNull String memberId, int importBehavior) throws RepositoryException {
+        if (getID().equals(memberId)) {
+            log.debug("Attempt to add or remove a group as member of itself ({}).", getID());
+            return false;
+        }
+
+        if (ImportBehavior.BESTEFFORT != importBehavior) {
+            Authorizable member = getUserManager().getAuthorizable(memberId);
+            String msg = null;
+            if (member == null) {
+                msg = "Attempt to add or remove a non-existing member '" + memberId + "' with ImportBehavior = " + ImportBehavior.nameFromValue(importBehavior);
+            } else if (member.isGroup()) {
+                if (((AuthorizableImpl) member).isEveryone()) {
+                    log.debug("Attempt to add everyone group as member.");
+                    return false;
+                } else if (isCyclicMembership((Group) member)) {
+                    msg = "Cyclic group membership detected for group " + getID() + " and member " + member.getID();
+                }
+            }
+            if (msg != null) {
+                if (ImportBehavior.ABORT == importBehavior) {
+                    throw new ConstraintViolationException(msg);
+                } else {
+                    // ImportBehavior.IGNORE is default in UserUtil.getImportBehavior
+                    log.debug(msg);
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     private boolean isCyclicMembership(@NotNull Group member) throws RepositoryException {
         return member.isMember(this);
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java Wed Sep 30 15:04:14 2020
@@ -151,51 +151,7 @@ class MembershipProvider extends Authori
         final Iterable<String> refPaths = identifierManager.getReferences(
                 authorizableTree, REP_MEMBERS, NT_REP_MEMBER_REFERENCES, true
         );
-
-        return new AbstractMemberIterator(refPaths.iterator()) {
-            @Override
-            protected String internalGetNext(@NotNull String propPath) {
-                String next = null;
-
-                String groupPath = getGroupPath(propPath);
-                if (groupPath != null) {
-                    if (processedPaths.add(groupPath)) {
-                        // we didn't see this path before, so continue
-                        next = groupPath;
-                        if (includeInherited) {
-                            // inject a parent iterator if inherited memberships is requested
-                            Tree group = getByPath(groupPath, AuthorizableType.GROUP);
-                            if (group != null) {
-                                remember(group);
-                            }
-                        }
-                    }
-                } else {
-                    log.debug("Not a membership reference property {}", propPath);
-                }
-                return next;
-            }
-
-            @NotNull
-            @Override
-            protected Iterator<String> getNextIterator(@NotNull Tree groupTree) {
-                return getMembership(groupTree, true, processedPaths);
-            }
-
-            @Nullable
-            private String getGroupPath(@NotNull String membersPropPath) {
-                int index = membersPropPath.indexOf('/' + REP_MEMBERS_LIST);
-                if (index < 0) {
-                    index = membersPropPath.indexOf('/' + REP_MEMBERS);
-                }
-
-                if (index > 0) {
-                    return membersPropPath.substring(0, index);
-                } else {
-                    return null;
-                }
-            }
-        };
+        return new MembershipIterator(refPaths.iterator(), includeInherited, processedPaths);
     }
 
     /**
@@ -506,4 +462,59 @@ class MembershipProvider extends Authori
         @NotNull
         protected abstract Iterator<String> getNextIterator(@NotNull Tree groupTree);
     }
+
+    private final class MembershipIterator extends AbstractMemberIterator {
+
+        private final boolean includeInherited;
+        private final Set<String> processedPaths;
+
+        private MembershipIterator(@NotNull Iterator<String> references, boolean includeInherited, @NotNull Set<String> processedPaths) {
+            super(references);
+            this.includeInherited = includeInherited;
+            this.processedPaths = processedPaths;
+        }
+
+        @Override
+        protected String internalGetNext(@NotNull String propPath) {
+            String next = null;
+
+            String groupPath = getGroupPath(propPath);
+            if (groupPath != null) {
+                if (processedPaths.add(groupPath)) {
+                    // we didn't see this path before, so continue
+                    next = groupPath;
+                    if (includeInherited) {
+                        // inject a parent iterator if inherited memberships is requested
+                        Tree group = getByPath(groupPath, AuthorizableType.GROUP);
+                        if (group != null) {
+                            remember(group);
+                        }
+                    }
+                }
+            } else {
+                log.debug("Not a membership reference property {}", propPath);
+            }
+            return next;
+        }
+
+        @NotNull
+        @Override
+        protected Iterator<String> getNextIterator(@NotNull Tree groupTree) {
+            return getMembership(groupTree, true, processedPaths);
+        }
+
+        @Nullable
+        private String getGroupPath(@NotNull String membersPropPath) {
+            int index = membersPropPath.indexOf('/' + REP_MEMBERS_LIST);
+            if (index < 0) {
+                index = membersPropPath.indexOf('/' + REP_MEMBERS);
+            }
+
+            if (index > 0) {
+                return membersPropPath.substring(0, index);
+            } else {
+                return null;
+            }
+        }
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/PasswordHistoryException.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/PasswordHistoryException.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/PasswordHistoryException.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/PasswordHistoryException.java Wed Sep 30 15:04:14 2020
@@ -16,11 +16,13 @@
  */
 package org.apache.jackrabbit.oak.security.user;
 
+import org.jetbrains.annotations.NotNull;
+
 import javax.jcr.nodetype.ConstraintViolationException;
 
 class PasswordHistoryException extends ConstraintViolationException {
 
-    PasswordHistoryException(String message) {
+    PasswordHistoryException(@NotNull String message) {
         super(message);
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserContext.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserContext.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserContext.java Wed Sep 30 15:04:14 2020
@@ -77,8 +77,8 @@ final class UserContext implements Conte
             // group node (missing node type information on non-existing location)
             return USER_PROPERTY_NAMES.contains(name)
                     || GROUP_PROPERTY_NAMES.contains(name)
-                    || path.contains(REP_MEMBERS)
                     || path.contains(REP_MEMBERS_LIST)
+                    || path.contains(REP_MEMBERS)
                     || path.contains(REP_PWD);
         }
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java Wed Sep 30 15:04:14 2020
@@ -234,78 +234,15 @@ class UserImporter implements ProtectedP
 
             String propName = propInfo.getName();
             if (REP_AUTHORIZABLE_ID.equals(propName)) {
-                if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
-                    return false;
-                }
-                String id = propInfo.getTextValue().getString();
-                Authorizable existing = userManager.getAuthorizable(id);
-                if (existing == null) {
-                    String msg = "Cannot handle protected PropInfo " + propInfo + ". Invalid rep:authorizableId.";
-                    log.warn(msg);
-                    throw new ConstraintViolationException(msg);
-                }
-
-                if (a.getPath().equals(existing.getPath())) {
-                    parent.setProperty(REP_AUTHORIZABLE_ID, id);
-                } else {
-                    throw new AuthorizableExistsException(id);
-                }
-                return true;
-
+                return importAuthorizableId(parent, a, propInfo, def);
             } else if (REP_PRINCIPAL_NAME.equals(propName)) {
-                if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
-                    return false;
-                }
-
-                String principalName = propInfo.getTextValue().getString();
-                Principal principal = new PrincipalImpl(principalName);
-                userManager.checkValidPrincipal(principal, a.isGroup());
-                userManager.setPrincipal(parent, principal);
-
-                /*
-                 Remember principal of new user/group for further processing
-                 of impersonators
-                 */
-                principals.put(principalName, a.getPrincipal());
-
-                return true;
+                return importPrincipalName(parent, a, propInfo, def);
             } else if (REP_PASSWORD.equals(propName)) {
-                if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
-                    log.warn("Unexpected authorizable or definition for property rep:password");
-                    return false;
-                }
-                if (((User) a).isSystemUser()) {
-                    log.warn("System users may not have a password set.");
-                    return false;
-                }
-
-                String pw = propInfo.getTextValue().getString();
-                userManager.setPassword(parent, a.getID(), pw, true);
-                currentPw = pw;
-
-                return true;
-
+                return importPassword(parent, a, propInfo, def);
             } else if (REP_IMPERSONATORS.equals(propName)) {
-                if (a.isGroup() || !isValid(def, MIX_REP_IMPERSONATABLE, true)) {
-                    log.warn("Unexpected authorizable or definition for property rep:impersonators");
-                    return false;
-                }
-
-                // since impersonators may be imported later on, postpone processing
-                // to the end.
-                // see -> process References
-                referenceTracker.processedReference(new Impersonators(parent.getPath(), propInfo.getTextValues()));
-                return true;
-
+                return importImpersonators(parent, a, propInfo, def);
             } else if (REP_DISABLED.equals(propName)) {
-                if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
-                    log.warn("Unexpected authorizable or definition for property rep:disabled");
-                    return false;
-                }
-
-                ((User) a).disable(propInfo.getTextValue().getString());
-                return true;
-
+                return importDisabled(a, propInfo, def);
             } else if (REP_MEMBERS.equals(propName)) {
                 if (!a.isGroup() || !isValid(def, NT_REP_MEMBER_REFERENCES, true)) {
                     return false;
@@ -389,7 +326,7 @@ class UserImporter implements ProtectedP
         Authorizable auth = null;
         if (isMemberNode(protectedParent)) {
             Tree groupTree = protectedParent;
-            while (isMemberNode(groupTree) && !groupTree.isRoot()) {
+            while (isMemberNode(groupTree)) {
                 groupTree = groupTree.getParent();
             }
             auth = userManager.getAuthorizable(groupTree);
@@ -458,9 +395,88 @@ class UserImporter implements ProtectedP
                 definition.getDeclaringNodeType().isNodeType(namePathMapper.getJcrName(oakNodeTypeName));
     }
 
+    private boolean importAuthorizableId(@NotNull Tree parent, @NotNull Authorizable a, @NotNull PropInfo propInfo, @NotNull PropertyDefinition def) throws RepositoryException {
+        if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
+            return false;
+        }
+        String id = propInfo.getTextValue().getString();
+        Authorizable existing = userManager.getAuthorizable(id);
+        if (existing == null) {
+            String msg = "Cannot handle protected PropInfo " + propInfo + ". Invalid rep:authorizableId.";
+            log.warn(msg);
+            throw new ConstraintViolationException(msg);
+        }
+
+        if (a.getPath().equals(existing.getPath())) {
+            parent.setProperty(REP_AUTHORIZABLE_ID, id);
+        } else {
+            throw new AuthorizableExistsException(id);
+        }
+        return true;
+
+    }
+
+    private boolean importPrincipalName(@NotNull Tree parent, @NotNull Authorizable a, @NotNull PropInfo propInfo, @NotNull PropertyDefinition def) throws RepositoryException {
+        if (!isValid(def, NT_REP_AUTHORIZABLE, false)) {
+            return false;
+        }
+
+        String principalName = propInfo.getTextValue().getString();
+        Principal principal = new PrincipalImpl(principalName);
+        userManager.checkValidPrincipal(principal, a.isGroup());
+        userManager.setPrincipal(parent, principal);
+
+                /*
+                 Remember principal of new user/group for further processing
+                 of impersonators
+                 */
+        principals.put(principalName, a.getPrincipal());
+        return true;
+    }
+
+    private boolean importPassword(@NotNull Tree parent, @NotNull Authorizable a, @NotNull PropInfo propInfo, @NotNull PropertyDefinition def) throws RepositoryException {
+        if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
+            log.warn("Unexpected authorizable or definition for property rep:password");
+            return false;
+        }
+        if (((User) a).isSystemUser()) {
+            log.warn("System users may not have a password set.");
+            return false;
+        }
+
+        String pw = propInfo.getTextValue().getString();
+        userManager.setPassword(parent, a.getID(), pw, true);
+        currentPw = pw;
+
+        return true;
+    }
+
+    private boolean importImpersonators(@NotNull Tree parent, @NotNull Authorizable a, @NotNull PropInfo propInfo, @NotNull PropertyDefinition def) {
+        if (a.isGroup() || !isValid(def, MIX_REP_IMPERSONATABLE, true)) {
+            log.warn("Unexpected authorizable or definition for property rep:impersonators");
+            return false;
+        }
+
+        // since impersonators may be imported later on, postpone processing
+        // to the end.
+        // see -> process References
+        referenceTracker.processedReference(new Impersonators(parent.getPath(), propInfo.getTextValues()));
+        return true;
+    }
+
+    private boolean importDisabled(@NotNull Authorizable a, @NotNull PropInfo propInfo, @NotNull PropertyDefinition def) throws RepositoryException {
+        if (a.isGroup() || !isValid(def, NT_REP_USER, false)) {
+            log.warn("Unexpected authorizable or definition for property rep:disabled");
+            return false;
+        }
+
+        ((User) a).disable(propInfo.getTextValue().getString());
+        return true;
+    }
+
     private static boolean isMemberNode(@NotNull Tree tree) {
         //noinspection deprecation
-        return tree.exists() && NT_REP_MEMBERS.equals(TreeUtil.getPrimaryTypeName(tree));
+        return tree.exists() && !tree.isRoot() && NT_REP_MEMBERS.equals(TreeUtil.getPrimaryTypeName(tree));
     }
 
     private static boolean isMemberReferencesListNode(@NotNull Tree tree) {
@@ -512,15 +528,13 @@ class UserImporter implements ProtectedP
      */
     private void handleFailure(String msg) throws ConstraintViolationException {
         switch (importBehavior) {
+            case ImportBehavior.ABORT:
+                throw new ConstraintViolationException(msg);
             case ImportBehavior.IGNORE:
             case ImportBehavior.BESTEFFORT:
+            default:
                 log.warn(msg);
                 break;
-            case ImportBehavior.ABORT:
-                throw new ConstraintViolationException(msg);
-            default:
-                // no other behavior. nothing to do.
-
         }
     }
 
@@ -566,37 +580,8 @@ class UserImporter implements ProtectedP
                 Authorizable dm = declMembers.next();
                 toRemove.put(dm.getID(), dm);
             }
-
-            Map<String, Authorizable> toAdd = Maps.newHashMapWithExpectedSize(members.size());
             Map<String, String> nonExisting = Maps.newHashMap();
-
-            for (String contentId : members) {
-                String remapped = referenceTracker.get(contentId);
-                String memberContentId = (remapped == null) ? contentId : remapped;
-
-                Authorizable member = null;
-                try {
-                    Tree n = getIdentifierManager().getTree(memberContentId);
-                    member = userManager.getAuthorizable(n);
-                } catch (RepositoryException e) {
-                    // no such node or failed to retrieve authorizable
-                    // warning is logged below.
-                }
-                if (member != null) {
-                    if (toRemove.remove(member.getID()) == null) {
-                        toAdd.put(member.getID(), member);
-                    } // else: no need to remove from rep:members
-                } else {
-                    handleFailure("New member of " + gr + ": No such authorizable (NodeID = " + memberContentId + ')');
-                    if (importBehavior == ImportBehavior.BESTEFFORT) {
-                        log.debug("ImportBehavior.BESTEFFORT: Remember non-existing member for processing.");
-                        /* since we ignore the set of failed ids later on and
-                           don't know the real memberId => use fake memberId as
-                           value in the map */
-                        nonExisting.put(contentId, "-");
-                    }
-                }
-            }
+            Map<String, Authorizable> toAdd = getAuthorizablesToAdd(gr, toRemove, nonExisting);
 
             // 2. adjust members of the group
             if (!toRemove.isEmpty()) {
@@ -629,6 +614,39 @@ class UserImporter implements ProtectedP
         }
 
         @NotNull
+        Map<String, Authorizable> getAuthorizablesToAdd(@NotNull Group gr, @NotNull Map<String, Authorizable> toRemove,
+                                                        @NotNull Map<String, String> nonExisting) throws RepositoryException {
+            Map<String, Authorizable> toAdd = Maps.newHashMapWithExpectedSize(members.size());
+            for (String contentId : members) {
+                // NOTE: no need to check for re-mapped uuids with the referenceTracker because
+                // ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW is not supported for user/group imports (see line 189)
+                Authorizable member = null;
+                try {
+                    Tree n = getIdentifierManager().getTree(contentId);
+                    member = userManager.getAuthorizable(n);
+                } catch (RepositoryException e) {
+                    // no such node or failed to retrieve authorizable
+                    // warning is logged below.
+                }
+                if (member != null) {
+                    if (toRemove.remove(member.getID()) == null) {
+                        toAdd.put(member.getID(), member);
+                    } // else: no need to remove from rep:members
+                } else {
+                    handleFailure("New member of " + gr + ": No such authorizable (NodeID = " + contentId + ')');
+                    if (importBehavior == ImportBehavior.BESTEFFORT) {
+                        log.debug("ImportBehavior.BESTEFFORT: Remember non-existing member for processing.");
+                        /* since we ignore the set of failed ids later on and
+                           don't know the real memberId => use fake memberId as
+                           value in the map */
+                        nonExisting.put(contentId, "-");
+                    }
+                }
+            }
+            return toAdd;
+        }
+
+        @NotNull
         private IdentifierManager getIdentifierManager() {
             if (identifierManager == null) {
                 identifierManager = new IdentifierManager(root);
@@ -680,6 +698,25 @@ class UserImporter implements ProtectedP
             }
 
             // 2. adjust set of impersonators
+            List<String> nonExisting = updateImpersonators(a, imp, toRemove, toAdd);
+            if (!nonExisting.isEmpty()) {
+                Tree userTree = checkNotNull(root.getTree(a.getPath()));
+                // copy over all existing impersonators to the nonExisting list
+                PropertyState impersonators = userTree.getProperty(REP_IMPERSONATORS);
+                if (impersonators != null) {
+                    for (String existing : impersonators.getValue(STRINGS)) {
+                        nonExisting.add(existing);
+                    }
+                }
+                // and write back the complete list including those principal
+                // names that are unknown to principal provider.
+                userTree.setProperty(REP_IMPERSONATORS, nonExisting, Type.STRINGS);
+            }
+        }
+
+        @NotNull
+        private List<String> updateImpersonators(@NotNull Authorizable a, @NotNull Impersonation imp,
+                                                 @NotNull Map<String, Principal> toRemove, @NotNull List<String> toAdd) throws RepositoryException {
             for (Principal p : toRemove.values()) {
                 if (!imp.revokeImpersonation(p)) {
                     String principalName = p.getName();
@@ -700,20 +737,7 @@ class UserImporter implements ProtectedP
                     }
                 }
             }
-
-            if (!nonExisting.isEmpty()) {
-                Tree userTree = checkNotNull(root.getTree(a.getPath()));
-                // copy over all existing impersonators to the nonExisting list
-                PropertyState impersonators = userTree.getProperty(REP_IMPERSONATORS);
-                if (impersonators != null) {
-                    for (String existing : impersonators.getValue(STRINGS)) {
-                        nonExisting.add(existing);
-                    }
-                }
-                // and write back the complete list including those principal
-                // names that are unknown to principal provider.
-                userTree.setProperty(REP_IMPERSONATORS, nonExisting, Type.STRINGS);
-            }
+            return nonExisting;
         }
 
         @NotNull

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java Wed Sep 30 15:04:14 2020
@@ -20,6 +20,7 @@ import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
+import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
 import org.apache.jackrabbit.api.security.principal.ItemBasedPrincipal;
@@ -228,7 +229,7 @@ class UserPrincipalProvider implements P
             if (AuthorizableType.GROUP == type) {
                 return createGroupPrincipal(authorizableTree);
             } else if (AuthorizableType.USER == type) {
-                return createUserPrincipal(UserUtil.getAuthorizableId(authorizableTree, type), authorizableTree);
+                return createUserPrincipal(UserUtil.getAuthorizableId(authorizableTree, AuthorizableType.USER), authorizableTree);
             }
         }
         return null;
@@ -272,15 +273,15 @@ class UserPrincipalProvider implements P
 
     @NotNull
     private Set<Principal> getGroupMembership(@NotNull Tree authorizableTree) {
-        Set<Principal> groupPrincipals = null;
+        Set<Principal> groupPrincipals = new HashSet<>();
         boolean doCache = cacheEnabled && UserUtil.isType(authorizableTree, AuthorizableType.USER);
+        boolean doLoad = true;
         if (doCache) {
-            groupPrincipals = readGroupsFromCache(authorizableTree);
+            doLoad = readGroupsFromCache(authorizableTree, groupPrincipals);
         }
 
         // caching not configured or cache expired: use the membershipProvider to calculate
-        if (groupPrincipals == null) {
-            groupPrincipals = new HashSet<>();
+        if (doLoad) {
             Iterator<String> groupPaths = membershipProvider.getMembership(authorizableTree, true);
             while (groupPaths.hasNext()) {
                 Tree groupTree = userProvider.getAuthorizableByPath(groupPaths.next());
@@ -319,12 +320,7 @@ class UserPrincipalProvider implements P
             }
 
             cache.setProperty(CacheConstants.REP_EXPIRATION, LongUtils.calculateExpirationTime(expiration));
-            String value = (groupPrincipals.isEmpty()) ? "" : Joiner.on(",").join(Iterables.transform(groupPrincipals, new Function<Principal, String>() {
-                @Override
-                public String apply(Principal input) {
-                    return Text.escape(input.getName());
-                }
-            }));
+            String value = (groupPrincipals.isEmpty()) ? "" : Joiner.on(",").join(Iterables.transform(groupPrincipals, input -> Text.escape(input.getName())));
             cache.setProperty(CacheConstants.REP_GROUP_PRINCIPAL_NAMES, value);
 
             root.commit(CacheValidatorProvider.asCommitAttributes());
@@ -337,31 +333,29 @@ class UserPrincipalProvider implements P
         }
     }
 
-    @Nullable
-    private Set<Principal> readGroupsFromCache(@NotNull Tree authorizableNode) {
+    private boolean readGroupsFromCache(@NotNull Tree authorizableNode, @NotNull Set<Principal> groups) {
         Tree principalCache = authorizableNode.getChild(CacheConstants.REP_CACHE);
         if (!principalCache.exists()) {
             log.debug("No group cache at {}", authorizableNode.getPath());
-            return null;
+            return true;
         }
 
         if (isValidCache(principalCache)) {
             log.debug("Reading group membership at {}", authorizableNode.getPath());
 
             String str = TreeUtil.getString(principalCache, CacheConstants.REP_GROUP_PRINCIPAL_NAMES);
-            if (str == null || str.isEmpty()) {
-                return new HashSet<>(1);
+            if (Strings.isNullOrEmpty(str)) {
+                return false;
             }
 
-            Set<Principal> groups = new HashSet<>();
             for (String s : Text.explode(str, ',')) {
                 final String name = Text.unescape(s);
                 groups.add(new CachedGroupPrincipal(name, namePathMapper, root, config));
             }
-            return groups;
+            return false;
         } else {
             log.debug("Expired group cache for {}", authorizableNode.getPath());
-            return null;
+            return true;
         }
     }
 
@@ -466,7 +460,7 @@ class UserPrincipalProvider implements P
         @Override
         Iterator<Authorizable> getMembers() throws RepositoryException {
             org.apache.jackrabbit.api.security.user.Group g = getGroup();
-            return (g == null) ? Collections.<Authorizable>emptyIterator() : g.getMembers();
+            return (g == null) ? Collections.emptyIterator() : g.getMembers();
         }
 
         @Nullable

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserProvider.java Wed Sep 30 15:04:14 2020
@@ -290,8 +290,8 @@ class UserProvider extends AuthorizableB
      * @throws RepositoryException If an error occurs
      */
     private Tree createFolderNodes(@NotNull String nodeName,
-                                       boolean isGroup,
-                                       @Nullable String intermediatePath) throws RepositoryException {
+                                   boolean isGroup,
+                                   @Nullable String intermediatePath) throws RepositoryException {
         String authRoot = (isGroup) ? groupPath : userPath;
         String folderPath = new StringBuilder()
                 .append(authRoot)

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/autosave/AuthorizableWrapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/autosave/AuthorizableWrapper.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/autosave/AuthorizableWrapper.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/autosave/AuthorizableWrapper.java Wed Sep 30 15:04:14 2020
@@ -41,10 +41,10 @@ final class AuthorizableWrapper<T extend
     }
 
     static Iterator<Authorizable> createIterator(Iterator<Authorizable> dlgs, AutoSaveEnabledManager mgr) {
-        return Iterators.transform(dlgs, new AuthorizableWrapper<Authorizable>(mgr));
+        return Iterators.transform(dlgs, new AuthorizableWrapper<>(mgr));
     }
 
     static Iterator<Group> createGroupIterator(Iterator<Group> dlgs, AutoSaveEnabledManager mgr) {
-        return Iterators.transform(dlgs, new AuthorizableWrapper<Group>(mgr));
+        return Iterators.transform(dlgs, new AuthorizableWrapper<>(mgr));
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/QueryUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/QueryUtil.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/QueryUtil.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/QueryUtil.java Wed Sep 30 15:04:14 2020
@@ -32,6 +32,7 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.user.util.UserUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.jackrabbit.api.security.user.QueryBuilder.Direction.ASCENDING;
@@ -41,7 +42,7 @@ import static org.apache.jackrabbit.api.
  */
 public final class QueryUtil {
 
-    private static final org.slf4j.Logger log = LoggerFactory.getLogger(GroupPredicate.class);
+    private static final Logger log = LoggerFactory.getLogger(QueryUtil.class);
 
     private QueryUtil() {}
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/UserQueryManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/UserQueryManager.java?rev=1882156&r1=1882155&r2=1882156&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/UserQueryManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/UserQueryManager.java Wed Sep 30 15:04:14 2020
@@ -204,7 +204,7 @@ public class UserQueryManager {
             stmt.append(ISO9075.encode(propName));
             if (exact) {
                 stmt.append("='");
-                stmt.append(value.replaceAll("'", "''"));
+                stmt.append(value.replace("'", "''"));
                 stmt.append('\'');
             } else {
                 stmt.append(",'%");
@@ -276,8 +276,7 @@ public class UserQueryManager {
             Iterator<Authorizable> authorizables = Iterators.transform(resultRows.iterator(), new ResultRowToAuthorizable(userManager, root, type));
             return Iterators.filter(authorizables, new UniqueResultPredicate());
         } catch (ParseException e) {
-            log.warn("Invalid user query: " + statement, e);
-            throw new RepositoryException(e);
+            throw new RepositoryException("Invalid user query "+statement, e);
         }
     }