/**
   * Executes a delete user action.
   *
   * @param request HTTP request.
   * @param response HTTP response.
   * @param context request context
   * @throws Exception if an exception occurs
   */
  private void executeDeleteUser(
      HttpServletRequest request, HttpServletResponse response, RequestContext context)
      throws Exception {
    try {
      String[] parts = request.getRequestURI().toString().split("/");
      if (parts.length > 0) {
        String userIdentifier = URLDecoder.decode(parts[5].trim(), "UTF-8");
        if (userIdentifier.endsWith(userDIT)) {
          String attempt = Val.chkStr(request.getParameter("attempt"));
          IdentityAdapter idAdapter = context.newIdentityAdapter();
          User user = new User();
          user.setDistinguishedName(userIdentifier);
          idAdapter.readUserProfile(user);
          idAdapter.readUserGroups(user);

          boolean isSelf = checkSelf(context, userIdentifier);
          if ((isSelf && attempt.equals("2")) || !isSelf) {
            idAdapter.deleteUser(user);
            response
                .getWriter()
                .write(msgBroker.retrieveMessage("catalog.identity.deleteUser.success"));
          } else {
            response.getWriter().write("prompt");
          }
        }
      }
    } finally {
    }
  }
  /**
   * Reads user profile from ldap.
   *
   * @param context the current request context (contains the active user)
   * @param request HTTP request.
   * @return user the user whose profile was read
   * @throws IdentityException if a system error occurs preventing the action
   * @throws NamingException if an LDAP naming exception occurs
   * @throws SQLException if a database communication exception occurs
   * @throws CredentialsDeniedException
   * @throws UnsupportedEncodingException
   */
  protected User readUserProfile(RequestContext context, HttpServletRequest request)
      throws Exception {

    IdentityAdapter idAdapter = context.newIdentityAdapter();
    User user = new User();
    String[] parts = request.getRequestURI().toString().split("/");
    String sEncoding = request.getCharacterEncoding();
    if ((sEncoding == null) || (sEncoding.trim().length() == 0)) {
      sEncoding = "UTF-8";
    }

    if (parts.length > 0) {
      String userIdentifier = Val.chkStr(URLDecoder.decode(parts[5].trim(), "UTF-8"));
      if (userIdentifier.endsWith(userDIT)) {
        user.setDistinguishedName(userIdentifier);
        DistinguishedNameCredential dnCredential = new DistinguishedNameCredential();
        dnCredential.setDistinguishedName(userIdentifier);
        user.setCredentials(dnCredential);
      } else if (userIdentifier.length() > 0) {
        user.setCredentials(new UsernameCredential(userIdentifier));
      }
      ((LdapIdentityAdapter) idAdapter).populateUser(context, user);
      return user;
    } else {
      throw new Exception("error");
    }
  }
 /**
  * Add attribute to ldap entry.
  *
  * @param request HTTP request.
  * @param response HTTP response.
  * @param context request context
  * @throws IdentityException if a system error occurs preventing the action
  * @throws IOException if error writing to the buffer
  * @throws NamingException if an LDAP naming exception occurs
  * @throws SQLException
  * @throws CredentialPolicyException
  */
 private void executeModifyUserAttribute(
     HttpServletRequest request,
     HttpServletResponse response,
     RequestContext context,
     boolean isAddAttributeRequest)
     throws IdentityException, IOException, NamingException, SQLException,
         CredentialPolicyException {
   String mimeType = "application/json";
   String filter = Val.chkStr(request.getParameter("q"));
   String attributeName = Val.chkStr(request.getParameter("an"));
   String attributeValue = Val.chkStr(request.getParameter("av"));
   if (filter.length() == 0) {
     response.getWriter().write("{ \"response\" : \"noResults\" }");
     return;
   }
   IdentityAdapter idAdapter = context.newIdentityAdapter();
   Users users = idAdapter.readUsers(filter, null);
   for (User u : users.values()) {
     if (isAddAttributeRequest) {
       try {
         idAdapter.addAttribute(u.getDistinguishedName(), attributeName, attributeValue);
       } catch (AttributeInUseException aiue) {
         // TODO : do nothing if attribute exists ? or overwrite ?
       }
     } else {
       idAdapter.removeAttribute(u.getDistinguishedName(), attributeName, attributeValue);
     }
   }
   writeCharacterResponse(
       response,
       "{ \"response\" : \"User attribute modification was successful.\" }",
       "UTF-8",
       mimeType + ";charset=UTF-8");
 }
 /**
  * Checks if managed user is active user.
  *
  * @param context
  * @param managedUserDn
  * @return true if managed user is same as active user
  */
 protected boolean checkSelf(RequestContext context, String managedUserDn) {
   boolean isSelf = false;
   User user = context.getUser();
   if (user.getDistinguishedName().equals(managedUserDn)) {
     isSelf = true;
   }
   return isSelf;
 }
  /**
   * Executes a remove member action.
   *
   * @param request HTTP request.
   * @param response HTTP response.
   * @param context request context
   * @throws Exception if an exception occurs
   */
  protected void executeRemoveMember(
      HttpServletRequest request, HttpServletResponse response, RequestContext context)
      throws Exception {
    try {
      String[] parts = request.getRequestURI().toString().split("/");
      String member = Val.chkStr(request.getParameter("member"));
      String attempt = Val.chkStr(request.getParameter("attempt"));
      IdentityAdapter idAdapter = context.newIdentityAdapter();
      User user = new User();
      user.setDistinguishedName(member);
      idAdapter.readUserProfile(user);
      if (parts.length > 0) {
        String groupIdentifier = URLDecoder.decode(parts[5].trim(), "UTF-8");
        if (!groupIdentifier.endsWith(groupDIT)) {
          IdentityConfiguration idConfig = context.getIdentityConfiguration();
          Roles configuredRoles = idConfig.getConfiguredRoles();
          Role roleRegistered = configuredRoles.get(groupIdentifier);
          groupIdentifier = roleRegistered.getDistinguishedName();
        }
        boolean isSelf = checkSelf(context, member);
        if ((isSelf && attempt.equals("2")) || !isSelf) {

          boolean checkGroupConfigured = true;
          if (checkIfAllowConfigured(context)) {
            checkGroupConfigured = checkIfConfigured(context, groupIdentifier);
          }
          boolean isAllowedToManage = true;
          isAllowedToManage = checkIfAllowedToManage(context, groupIdentifier);
          if (checkGroupConfigured) {
            if (isAllowedToManage) {
              idAdapter.removeUserFromGroup(user, groupIdentifier);
              response
                  .getWriter()
                  .write(msgBroker.retrieveMessage("catalog.identity.removeRole.success"));
            } else {
              response.sendError(
                  HttpServletResponse.SC_BAD_REQUEST,
                  "{ \"error\":\""
                      + groupIdentifier
                      + " is not allowed to be managed in geoportal. \"}");
              return;
            }
          } else {
            response.sendError(
                HttpServletResponse.SC_BAD_REQUEST,
                "{ \"error\":\"" + groupIdentifier + " is not configured in geoportal. \"}");
            return;
          }

        } else {
          response.getWriter().write("prompt");
        }
      }
    } finally {
    }
  }
  /**
   * Serializes list of ldap users matching filter.
   *
   * @param context the current request context
   * @param filter the user search filter for ldap
   * @return the list of users as json
   * @throws IdentityException if a system error occurs preventing the action
   * @throws NamingException if an LDAP naming exception occurs
   * @throws SQLException
   */
  protected String serializeUsersAsJson(
      RequestContext context, String filter, String attributeName, boolean isMemberSearch)
      throws IdentityException, NamingException, SQLException {
    Users users = new Users();
    int totalMatches = 0;
    if (!isMemberSearch) {
      HashMap<String, Object> resultsMap = buildUsersList(context, filter, null);
      users = (Users) resultsMap.get("topUserMatches");
      totalMatches = (Integer) resultsMap.get("totalMatches");
    } else if (isMemberSearch && attributeName != null) {
      Roles configuredRoles = context.getIdentityConfiguration().getConfiguredRoles();
      Role role = configuredRoles.get(attributeName);
      String sDn = role.getDistinguishedName();
      IdentityAdapter idAdapter = context.newIdentityAdapter();
      users = idAdapter.readGroupMembers(sDn);
      totalMatches = users.size();
      users.sort();
    } else {
      IdentityAdapter idAdapter = context.newIdentityAdapter();
      Users members = idAdapter.readGroupMembers(filter);
      for (User u : members.values()) {
        users.add(u);
      }
      users.sort();
      totalMatches = users.size();
    }

    String usersJson =
        "{ \"totalUsers\" : \""
            + totalMatches
            + "\" ,\"topUsers\" : \""
            + users.size()
            + "\" , \"users\": [";
    boolean firstUser = true;
    for (User user : users.values()) {
      String userName = user.getName();
      String dn = user.getKey();
      if (!firstUser) {
        usersJson += ",";
      } else {
        firstUser = false;
      }
      usersJson +=
          " { \"dn\" : \""
              + dn
              + "\" , \"userName\" : \""
              + Val.escapeStrForJson(userName)
              + "\" }";
    }
    usersJson += " ] }";
    return usersJson;
  }
 /**
  * Checks if user role matches provided groups distinguished name.
  *
  * @param context
  * @param groupDn
  * @return true if managed user role is same as groupDn
  */
 protected boolean checkRole(User user, String groupDn) {
   boolean isSelf = false;
   Groups groups = user.getGroups();
   for (Group group : groups.values()) {
     String dn = Val.chkStr(group.getDistinguishedName());
     if (dn.equals(groupDn)) {
       isSelf = true;
       break;
     }
   }
   return isSelf;
 }
  /**
   * Establishes the user associated with the operation.
   *
   * @param context the assertion operation context
   * @throws NotAuthorizedException if authentication was required
   * @throws AsnInsufficientPrivilegeException if the user has insufficient privilege
   * @throws AsnUnestablishedUserException if the user could not be established
   */
  public void establishUser(AsnContext context)
      throws NotAuthorizedException, AsnUnestablishedUserException {

    // initialize
    this.setWasUserEstablished(false);
    AsnOperation operation = context.getOperation();
    User user = context.getRequestContext().getUser();

    // establish the user part of the operation
    if (operation.getUserPart() == null) {
      operation.setUserPart(new AsnUserPart());
    }
    operation.getUserPart().setIPAddress(context.getRequestOptions().getIPAddress());
    AsnAuthPolicy authPolicy = operation.getAuthPolicy();
    if (authPolicy.getAuthenticationRequired()) {
      if ((user == null) || !user.getAuthenticationStatus().getWasAuthenticated()) {
        throw new NotAuthorizedException("Not authorized.");
      }
    }
    if ((user == null) || !user.getAuthenticationStatus().getWasAuthenticated()) {
      operation.getUserPart().setName(AsnConstants.ANONYMOUS_USERNAME);
      this.setWasUserEstablished(true);
    } else {
      String key = Val.chkStr(user.getKey());
      if (key.length() > 0) {
        operation.getUserPart().setKey(key);
        if (user.getLocalID() >= 0) {
          operation.getUserPart().setID("" + user.getLocalID());
          String name = Val.chkStr(user.getName());
          if (name.length() > 0) {
            operation.getUserPart().setName(name);
            this.setWasUserEstablished(true);
          }
        }
      }
    }
    if (!this.getWasUserEstablished()) {
      throw new AsnUnestablishedUserException();
    }

    // check the admin database for a disabled user:ipaddress or user:key

    // check the admin index for moderation privileges

  }
 /**
  * Gets the status indicating whether this publisher is an administrator.
  *
  * @return true if this publisher is an administrator
  */
 private boolean getIsAdministrator(User user) {
   RoleSet roles = user.getAuthenticationStatus().getAuthenticatedRoles();
   return roles.hasRole("gptAdministrator");
 }
 /**
  * Asserts the administrator role.
  *
  * @throws NotAuthorizedException if the administrator role has not been granted
  */
 private void assertAdministratorRole(User user) throws NotAuthorizedException {
   RoleSet roles = user.getAuthenticationStatus().getAuthenticatedRoles();
   roles.assertRole("gptAdministrator");
 }
  /**
   * Constructs a administrator based upon the user associated with the current request context.
   *
   * @param context the current request context (contains the active user)
   * @throws NotAuthorizedException if the user does not have publishing rights
   */
  protected void checkRole(RequestContext context) throws NotAuthorizedException {

    // initialize
    User user = context.getUser();
    user.setKey(user.getKey());
    user.setLocalID(user.getLocalID());
    user.setDistinguishedName(user.getDistinguishedName());
    user.setName(user.getName());

    // establish credentials
    UsernamePasswordCredentials creds = new UsernamePasswordCredentials();
    creds.setUsername(user.getName());
    user.setCredentials(creds);

    user.setAuthenticationStatus(user.getAuthenticationStatus());
    assertAdministratorRole(user);
  }
  /**
   * Serializes user information from ldap to json string.
   *
   * @param context request context
   * @param user the user to be serialized
   * @return the user profile information serialized as json string.
   * @throws IdentityException if a system error occurs preventing the action
   * @throws NamingException if an LDAP naming exception occurs
   */
  protected String serializeUserAsJson(RequestContext context, User user)
      throws IdentityException, NamingException {
    String usersJson = "{ \"attributes\": [";
    UserAttributeMap attributes = user.getProfile();
    boolean first = true;
    List<String> sortedKeys = new ArrayList<String>(attributes.keySet());
    // Collections.sort(sortedKeys); TODO to sort or not ?
    for (int i = 0; i < sortedKeys.size(); i++) {
      UserAttribute attr = attributes.get(sortedKeys.get(i));
      String key =
          Val.chkStr(msgBroker.retrieveMessage("catalog.identity.profile.label." + attr.getKey()));
      String value = "";
      value = Val.chkStr(attr.getValue());
      if (attr.getKey().equalsIgnoreCase("password")) continue;
      if (!first) {
        usersJson += ",";
      } else {
        first = false;
      }
      usersJson +=
          " { \"key\" : \""
              + Val.escapeStrForJson(key)
              + "\" , \"value\" : \""
              + Val.escapeStrForJson(value)
              + "\" }";
    }
    usersJson += " ] , ";

    usersJson += " \"userDn\" : \"" + user.getDistinguishedName() + " \" , ";

    String groupsJson = " \"groups\" : [";
    Groups groups = user.getGroups();
    groups.sort();
    boolean firstGroup = true;
    for (Group group : groups.values()) {
      String gkey = Val.chkStr(group.getKey());
      String name = Val.chkStr(group.getName());
      String dn = Val.chkStr(group.getDistinguishedName());
      if (!firstGroup) {
        groupsJson += ",";
      } else {
        firstGroup = false;
      }
      groupsJson +=
          " { \"key\" : \""
              + Val.escapeStrForJson(gkey)
              + "\" , \"name\" : \""
              + Val.escapeStrForJson(name)
              + "\" , \"dn\" : \""
              + Val.escapeStrForJson(dn)
              + "\" }";
    }
    groupsJson += " ] , ";

    String rolesJson = " \"selectableRoles\" : [";
    Roles roles = buildSelectableRoles(context);
    sortedKeys = new ArrayList<String>(roles.keySet());
    Collections.sort(sortedKeys);
    boolean firstRole = true;
    for (int i = 0; i < sortedKeys.size(); i++) {
      Role role = roles.get(sortedKeys.get(i));
      String roleDn = Val.chkStr(role.getDistinguishedName());
      String roleKey = Val.chkStr(role.getKey());
      String roleName = msgBroker.retrieveMessage(Val.chkStr(role.getResKey()));
      if (!role.isManage()) continue;
      boolean hasRole = false;
      for (Group group : groups.values()) {
        String groupDn = Val.chkStr(group.getDistinguishedName());
        if (roleDn.equals(groupDn)) {
          hasRole = true;
          break;
        }
      }
      if (!firstRole) {
        rolesJson += ",";
      } else {
        firstRole = false;
      }
      rolesJson +=
          " { \"roleName\" : \""
              + Val.escapeStrForJson(roleName)
              + "\" , \"roleDn\" : \""
              + Val.escapeStrForJson(roleDn)
              + "\" , \"roleKey\" : \""
              + Val.escapeStrForJson(roleKey)
              + "\" , \"hasRole\" : \""
              + hasRole
              + "\" }";
    }
    rolesJson += " ] } ";
    String json = usersJson + groupsJson + rolesJson;
    return json;
  }
  /**
   * Executes the query request.
   *
   * @throws SQLException if a database exception occurs
   * @throws IOException
   * @throws SAXException
   * @throws ParserConfigurationException
   */
  public void execute()
      throws SQLException, IdentityException, NamingException, ParserConfigurationException,
          SAXException, IOException {

    // intitalize
    PreparedStatement st = null;
    PreparedStatement stCount = null;
    MmdQueryCriteria criteria = getQueryCriteria();
    MmdRecords records = getQueryResult().getRecords();
    PageCursor pageCursor = getQueryResult().getPageCursor();
    criteria.getDateRange().check();
    pageCursor.setTotalRecordCount(0);

    adminDao = new ImsMetadataAdminDao(getRequestContext());
    tblImsUser = getRequestContext().getCatalogConfiguration().getUserTableName();
    Users editablePublishers = Publisher.buildSelectablePublishers(getRequestContext(), false);
    for (User u : editablePublishers.values()) {
      if (u.getName().length() > 0) {
        hmEditablePublishers.put(u.getName().toLowerCase(), u.getKey());
      }
    }
    User tmpUser = new User();
    tmpUser.setDistinguishedName("*");
    getRequestContext().newIdentityAdapter().readUserGroups(tmpUser);
    allGroups = tmpUser.getGroups();

    isGptAdministrator = new RoleMap(getRequestContext().getUser()).get("gptAdministrator");

    // determine if we are in ArcIMS metadata server proxy mode

    try {

      // establish the connection
      ManagedConnection mc = returnConnection();
      Connection con = mc.getJdbcConnection();

      // start the SQL expression
      StringBuilder sbSql = new StringBuilder();
      StringBuilder sbCount = new StringBuilder();
      StringBuilder sbFrom = new StringBuilder();
      StringBuilder sbWhere = new StringBuilder();
      sbSql.append("SELECT A.TITLE,A.DOCUUID,A.SITEUUID,C.USERNAME");
      sbSql.append(",A.APPROVALSTATUS,A.PUBMETHOD,A.UPDATEDATE,A.ACL");
      sbSql.append(",A.ID,A.HOST_URL,A.FREQUENCY,A.SEND_NOTIFICATION,A.PROTOCOL");
      sbSql.append(",A.FINDABLE,A.SEARCHABLE,A.SYNCHRONIZABLE");
      sbCount.append("SELECT COUNT(*)");

      // append from clause
      sbFrom.append(" FROM ").append(tblImsUser).append(" C");
      sbFrom.append(",").append(getResourceTableName()).append(" A");
      sbSql.append(sbFrom);
      sbCount.append(sbFrom);

      // build the where clause
      if (sbWhere.length() > 0) {
        sbWhere.append(" AND");
      }
      sbWhere.append(" (A.OWNER = C.USERID)");

      Map<String, Object> args = criteria.appendWherePhrase("A", sbWhere, getPublisher());

      // append the where clause expressions
      if (sbWhere.length() > 0) {
        sbSql.append(" WHERE ").append(sbWhere.toString());
        sbCount.append(" WHERE ").append(sbWhere.toString());
      }

      // append the order by clause
      String sSortColumn = criteria.getSortOption().getColumnKey();
      String sSortDir = criteria.getSortOption().getDirection().toString();
      if (sSortColumn.equalsIgnoreCase("title")) {
        sSortColumn = "UPPER(A.TITLE)";
      } else if (sSortColumn.equalsIgnoreCase("uuid")) {
        sSortColumn = "A.DOCUUID";
      } else if (sSortColumn.equalsIgnoreCase("owner")) {
        sSortColumn = "UPPER(C.USERNAME)";
      } else if (sSortColumn.equalsIgnoreCase("status")) {
        sSortColumn = "A.APPROVALSTATUS";
      } else if (sSortColumn.equalsIgnoreCase("method")) {
        sSortColumn = "A.PUBMETHOD";
      } else if (sSortColumn.equalsIgnoreCase("acl")) {
        sSortColumn = "A.ACL";
      } else if (sSortColumn.equalsIgnoreCase("updatedate")) {
        sSortColumn = "A.UPDATEDATE";
      } else {
        sSortColumn = "A.UPDATEDATE";
        sSortDir = "DESC";
        criteria.getSortOption().setColumnKey("updatedate");
        criteria.getSortOption().setDirection("desc");
      }
      sbSql.append(" ORDER BY ");
      sbSql.append(sSortColumn).append(" ").append(sSortDir.toUpperCase());
      if (!sSortColumn.equalsIgnoreCase("A.UPDATEDATE")) {
        sbSql.append(", A.UPDATEDATE DESC");
      }

      // prepare the statements
      st = con.prepareStatement(sbSql.toString());
      stCount = con.prepareStatement(sbCount.toString());

      int n = 1;
      criteria.applyArgs(st, n, args);
      criteria.applyArgs(stCount, n, args);

      // query the count
      logExpression(sbCount.toString());
      ResultSet rsCount = stCount.executeQuery();
      if (rsCount.next()) {
        pageCursor.setTotalRecordCount(rsCount.getInt(1));
      }
      stCount.close();
      stCount = null;

      // query records if a count was found
      pageCursor.checkCurrentPage();
      if (pageCursor.getTotalRecordCount() > 0) {

        // set the start record and the number of records to retrieve
        int nCurPage = pageCursor.getCurrentPage();
        int nRecsPerPage = getQueryResult().getPageCursor().getRecordsPerPage();
        int nStartRecord = ((nCurPage - 1) * nRecsPerPage) + 1;
        int nMaxRecsToRetrieve = nCurPage * nRecsPerPage;
        st.setMaxRows(nMaxRecsToRetrieve);

        // determine publisher names associated with editable records

        // execute the query
        logExpression(sbSql.toString());
        ResultSet rs = st.executeQuery();

        // build the record set
        int nCounter = 0;

        while (rs.next()) {
          n = 1;
          nCounter++;
          if (nCounter >= nStartRecord) {
            MmdRecord record = new MmdRecord();
            records.add(record);

            readRecord(rs, record);

            // break if we hit the max value for the cursor
            if (records.size() >= nRecsPerPage) {
              break;
            }
          }
        }

        TreeMap<String, MmdRecord> recordsMap =
            new TreeMap<String, MmdRecord>(String.CASE_INSENSITIVE_ORDER);
        StringBuilder keys = new StringBuilder();

        for (MmdRecord r : records) {
          if (r.getProtocol() == null) continue;
          recordsMap.put(r.getUuid(), r);
          if (keys.length() > 0) {
            keys.append(",");
          }
          keys.append("'").append(r.getUuid().toUpperCase()).append("'");
        }

        readJobStatus(con, recordsMap, keys.toString());
        readLastHarvestDate(con, recordsMap, keys.toString());
      }

    } finally {
      closeStatement(st);
      closeStatement(stCount);
    }
  }
  /**
   * Authorizes a create, update, delete or query based operation.
   *
   * @param context the assertion operation context
   * @param assertion the active assertion
   * @param action the action
   * @throws NotAuthorizedException if authentication was required
   * @throws AsnInsufficientPrivilegeException if the user has insufficient privilege
   */
  private void authorizeAction(AsnContext context, Assertion assertion, String action)
      throws NotAuthorizedException, AsnInsufficientPrivilegeException {

    // ensure an authorization policy
    AsnOperation operation = context.getOperation();
    if (operation.getAuthPolicy() == null) {
      String msg = "An authorization policy was not configured.";
      throw new ConfigurationException(msg);
    }

    // check the user, ensure an authenticated user if required
    User user = context.getRequestContext().getUser();
    boolean userWasAuthenticated = false;
    if ((user != null) && user.getAuthenticationStatus().getWasAuthenticated()) {
      userWasAuthenticated = true;
    }
    if (operation.getAuthPolicy().getAuthenticationRequired() && !userWasAuthenticated) {
      throw new NotAuthorizedException("Not authorized.");
    }

    // determine the principals
    AsnPrincipals principals = null;
    boolean isWrite = false;
    if (action.equals(AsnAuthorizer.ACTION_CREATE)) {
      isWrite = true;
      principals = operation.getAuthPolicy().getCreatePrincipals();
      if (principals == null) {
        String msg = "Create principals were not configured.";
        throw new ConfigurationException(msg);
      }

    } else if (action.equals(AsnAuthorizer.ACTION_DELETE)) {
      isWrite = true;
      principals = operation.getAuthPolicy().getDeletePrincipals();
      if (principals == null) {
        String msg = "Delete principals were not configured.";
        throw new ConfigurationException(msg);
      }

    } else if (action.equals(AsnAuthorizer.ACTION_ENABLE)
        || action.equals(AsnAuthorizer.ACTION_DISABLE)) {
      isWrite = true;
      principals = operation.getAuthPolicy().getEnableDisablePrincipals();
      if (principals == null) {
        String msg = "Enable/Disable principals were not configured.";
        throw new ConfigurationException(msg);
      }

    } else if (action.equals(AsnAuthorizer.ACTION_QUERY)) {
      principals = operation.getAuthPolicy().getQueryPrincipals();
      if (principals == null) {
        String msg = "Query principals were not configured.";
        throw new ConfigurationException(msg);
      }

    } else if (action.equals(AsnAuthorizer.ACTION_UPDATE)) {
      isWrite = true;
      principals = operation.getAuthPolicy().getQueryPrincipals();
      if (principals == null) {
        String msg = "Query principals were not configured.";
        throw new ConfigurationException(msg);
      }
    }

    // hard check to ensure an authenticated user for any modifications
    // (regardless of configuration)
    if (isWrite && !userWasAuthenticated) {
      throw new AsnInsufficientPrivilegeException();
    }

    // check "any user" user privilege
    if (principals.contains(AsnConstants.PRINCIPAL_ANY)) {
      return;
    }

    // check administrator privilege
    if (userWasAuthenticated) {
      if (principals.contains(AsnConstants.PRINCIPAL_ADMINISTRATOR)) {
        RoleSet roles = user.getAuthenticationStatus().getAuthenticatedRoles();
        if (roles.hasRole("gptAdministrator")) {
          return;
        }
      }
    }

    // check for ownership
    if (userWasAuthenticated && (assertion != null) && assertion.getWasReadFromIndex()) {
      if (principals.contains(AsnConstants.PRINCIPAL_OWNER)) {
        String asnUserKey = Val.chkStr(assertion.getUserPart().getKey());
        String userKey = Val.chkStr(user.getKey());
        if ((asnUserKey.length() > 0) && asnUserKey.equals(userKey)) {
          return;
        }
      }
    }

    throw new AsnInsufficientPrivilegeException();
  }
  /**
   * Determines if the user can perform an action.
   *
   * @param context the assertion operation context
   * @param policy the authorization policy
   * @param assertion the active assertion
   * @param action the action
   * @return true if the user can perform the action
   */
  private boolean canAct(
      AsnContext context, AsnAuthPolicy policy, Assertion assertion, String action) {

    // ensure an authorization policy
    if (policy == null) {
      return false;
    }

    // check the user, ensure an authenticated user if required
    User user = context.getRequestContext().getUser();
    boolean userWasAuthenticated = false;
    if ((user != null) && user.getAuthenticationStatus().getWasAuthenticated()) {
      userWasAuthenticated = true;
    }
    if (policy.getAuthenticationRequired() && !userWasAuthenticated) {
      return false;
    }

    // determine the write principals (creation or modification)
    AsnPrincipals principals = null;
    boolean isWrite = false;
    if (action.equals(AsnAuthorizer.ACTION_CREATE)) {
      isWrite = true;
      principals = policy.getCreatePrincipals();
    } else if (action.equals(AsnAuthorizer.ACTION_DELETE)) {
      isWrite = true;
      principals = policy.getDeletePrincipals();
      if (assertion == null) return false;
    } else if (action.equals(AsnAuthorizer.ACTION_DISABLE)) {
      isWrite = true;
      principals = policy.getEnableDisablePrincipals();
      if (assertion == null) return false;
      if (!assertion.getSystemPart().getEnabled()) return false;
    } else if (action.equals(AsnAuthorizer.ACTION_ENABLE)) {
      isWrite = true;
      principals = policy.getEnableDisablePrincipals();
      if (assertion.getSystemPart().getEnabled()) return false;
      if (assertion == null) return false;
    } else if (action.equals(AsnAuthorizer.ACTION_QUERY)) {
      principals = policy.getQueryPrincipals();
    } else if (action.equals(AsnAuthorizer.ACTION_UPDATE)) {
      isWrite = true;
      principals = policy.getQueryPrincipals();
      if (assertion == null) return false;
      if (!assertion.getSystemPart().getEnabled()) return false;
    }
    if ((policy == null) || (principals == null)) {
      return false;
    }

    // hard check to ensure an authenticated user for any modifications
    // (regardless of configuration)
    if (isWrite && !userWasAuthenticated) {
      return false;
    }

    // check "any user" user privilege
    if (principals.contains(AsnConstants.PRINCIPAL_ANY)) {
      return true;
    }

    // check administrator privilege
    if (userWasAuthenticated) {
      if (principals.contains(AsnConstants.PRINCIPAL_ADMINISTRATOR)) {
        RoleSet roles = user.getAuthenticationStatus().getAuthenticatedRoles();
        if (roles.hasRole("gptAdministrator")) {
          return true;
        }
      }
    }

    // check for ownership
    if (userWasAuthenticated && (assertion != null) && assertion.getWasReadFromIndex()) {
      if (principals.contains(AsnConstants.PRINCIPAL_OWNER)) {
        String asnUserKey = Val.chkStr(assertion.getUserPart().getKey());
        String userKey = Val.chkStr(user.getKey());
        if ((asnUserKey.length() > 0) && asnUserKey.equals(userKey)) {
          return true;
        }
      }
    }

    return false;
  }