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}