001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Thomas Roger 016 */ 017 018package org.nuxeo.ecm.permissions; 019 020import static org.nuxeo.ecm.core.api.event.CoreEventConstants.DOCUMENT_REFS; 021import static org.nuxeo.ecm.core.api.event.CoreEventConstants.REPOSITORY_NAME; 022import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.ACE_STATUS_UPDATED; 023import static org.nuxeo.ecm.core.api.security.ACL.INHERITED_ACL; 024import static org.nuxeo.ecm.permissions.Constants.ACE_INFO_COMMENT; 025import static org.nuxeo.ecm.permissions.Constants.ACE_INFO_DIRECTORY; 026import static org.nuxeo.ecm.permissions.Constants.ACE_INFO_NOTIFIED; 027import static org.nuxeo.ecm.permissions.Constants.ACE_INFO_NOTIFY; 028import static org.nuxeo.ecm.permissions.Constants.ACE_KEY; 029import static org.nuxeo.ecm.permissions.Constants.ACL_NAME_KEY; 030import static org.nuxeo.ecm.permissions.Constants.COMMENT_KEY; 031import static org.nuxeo.ecm.permissions.Constants.PERMISSION_NOTIFICATION_EVENT; 032import static org.nuxeo.ecm.permissions.PermissionHelper.computeDirectoryId; 033 034import java.util.List; 035 036import org.nuxeo.ecm.core.api.CoreInstance; 037import org.nuxeo.ecm.core.api.CoreSession; 038import org.nuxeo.ecm.core.api.DocumentModel; 039import org.nuxeo.ecm.core.api.DocumentRef; 040import org.nuxeo.ecm.core.api.security.ACE; 041import org.nuxeo.ecm.core.api.security.ACL; 042import org.nuxeo.ecm.core.api.security.ACP; 043import org.nuxeo.ecm.core.event.Event; 044import org.nuxeo.ecm.core.event.EventBundle; 045import org.nuxeo.ecm.core.event.EventContext; 046import org.nuxeo.ecm.core.event.EventService; 047import org.nuxeo.ecm.core.event.PostCommitFilteringEventListener; 048import org.nuxeo.ecm.core.event.impl.DocumentEventContext; 049import org.nuxeo.ecm.directory.Session; 050import org.nuxeo.ecm.directory.api.DirectoryService; 051import org.nuxeo.runtime.api.Framework; 052 053/** 054 * Listener listening for {@code ACEStatusUpdated} event to send a notification for ACEs becoming effective. 055 * 056 * @since 7.4 057 */ 058public class ACEStatusUpdatedListener implements PostCommitFilteringEventListener { 059 060 @Override 061 public void handleEvent(EventBundle events) { 062 for (Event event : events) { 063 handleEvent(event); 064 } 065 } 066 067 @SuppressWarnings("unchecked") 068 protected void handleEvent(Event event) { 069 EventContext ctx = event.getContext(); 070 String repositoryName = (String) ctx.getProperty(REPOSITORY_NAME); 071 List<DocumentRef> docRefs = (List<DocumentRef>) ctx.getProperty(DOCUMENT_REFS); 072 if (repositoryName == null || docRefs == null) { 073 return; 074 } 075 076 try (CoreSession session = CoreInstance.openCoreSessionSystem(repositoryName)) { 077 078 for (DocumentRef ref : docRefs) { 079 if (session.exists(ref)) { 080 DocumentModel doc = session.getDocument(ref); 081 checkForEffectiveACE(session, doc); 082 } 083 } 084 } 085 } 086 087 protected void checkForEffectiveACE(CoreSession session, DocumentModel doc) { 088 DirectoryService directoryService = Framework.getService(DirectoryService.class); 089 ACP acp = doc.getACP(); 090 for (ACL acl : acp.getACLs()) { 091 String aclName = acl.getName(); 092 if (INHERITED_ACL.equals(aclName)) { 093 // ignore inherited acl 094 continue; 095 } 096 097 for (ACE ace : acl) { 098 if (ace.isGranted() && ace.isEffective()) { 099 try (Session dirSession = directoryService.open(ACE_INFO_DIRECTORY)) { 100 String id = computeDirectoryId(doc, acl.getName(), ace.getId()); 101 DocumentModel entry = dirSession.getEntry(id); 102 if (entry != null) { 103 boolean notify = (boolean) entry.getPropertyValue(ACE_INFO_NOTIFY); 104 boolean notified = (boolean) entry.getPropertyValue(ACE_INFO_NOTIFIED); 105 String comment = (String) entry.getPropertyValue(ACE_INFO_COMMENT); 106 if (notify && !notified) { 107 // send the event for the notification 108 if (comment != null) { 109 ace.putContextData(COMMENT_KEY, comment); 110 } 111 firePermissionNotificationEvent(session, doc, aclName, ace); 112 } 113 } 114 } 115 } 116 } 117 } 118 } 119 120 protected void firePermissionNotificationEvent(CoreSession session, DocumentModel doc, String aclName, ACE ace) { 121 DocumentEventContext docCtx = new DocumentEventContext(session, session.getPrincipal(), doc); 122 docCtx.setProperty(ACE_KEY, ace); 123 docCtx.setProperty(ACL_NAME_KEY, aclName); 124 EventService eventService = Framework.getService(EventService.class); 125 eventService.fireEvent(PERMISSION_NOTIFICATION_EVENT, docCtx); 126 } 127 128 @Override 129 public boolean acceptEvent(Event event) { 130 return ACE_STATUS_UPDATED.equals(event.getName()); 131 } 132}