UserPropertiesServiceImpl.java 17.4 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.google.common.collect.ImmutableMap
 *  javax.annotation.Nonnull
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.Value
 *  javax.jcr.ValueFactory
 *  javax.jcr.security.AccessControlManager
 *  javax.jcr.security.AccessControlPolicy
 *  javax.jcr.security.Privilege
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.jackrabbit.api.JackrabbitSession
 *  org.apache.jackrabbit.api.security.JackrabbitAccessControlList
 *  org.apache.jackrabbit.api.security.user.Authorizable
 *  org.apache.jackrabbit.api.security.user.Group
 *  org.apache.jackrabbit.api.security.user.UserManager
 *  org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils
 *  org.apache.sling.api.adapter.AdapterFactory
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.commons.osgi.PropertiesUtil
 *  org.apache.sling.jcr.api.SlingRepository
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.granite.security.user.internal;

import com.adobe.granite.security.user.UserManagementService;
import com.adobe.granite.security.user.UserProperties;
import com.adobe.granite.security.user.UserPropertiesManager;
import com.adobe.granite.security.user.UserPropertiesService;
import com.adobe.granite.security.user.internal.AuthorizableInfo;
import com.adobe.granite.security.user.internal.UserPropertiesManagerImpl;
import com.google.common.collect.ImmutableMap;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
import javax.jcr.security.Privilege;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.apache.sling.api.adapter.AdapterFactory;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.jcr.api.SlingRepository;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=1, label="Adobe Granite UserProperties Service", description="Service used to retrieve the UserPropertiesManager for a given Session.", name="com.adobe.granite.security.user.UserPropertiesService")
@Service(value={UserPropertiesService.class, AdapterFactory.class})
@Properties(value={@org.apache.felix.scr.annotations.Property(name="service.description", value={"Service to access the UserPropertiesManager."}), @org.apache.felix.scr.annotations.Property(name="adapter.condition", value={"If the Resource can be adapted to a JCR Node and is one of the configured resource types."})})
public class UserPropertiesServiceImpl
extends UserPropertiesService
implements AdapterFactory {
    private static final Logger log = LoggerFactory.getLogger(UserPropertiesServiceImpl.class);
    private static final String DEFAULT_RESOURCE_TYPE = "cq:Preferences";
    public static final String PROP_SLING_RESOURCE_TYPE = "sling:resourceType";
    private static final String USER_PROPERTIES_SERVICE = "userproperties-service";
    @org.apache.felix.scr.annotations.Property(value={"preferences=nt:unstructured", "profiles/.*=nt:unstructured"}, label="Node Types", description="Node types to use for the creation of the preferences or profile nodes. (Format: regexp=resourceType)", cardinality=1024)
    private static final String PROPERTY_NODETYPES = "granite.userproperties.nodetypes";
    @org.apache.felix.scr.annotations.Property(value={"preferences=cq:Preferences", "profiles/.*=cq/security/components/profile", "profile=cq/security/components/profile"}, label="Resource Types", description="Resource type to use for preferences or profile nodes. (Format: regexp=resourceType)", cardinality=1024)
    private static final String PROPERTY_RESOURCETYPES = "granite.userproperties.resourcetypes";
    @org.apache.felix.scr.annotations.Property(name="Adapters", propertyPrivate=1)
    private static final String[] ADAPTER_CLASSES = new String[]{UserProperties.class.getName(), UserPropertiesManager.class.getName()};
    @org.apache.felix.scr.annotations.Property(name="Adaptables", propertyPrivate=1)
    private static final String[] ADAPTABLE_CLASSES = new String[]{Resource.class.getName(), ResourceResolver.class.getName()};
    @Reference
    private SlingRepository repository;
    @Reference
    private UserManagementService ums;
    private final HashMap<Pattern, String> nodeTypes = new HashMap();
    private final HashMap<Pattern, String> resourceTypes = new HashMap();

    @Override
    public UserPropertiesManager createUserPropertiesManager(ResourceResolver resolver) throws RepositoryException {
        return new UserPropertiesManagerImpl((Session)resolver.adaptTo(Session.class), resolver, this);
    }

    @Override
    public UserPropertiesManager createUserPropertiesManager(Session session, ResourceResolver resolver) throws RepositoryException {
        return new UserPropertiesManagerImpl(session, resolver, this);
    }

    @Override
    public String getResourceType(String userPropertiesName) {
        for (Map.Entry<Pattern, String> entry : this.resourceTypes.entrySet()) {
            if (!entry.getKey().matcher(userPropertiesName).matches()) continue;
            return entry.getValue();
        }
        return null;
    }

    @Override
    public String getNodeType(String userPropertiesName) {
        for (Map.Entry<Pattern, String> entry : this.nodeTypes.entrySet()) {
            if (!entry.getKey().matcher(userPropertiesName).matches()) continue;
            return entry.getValue();
        }
        return "nt:unstructured";
    }

    @Override
    public String getAuthorizablePath(String authorizableId) throws RepositoryException {
        AuthorizableInfo info = this.getAuthorizableInfo(authorizableId);
        return info == null ? null : info.getPath();
    }

    @Override
    public String getAuthorizableId(String userPropertiesPath) throws RepositoryException {
        AuthorizableInfo info = this.getAuthorizableInfoByPath(userPropertiesPath);
        return info == null ? null : info.getId();
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public AuthorizableInfo getAuthorizableInfo(String authorizableId) throws RepositoryException {
        Session s = this.repository.loginService("userproperties-service", null);
        try {
            Authorizable a;
            if (s instanceof JackrabbitSession && (a = ((JackrabbitSession)s).getUserManager().getAuthorizable(authorizableId)) != null) {
                AuthorizableInfo authorizableInfo = new AuthorizableInfo(authorizableId, a.getPath(), a.isGroup());
                return authorizableInfo;
            }
        }
        finally {
            s.logout();
        }
        return null;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    List<Node> listUserPropertiesNodes(String authorizableId, String relRootPath, ResourceResolver userResolver) throws RepositoryException {
        Session s = this.repository.loginService("userproperties-service", null);
        try {
            Node n;
            AuthorizableInfo info = this.getAuthorizableInfo(authorizableId);
            if (relRootPath == null) {
                relRootPath = "profiles";
            }
            Node profiles = s.getNode(info.getPath() + '/' + relRootPath);
            NodeIterator it = profiles.getNodes();
            Node list = new Node();
            while (it.hasNext()) {
                Node candidate;
                n = it.nextNode();
                Resource resource = userResolver.getResource(n.getPath());
                if (resource == null || (candidate = (Node)resource.adaptTo(Node.class)) == null || !candidate.hasProperty("sling:resourceType") || !"cq/security/components/profile".equals(candidate.getProperty("sling:resourceType").getString())) continue;
                list.add(candidate);
            }
            n = list;
            return n;
        }
        finally {
            s.logout();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    AuthorizableInfo getAuthorizableInfoByPath(String userPropertiesPath) throws RepositoryException {
        Session s = this.repository.loginService("userproperties-service", null);
        try {
            if (s instanceof JackrabbitSession) {
                Node authorizableNode = null;
                Node n = s.getNode(userPropertiesPath);
                while (n.getDepth() != 0) {
                    if (n.isNodeType("rep:Authorizable")) {
                        authorizableNode = n;
                        break;
                    }
                    n = n.getParent();
                }
                if (authorizableNode != null) {
                    String authorizablePath = authorizableNode.getPath();
                    UserManager userMgr = ((JackrabbitSession)s).getUserManager();
                    Authorizable a = userMgr.getAuthorizableByPath(authorizablePath);
                    if (a != null) {
                        AuthorizableInfo authorizableInfo = new AuthorizableInfo(a.getID(), a.getPath(), a.isGroup());
                        return authorizableInfo;
                    }
                }
            }
        }
        finally {
            s.logout();
        }
        return null;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Iterator<AuthorizableInfo> getMemberOf(String id, boolean declaredOnly) throws RepositoryException {
        ArrayList<AuthorizableInfo> groups;
        groups = new ArrayList<AuthorizableInfo>();
        Session s = this.repository.loginService("userproperties-service", null);
        try {
            UserManager userMgr;
            Authorizable auth;
            if (s instanceof JackrabbitSession && (auth = (userMgr = ((JackrabbitSession)s).getUserManager()).getAuthorizable(id)) != null) {
                Iterator iter;
                Iterator iterator = iter = declaredOnly ? auth.declaredMemberOf() : auth.memberOf();
                while (iter.hasNext()) {
                    groups.add(new AuthorizableInfo((Authorizable)iter.next()));
                }
            }
        }
        finally {
            s.logout();
        }
        return groups.iterator();
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Iterator<AuthorizableInfo> getMembers(Group group, boolean declaredOnly) throws RepositoryException {
        ArrayList<AuthorizableInfo> members;
        members = new ArrayList<AuthorizableInfo>();
        Session s = this.repository.loginService("userproperties-service", null);
        try {
            UserManager userMgr;
            if (s instanceof JackrabbitSession && (group = (Group)(userMgr = ((JackrabbitSession)s).getUserManager()).getAuthorizable(group.getID())) != null) {
                Iterator iter;
                Iterator iterator = iter = declaredOnly ? group.getDeclaredMembers() : group.getMembers();
                while (iter.hasNext()) {
                    members.add(new AuthorizableInfo((Authorizable)iter.next()));
                }
            }
        }
        finally {
            s.logout();
        }
        return members.iterator();
    }

    public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
        try {
            if (adaptable instanceof Resource) {
                Resource resource = (Resource)adaptable;
                ResourceResolver resolver = resource.getResourceResolver();
                Node n = (Node)resource.adaptTo(Node.class);
                if (n != null) {
                    UserPropertiesManager mgr = this.createUserPropertiesManager(resolver);
                    if (type == UserProperties.class && this.resourceTypes.containsValue(resource.getResourceType())) {
                        return (AdapterType)mgr.getUserProperties(n);
                    }
                    if (type == UserPropertiesManager.class) {
                        return (AdapterType)mgr;
                    }
                } else {
                    log.warn("Resource is not adaptable to a node");
                }
            } else if (adaptable instanceof ResourceResolver && type == UserPropertiesManager.class) {
                ResourceResolver resolver = (ResourceResolver)adaptable;
                UserPropertiesManager mgr = this.createUserPropertiesManager(resolver);
                return (AdapterType)mgr;
            }
        }
        catch (RepositoryException e) {
            log.error("Could not adapt " + adaptable + " to " + type.getName(), (Throwable)e);
        }
        log.warn("Requested adapter type not supported: {}, adaptable {}", (Object)type.getName(), adaptable);
        return null;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Activate
    protected void activate(ComponentContext context) {
        String[] nts;
        Dictionary props = context.getProperties();
        String[] rts = PropertiesUtil.toStringArray(props.get("granite.userproperties.resourcetypes"));
        if (rts != null && rts.length > 0) {
            for (String s : rts) {
                String[] args = s.split("=");
                if (args.length != 2) continue;
                this.resourceTypes.put(Pattern.compile(args[0].trim()), args[1].trim());
            }
        }
        if ((nts = PropertiesUtil.toStringArray(props.get("granite.userproperties.nodetypes"))) != null) {
            for (String s : nts) {
                String[] args = s.split("=");
                if (args.length != 2) continue;
                this.nodeTypes.put(Pattern.compile(args[0].trim()), args[1].trim());
            }
        }
        try {
            Session s = null;
            try {
                s = this.repository.loginService("userproperties-service", null);
                UserPropertiesServiceImpl.setupDefaultReadPermissions(s, this.ums.getAuthorizableRootPath());
                log.info("Default permissions for public profile were successfully set up.");
            }
            finally {
                if (s != null) {
                    s.logout();
                }
            }
        }
        catch (RepositoryException e) {
            log.error("Couldn't set up permissions for public profile", (Throwable)e);
        }
    }

    private static void setupDefaultReadPermissions(@Nonnull Session session, @Nonnull String path) throws RepositoryException {
        Principal everyone = AccessControlUtils.getEveryonePrincipal((Session)session);
        AccessControlManager accessControlManager = session.getAccessControlManager();
        JackrabbitAccessControlList acl = AccessControlUtils.getAccessControlList((AccessControlManager)accessControlManager, (String)path);
        if (acl != null) {
            Privilege[] readPriv = AccessControlUtils.privilegesFromNames((AccessControlManager)accessControlManager, (String[])new String[]{"{http://www.jcp.org/jcr/1.0}read"});
            acl.addEntry(everyone, readPriv, true, (Map)ImmutableMap.of((Object)"rep:glob", (Object)session.getValueFactory().createValue("*/profiles/public")));
            acl.addEntry(everyone, readPriv, true, (Map)ImmutableMap.of((Object)"rep:glob", (Object)session.getValueFactory().createValue("*/profiles/public/*")));
            accessControlManager.setPolicy(acl.getPath(), (AccessControlPolicy)acl);
        }
        if (session.hasPendingChanges()) {
            session.save();
        }
    }

    protected void bindRepository(SlingRepository slingRepository) {
        this.repository = slingRepository;
    }

    protected void unbindRepository(SlingRepository slingRepository) {
        if (this.repository == slingRepository) {
            this.repository = null;
        }
    }

    protected void bindUms(UserManagementService userManagementService) {
        this.ums = userManagementService;
    }

    protected void unbindUms(UserManagementService userManagementService) {
        if (this.ums == userManagementService) {
            this.ums = null;
        }
    }
}