/**
   * 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;
  }