/** * {@inheritDoc} * * <p>Processes page caching. */ @Override protected void afterRender(final HTTPRequestContext context) throws Exception { final HttpServletRequest request = context.getRequest(); final String pageContent = (String) request.getAttribute(PageCaches.CACHED_CONTENT); if (null == pageContent) { return; } if (Latkes.isPageCacheEnabled()) { final String cachedPageKey = (String) request.getAttribute(Keys.PAGE_CACHE_KEY); if (Strings.isEmptyOrNull(cachedPageKey)) { return; } LOGGER.log(Level.FINEST, "Caching page[cachedPageKey={0}]", cachedPageKey); check(request, pageContent); final JSONObject cachedValue = new JSONObject(); cachedValue.put(PageCaches.CACHED_CONTENT, pageContent); cachedValue.put(PageCaches.CACHED_TYPE, request.getAttribute(PageCaches.CACHED_TYPE)); cachedValue.put(PageCaches.CACHED_OID, request.getAttribute(PageCaches.CACHED_OID)); cachedValue.put(PageCaches.CACHED_TITLE, request.getAttribute(PageCaches.CACHED_TITLE)); cachedValue.put(PageCaches.CACHED_LINK, request.getAttribute(PageCaches.CACHED_LINK)); if (null != request.getAttribute(PageCaches.CACHED_PWD)) { cachedValue.put(PageCaches.CACHED_PWD, request.getAttribute(PageCaches.CACHED_PWD)); } PageCaches.put(cachedPageKey, cachedValue, request); LOGGER.log(Level.FINEST, "Cached page[cachedPageKey={0}]", cachedPageKey); } }
/** * Resets forgotten password. * * <p>Renders the response with a json object, for example, * * <pre> * { * "isLoggedIn": boolean, * "msg": "" // optional, exists if isLoggedIn equals to false * } * </pre> * * @param context the specified context */ @RequestProcessing(value = "/reset", method = HTTPRequestMethod.POST) public void reset(final HTTPRequestContext context) { final HttpServletRequest request = context.getRequest(); final JSONRenderer renderer = new JSONRenderer(); context.setRenderer(renderer); final JSONObject jsonObject = new JSONObject(); renderer.setJSONObject(jsonObject); try { final JSONObject requestJSONObject; requestJSONObject = Requests.parseRequestJSONObject(request, context.getResponse()); final String userEmail = requestJSONObject.getString(User.USER_EMAIL); final String newPwd = requestJSONObject.getString("newPwd"); final JSONObject user = userQueryService.getUserByEmail(userEmail); user.put(User.USER_PASSWORD, newPwd); userMgmtService.updateUser(user); LOGGER.log(Level.DEBUG, "[{0}]'s password updated successfully.", new Object[] {userEmail}); jsonObject.put("succeed", true); jsonObject.put("to", Latkes.getServePath() + "/login?from=reset"); jsonObject.put(Keys.MSG, langPropsService.get("resetPwdSuccessMsg")); } catch (final Exception e) { LOGGER.log(Level.ERROR, e.getMessage(), e); } }
/** * Logins. * * <p>Renders the response with a json object, for example, * * <pre> * { * "isLoggedIn": boolean, * "msg": "" // optional, exists if isLoggedIn equals to false * } * </pre> * * @param context the specified context */ @RequestProcessing(value = "/login", method = HTTPRequestMethod.POST) public void login(final HTTPRequestContext context) { final HttpServletRequest request = context.getRequest(); final JSONRenderer renderer = new JSONRenderer(); context.setRenderer(renderer); final JSONObject jsonObject = new JSONObject(); renderer.setJSONObject(jsonObject); try { jsonObject.put(Common.IS_LOGGED_IN, false); final String loginFailLabel = langPropsService.get("loginFailLabel"); jsonObject.put(Keys.MSG, loginFailLabel); final JSONObject requestJSONObject = Requests.parseRequestJSONObject(request, context.getResponse()); final String userEmail = requestJSONObject.getString(User.USER_EMAIL); final String userPwd = requestJSONObject.getString(User.USER_PASSWORD); if (Strings.isEmptyOrNull(userEmail) || Strings.isEmptyOrNull(userPwd)) { return; } LOGGER.log(Level.INFO, "Login[email={0}]", userEmail); final JSONObject user = userQueryService.getUserByEmail(userEmail); if (null == user) { LOGGER.log(Level.WARN, "Not found user[email={0}]", userEmail); return; } if (MD5.hash(userPwd).equals(user.getString(User.USER_PASSWORD))) { Sessions.login(request, context.getResponse(), user); LOGGER.log(Level.INFO, "Logged in[email={0}]", userEmail); jsonObject.put(Common.IS_LOGGED_IN, true); if (Role.VISITOR_ROLE.equals(user.optString(User.USER_ROLE))) { jsonObject.put("to", Latkes.getServePath()); } else { jsonObject.put("to", Latkes.getServePath() + Common.ADMIN_INDEX_URI); } jsonObject.remove(Keys.MSG); return; } LOGGER.log(Level.WARN, "Wrong password[{0}]", userPwd); } catch (final Exception e) { LOGGER.log(Level.ERROR, e.getMessage(), e); } }
@Override public void doAdvice(final HTTPRequestContext context, final Object ret) { final AbstractHTTPResponseRenderer renderer = context.getRenderer(); if (null != renderer) { final Map<String, Object> dataModel = renderer.getRenderDataModel(); dataModel.put(Common.CSRF_TOKEN, Sessions.getCSRFToken(context.getRequest())); } }
@Override public void handle(final HTTPRequestContext context, final HttpControl httpControl) throws Exception { final HttpServletRequest request = context.getRequest(); final long startTimeMillis = System.currentTimeMillis(); request.setAttribute(Keys.HttpRequest.START_TIME_MILLIS, startTimeMillis); httpControl.nextHandler(); }
/** * Shows forgotten password page. * * @param context the specified context * @throws Exception exception */ @RequestProcessing(value = "/forgot", method = HTTPRequestMethod.GET) public void showForgot(final HTTPRequestContext context) throws Exception { final HttpServletRequest request = context.getRequest(); String destinationURL = request.getParameter(Common.GOTO); if (Strings.isEmptyOrNull(destinationURL)) { destinationURL = Latkes.getServePath() + Common.ADMIN_INDEX_URI; } renderPage(context, "reset-pwd.ftl", destinationURL, request); }
/** * Logout. * * @param context the specified context * @throws IOException io exception */ @RequestProcessing(value = "/logout", method = HTTPRequestMethod.GET) public void logout(final HTTPRequestContext context) throws IOException { final HttpServletRequest httpServletRequest = context.getRequest(); Sessions.logout(httpServletRequest, context.getResponse()); String destinationURL = httpServletRequest.getParameter(Common.GOTO); if (Strings.isEmptyOrNull(destinationURL)) { destinationURL = "/"; } context.getResponse().sendRedirect(destinationURL); }
/** * Resets forgotten password. * * <p>Renders the response with a json object, for example, * * <pre> * { * "isLoggedIn": boolean, * "msg": "" // optional, exists if isLoggedIn equals to false * } * </pre> * * @param context the specified context */ @RequestProcessing(value = "/forgot", method = HTTPRequestMethod.POST) public void forgot(final HTTPRequestContext context) { final HttpServletRequest request = context.getRequest(); final JSONRenderer renderer = new JSONRenderer(); context.setRenderer(renderer); final JSONObject jsonObject = new JSONObject(); renderer.setJSONObject(jsonObject); try { jsonObject.put("succeed", false); jsonObject.put(Keys.MSG, langPropsService.get("resetPwdSuccessMsg")); final JSONObject requestJSONObject = Requests.parseRequestJSONObject(request, context.getResponse()); final String userEmail = requestJSONObject.getString(User.USER_EMAIL); if (Strings.isEmptyOrNull(userEmail)) { LOGGER.log(Level.WARN, "Why user's email is empty"); return; } LOGGER.log(Level.INFO, "Login[email={0}]", userEmail); final JSONObject user = userQueryService.getUserByEmail(userEmail); if (null == user) { LOGGER.log(Level.WARN, "Not found user[email={0}]", userEmail); jsonObject.put(Keys.MSG, langPropsService.get("userEmailNotFoundMsg")); return; } sendResetUrl(userEmail, jsonObject); } catch (final Exception e) { LOGGER.log(Level.ERROR, e.getMessage(), e); } }
/** * Shows login page. * * @param context the specified context * @throws Exception exception */ @RequestProcessing(value = "/login", method = HTTPRequestMethod.GET) public void showLogin(final HTTPRequestContext context) throws Exception { final HttpServletRequest request = context.getRequest(); String destinationURL = request.getParameter(Common.GOTO); if (Strings.isEmptyOrNull(destinationURL)) { destinationURL = Latkes.getServePath() + Common.ADMIN_INDEX_URI; } final HttpServletResponse response = context.getResponse(); userMgmtService.tryLogInWithCookie(request, response); if (null != userService.getCurrentUser(request)) { // User has already logged in response.sendRedirect(destinationURL); return; } renderPage(context, "login.ftl", destinationURL, request); }
@Override public void doAdvice(final HTTPRequestContext context, final Map<String, Object> args) throws RequestProcessAdviceException { final HttpServletRequest request = context.getRequest(); JSONObject requestJSONObject; try { requestJSONObject = Requests.parseRequestJSONObject(request, context.getResponse()); request.setAttribute(Keys.REQUEST, requestJSONObject); } catch (final Exception e) { throw new RequestProcessAdviceException(new JSONObject().put(Keys.MSG, e.getMessage())); } final String userURL = requestJSONObject.optString(User.USER_URL); if (!Strings.isEmptyOrNull(userURL) && invalidUserURL(userURL)) { throw new RequestProcessAdviceException( new JSONObject() .put( Keys.MSG, "URL" + langPropsService.get("colonLabel") + langPropsService.get("invalidUserURLLabel"))); } final String userQQ = requestJSONObject.optString(UserExt.USER_QQ); if (!Strings.isEmptyOrNull(userQQ) && (!Strings.isNumeric(userQQ) || userQQ.length() > MAX_USER_QQ_LENGTH)) { throw new RequestProcessAdviceException( new JSONObject().put(Keys.MSG, langPropsService.get("invalidUserQQLabel"))); } final String userIntro = requestJSONObject.optString(UserExt.USER_INTRO); if (!Strings.isEmptyOrNull(userIntro) && userIntro.length() > MAX_USER_INTRO_LENGTH) { throw new RequestProcessAdviceException( new JSONObject().put(Keys.MSG, langPropsService.get("invalidUserIntroLabel"))); } final String tagErrMsg = langPropsService.get("selfTagLabel") + langPropsService.get("colonLabel") + langPropsService.get("tagsErrorLabel"); String userTags = requestJSONObject.optString(UserExt.USER_TAGS); if (Strings.isEmptyOrNull(userTags)) { throw new RequestProcessAdviceException(new JSONObject().put(Keys.MSG, tagErrMsg)); } final LatkeBeanManager beanManager = Lifecycle.getBeanManager(); final UserMgmtService userMgmtService = beanManager.getReference(UserMgmtService.class); userTags = userMgmtService.formatUserTags(userTags); String[] tagTitles = userTags.split(","); if (null == tagTitles || 0 == tagTitles.length) { throw new RequestProcessAdviceException(new JSONObject().put(Keys.MSG, tagErrMsg)); } tagTitles = new LinkedHashSet<String>(Arrays.asList(tagTitles)).toArray(new String[0]); final StringBuilder tagBuilder = new StringBuilder(); for (int i = 0; i < tagTitles.length; i++) { final String tagTitle = tagTitles[i].trim(); if (Strings.isEmptyOrNull(tagTitle)) { throw new RequestProcessAdviceException(new JSONObject().put(Keys.MSG, tagErrMsg)); } if (!Tag.TAG_TITLE_PATTERN.matcher(tagTitle).matches()) { throw new RequestProcessAdviceException(new JSONObject().put(Keys.MSG, tagErrMsg)); } if (Strings.isEmptyOrNull(tagTitle) || tagTitle.length() > Tag.MAX_TAG_TITLE_LENGTH || tagTitle.length() < 1) { throw new RequestProcessAdviceException(new JSONObject().put(Keys.MSG, tagErrMsg)); } final JSONObject currentUser = (JSONObject) request.getAttribute(User.USER); if (!Role.ADMIN_ROLE.equals(currentUser.optString(User.USER_ROLE)) && ArrayUtils.contains(Symphonys.RESERVED_TAGS, tagTitle)) { throw new RequestProcessAdviceException( new JSONObject() .put( Keys.MSG, langPropsService.get("selfTagLabel") + langPropsService.get("colonLabel") + langPropsService.get("articleTagReservedLabel") + " [" + tagTitle + "]")); } tagBuilder.append(tagTitle).append(","); } if (tagBuilder.length() > 0) { tagBuilder.deleteCharAt(tagBuilder.length() - 1); } requestJSONObject.put(UserExt.USER_TAGS, tagBuilder.toString()); }
@Override public void doAdvice(final HTTPRequestContext context, final Map<String, Object> args) throws RequestProcessAdviceException { final String requestURI = context.getRequest().getRequestURI(); Stopwatchs.start("Request URI [" + requestURI + ']'); }
/** * Shows articles related with a tag with the specified context. * * @param context the specified context * @throws IOException io exception */ @RequestProcessing(value = "/tags/**", method = HTTPRequestMethod.GET) public void showTagArticles(final HTTPRequestContext context) throws IOException { final AbstractFreeMarkerRenderer renderer = new FreeMarkerRenderer(); context.setRenderer(renderer); renderer.setTemplateName("tag-articles.ftl"); final Map<String, Object> dataModel = renderer.getDataModel(); final HttpServletRequest request = context.getRequest(); final HttpServletResponse response = context.getResponse(); try { String requestURI = request.getRequestURI(); if (!requestURI.endsWith("/")) { requestURI += "/"; } String tagTitle = getTagTitle(requestURI); final int currentPageNum = getCurrentPageNum(requestURI, tagTitle); if (-1 == currentPageNum) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } LOGGER.log( Level.DEBUG, "Tag[title={0}, currentPageNum={1}]", new Object[] {tagTitle, currentPageNum}); tagTitle = URLDecoder.decode(tagTitle, "UTF-8"); final JSONObject result = tagQueryService.getTagByTitle(tagTitle); if (null == result) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } final JSONObject tag = result.getJSONObject(Tag.TAG); final String tagId = tag.getString(Keys.OBJECT_ID); final JSONObject preference = preferenceQueryService.getPreference(); Skins.fillLangs( preference.optString(Option.ID_C_LOCALE_STRING), (String) request.getAttribute(Keys.TEMAPLTE_DIR_NAME), dataModel); final int pageSize = preference.getInt(Option.ID_C_ARTICLE_LIST_DISPLAY_COUNT); final int windowSize = preference.getInt(Option.ID_C_ARTICLE_LIST_PAGINATION_WINDOW_SIZE); final List<JSONObject> articles = articleQueryService.getArticlesByTag(tagId, currentPageNum, pageSize); if (articles.isEmpty()) { try { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } catch (final IOException ex) { LOGGER.error(ex.getMessage()); } } final boolean hasMultipleUsers = userQueryService.hasMultipleUsers(); if (hasMultipleUsers) { filler.setArticlesExProperties(request, articles, preference); } else { // All articles composed by the same author final JSONObject author = articleQueryService.getAuthor(articles.get(0)); filler.setArticlesExProperties(request, articles, author, preference); } final int tagArticleCount = tag.getInt(Tag.TAG_PUBLISHED_REFERENCE_COUNT); final int pageCount = (int) Math.ceil((double) tagArticleCount / (double) pageSize); LOGGER.log( Level.TRACE, "Paginate tag-articles[currentPageNum={0}, pageSize={1}, pageCount={2}, windowSize={3}]", new Object[] {currentPageNum, pageSize, pageCount, windowSize}); final List<Integer> pageNums = Paginator.paginate(currentPageNum, pageSize, pageCount, windowSize); LOGGER.log(Level.TRACE, "tag-articles[pageNums={0}]", pageNums); Collections.sort(articles, Comparators.ARTICLE_CREATE_DATE_COMPARATOR); fillPagination(dataModel, pageCount, currentPageNum, articles, pageNums); dataModel.put(Common.PATH, "/tags/" + URLEncoder.encode(tagTitle, "UTF-8")); dataModel.put(Keys.OBJECT_ID, tagId); dataModel.put(Tag.TAG, tag); filler.fillSide(request, dataModel, preference); filler.fillBlogHeader(request, response, dataModel, preference); filler.fillBlogFooter(request, dataModel, preference); statisticMgmtService.incBlogViewCount(request, response); } catch (final ServiceException e) { LOGGER.log(Level.ERROR, e.getMessage(), e); try { response.sendError(HttpServletResponse.SC_NOT_FOUND); } catch (final IOException ex) { LOGGER.error(ex.getMessage()); } } catch (final JSONException e) { LOGGER.log(Level.ERROR, e.getMessage(), e); try { response.sendError(HttpServletResponse.SC_NOT_FOUND); } catch (final IOException ex) { LOGGER.error(ex.getMessage()); } } }