001package org.nuxeo.elasticsearch.http.readonly.filter;/*
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 *     Benoit Delbosc
016 */
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.HashSet;
021import java.util.List;
022import java.util.Map;
023import java.util.Set;
024
025import javax.validation.constraints.NotNull;
026
027import org.apache.commons.lang.StringUtils;
028import org.json.JSONArray;
029import org.json.JSONException;
030import org.json.JSONObject;
031import org.nuxeo.ecm.core.api.NuxeoPrincipal;
032import org.nuxeo.ecm.core.security.SecurityService;
033import org.nuxeo.elasticsearch.ElasticSearchConstants;
034import org.nuxeo.elasticsearch.api.ElasticSearchAdmin;
035import org.nuxeo.runtime.api.Framework;
036
037/**
038 * Validate request inputs.
039 *
040 * @since 7.3
041 */
042public class RequestValidator {
043    final private Map<String, List<String>> indexTypes;
044
045    public RequestValidator() {
046        ElasticSearchAdmin esa = Framework.getLocalService(ElasticSearchAdmin.class);
047        indexTypes = new HashMap<>();
048        for (String name : esa.getRepositoryNames()) {
049            List<String> types = new ArrayList<>();
050            types.add(ElasticSearchConstants.DOC_TYPE);
051            indexTypes.put(esa.getIndexNameForRepository(name), types);
052        }
053    }
054
055    public void checkValidDocumentId(String documentId) {
056        if (documentId == null) {
057            throw new IllegalArgumentException("Invalid document id");
058        }
059    }
060
061    public @NotNull String getTypes(String indices, String types) {
062        Set<String> validTypes = new HashSet<>();
063        for (String index : indices.split(",")) {
064            validTypes.addAll(indexTypes.get(index));
065        }
066        if (types == null || "*".equals(types) || "_all".equals(types)) {
067            return StringUtils.join(validTypes, ',');
068        }
069        for (String type : types.split(",")) {
070            if (!validTypes.contains(type)) {
071                throw new IllegalArgumentException("Invalid index type: " + type);
072            }
073        }
074        return types;
075    }
076
077    public @NotNull String getIndices(String indices) {
078        if (indices == null || "*".equals(indices) || "_all".equals(indices)) {
079            return StringUtils.join(indexTypes.keySet(), ',');
080        }
081
082        for (String index : indices.split(",")) {
083            if (!indexTypes.containsKey(index)) {
084                throw new IllegalArgumentException("Invalid index submitted: " + index);
085            }
086        }
087        return indices;
088    }
089
090    public void checkAccess(NuxeoPrincipal principal, String docAcl) {
091        try {
092            JSONObject docAclJson = new JSONObject(docAcl);
093            JSONArray acl = docAclJson.getJSONObject("fields").getJSONArray("ecm:acl");
094            String[] principals = SecurityService.getPrincipalsToCheck(principal);
095            for (int i = 0; i < acl.length(); i++)
096                for (String name : principals) {
097                    if (name.equals(acl.getString(i))) {
098                        return;
099                    }
100                }
101        } catch (JSONException e) {
102            // throw a securityException
103        }
104        throw new SecurityException("Unauthorized access");
105    }
106}