/* See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Esri Inc. licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.esri.geoportal.lib.elastic.util;
import com.esri.geoportal.context.AppUser;
import com.esri.geoportal.context.GeoportalContext;
import com.esri.geoportal.lib.elastic.ElasticContext;

import java.util.Map;

import org.elasticsearch.action.get.GetRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.springframework.security.access.AccessDeniedException;

/**
 * Access utilities.
 */
public class AccessUtil {
  
  /** Instance variables. */
  protected String accessDeniedMessage = "Access denied.";
  protected String notOwnerMessage = "Access denied - not owner.";
  
  /** Constructor */
  public AccessUtil() {}
    
  /**
   * Determines an item id
   * @param id the id
   * @return the item id
   */
  public String determineId(String id) {
    // TODO determineId
    return id;
  }
  
  /**
   * Ensure that a user has an Admin role.
   * @param user the user
   * @throws AccessDeniedException if not
   */
  public void ensureAdmin(AppUser user) {
    if (user == null || user.getUsername() == null || user.getUsername().length() == 0) {
      throw new AccessDeniedException(accessDeniedMessage);
    }
    if (!user.isAdmin()) throw new AccessDeniedException(accessDeniedMessage);
  }
  
  /**
   * Ensures that a user owns an item.
   * @param user the user
   * @param ownerField the owner field name (username)
   * @param source the Elasticsearch item source
   * @throws AccessDeniedException if not
   */
  public void ensureOwner(AppUser user, String ownerField, Map<String,Object> source) {
    if (!user.isAdmin()) {
      String owner = (String)source.get(ownerField);
      boolean ok = (owner != null) && (owner.equalsIgnoreCase(user.getUsername()));
      if (!ok) throw new AccessDeniedException(notOwnerMessage);
    }
  }
  
  /**
   * Ensure that a user has a Publisher role.
   * @param user the user
   * @throws AccessDeniedException if not
   */
  public void ensurePublisher(AppUser user) {
    if (user == null || user.getUsername() == null || user.getUsername().length() == 0) {
      throw new AccessDeniedException(accessDeniedMessage);
    }
    if (!user.isAdmin() && !user.isPublisher()) {
      throw new AccessDeniedException(accessDeniedMessage);
    }
  }
  
  /**
   * Ensure that a user has read access to an item.
   * @param user the user
   * @param id the item id
   * @throws AccessDeniedException if not
   */
  public void ensureReadAccess(AppUser user, String id) {
    // TODO ensure read access
  }

  /**
   * Ensure that a user has write access to an item.
   * @param user the user
   * @param id the item id
   * @throws AccessDeniedException if not
   */
  public void ensureWriteAccess(AppUser user, String id) {
    ElasticContext ec = GeoportalContext.getInstance().getElasticContext();
    String ownerField = FieldNames.FIELD_SYS_OWNER;
    if (user == null || user.getUsername() == null || user.getUsername().length() == 0) {
      throw new AccessDeniedException(accessDeniedMessage);
    }
    if (user.isAdmin()) return;
    if (!user.isPublisher()) throw new AccessDeniedException(accessDeniedMessage);
    
    GetRequestBuilder request = ec.getTransportClient().prepareGet(
        ec.getItemIndexName(),ec.getItemIndexType(),id);
    //request.setFetchSource(false);
    /* ES 2to5 */
    //request.setFields(ownerField);
    //request.setStoredFields(ownerField);
    GetResponse response = request.get();
    String owner = (String)response.getSource().get(ownerField);
    boolean ok = (owner != null) && (owner.equalsIgnoreCase(user.getUsername()));
    if (!ok) throw new AccessDeniedException(notOwnerMessage);
  }
  
}

@@ -1013,16 +1013,232 @@
 sponse;%0A
+import org.elasticsearch.action.search.SearchRequestBuilder;%0Aimport org.elasticsearch.client.transport.TransportClient;%0Aimport org.elasticsearch.index.query.QueryBuilders;%0Aimport org.elasticsearch.search.SearchHits;%0A
 import o
@@ -1295,16 +1295,16 @@
 eption;%0A
-
 %0A/**%0A * 
@@ -1698,27 +1698,1001 @@
     
-// TODO determineId
+try %7B%0A      ElasticContext ec = GeoportalContext.getInstance().getElasticContext();%0A      TransportClient client = ec.getTransportClient();%0A      GetResponse result = client.prepareGet(%0A          ec.getItemIndexName(),ec.getItemIndexType(),id).get();%0A      if (result.isExists()) %7B%0A        //System.err.println(%22result.isExists: %22+id+%22 - resultId = %22+result.getId());%0A        return id;%0A      %7D else %7B%0A        SearchRequestBuilder builder = client.prepareSearch(ec.getItemIndexName());%0A        builder.setTypes(ec.getItemIndexType());%0A        builder.setSize(1);%0A        builder.setQuery(QueryBuilders.matchQuery(FieldNames.FIELD_FILEID,id));%0A        SearchHits hits = builder.get().getHits();%0A        // TODO what if there is more than one hit%0A        if (hits.getTotalHits() == 1) %7B%0A          //System.err.println(%22fileid exists: %22+id+%22 - hitId = %22+hits.getAt(0).getId());%0A          return hits.getAt(0).getId();%0A        %7D%0A      %7D%0A    %7D catch (Exception e) %7B%0A      e.printStackTrace();%0A    %7D
 %0A   

Allow file identifier for rest requests: rest/metadata/item/{id}/xml rest/metadata/item/{id}/html