/**
   * Find the page with the lowest position value which is visible in the current securit context
   *
   * @param securityContext
   * @return
   * @throws FrameworkException
   */
  private Page findIndexPage(final SecurityContext securityContext) throws FrameworkException {

    Result<Page> results =
        StructrApp.getInstance(securityContext)
            .nodeQuery(Page.class)
            .sort(Page.position)
            .order(false)
            .getResult();
    Collections.sort(
        results.getResults(),
        new GraphObjectComparator(Page.position, GraphObjectComparator.ASCENDING));

    // Find first visible page
    Page page = null;

    if (!results.isEmpty()) {

      int i = 0;

      while (page == null || (i < results.size() && !securityContext.isVisible(page))) {

        page = results.get(i++);
      }
    }

    return page;
  }
  @Override
  public boolean isValid(
      GraphObject object, PropertyKey<String> key, String value, ErrorBuffer errorBuffer) {

    if (key == null) {
      return false;
    }

    if (StringUtils.isBlank(value)) {
      errorBuffer.add(object.getType(), new EmptyPropertyToken(key));
      return false;
    }

    // FIXME: search should be case-sensitive!

    List<SearchAttribute> attrs = new LinkedList<SearchAttribute>();
    attrs.add(Search.andExactName(value));
    attrs.add(Search.andType(type));

    // just check for existance
    try {
      Result nodes = Services.command(securityContext, SearchNodeCommand.class).execute(attrs);
      if (nodes != null && !nodes.isEmpty()) {

        return true;

      } else {

        errorBuffer.add(object.getType(), new PropertyNotFoundToken(key, value));
        return false;
      }

    } catch (FrameworkException fex) {
      // handle error
    }

    return false;
  }
  /**
   * This method checks if the current request is a user registration confirmation, usually
   * triggered by a user clicking on a confirmation link in an e-mail.
   *
   * @param request
   * @param response
   * @param path
   * @return true if the registration was successful
   * @throws FrameworkException
   * @throws IOException
   */
  private boolean checkRegistration(
      final Authenticator auth,
      final HttpServletRequest request,
      final HttpServletResponse response,
      final String path)
      throws FrameworkException, IOException {

    logger.log(Level.FINE, "Checking registration ...");

    String key = request.getParameter(CONFIRM_KEY_KEY);

    if (StringUtils.isEmpty(key)) {
      return false;
    }

    String targetPage = request.getParameter(TARGET_PAGE_KEY);
    String errorPage = request.getParameter(ERROR_PAGE_KEY);

    if (CONFIRM_REGISTRATION_PAGE.equals(path)) {

      final App app = StructrApp.getInstance();

      Result<Principal> results;
      try (final Tx tx = app.tx()) {

        results = app.nodeQuery(Principal.class).and(User.confirmationKey, key).getResult();
      }

      if (!results.isEmpty()) {

        final Principal user = results.get(0);

        try (final Tx tx = app.tx()) {

          // Clear confirmation key and set session id
          user.setProperty(User.confirmationKey, null);

          if (auth.getUserAutoLogin()) {

            AuthHelper.doLogin(request, user);
          }

          tx.success();
        }

        // Redirect to target page
        if (StringUtils.isNotBlank(targetPage)) {
          response.sendRedirect("/" + targetPage);
        }

        return true;

      } else {
        // Redirect to error page
        if (StringUtils.isNotBlank(errorPage)) {
          response.sendRedirect("/" + errorPage);
        }

        return true;
      }
    }

    return false;
  }