Package org.infoglue.cms.security

Source Code of org.infoglue.cms.security.BasicIndexedAuthorizationModule

package org.infoglue.cms.security;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopFieldDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.infoglue.deliver.util.Timer;

/**
* @author Mattias Bogeblad
*
* This authorization module can be used by all Authorization modules that cannot provide advanced paging/search directly from the source but
* wants a search enabled / paged experience anyway. Works on cached data and the update interval can be decided by using the normal extra security settings (parameter name 'indexTimeout').
*/

public abstract class BasicIndexedAuthorizationModule implements AuthorizationModule
{
    private final static Logger logger = Logger.getLogger(TestAuthorizationModule.class.getName());

  private static Directory   idx         = null;
  private static long     idxCreatedDateTime   = 0L;

  public abstract List<InfoGlueRole> getAllRoles() throws Exception;
  public abstract List<InfoGlueGroup> getAllGroups() throws Exception;
  public abstract List<InfoGluePrincipal> getAllUsers(boolean populateRolesAndGroups) throws Exception;

  /**
   * Call this method directly if you have a threaded implementation which syncs and caches the users on a regular basis.
   *
   * @throws Exception
   */

  public synchronized void reIndex() throws Exception
  {
    Directory newIndex = new RAMDirectory();
    logger.info("creating index....");
    createIndex(newIndex);
    idx = newIndex;
    idxCreatedDateTime = System.currentTimeMillis();
  }

  private synchronized void validateIndex() throws Exception
  {
    long indexTimeout = 30000;
    if(getExtraProperties() != null)
    {
      String indexTimeoutFromProperties = (String)getExtraProperties().get("indexTimeout");
      if(indexTimeoutFromProperties != null && !indexTimeoutFromProperties.equals(""))
      {
        try
        {
          indexTimeout = Long.parseLong(indexTimeoutFromProperties);
        }
        catch (Exception e)
        {
          logger.error("Error parsing indexTimeout from the extra settings. Using default. Message:" + e.getMessage());
        }
      }
    }
   
    long diff = System.currentTimeMillis() - idxCreatedDateTime;
    if(idx == null || diff > indexTimeout)
    {
      reIndex();
    }
  }
 
  /**
   * This method is used to fetch all users part of the named role. 
   */
  public List<InfoGluePrincipal> getRoleUsers(String roleName) throws Exception
  {
    return getRoleUsers(roleName, null, 1000000, null, null, null);
  }
 
  /**
   * This method is used to fetch all users part of the named group. 
   */

  public List<InfoGluePrincipal> getGroupUsers(String groupName) throws Exception
  {
    return getGroupUsers(groupName, null, 1000000, null, null, null);
  }
 
  /**
   * This method is used to fetch all or a subset of sorted users either filtered on a text or not. 
   * If the index is not created or older than set interval the index is created.
   */

  public List<InfoGluePrincipal> getFilteredUsers(Integer offset, Integer limit, String sortProperty, String direction, String searchString, boolean populateRolesAndGroups) throws Exception
  {
    if(logger.isInfoEnabled())
    {
      logger.info("offset: " + offset);
      logger.info("limit: " + limit);
      logger.info("sortProperty: " + sortProperty);
      logger.info("direction: " + direction);
      logger.info("searchString: " + searchString);     
      logger.info("populateRolesAndGroups: " + populateRolesAndGroups);     
    }

    validateIndex();
   
    List<InfoGluePrincipal> users = new ArrayList<InfoGluePrincipal>();
   
    try
    {
      List<Document> docs;
     
      if(searchString == null || searchString.equals(""))
        docs = queryDocuments(offset, limit, sortProperty, direction);
      else
        docs = queryDocuments(offset, limit, sortProperty, direction, searchString);
     
      logger.info("docs:" + docs.size());
      for(Document doc : docs)
      {
        String userName = doc.get("userName");
        InfoGluePrincipal user = new InfoGluePrincipal(userName, doc.get("userName"), doc.get("firstName"), doc.get("lastName"), doc.get("email"), doc.get("source"), true, new Date(), new ArrayList(), new ArrayList(), new HashMap(), false, this);
        users.add(user);
      }
    }
    catch (Exception e)
    {
      logger.warn("Error getting filtered users:" + e.getMessage(), e);
    }
   
    return users;   
  }
   
  /**
   * A method returning the number of users matching a roleName and also contains searched text
   */
  public Integer getRoleUserCount(String roleName, String searchString) throws Exception
  {
    return getRoleUsers(roleName, null, 1000000, null, null, searchString).size();
  }

  /**
   * A method returning the number of users not matching a roleName and also contains searched text
   */
  public Integer getRoleUserInvertedCount(String roleName, String searchString) throws Exception
  {
    List<InfoGluePrincipal> allUsers = getFilteredUsers(null, 1000000, null, null, searchString, false);
    List<InfoGluePrincipal> assignedUsers = getRoleUsers(roleName, null, 1000000, null, null, searchString);
   
    List<InfoGluePrincipal> newAllUsers = new ArrayList<InfoGluePrincipal>();
    newAllUsers.addAll(allUsers);
    newAllUsers.removeAll(assignedUsers);
   
    return newAllUsers.size();
  }

  /**
   * A method returning the number of users matching a groupName and also contains searched text
   */
  public Integer getGroupUserCount(String groupName, String searchString) throws Exception
  {
    return getGroupUsers(groupName, null, 1000000, null, null, searchString).size();
  }

  /**
   * A method returning the number of users not matching a groupName and also contains searched text
   */
  public Integer getGroupUserInvertedCount(String groupName, String searchString) throws Exception
  {
    List<InfoGluePrincipal> allUsers = getFilteredUsers(null, 1000000, null, null, searchString, false);
    List<InfoGluePrincipal> assignedUsers = getGroupUsers(groupName, null, 1000000, null, null, searchString);
   
    List<InfoGluePrincipal> newAllUsers = new ArrayList<InfoGluePrincipal>();
    newAllUsers.addAll(allUsers);
    newAllUsers.removeAll(assignedUsers);
   
    return newAllUsers.size();
  }

  /**
   * A method returning the all/subset of sorted users part of stated role and optionally contains searched text
   */

  public List<InfoGluePrincipal> getRoleUsers(String roleName, Integer offset, Integer limit, String sortProperty, String direction, String searchString) throws Exception
  {
    List<InfoGluePrincipal> users = new ArrayList<InfoGluePrincipal>();
   
    try
    {
      validateIndex();
     
      List<Document> docs = getDocuments("roles", roleName, offset, limit, sortProperty, direction, searchString);
     
      logger.info("docs:" + docs.size());
      for(Document doc : docs)
      {
        String userName = doc.get("userName");
        InfoGluePrincipal user = new InfoGluePrincipal(userName, doc.get("userName"), doc.get("firstName"), doc.get("lastName"), doc.get("email"), doc.get("source"), true, new Date(), new ArrayList(), new ArrayList(), new HashMap(), false, this);
        users.add(user);
      }
    }
    catch (Exception e)
    {
      logger.error("Error getting roleUsers:" + e.getMessage(), e);
    }
   
      return users;
  }

  /**
   * A method returning the all/subset of sorted users not part of stated role and optionally contains searched text
   */

  public List<InfoGluePrincipal> getRoleUsersInverted(String roleName, Integer offset, Integer limit, String sortProperty, String direction, String searchString) throws Exception
  {
    List<InfoGluePrincipal> allUsers = getFilteredUsers(null, 1000000, sortProperty, direction, searchString, false);
    List<InfoGluePrincipal> assignedUsers = getRoleUsers(roleName, null, 1000000, null, null, searchString);
   
    List<InfoGluePrincipal> newAllUsers = new ArrayList<InfoGluePrincipal>();
    newAllUsers.addAll(allUsers);
    newAllUsers.removeAll(assignedUsers);

    return newAllUsers;
  }

  /**
   * A method returning the all/subset of sorted users part of stated group and optionally contains searched text
   */

  public List<InfoGluePrincipal> getGroupUsers(String groupName, Integer offset, Integer limit, String sortProperty, String direction, String searchString) throws Exception
  {
    List<InfoGluePrincipal> users = new ArrayList<InfoGluePrincipal>();
   
    try
    {
      validateIndex();

      List<Document> docs = getDocuments("groups", groupName, offset, limit, sortProperty, direction, searchString);
     
      logger.info("docs:" + docs.size());
      for(Document doc : docs)
      {
        String userName = doc.get("userName");
        InfoGluePrincipal user = new InfoGluePrincipal(userName, doc.get("userName"), doc.get("firstName"), doc.get("lastName"), doc.get("email"), doc.get("source"), true, new Date(), new ArrayList(), new ArrayList(), new HashMap(), false, this);
        users.add(user);
      }
    }
    catch (Exception e)
    {
      logger.error("Error getting groupUsers: " + e.getMessage(), e);
    }
   
      return users;
  }

  /**
   * A method returning the all/subset of sorted users not part of stated group and optionally contains searched text
   */

  public List<InfoGluePrincipal> getGroupUsersInverted(String groupName, Integer offset, Integer limit, String sortProperty, String direction, String searchString) throws Exception
  {
    List<InfoGluePrincipal> allUsers = getFilteredUsers(null, null, sortProperty, direction, searchString, false);
    List<InfoGluePrincipal> assignedUsers = getGroupUsers(groupName, null, 1000000, null, null, searchString);
   
    List<InfoGluePrincipal> newAllUsers = new ArrayList<InfoGluePrincipal>();
    newAllUsers.addAll(allUsers);
    newAllUsers.removeAll(assignedUsers);

    return newAllUsers;
  }

  /**
   * This method returns the number of users in the system (optionally filtered by text search).
   * A basic implementation just barely implementing the feature. Should be done better.
   */

  public Integer getRoleCount(String searchString) throws Exception
  {
    return getRoles().size();
  }

  /**
   * This method returns the number of users in the system (optionally filtered by text search).
   * A basic implementation just barely implementing the feature. Should be done better.
   */

  public Integer getGroupCount(String searchString) throws Exception
  {
    return getGroups().size();
  }

  /**
   * This method returns the number of users in the system (optionally filtered by text search).
   */

  public Integer getUserCount(String searchString) throws Exception
  {
    List<Document> docs = null;
   
    if(searchString == null || searchString.equals(""))
      docs = queryDocuments(0, 1000000, "userName", "asc");
    else
      docs = queryDocuments(0, 1000000, "userName", "asc", searchString);

    return docs.size();
  }

 
 
 
  /**
   * This method creates the index by indexing all users.
   */

  private Directory createIndex(Directory directory) throws CorruptIndexException, LockObtainFailedException, IOException, Exception
  {
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_34);
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_34, analyzer);
    IndexWriter iw = new IndexWriter(directory, config);
   
    addDocuments(iw, getAllUsers(true));

    iw.optimize();
    iw.close();
    return idx;
  }


  /**
   * This method adds all users to the.
   */

  private void addDocuments(IndexWriter iw, List<InfoGluePrincipal> users) throws CorruptIndexException, IOException
  {
    logger.info("Indexing users:" + users.size());
    Timer t = new Timer();
   
    for (InfoGluePrincipal user : users)
    {
      Document doc = new Document();

      // Add user
      String contentToIndex = "" + user.getName() + " " + user.getFirstName() + " " + user.getLastName() + " " + user.getEmail() + " " + user.getSource();
     
      doc.add(new Field("contents", new StringReader(contentToIndex)));

      doc.add(new Field("userName", user.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
      doc.add(new Field("firstName", user.getFirstName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
      doc.add(new Field("lastName", user.getLastName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
      doc.add(new Field("email", user.getEmail(), Field.Store.YES, Field.Index.NOT_ANALYZED));
      doc.add(new Field("source", user.getSource(), Field.Store.YES, Field.Index.NOT_ANALYZED));
      doc.add(new NumericField("lastModified", Field.Store.YES, true).setLongValue(user.getModifiedDateTime().getTime()));
     
      for(InfoGlueRole role : user.getRoles())
      {
        if(!role.getName().equals("anonymous"))
          logger.info("role:" + role.getName());
        doc.add(new Field("roles", new StringReader("" + role.getName())));
      }
     
      for(InfoGlueGroup group : user.getGroups())
      {
        if(!group.getName().equals("anonymous"))
          logger.info("group:" + group.getName());
        doc.add(new Field("groups", new StringReader("" + group.getName())));
      }
     
      iw.addDocument(doc);
    }
   
    if(logger.isInfoEnabled())
      t.printElapsedTime("Indexing users took");
  }

  /**
   * Getting the index searcher
   */

  private IndexSearcher getIndexSearcher() throws Exception
  {
    IndexReader reader = IndexReader.open(idx, true);
      return new IndexSearcher(reader);
  }

  /**
   * A query api for getting all users sorted and paged
   */

  public List<Document> queryDocuments(Integer offset, Integer limit, String sortProperty, String direction) throws Exception
  {
    IndexSearcher searcher = getIndexSearcher();
    List<Document> docs = new ArrayList<Document>();

    if(offset == null)
      offset = 0;
   
    if(limit == null)
      limit = 10;
   
    if(sortProperty == null)
      sortProperty = "userName";

    boolean reverse = false;
    if(direction != null && direction.equalsIgnoreCase("desc"))
      reverse = true;
       
    SortField sf = new SortField(sortProperty, SortField.STRING, reverse);

    Query query = new MatchAllDocsQuery();
   
    TopFieldDocs topDocs = searcher.search(query, (Filter) null, 1000000, new Sort(sf));
    logger.info("offset:" + offset);
    logger.info("limit:" + limit);
    logger.info("topDocs.totalHits:" + topDocs.totalHits);
   
    int start = offset;
    int end = offset+limit;
    if(end > topDocs.totalHits)
      end = topDocs.totalHits;

    logger.info("start:" + start);
    logger.info("end:" + end);

    for(int i=start; i<end; i++)
    {
      ScoreDoc scoreDoc = topDocs.scoreDocs[i];
      Document doc = searcher.doc(scoreDoc.doc);
      docs.add(doc);
    }

    searcher.close();
    return docs;
  }

  /**
   * A query api for getting all users sorted and paged filtered on search text
   */

  public List<Document> queryDocuments(Integer offset, Integer limit, String sortProperty, String direction, String searchText) throws Exception
  {
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_34);
    IndexSearcher searcher = getIndexSearcher();
    List<Document> docs = new ArrayList<Document>();

    if(offset == null)
      offset = 0;
   
    if(limit == null)
      limit = 10;
   
    if(sortProperty == null)
      sortProperty = "userName";

    boolean reverse = false;
    if(direction != null && direction.equalsIgnoreCase("desc"))
      reverse = true;
   
    SortField sf = new SortField(sortProperty, SortField.STRING, reverse);
    logger.info("searchText:" + searchText);
    Query query = new QueryParser(Version.LUCENE_34, "contents", analyzer).parse(searchText+"*");
   
    TopFieldDocs topDocs = searcher.search(query, (Filter) null, 1000000, new Sort(sf));
    logger.info("offset:" + offset);
    logger.info("limit:" + limit);
    logger.info("topDocs.totalHits:" + topDocs.totalHits);
   
    int start = offset;
    int end = offset+limit;
    if(end > topDocs.totalHits)
      end = topDocs.totalHits;

    logger.info("start:" + start);
    logger.info("end:" + end);

    for(int i=start; i<end; i++)
    {
      ScoreDoc scoreDoc = topDocs.scoreDocs[i];
      Document doc = searcher.doc(scoreDoc.doc);
      docs.add(doc);
    }

    searcher.close();
    return docs;
  }
 
  /**
   * A query api for getting user docs found by role or group mainly sorted and paged and optinally filtered on search text
   */

  public List<Document> getDocuments(String field, String entityName, Integer offset, Integer limit, String sortProperty, String direction, String searchText) throws Exception
  {
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_34);
    IndexSearcher searcher = getIndexSearcher();
    List<Document> docs = new ArrayList<Document>();

    if(offset == null)
      offset = 0;
   
    if(limit == null)
      limit = 10;
   
    if(sortProperty == null)
      sortProperty = "userName";

    boolean reverse = false;
    if(direction != null && direction.equalsIgnoreCase("desc"))
      reverse = true;
   
    SortField sf = new SortField(sortProperty, SortField.STRING, reverse);
    logger.info("searchText:" + searchText);
    Query query = new QueryParser(Version.LUCENE_34, field, analyzer).parse(entityName);
    if(searchText != null && !searchText.equals(""))
    {
      MultiFieldQueryParser mfqp = new MultiFieldQueryParser(Version.LUCENE_34, new String[]{field, "contents"}, analyzer);
      mfqp.setDefaultOperator(MultiFieldQueryParser.AND_OPERATOR);
      query = mfqp.parse(entityName + " " + searchText + "*");
    }
   
    logger.info("query" + query);
   
    TopFieldDocs topDocs = searcher.search(query, (Filter) null, 1000000, new Sort(sf));
    logger.info("offset:" + offset);
    logger.info("limit:" + limit);
    logger.info("topDocs.totalHits:" + topDocs.totalHits);
   
    int start = offset;
    int end = offset+limit;
    if(end > topDocs.totalHits)
      end = topDocs.totalHits;

    logger.info("start:" + start);
    logger.info("end:" + end);

    for(int i=start; i<end; i++)
    {
      ScoreDoc scoreDoc = topDocs.scoreDocs[i];
      Document doc = searcher.doc(scoreDoc.doc);
      docs.add(doc);
    }

    searcher.close();
    return docs;
  }


}

TOP

Related Classes of org.infoglue.cms.security.BasicIndexedAuthorizationModule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.