package org.elasticsearch.plugin.readonlyrest;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.support.ActionFilter;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugin.readonlyrest.acl.ACL;
import org.elasticsearch.plugin.readonlyrest.acl.RequestContext;
import org.elasticsearch.plugin.readonlyrest.acl.RuleConfigurationError;
import org.elasticsearch.plugin.readonlyrest.acl.blocks.Block;
import org.elasticsearch.plugin.readonlyrest.acl.blocks.BlockExitResult;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus;

/**
 * Created by sscarduzio on 19/12/2015.
 */
public class IndexLevelActionFilter extends ActionFilter.Simple {
  private ACL acl;
  private ConfigurationHelper conf;

  @Inject
  public IndexLevelActionFilter(Settings settings) {
    super(settings);
    logger.info("Readonly REST plugin was loaded...");
    this.conf = new ConfigurationHelper(settings, logger);

    if (!conf.enabled) {
      logger.info("Readonly REST plugin is disabled!");
      return;
    }

    logger.info("Readonly REST plugin is enabled. Yay, ponies!");

    try {
      acl = new ACL(settings);
      logger.info("ACL configuration: OK");
    } catch (RuleConfigurationError e) {
      logger.error("impossible to initialize ACL configuration", e);
      throw e;
    }
  }

  @Override
  public int order() {
    return 0;
  }

  @Override
  public boolean apply(String action, ActionRequest actionRequest, final ActionListener listener) {

    // Skip if disabled
    if (!conf.enabled) {
      return true;
    }

    RestRequest req = actionRequest.getFromContext("request");
    RestChannel channel = actionRequest.getFromContext("channel");

    boolean reqNull = req == null;
    boolean chanNull = channel == null;

    // This was not a REST message
    if (reqNull && chanNull) {
      return true;
    }

    // Bailing out in case of catastrophical misconfiguration that would lead to insecurity
    if (reqNull != chanNull) {
      if (chanNull)
        throw new RuntimeException("Problems analyzing the channel object. Have you checked the security permissions?");
      if (reqNull)
        throw new RuntimeException("Problems analyzing the request object. Have you checked the security permissions?");
    }

    RequestContext rc = new RequestContext(channel, req, action);
    BlockExitResult exitResult = acl.check(rc);

    // The request is allowed to go through
    if (exitResult.isMatch() && exitResult.getBlock().getPolicy() == Block.Policy.ALLOW) {
      return true;
    }

    // Barring
    logger.trace("forbidden request: " + req + " Reason: " + exitResult.getBlock() + " (" + exitResult.getBlock() + ")");
    String reason = "Forbidden";
    if (conf.forbiddenResponse != null) {
      reason = conf.forbiddenResponse;
    }

    BytesRestResponse resp;

    if (acl.isBasicAuthConfigured()) {
      resp = new BytesRestResponse(RestStatus.UNAUTHORIZED, reason);
      logger.debug("Sending login prompt header...");
      resp.addHeader("WWW-Authenticate", "Basic");
    }
    else {
      resp = new BytesRestResponse(RestStatus.FORBIDDEN, reason);
    }

    channel.sendResponse(resp);

    return false;
  }

  @Override
  public boolean apply(String s, ActionResponse actionResponse, ActionListener actionListener) {
    System.out.println(s);
    return true;
  }
}

@@ -966,16 +966,23 @@
 private 
+static 
 ACL acl;
@@ -992,16 +992,23 @@
 private 
+static 
 Configur
@@ -1106,24 +1106,50 @@
 (settings);%0A
+    if (conf == null) %7B%0A  
     logger.i
@@ -1187,24 +1187,26 @@
 oaded...%22);%0A
+  
     this.con
@@ -1249,24 +1249,26 @@
 , logger);%0A%0A
+  
     if (!con
@@ -1278,32 +1278,34 @@
 nabled) %7B%0A      
+  
 logger.info(%22Rea
@@ -1348,16 +1348,18 @@
     
+  
 return;%0A
     
@@ -1354,16 +1354,18 @@
 return;%0A
+  
     %7D%0A%0A 
@@ -1363,24 +1363,26 @@
      %7D%0A%0A    
+  
 logger.info(
@@ -1440,14 +1440,18 @@
     
+  
 try %7B%0A
+  
     
@@ -1483,50 +1483,8 @@
 ;%0A  
-    logger.info(%22ACL configuration: OK%22);%0A
     
@@ -1516,24 +1516,26 @@
 nError e) %7B%0A
+  
       logger
@@ -1593,24 +1593,26 @@
 , e);%0A      
+  
 throw e;%0A   
@@ -1608,16 +1608,24 @@
 hrow e;%0A
+      %7D%0A
     %7D%0A  
@@ -2642,16 +2642,31 @@
 , action
+, actionRequest
 );%0A    B
@@ -3375,20 +3375,16 @@
 );%0A    %7D
-%0A   
  else %7B%0A

make configuration, acl and logger static