| /* |
| * 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.jcr.jackrabbit.accessmanager.post; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.jcr.Item; |
| import javax.jcr.RepositoryException; |
| import javax.jcr.Session; |
| import javax.jcr.security.AccessControlEntry; |
| import javax.jcr.security.AccessControlList; |
| import javax.jcr.security.AccessControlManager; |
| import javax.servlet.Servlet; |
| |
| import org.apache.sling.api.SlingHttpServletRequest; |
| import org.apache.sling.api.resource.ResourceNotFoundException; |
| import org.apache.sling.jcr.base.util.AccessControlUtil; |
| import org.apache.sling.jcr.jackrabbit.accessmanager.DeleteAces; |
| import org.apache.sling.servlets.post.Modification; |
| import org.apache.sling.servlets.post.PostResponse; |
| import org.apache.sling.servlets.post.PostResponseCreator; |
| import org.apache.sling.servlets.post.SlingPostConstants; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.Reference; |
| import org.osgi.service.component.annotations.ReferenceCardinality; |
| import org.osgi.service.component.annotations.ReferencePolicy; |
| |
| /** |
| * <p> |
| * Sling Post Servlet implementation for deleting the ACE for a set of principals on a JCR |
| * resource. |
| * </p> |
| * <h2>Rest Service Description</h2> |
| * <p> |
| * Delete a set of Ace's from a node, the node is identified as a resource by the request |
| * url >resource<.deleteAce.html |
| * </p> |
| * <h4>Methods</h4> |
| * <ul> |
| * <li>POST</li> |
| * </ul> |
| * <h4>Post Parameters</h4> |
| * <dl> |
| * <dt>:applyTo</dt> |
| * <dd>An array of ace principal names to delete. Note the principal name is the primary |
| * key of the Ace in the Acl</dd> |
| * </dl> |
| * |
| * <h4>Response</h4> |
| * <dl> |
| * <dt>200</dt> |
| * <dd>Success.</dd> |
| * <dt>404</dt> |
| * <dd>The resource was not found.</dd> |
| * <dt>500</dt> |
| * <dd>Failure. HTML explains the failure.</dd> |
| * </dl> |
| */ |
| |
| @Component(service = {Servlet.class, DeleteAces.class}, |
| property= { |
| "sling.servlet.resourceTypes=sling/servlet/default", |
| "sling.servlet.methods=POST", |
| "sling.servlet.selectors=deleteAce" |
| }) |
| public class DeleteAcesServlet extends AbstractAccessPostServlet implements DeleteAces { |
| private static final long serialVersionUID = 3784866802938282971L; |
| |
| /** |
| * Overridden since the @Reference annotation is not inherited from the super method |
| * |
| * @see org.apache.sling.jackrabbit.usermanager.impl.post.AbstractPostServlet#bindPostResponseCreator(org.apache.sling.servlets.post.PostResponseCreator, java.util.Map) |
| */ |
| @Override |
| @Reference(service = PostResponseCreator.class, |
| cardinality = ReferenceCardinality.MULTIPLE, |
| policy = ReferencePolicy.DYNAMIC) |
| protected void bindPostResponseCreator(PostResponseCreator creator, Map<String, Object> properties) { |
| super.bindPostResponseCreator(creator, properties); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.sling.jackrabbit.usermanager.impl.post.AbstractPostServlet#unbindPostResponseCreator(org.apache.sling.servlets.post.PostResponseCreator, java.util.Map) |
| */ |
| @Override |
| protected void unbindPostResponseCreator(PostResponseCreator creator, Map<String, Object> properties) { |
| super.unbindPostResponseCreator(creator, properties); |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.apache.sling.jackrabbit.accessmanager.post.AbstractAccessPostServlet#handleOperation(org.apache.sling.api.SlingHttpServletRequest, org.apache.sling.servlets.post.PostResponse, java.util.List) |
| */ |
| @Override |
| protected void handleOperation(SlingHttpServletRequest request, |
| PostResponse htmlResponse, List<Modification> changes) |
| throws RepositoryException { |
| |
| Session session = request.getResourceResolver().adaptTo(Session.class); |
| String resourcePath = request.getResource().getPath(); |
| String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO); |
| deleteAces(session, resourcePath, applyTo); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.sling.jcr.jackrabbit.accessmanager.DeleteAces#deleteAces(javax.jcr.Session, java.lang.String, java.lang.String[]) |
| */ |
| public void deleteAces(Session jcrSession, String resourcePath, |
| String[] principalNamesToDelete) throws RepositoryException { |
| |
| if (principalNamesToDelete == null) { |
| throw new RepositoryException("principalIds were not sumitted."); |
| } else { |
| if (jcrSession == null) { |
| throw new RepositoryException("JCR Session not found"); |
| } |
| |
| if (resourcePath == null) { |
| throw new ResourceNotFoundException("Resource path was not supplied."); |
| } |
| |
| Item item = jcrSession.getItem(resourcePath); |
| if (item != null) { |
| resourcePath = item.getPath(); |
| } else { |
| throw new ResourceNotFoundException("Resource is not a JCR Node"); |
| } |
| |
| //load the principalIds array into a set for quick lookup below |
| Set<String> pidSet = new HashSet<String>(); |
| pidSet.addAll(Arrays.asList(principalNamesToDelete)); |
| |
| try { |
| AccessControlManager accessControlManager = AccessControlUtil.getAccessControlManager(jcrSession); |
| AccessControlList updatedAcl = getAccessControlList(accessControlManager, resourcePath, false); |
| |
| //keep track of the existing Aces for the target principal |
| AccessControlEntry[] accessControlEntries = updatedAcl.getAccessControlEntries(); |
| List<AccessControlEntry> oldAces = new ArrayList<AccessControlEntry>(); |
| for (AccessControlEntry ace : accessControlEntries) { |
| if (pidSet.contains(ace.getPrincipal().getName())) { |
| oldAces.add(ace); |
| } |
| } |
| |
| //remove the old aces |
| if (!oldAces.isEmpty()) { |
| for (AccessControlEntry ace : oldAces) { |
| updatedAcl.removeAccessControlEntry(ace); |
| } |
| } |
| |
| //apply the changed policy |
| accessControlManager.setPolicy(resourcePath, updatedAcl); |
| } catch (RepositoryException re) { |
| throw new RepositoryException("Failed to delete access control.", re); |
| } |
| } |
| } |
| |
| } |