001/* 002 * (C) Copyright 2014 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 * Michal Obrebski - Nuxeo 016 */ 017 018package org.nuxeo.easyshare; 019 020import java.io.IOException; 021import java.io.Serializable; 022import java.util.Calendar; 023import java.util.HashMap; 024import java.util.Hashtable; 025import java.util.List; 026import java.util.Map; 027 028import javax.mail.MessagingException; 029import javax.ws.rs.GET; 030import javax.ws.rs.Path; 031import javax.ws.rs.PathParam; 032import javax.ws.rs.Produces; 033import javax.ws.rs.core.Response; 034 035import org.apache.commons.lang.StringUtils; 036import org.apache.commons.logging.Log; 037import org.apache.commons.logging.LogFactory; 038import org.nuxeo.ecm.automation.AutomationService; 039import org.nuxeo.ecm.automation.OperationContext; 040import org.nuxeo.ecm.automation.OperationException; 041import org.nuxeo.ecm.core.api.Blob; 042import org.nuxeo.ecm.core.api.CoreSession; 043import org.nuxeo.ecm.core.api.DocumentModel; 044import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 045import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 046import org.nuxeo.ecm.platform.ec.notification.email.EmailHelper; 047import org.nuxeo.ecm.platform.query.api.PageProvider; 048import org.nuxeo.ecm.platform.query.api.PageProviderService; 049import org.nuxeo.ecm.platform.query.nxql.CoreQueryDocumentPageProvider; 050import org.nuxeo.ecm.webengine.model.WebObject; 051import org.nuxeo.ecm.webengine.model.impl.ModuleRoot; 052import org.nuxeo.runtime.api.Framework; 053import org.nuxeo.ecm.core.api.IdRef; 054 055/** 056 * The root entry for the WebEngine module. 057 * 058 * @author mikeobrebski 059 */ 060@Path("/easyshare") 061@Produces("text/html;charset=UTF-8") 062@WebObject(type = "EasyShare") 063public class EasyShare extends ModuleRoot { 064 065 private static final Log log = LogFactory.getLog(EasyShare.class); 066 067 @GET 068 public Object doGet() { 069 return getView("index"); 070 } 071 072 @Path("{folderId}") 073 @GET 074 public Object getFolderListing(@PathParam("folderId") String folderId) { 075 return new EasyShareUnrestrictedRunner() { 076 @Override 077 public Object run(CoreSession session, IdRef docRef) { 078 if (session.exists(docRef)) { 079 DocumentModel docFolder = session.getDocument(docRef); 080 081 Calendar today = Calendar.getInstance(); 082 if (today.after(docFolder.getPropertyValue("dc:expired"))) { 083 return getView("denied"); 084 } 085 086 if (!docFolder.getType().equals("EasyShareFolder")) { 087 return Response.serverError().status(Response.Status.NOT_FOUND).build(); 088 } 089 090 final PageProviderService ppService = Framework.getService(PageProviderService.class); 091 final Map<String, Serializable> props = new HashMap<String, Serializable>(); 092 props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) session); 093 @SuppressWarnings("unchecked") 094 final PageProvider<DocumentModel> pp = (PageProvider<DocumentModel>) ppService.getPageProvider( 095 "EASYSHARE_FOLDER_CONTENT_PP", null, null, null, props, new Object[] { docRef.value }); 096 097 // Note: for now we do not use pagination: 098 final List<DocumentModel> docList = pp.getCurrentPage(); 099 100 // Audit Log 101 OperationContext ctx = new OperationContext(session); 102 ctx.setInput(docFolder); 103 104 // Audit.Log operation parameter setting 105 try { 106 Map<String, Object> params = new HashMap<String, Object>(); 107 params.put("event", "Access"); 108 params.put("category", "Document"); 109 params.put("comment", "IP: " + request.getRemoteAddr()); 110 AutomationService service = Framework.getService(AutomationService.class); 111 service.run(ctx, "Audit.Log", params); 112 } catch (OperationException ex) { 113 log.error(ex.getMessage()); 114 return getView("denied"); 115 } 116 117 return getView("folderList").arg("docFolder", docFolder).arg("docList", docList); 118 } else { 119 120 return getView("denied"); 121 } 122 } 123 }.runUnrestricted(folderId); 124 125 } 126 127 public String getFileName(DocumentModel doc) { 128 Blob blob = doc.getAdapter(BlobHolder.class).getBlob(); 129 return blob.getFilename(); 130 } 131 132 @GET 133 @Path("{folderId}/{fileId}/{fileName}") 134 public Response getFileStream(@PathParam("fileId") String fileId) { 135 136 return (Response) new EasyShareUnrestrictedRunner() { 137 @Override 138 public Object run(CoreSession session, IdRef docRef) { 139 if (session.exists(docRef)) { 140 try { 141 DocumentModel doc = session.getDocument(docRef); 142 143 Blob blob = doc.getAdapter(BlobHolder.class).getBlob(); 144 DocumentModel docFolder = session.getDocument(doc.getParentRef()); 145 146 // Audit Log 147 OperationContext ctx = new OperationContext(session); 148 ctx.setInput(doc); 149 150 Calendar today = Calendar.getInstance(); 151 if (today.after(docFolder.getPropertyValue("dc:expired"))) { 152 return Response.serverError().status(Response.Status.NOT_FOUND).build(); 153 } 154 155 // Audit.Log operation parameter setting 156 Map<String, Object> params = new HashMap<String, Object>(); 157 params.put("event", "Download"); 158 params.put("category", "Document"); 159 params.put("comment", "IP: " + request.getRemoteAddr()); 160 AutomationService service = Framework.getLocalService(AutomationService.class); 161 service.run(ctx, "Audit.Log", params); 162 163 if (doc.isProxy()) { 164 DocumentModel liveDoc = session.getSourceDocument(docRef); 165 ctx.setInput(liveDoc); 166 service.run(ctx, "Audit.Log", params); 167 } 168 169 // Email notification 170 String email = (String) docFolder.getPropertyValue("eshare:contactEmail"); 171 if (!StringUtils.isBlank(email)) { 172 String fileName = blob.getFilename(); 173 String shareName = docFolder.getName(); 174 try { 175 log.debug("Easyshare: starting email"); 176 EmailHelper emailer = new EmailHelper(); 177 Map<String, Object> mailProps = new Hashtable<String, Object>(); 178 mailProps.put("mail.from", "system@nuxeo.com"); 179 mailProps.put("mail.to", email); 180 mailProps.put("subject", "EasyShare Download Notification"); 181 mailProps.put("body", "File " + fileName + " from " + shareName + " downloaded by " 182 + request.getRemoteAddr()); 183 mailProps.put("template", "easyShareEmail"); 184 emailer.sendmail(mailProps); 185 log.debug("Easyshare: completed email"); 186 } catch (MessagingException ex) { 187 log.error("Cannot send easyShare notification email", ex); 188 } 189 } 190 191 return Response.ok(blob.getStream(), blob.getMimeType()).build(); 192 193 } catch (OperationException | PropertyNotFoundException | IOException ex) { 194 log.error("error ", ex); 195 return Response.serverError().status(Response.Status.NOT_FOUND).build(); 196 } 197 198 } else { 199 return Response.serverError().status(Response.Status.NOT_FOUND).build(); 200 } 201 } 202 }.runUnrestricted(fileId); 203 204 } 205 206}