/* * 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.sling.jackrabbit.usermanager.impl.resource; import java.security.Principal; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.jackrabbit.api.security.principal.PrincipalIterator; 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.sling.api.SlingException; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.SyntheticResource; import org.apache.sling.jcr.base.util.AccessControlUtil; import org.apache.sling.spi.resource.provider.ResolveContext; import org.apache.sling.spi.resource.provider.ResourceContext; import org.apache.sling.spi.resource.provider.ResourceProvider; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Resource Provider implementation for jackrabbit UserManager resources. */ @Component(service = ResourceProvider.class, property={ "service.description=Resource provider implementation for UserManager resources", "service.vendor=The Apache Software Foundation", ResourceProvider.PROPERTY_ROOT + "=" + AuthorizableResourceProvider.SYSTEM_USER_MANAGER_PATH }) public class AuthorizableResourceProvider extends ResourceProvider<Object> { /** * default log */ private final Logger log = LoggerFactory.getLogger(getClass()); public static final String SYSTEM_USER_MANAGER_PATH = "/system/userManager"; public static final String SYSTEM_USER_MANAGER_USER_PATH = SYSTEM_USER_MANAGER_PATH + "/user"; public static final String SYSTEM_USER_MANAGER_GROUP_PATH = SYSTEM_USER_MANAGER_PATH + "/group"; public static final String SYSTEM_USER_MANAGER_USER_PREFIX = SYSTEM_USER_MANAGER_USER_PATH + "/"; public static final String SYSTEM_USER_MANAGER_GROUP_PREFIX = SYSTEM_USER_MANAGER_GROUP_PATH + "/"; @Override public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext resourceContext, Resource parent) { // handle resources for the virtual container resources if (path.equals(SYSTEM_USER_MANAGER_PATH)) { return new SyntheticResource(ctx.getResourceResolver(), path, "sling/userManager"); } else if (path.equals(SYSTEM_USER_MANAGER_USER_PATH)) { return new SyntheticResource(ctx.getResourceResolver(), path, "sling/users"); } else if (path.equals(SYSTEM_USER_MANAGER_GROUP_PATH)) { return new SyntheticResource(ctx.getResourceResolver(), path, "sling/groups"); } // the principalId should be the first segment after the prefix String pid = null; if (path.startsWith(SYSTEM_USER_MANAGER_USER_PREFIX)) { pid = path.substring(SYSTEM_USER_MANAGER_USER_PREFIX.length()); } else if (path.startsWith(SYSTEM_USER_MANAGER_GROUP_PREFIX)) { pid = path.substring(SYSTEM_USER_MANAGER_GROUP_PREFIX.length()); } if (pid != null) { if (pid.indexOf('/') != -1) { return null; // something bogus on the end of the path so bail // out now. } try { Session session = ctx.getResourceResolver().adaptTo(Session.class); if (session != null) { UserManager userManager = AccessControlUtil.getUserManager(session); if (userManager != null) { Authorizable authorizable = userManager.getAuthorizable(pid); if (authorizable != null) { // found the Authorizable, so return the resource // that wraps it. return new AuthorizableResource(authorizable, ctx.getResourceResolver(), path); } } } } catch (RepositoryException re) { throw new SlingException( "Error looking up Authorizable for principal: " + pid, re); } } return null; } @Override public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) { try { String path = parent.getPath(); ResourceResolver resourceResolver = parent.getResourceResolver(); // handle children of /system/userManager if (SYSTEM_USER_MANAGER_PATH.equals(path)) { List<Resource> resources = new ArrayList<Resource>(); if (resourceResolver != null) { resources.add(getResource(ctx, SYSTEM_USER_MANAGER_USER_PATH, null, null)); resources.add(getResource(ctx, SYSTEM_USER_MANAGER_GROUP_PATH, null, null)); } return resources.iterator(); } int searchType = -1; if (SYSTEM_USER_MANAGER_USER_PATH.equals(path)) { searchType = PrincipalManager.SEARCH_TYPE_NOT_GROUP; } else if (SYSTEM_USER_MANAGER_GROUP_PATH.equals(path)) { searchType = PrincipalManager.SEARCH_TYPE_GROUP; } if (searchType != -1) { PrincipalIterator principals = null; Session session = resourceResolver.adaptTo(Session.class); if (session != null) { PrincipalManager principalManager = AccessControlUtil.getPrincipalManager(session); principals = principalManager.getPrincipals(searchType); } if (principals != null) { return new ChildrenIterator(parent, principals); } } } catch (RepositoryException re) { throw new SlingException("Error listing children of resource: " + parent.getPath(), re); } return null; } private final class ChildrenIterator implements Iterator<Resource> { private PrincipalIterator principals; private Resource parent; public ChildrenIterator(Resource parent, PrincipalIterator principals) { this.parent = parent; this.principals = principals; } public boolean hasNext() { return principals.hasNext(); } public Resource next() { Principal nextPrincipal = principals.nextPrincipal(); try { ResourceResolver resourceResolver = parent.getResourceResolver(); if (resourceResolver != null) { Session session = resourceResolver.adaptTo(Session.class); if (session != null) { UserManager userManager = AccessControlUtil.getUserManager(session); if (userManager != null) { Authorizable authorizable = userManager.getAuthorizable(nextPrincipal.getName()); if (authorizable != null) { String path; if (authorizable.isGroup()) { path = SYSTEM_USER_MANAGER_GROUP_PREFIX + nextPrincipal.getName(); } else { path = SYSTEM_USER_MANAGER_USER_PREFIX + nextPrincipal.getName(); } return new AuthorizableResource(authorizable, resourceResolver, path); } } } } } catch (RepositoryException re) { log.error("Exception while looking up authorizable resource.", re); } return null; } public void remove() { throw new UnsupportedOperationException(); } } }