/* $Id$ */

/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.solr.mcf;

import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.queries.*;
import org.apache.solr.search.*;
import org.apache.solr.client.solrj.*;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.*;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.*;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.core.*;
import org.apache.solr.handler.component.*;
import org.apache.solr.request.*;
import org.apache.solr.util.*;
import org.apache.solr.util.plugin.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.slf4j.*;
import org.slf4j.Logger;

import java.io.*;
import java.util.*;
import java.net.*;

/**
* SearchComponent plugin for ManifoldCF-specific document-level access control.
* Configuration is under the SolrACLSecurity name.
*/
public class ManifoldCFSecurityFilter extends SearchComponent
{
  /** The component name */
  static final public String COMPONENT_NAME = "ManifoldCFSecurityFilter";
  /** The parameter that is supposed to contain the authenticated user name, possibly including the domain */
  static final public String AUTHENTICATED_USER_NAME = "AuthenticatedUserName";
  /** This parameter is an array of strings, which contain the tokens to use if there is no authenticated user name.  It's meant to work with mod_authz_annotate,
  * running under Apache */
  static final public String USER_TOKENS = "UserTokens";
  
  /** The queries that we will not attempt to interfere with */
  static final private String[] globalAllowed = { "solrpingquery" };
  
  /** A logger we can use */
  private static final Logger LOG = LoggerFactory.getLogger(ManifoldCFSecurityFilter.class);

  // Member variables
  private boolean security = false;
  private String authorityBaseURL = null;
  private String fieldAllowDocument = null;
  private String fieldDenyDocument = null;
  private String fieldAllowShare = null;
  private String fieldDenyShare = null;
  
  public ManifoldCFSecurityFilter()
  {
    super();
  }

  @Override
  public void init(NamedList args)
  {
    super.init(args);
    String securityString = (String)args.get("Security");
    security = ((securityString==null)?true:securityString.equals("on"));
    authorityBaseURL = (String)args.get("AuthorityServiceBaseURL");
    if (authorityBaseURL == null)
      authorityBaseURL = "http://localhost:8345/mcf-authority-service";
    String allowAttributePrefix = (String)args.get("AllowAttributePrefix");
    String denyAttributePrefix = (String)args.get("DenyAttributePrefix");
    if (allowAttributePrefix == null)
      allowAttributePrefix = "allow_token_";
    if (denyAttributePrefix == null)
      denyAttributePrefix = "deny_token_";
    fieldAllowDocument = allowAttributePrefix+"document";
    fieldDenyDocument = denyAttributePrefix+"document";
    fieldAllowShare = allowAttributePrefix+"share";
    fieldDenyShare = denyAttributePrefix+"share";
  }

  @Override
  public void prepare(ResponseBuilder rb) throws IOException
  {
    if (!security)
      return;
    
    SolrParams params = rb.req.getParams();

    // Log that we got here
    LOG.info("prepare() entry params:\n" + params + "\ncontext: " + rb.req.getContext());
		
    String qry = (String)params.get(CommonParams.Q);
    if (qry != null)
    {
      //Check global allowed searches
      for (String ga : globalAllowed)
      {
	if (qry.equalsIgnoreCase(ga.trim()))
	  // Allow this query through unchanged
	  return;
      }
    }

    List<String> userAccessTokens;
    
    // Get the authenticated user name from the parameters
    String authenticatedUserName = params.get(AUTHENTICATED_USER_NAME);
    
    // If this parameter is empty or does not exist, we have to presume this is a guest, and treat them accordingly
    if (authenticatedUserName == null || authenticatedUserName.length() == 0)
    {
      // No authenticated user name.
      // mod_authz_annotate may be in use upstream, so look for tokens from it.
      String[] passedTokens = params.getParams(USER_TOKENS);
      if (passedTokens == null)
      {
        // Only return 'public' documents (those with no security tokens at all)
        LOG.info("ManifoldCFSecurityFilter: Default no-user response (open documents only)");
        userAccessTokens = new ArrayList<String>();
      }
      else
      {
        // Only return 'public' documents (those with no security tokens at all)
        LOG.info("ManifoldCFSecurityFilter: Group tokens received from caller");
        userAccessTokens = new ArrayList<String>();
        for (int i = 0; i < passedTokens.length; i++)
        {
          userAccessTokens.add(passedTokens[i]);
        }
      }
    }
    else
    {
      LOG.info("ManifoldCFSecurityFilter: Trying to match docs for user '"+authenticatedUserName+"'");
      // Valid authenticated user name.  Look up access tokens for the user.
      // Check the configuration arguments for validity
      if (authorityBaseURL == null)
      {
        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Error initializing ManifoldCFSecurityFilter component: 'AuthorityServiceBaseURL' init parameter required");
      }
      userAccessTokens = getAccessTokens(authenticatedUserName);
    }

    BooleanFilter bf = new BooleanFilter();
    
    if (userAccessTokens.size() == 0)
    {
      // Only open documents can be included.
      // That query is:
      // (fieldAllowShare is empty AND fieldDenyShare is empty AND fieldAllowDocument is empty AND fieldDenyDocument is empty)
      // We're trying to map to:  -(fieldAllowShare:*) , which should be pretty efficient in Solr because it is negated.  If this turns out not to be so, then we should
      // have the SolrConnector inject a special token into these fields when they otherwise would be empty, and we can trivially match on that token.
      bf.add(new FilterClause(new QueryWrapperFilter(new WildcardQuery(new Term(fieldAllowShare,"*"))),BooleanClause.Occur.MUST_NOT));
      bf.add(new FilterClause(new QueryWrapperFilter(new WildcardQuery(new Term(fieldDenyShare,"*"))),BooleanClause.Occur.MUST_NOT));
      bf.add(new FilterClause(new QueryWrapperFilter(new WildcardQuery(new Term(fieldAllowDocument,"*"))),BooleanClause.Occur.MUST_NOT));
      bf.add(new FilterClause(new QueryWrapperFilter(new WildcardQuery(new Term(fieldDenyDocument,"*"))),BooleanClause.Occur.MUST_NOT));
    }
    else
    {
      // Extend the query appropriately for each user access token.
      bf.add(new FilterClause(calculateCompleteSubfilter(fieldAllowShare,fieldDenyShare,userAccessTokens),BooleanClause.Occur.MUST));
      bf.add(new FilterClause(calculateCompleteSubfilter(fieldAllowDocument,fieldDenyDocument,userAccessTokens),BooleanClause.Occur.MUST));
    }

    // Concatenate with the user's original query.
    //FilteredQuery query = new FilteredQuery(rb.getQuery(),bf);
    //rb.setQuery(query);
    List<Query> list = rb.getFilters();
    if (list == null)
    {
      list = new ArrayList<Query>();
      rb.setFilters(list);
    }
    list.add(new ConstantScoreQuery(bf));
  }

  @Override
  public void process(ResponseBuilder rb) throws IOException
  {
    LOG.info("ManifoldCFSecurityFilter: process() called");
  }

  /** Calculate a complete subclause, representing something like:
  * ((fieldAllowShare is empty AND fieldDenyShare is empty) OR fieldAllowShare HAS token1 OR fieldAllowShare HAS token2 ...)
  *     AND fieldDenyShare DOESN'T_HAVE token1 AND fieldDenyShare DOESN'T_HAVE token2 ...
  */
  protected Filter calculateCompleteSubfilter(String allowField, String denyField, List<String> userAccessTokens)
  {
    BooleanFilter bf = new BooleanFilter();
    
    // Add a clause for each token.  This will be added directly to the main filter (as a deny test), as well as to an OR's subclause (as an allow test).
    BooleanFilter orFilter = new BooleanFilter();
    // Add the empty-acl case
    BooleanFilter subUnprotectedClause = new BooleanFilter();
    subUnprotectedClause.add(new FilterClause(new QueryWrapperFilter(new WildcardQuery(new Term(allowField,"*"))),BooleanClause.Occur.MUST_NOT));
    subUnprotectedClause.add(new FilterClause(new QueryWrapperFilter(new WildcardQuery(new Term(denyField,"*"))),BooleanClause.Occur.MUST_NOT));
    orFilter.add(new FilterClause(subUnprotectedClause,BooleanClause.Occur.SHOULD));
    for (int i = 0; i < userAccessTokens.size(); i++)
    {
      String accessToken = userAccessTokens.get(i);
      TermsFilter tf = new TermsFilter();
      tf.addTerm(new Term(allowField,accessToken));
      orFilter.add(new FilterClause(tf,BooleanClause.Occur.SHOULD));
      tf = new TermsFilter();
      tf.addTerm(new Term(denyField,accessToken));
      bf.add(new FilterClause(tf,BooleanClause.Occur.MUST_NOT));
    }
    bf.add(new FilterClause(orFilter,BooleanClause.Occur.MUST));
    return bf;
  }
  
  //---------------------------------------------------------------------------------
  // SolrInfoMBean
  //---------------------------------------------------------------------------------
  @Override
  public String getDescription()
  {
    return "ManifoldCF Solr security enforcement plugin";
  }

  @Override
  public String getVersion()
  {
    return "$Revision: 02.05.10096 $";
  }

  @Override
  public String getSourceId()
  {
    return "$Id$";
  }

  @Override
  public String getSource()
  {
    return "ManifoldCFSecurityFilter.java $";
  }
	
  // Protected methods
  
  /** Get access tokens given a username */
  protected List<String> getAccessTokens(String authenticatedUserName)
    throws IOException
  {
    // We can make this more complicated later, with support for https etc., but this is enough to demonstrate how it all should work.
    HttpClient client = new HttpClient();
    String theURL = authorityBaseURL + "/UserACLs?username="+URLEncoder.encode(authenticatedUserName,"utf-8");
      
    GetMethod method = new GetMethod(theURL);
    try
    {
      method.getParams().setParameter("http.socket.timeout", new Integer(300000));
      method.setFollowRedirects(true);
      int rval = client.executeMethod(method);
      if (rval != 200)
      {
	String response = method.getResponseBodyAsString();
	throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,"Couldn't fetch user's access tokens from ManifoldCF authority service: "+Integer.toString(rval)+"; "+response);
      }
      InputStream is = method.getResponseBodyAsStream();
      try
      {
	Reader r = new InputStreamReader(is,"utf-8");
	try
	{
	  BufferedReader br = new BufferedReader(r);
	  try
	  {
	    // Read the tokens, one line at a time.  If any authorities are down, we have no current way to note that, but someday we will.
	    List<String> tokenList = new ArrayList<String>();
	    while (true)
	    {
	      String line = br.readLine();
	      if (line == null)
		break;
	      if (line.startsWith("TOKEN:"))
	      {
		tokenList.add(line.substring("TOKEN:".length()));
	      }
	      else
	      {
		// It probably says something about the state of the authority(s) involved, so log it
		LOG.info("ManifoldCFSecurityFilter: For user '"+authenticatedUserName+"', saw authority response "+line);
	      }
	    }
	    return tokenList;
	  }
	  finally
	  {
	    br.close();
	  }
	}
	finally
	{
	  r.close();
	}
      }
      finally
      {
	is.close();
      }
    }
    finally
    {
      method.releaseConnection();
    }
  }
  
}