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.permissions.Constants.ACE_GRANTED_TEMPLATE; 021import static org.nuxeo.ecm.permissions.Constants.ACE_INFO_COMMENT; 022import static org.nuxeo.ecm.permissions.Constants.ACE_INFO_DIRECTORY; 023import static org.nuxeo.ecm.permissions.Constants.ACE_KEY; 024import static org.nuxeo.ecm.permissions.Constants.ACL_NAME_KEY; 025import static org.nuxeo.ecm.permissions.Constants.PERMISSION_NOTIFICATION_EVENT; 026 027import java.util.Collections; 028 029import org.apache.commons.lang.StringEscapeUtils; 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.ecm.automation.AutomationService; 033import org.nuxeo.ecm.automation.OperationChain; 034import org.nuxeo.ecm.automation.OperationContext; 035import org.nuxeo.ecm.automation.OperationException; 036import org.nuxeo.ecm.automation.core.operations.notification.SendMail; 037import org.nuxeo.ecm.automation.core.scripting.Expression; 038import org.nuxeo.ecm.automation.core.scripting.Scripting; 039import org.nuxeo.ecm.automation.core.util.StringList; 040import org.nuxeo.ecm.automation.features.PlatformFunctions; 041import org.nuxeo.ecm.core.api.CoreSession; 042import org.nuxeo.ecm.core.api.DocumentModel; 043import org.nuxeo.ecm.core.api.NuxeoGroup; 044import org.nuxeo.ecm.core.api.NuxeoPrincipal; 045import org.nuxeo.ecm.core.api.security.ACE; 046import org.nuxeo.ecm.core.event.Event; 047import org.nuxeo.ecm.core.event.EventBundle; 048import org.nuxeo.ecm.core.event.EventContext; 049import org.nuxeo.ecm.core.event.PostCommitFilteringEventListener; 050import org.nuxeo.ecm.core.event.impl.DocumentEventContext; 051import org.nuxeo.ecm.directory.Session; 052import org.nuxeo.ecm.directory.api.DirectoryService; 053import org.nuxeo.ecm.platform.ec.notification.service.NotificationService; 054import org.nuxeo.ecm.platform.ec.notification.service.NotificationServiceHelper; 055import org.nuxeo.ecm.platform.ui.web.tag.fn.Functions; 056import org.nuxeo.ecm.platform.usermanager.UserManager; 057import org.nuxeo.runtime.api.Framework; 058 059/** 060 * Listener sending an email notification for a granted ACE. 061 * <p> 062 * This listener checks only if the ACE is granted. It assumes that other checks (such as the ACE becomes effective) 063 * have been done before. 064 * 065 * @since 7.4 066 */ 067public class PermissionGrantedNotificationListener implements PostCommitFilteringEventListener { 068 069 private static final Log log = LogFactory.getLog(PermissionGrantedNotificationListener.class); 070 071 public static final String SUBJECT_FORMAT = "%s %s %s"; 072 073 @Override 074 public void handleEvent(EventBundle events) { 075 for (Event event : events) { 076 handleEvent(event); 077 } 078 } 079 080 protected void handleEvent(Event event) { 081 EventContext eventCtx = event.getContext(); 082 if (!(eventCtx instanceof DocumentEventContext)) { 083 return; 084 } 085 086 DocumentEventContext docCtx = (DocumentEventContext) eventCtx; 087 CoreSession coreSession = docCtx.getCoreSession(); 088 DocumentModel doc = docCtx.getSourceDocument(); 089 if (doc == null || !coreSession.exists(doc.getRef())) { 090 return; 091 } 092 093 ACE ace = (ACE) docCtx.getProperty(ACE_KEY); 094 String aclName = (String) docCtx.getProperty(ACL_NAME_KEY); 095 if (ace == null || ace.isDenied() || aclName == null) { 096 return; 097 } 098 099 StringList to = getRecipients(ace.getUsername()); 100 if (to == null) { 101 // no recipient 102 return; 103 } 104 105 Expression from = Scripting.newExpression("Env[\"mail.from\"]"); 106 NotificationService notificationService = NotificationServiceHelper.getNotificationService(); 107 String subject = String.format(SUBJECT_FORMAT, notificationService.getEMailSubjectPrefix(), 108 "New permission on", doc.getTitle()); 109 110 DirectoryService directoryService = Framework.getService(DirectoryService.class); 111 try (Session session = directoryService.open(ACE_INFO_DIRECTORY)) { 112 String id = PermissionHelper.computeDirectoryId(doc, aclName, ace.getId()); 113 DocumentModel entry = session.getEntry(id); 114 115 OperationContext ctx = new OperationContext(coreSession); 116 ctx.setInput(doc); 117 ctx.put("ace", ace); 118 if (entry != null) { 119 String comment = (String) entry.getPropertyValue(ACE_INFO_COMMENT); 120 if (comment != null) { 121 comment = StringEscapeUtils.escapeHtml(comment); 122 comment = comment.replaceAll("\n", "<br/>"); 123 ctx.put("comment", comment); 124 } 125 } 126 String aceCreator = ace.getCreator(); 127 if (aceCreator != null) { 128 UserManager userManager = Framework.getService(UserManager.class); 129 NuxeoPrincipal creator = userManager.getPrincipal(aceCreator); 130 if (creator != null) { 131 ctx.put("aceCreator", 132 String.format("%s (%s)", Functions.principalFullName(creator), creator.getName())); 133 } 134 } 135 136 OperationChain chain = new OperationChain("SendMail"); 137 chain.add(SendMail.ID) 138 .set("from", from) 139 .set("to", to) 140 .set("HTML", true) 141 .set("subject", subject) 142 .set("message", ACE_GRANTED_TEMPLATE); 143 Framework.getService(AutomationService.class).run(ctx, chain); 144 } catch (OperationException e) { 145 log.warn("Unable to notify user", e); 146 log.debug(e, e); 147 } 148 } 149 150 protected StringList getRecipients(String username) { 151 UserManager userManager = Framework.getService(UserManager.class); 152 NuxeoPrincipal principal = userManager.getPrincipal(username); 153 StringList to = null; 154 if (principal != null) { 155 to = new StringList(Collections.singletonList(principal.getEmail())); 156 } else { 157 NuxeoGroup group = userManager.getGroup(username); 158 if (group != null) { 159 PlatformFunctions platformFunctions = new PlatformFunctions(); 160 to = platformFunctions.getEmailsFromGroup(group.getName()); 161 } 162 } 163 return to; 164 } 165 166 @Override 167 public boolean acceptEvent(Event event) { 168 String eventName = event.getName(); 169 return PERMISSION_NOTIFICATION_EVENT.equals(eventName); 170 } 171}