@Override
  public ActionResult doExecute(
      HttpServletRequest req,
      RenderContext renderContext,
      Resource resource,
      JCRSessionWrapper session,
      Map<String, List<String>> parameters,
      URLResolver urlResolver)
      throws Exception {
    String authKey = getParameter(parameters, "authKey");
    RecoverPassword.PasswordToken passwordRecoveryToken =
        (RecoverPassword.PasswordToken) req.getSession().getAttribute("passwordRecoveryToken");
    if (StringUtils.isEmpty(authKey)
        || passwordRecoveryToken == null
        || !passwordRecoveryToken.getAuthkey().equals(authKey)
        || !passwordRecoveryToken.getUserpath().equals(resource.getNode().getPath())) {
      return ActionResult.BAD_REQUEST;
    }
    HttpSession httpSession = req.getSession();
    httpSession.removeAttribute("passwordRecoveryToken");
    httpSession.removeAttribute("passwordRecoveryAsked");

    String passwd = req.getParameter("password").trim();
    JSONObject json = new JSONObject();

    if (!resource.getNode().hasPermission("jcr:write_default")
        || !resource.getNode().isNodeType("jnt:user")) {
      return new ActionResult(HttpServletResponse.SC_FORBIDDEN, null, null);
    }

    if ("".equals(passwd)) {
      String userMessage =
          JahiaResourceBundle.getJahiaInternalResource(
              "org.jahia.admin.userMessage.specifyPassword.label", renderContext.getUILocale());
      json.put("errorMessage", userMessage);
    } else {
      String passwdConfirm = req.getParameter("passwordconfirm").trim();
      if (!passwdConfirm.equals(passwd)) {
        String userMessage =
            JahiaResourceBundle.getJahiaInternalResource(
                "org.jahia.admin.userMessage.passwdNotMatch.label", renderContext.getUILocale());
        json.put("errorMessage", userMessage);
      } else {
        JahiaPasswordPolicyService pwdPolicyService =
            ServicesRegistry.getInstance().getJahiaPasswordPolicyService();
        JahiaUser user =
            ServicesRegistry.getInstance()
                .getJahiaUserManagerService()
                .lookupUser(resource.getNode().getName());

        PolicyEnforcementResult evalResult =
            pwdPolicyService.enforcePolicyOnPasswordChange(user, passwd, true);
        if (!evalResult.isSuccess()) {
          EngineMessages policyMsgs = evalResult.getEngineMessages();
          String res = "";
          for (EngineMessage message : policyMsgs.getMessages()) {
            res +=
                (message.isResource()
                        ? MessageFormat.format(
                            JahiaResourceBundle.getJahiaInternalResource(
                                message.getKey(), renderContext.getUILocale()),
                            message.getValues())
                        : message.getKey())
                    + "\n";
          }
          json.put("errorMessage", res);
        } else {
          // change password
          user.setPassword(passwd);
          json.put(
              "errorMessage",
              JahiaResourceBundle.getJahiaInternalResource(
                  "org.jahia.admin.userMessage.passwordChanged.label",
                  renderContext.getUILocale()));

          httpSession.setAttribute(ProcessingContext.SESSION_USER, user);

          json.put("result", "success");
        }
      }
    }

    return new ActionResult(HttpServletResponse.SC_OK, null, json);
  }
  @Override
  public String prepare(RenderContext renderContext, Resource resource, RenderChain chain)
      throws Exception {

    if (renderContext.getRequest().getAttribute("portalContext") != null) {
      // Portal already init
      return null;
    }

    JCRNodeWrapper portalTabNode =
        renderContext.getMainResource().getNode().isNodeType(PortalConstants.JNT_PORTAL_TAB)
            ? renderContext.getMainResource().getNode()
            : JCRContentUtils.getParentOfType(
                renderContext.getMainResource().getNode(), PortalConstants.JNT_PORTAL_TAB);

    if (portalTabNode != null) {
      JCRNodeWrapper portalNode =
          JCRContentUtils.getParentOfType(portalTabNode, PortalConstants.JMIX_PORTAL);
      boolean updateLastViewed = resource.getNode().isNodeType(PortalConstants.JNT_PORTAL_TAB);
      PortalContext portalContext =
          portalService.buildPortalContext(
              renderContext, portalTabNode, resource.getNode().getSession(), updateLastViewed);

      // set tabs
      portalContext.setPortalTabs(new LinkedList<PortalTab>());
      QueryManager queryManager = resource.getNode().getSession().getWorkspace().getQueryManager();
      if (queryManager != null) {
        NodeIterator result = portalNode.getNodes();

        while (result.hasNext()) {
          JCRNodeWrapper tabNode = (JCRNodeWrapper) result.next();
          if (tabNode.isNodeType(PortalConstants.JNT_PORTAL_TAB)) {
            PortalTab portalTab = new PortalTab();
            portalTab.setPath(tabNode.getPath());
            portalTab.setDisplayableName(tabNode.getDisplayableName());
            portalTab.setUrl(portalContext.getBaseUrl() + tabNode.getPath() + ".html");
            portalTab.setCurrent(tabNode.getIdentifier().equals(portalTabNode.getIdentifier()));
            portalTab.setTemplateKey(
                tabNode.getProperty(PortalConstants.J_TEMPLATE_NAME).getString());
            portalTab.setSkinKey(tabNode.getProperty(PortalConstants.J_WIDGET_SKIN).getString());
            portalTab.setAccessibility(
                tabNode.hasProperty(PortalConstants.J_ACCESSIBILITY)
                    ? tabNode.getProperty(PortalConstants.J_ACCESSIBILITY).getString()
                    : "me");
            portalContext.getPortalTabs().add(portalTab);
            resource.getDependencies().add(portalTab.getPath());
          }
        }
      }

      // Add dependency to model portal
      if (!portalContext.isModel()) {
        resource.getDependencies().add(portalContext.getModelPath());
      }
      // Add dependency to parent portal
      resource.getDependencies().add(portalContext.getPath());

      // Add portal bean in request attributes, so it's can be used in jsp
      renderContext.getRequest().setAttribute("portalContext", portalContext);
    }
    return null;
  }