001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and contributors.
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 *     <a href="mailto:grenard@nuxeo.com">Guillaume Renard</a>
016 *
017 */
018
019package org.nuxeo.ecm.platform.routing.core.audit.es;
020
021import java.util.ArrayList;
022import java.util.List;
023
024import org.json.JSONArray;
025import org.json.JSONException;
026import org.json.JSONObject;
027import org.nuxeo.ecm.core.api.CoreSession;
028import org.nuxeo.ecm.core.api.NuxeoPrincipal;
029import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
030import org.nuxeo.ecm.platform.routing.api.DocumentRoute;
031import org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants;
032import org.nuxeo.ecm.platform.routing.api.DocumentRoutingService;
033import org.nuxeo.elasticsearch.audit.ESAuditBackend;
034import org.nuxeo.elasticsearch.http.readonly.filter.AuditRequestFilter;
035import org.nuxeo.runtime.api.Framework;
036
037/**
038 * Define a elasticsearch passthrough filter for audit_wf index view. Restrict to 'Routing' event category and, if the
039 * user is not an administrator, to the list of workflow model on which the user has the 'Data Visualization'
040 * permission.
041 *
042 * @since 7.4
043 */
044public class RoutingAuditRequestFilter extends AuditRequestFilter {
045
046    private CoreSession session;
047
048    public void init(CoreSession session, String indices, String types, String rawQuery, String payload) {
049        this.session = session;
050        this.principal = (NuxeoPrincipal) session.getPrincipal();
051        this.indices = ESAuditBackend.IDX_NAME;
052        this.types = ESAuditBackend.IDX_TYPE;
053        this.rawQuery = rawQuery;
054        this.payload = payload;
055        if (payload == null && !principal.isAdministrator()) {
056            // here we turn the UriSearch query_string into a body search
057            extractPayloadFromQuery();
058        }
059    }
060
061    @Override
062    public String getPayload() throws JSONException {
063        if (filteredPayload == null) {
064            if (payload.contains("\\")) {
065                // JSONObject removes backslash so we need to hide them
066                payload = payload.replaceAll("\\\\", BACKSLASH_MARKER);
067            }
068            JSONObject payloadJson = new JSONObject(payload);
069            JSONObject query;
070            if (payloadJson.has("query")) {
071                query = payloadJson.getJSONObject("query");
072
073                payloadJson.remove("query");
074            } else {
075                query = new JSONObject("{\"match_all\":{}}");
076            }
077            JSONObject categoryFilter = new JSONObject().put("term", new JSONObject().put(
078                    DocumentEventContext.CATEGORY_PROPERTY_KEY, DocumentRoutingConstants.ROUTING_CATEGORY));
079
080            JSONArray fs = new JSONArray().put(categoryFilter);
081
082            if (!principal.isAdministrator()) {
083                DocumentRoutingService documentRoutingService = Framework.getService(DocumentRoutingService.class);
084                List<DocumentRoute> wfModels = documentRoutingService.getAvailableDocumentRouteModel(session);
085                List<String> modelNames = new ArrayList<String>();
086                for (DocumentRoute model : wfModels) {
087                    if (session.hasPermission(model.getDocument().getRef(), DocumentRoutingConstants.CAN_DATA_VISU)) {
088                        modelNames.add(model.getModelName());
089                    }
090                }
091
092                JSONObject wfModelFilter = new JSONObject().put("terms",
093                        new JSONObject().put("extended.modelName", modelNames.toArray(new String[modelNames.size()])));
094
095                fs.put(wfModelFilter);
096            }
097
098            JSONObject filter = new JSONObject().put("bool", new JSONObject().put("must", fs));
099
100            JSONObject newQuery = new JSONObject().put("filtered",
101                    new JSONObject().put("query", query).put("filter", filter));
102            payloadJson.put("query", newQuery);
103            filteredPayload = payloadJson.toString();
104            if (filteredPayload.contains(BACKSLASH_MARKER)) {
105                filteredPayload = filteredPayload.replaceAll(BACKSLASH_MARKER, "\\\\");
106            }
107
108        }
109        return filteredPayload;
110    }
111
112}