/*
* Symphony - A modern community (forum/SNS/blog) platform written in Java.
* Copyright (C) 2012-2017, b3log.org & hacpai.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.b3log.symphony.processor;
import com.qiniu.util.Auth;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.b3log.latke.Keys;
import org.b3log.latke.Latkes;
import org.b3log.latke.ioc.inject.Inject;
import org.b3log.latke.logging.Level;
import org.b3log.latke.logging.Logger;
import org.b3log.latke.model.User;
import org.b3log.latke.service.LangPropsService;
import org.b3log.latke.service.ServiceException;
import org.b3log.latke.servlet.HTTPRequestContext;
import org.b3log.latke.servlet.HTTPRequestMethod;
import org.b3log.latke.servlet.annotation.After;
import org.b3log.latke.servlet.annotation.Before;
import org.b3log.latke.servlet.annotation.RequestProcessing;
import org.b3log.latke.servlet.annotation.RequestProcessor;
import org.b3log.latke.servlet.renderer.freemarker.AbstractFreeMarkerRenderer;
import org.b3log.latke.util.Locales;
import org.b3log.latke.util.Requests;
import org.b3log.latke.util.Strings;
import org.b3log.symphony.model.*;
import org.b3log.symphony.processor.advice.CSRFToken;
import org.b3log.symphony.processor.advice.LoginCheck;
import org.b3log.symphony.processor.advice.PermissionGrant;
import org.b3log.symphony.processor.advice.stopwatch.StopwatchEndAdvice;
import org.b3log.symphony.processor.advice.stopwatch.StopwatchStartAdvice;
import org.b3log.symphony.processor.advice.validate.UserForgetPwdValidation;
import org.b3log.symphony.processor.advice.validate.UserRegister2Validation;
import org.b3log.symphony.processor.advice.validate.UserRegisterValidation;
import org.b3log.symphony.service.*;
import org.b3log.symphony.util.Sessions;
import org.b3log.symphony.util.Symphonys;
import org.json.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Login/Register processor.
* <p>
* For user
* <ul>
* <li>Registration (/register), GET/POST</li>
* <li>Login (/login), GET/POST</li>
* <li>Logout (/logout), GET</li>
* <li>Reset password (/reset-pwd), GET/POST</li>
* </ul>
* </p>
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @author <a href="http://vanessa.b3log.org">LiYuan Li</a>
* @version 1.13.9.20, Jan 12, 2017
* @since 0.2.0
*/
@RequestProcessor
public class LoginProcessor {
/**
* Wrong password tries.
* <p>
* <userId, {"wrongCount": int, "captcha": ""}>
* </p>
*/
public static final Map<String, JSONObject> WRONG_PWD_TRIES = new ConcurrentHashMap<>();
/**
* Logger.
*/
private static final Logger LOGGER = Logger.getLogger(LoginProcessor.class.getName());
/**
* User management service.
*/
@Inject
private UserMgmtService userMgmtService;
/**
* User query service.
*/
@Inject
private UserQueryService userQueryService;
/**
* Language service.
*/
@Inject
private LangPropsService langPropsService;
/**
* Pointtransfer management service.
*/
@Inject
private PointtransferMgmtService pointtransferMgmtService;
/**
* Data model service.
*/
@Inject
private DataModelService dataModelService;
/**
* Verifycode management service.
*/
@Inject
private VerifycodeMgmtService verifycodeMgmtService;
/**
* Verifycode query service.
*/
@Inject
private VerifycodeQueryService verifycodeQueryService;
/**
* Timeline management service.
*/
@Inject
private TimelineMgmtService timelineMgmtService;
/**
* Option query service.
*/
@Inject
private OptionQueryService optionQueryService;
/**
* Invitecode query service.
*/
@Inject
private InvitecodeQueryService invitecodeQueryService;
/**
* Invitecode management service.
*/
@Inject
private InvitecodeMgmtService invitecodeMgmtService;
/**
* Invitecode management service.
*/
@Inject
private NotificationMgmtService notificationMgmtService;
/**
* Role query service.
*/
@Inject
private RoleQueryService roleQueryService;
/**
* Tag query service.
*/
@Inject
private TagQueryService tagQueryService;
/**
* Next guide step.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
*/
@RequestProcessing(value = "/guide/next", method = HTTPRequestMethod.POST)
@Before(adviceClass = {LoginCheck.class})
public void nextGuideStep(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response) {
context.renderJSON();
JSONObject requestJSONObject;
try {
requestJSONObject = Requests.parseRequestJSONObject(request, response);
} catch (final Exception e) {
LOGGER.warn(e.getMessage());
return;
}
JSONObject user = (JSONObject) request.getAttribute(User.USER);
final String userId = user.optString(Keys.OBJECT_ID);
int step = requestJSONObject.optInt(UserExt.USER_GUIDE_STEP);
if (UserExt.USER_GUIDE_STEP_STAR_PROJECT < step || UserExt.USER_GUIDE_STEP_FIN >= step) {
step = UserExt.USER_GUIDE_STEP_FIN;
}
try {
user = userQueryService.getUser(userId);
user.put(UserExt.USER_GUIDE_STEP, step);
userMgmtService.updateUser(userId, user);
} catch (final Exception e) {
LOGGER.log(Level.ERROR, "Guide next step [" + step + "] failed", e);
return;
}
context.renderJSON(true);
}
/**
* Shows login page.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws Exception exception
*/
@RequestProcessing(value = "/guide", method = HTTPRequestMethod.GET)
@Before(adviceClass = {StopwatchStartAdvice.class, LoginCheck.class})
@After(adviceClass = {CSRFToken.class, PermissionGrant.class, StopwatchEndAdvice.class})
public void showGuide(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws Exception {
final JSONObject currentUser = (JSONObject) request.getAttribute(User.USER);
final int step = currentUser.optInt(UserExt.USER_GUIDE_STEP);
if (UserExt.USER_GUIDE_STEP_FIN == step) {
response.sendRedirect(Latkes.getServePath());
return;
}
final AbstractFreeMarkerRenderer renderer = new SkinRenderer(request);
context.setRenderer(renderer);
renderer.setTemplateName("/verify/guide.ftl");
final Map<String, Object> dataModel = renderer.getDataModel();
dataModel.put(Common.CURRENT_USER, currentUser);
final List<JSONObject> tags = tagQueryService.getTags(32);
dataModel.put(Tag.TAGS, tags);
final List<JSONObject> users = userQueryService.getNiceUsers(6);
final Iterator<JSONObject> iterator = users.iterator();
while (iterator.hasNext()) {
final JSONObject user = iterator.next();
if (user.optString(Keys.OBJECT_ID).equals(currentUser.optString(Keys.OBJECT_ID))) {
iterator.remove();
break;
}
}
dataModel.put(User.USERS, users);
// Qiniu file upload authenticate
final Auth auth = Auth.create(Symphonys.get("qiniu.accessKey"), Symphonys.get("qiniu.secretKey"));
final String uploadToken = auth.uploadToken(Symphonys.get("qiniu.bucket"));
dataModel.put("qiniuUploadToken", uploadToken);
dataModel.put("qiniuDomain", Symphonys.get("qiniu.domain"));
if (!Symphonys.getBoolean("qiniu.enabled")) {
dataModel.put("qiniuUploadToken", "");
}
final long imgMaxSize = Symphonys.getLong("upload.img.maxSize");
dataModel.put("imgMaxSize", imgMaxSize);
final long fileMaxSize = Symphonys.getLong("upload.file.maxSize");
dataModel.put("fileMaxSize", fileMaxSize);
dataModelService.fillHeaderAndFooter(request, response, dataModel);
}
/**
* Shows login page.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws Exception exception
*/
@RequestProcessing(value = "/login", method = HTTPRequestMethod.GET)
@Before(adviceClass = StopwatchStartAdvice.class)
@After(adviceClass = {PermissionGrant.class, StopwatchEndAdvice.class})
public void showLogin(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws Exception {
if (null != userQueryService.getCurrentUser(request)
|| userMgmtService.tryLogInWithCookie(request, response)) {
response.sendRedirect(Latkes.getServePath());
return;
}
final AbstractFreeMarkerRenderer renderer = new SkinRenderer(request);
context.setRenderer(renderer);
String referer = request.getParameter(Common.GOTO);
if (StringUtils.isBlank(referer)) {
referer = request.getHeader("referer");
}
if (StringUtils.isBlank(referer)) {
referer = Latkes.getServePath();
}
renderer.setTemplateName("/verify/login.ftl");
final Map<String, Object> dataModel = renderer.getDataModel();
dataModel.put(Common.GOTO, referer);
dataModelService.fillHeaderAndFooter(request, response, dataModel);
}
/**
* Shows forget password page.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws Exception exception
*/
@RequestProcessing(value = "/forget-pwd", method = HTTPRequestMethod.GET)
@Before(adviceClass = StopwatchStartAdvice.class)
@After(adviceClass = {PermissionGrant.class, StopwatchEndAdvice.class})
public void showForgetPwd(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws Exception {
final AbstractFreeMarkerRenderer renderer = new SkinRenderer(request);
context.setRenderer(renderer);
final Map<String, Object> dataModel = renderer.getDataModel();
renderer.setTemplateName("verify/forget-pwd.ftl");
dataModelService.fillHeaderAndFooter(request, response, dataModel);
}
/**
* Forget password.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws Exception exception
*/
@RequestProcessing(value = "/forget-pwd", method = HTTPRequestMethod.POST)
@Before(adviceClass = UserForgetPwdValidation.class)
public void forgetPwd(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws Exception {
context.renderJSON();
final JSONObject requestJSONObject = (JSONObject) request.getAttribute(Keys.REQUEST);
final String email = requestJSONObject.optString(User.USER_EMAIL);
try {
final JSONObject user = userQueryService.getUserByEmail(email);
if (null == user) {
context.renderFalseResult().renderMsg(langPropsService.get("notFoundUserLabel"));
return;
}
final String userId = user.optString(Keys.OBJECT_ID);
final JSONObject verifycode = new JSONObject();
verifycode.put(Verifycode.BIZ_TYPE, Verifycode.BIZ_TYPE_C_RESET_PWD);
final String code = RandomStringUtils.randomAlphanumeric(6);
verifycode.put(Verifycode.CODE, code);
verifycode.put(Verifycode.EXPIRED, DateUtils.addDays(new Date(), 1).getTime());
verifycode.put(Verifycode.RECEIVER, email);
verifycode.put(Verifycode.STATUS, Verifycode.STATUS_C_UNSENT);
verifycode.put(Verifycode.TYPE, Verifycode.TYPE_C_EMAIL);
verifycode.put(Verifycode.USER_ID, userId);
verifycodeMgmtService.addVerifycode(verifycode);
context.renderTrueResult().renderMsg(langPropsService.get("verifycodeSentLabel"));
} catch (final ServiceException e) {
final String msg = langPropsService.get("resetPwdLabel") + " - " + e.getMessage();
LOGGER.log(Level.ERROR, msg + "[name={0}, email={1}]", email);
context.renderMsg(msg);
}
}
/**
* Shows reset password page.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws Exception exception
*/
@RequestProcessing(value = "/reset-pwd", method = HTTPRequestMethod.GET)
@Before(adviceClass = StopwatchStartAdvice.class)
@After(adviceClass = {PermissionGrant.class, StopwatchEndAdvice.class})
public void showResetPwd(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws Exception {
final AbstractFreeMarkerRenderer renderer = new SkinRenderer(request);
context.setRenderer(renderer);
final Map<String, Object> dataModel = renderer.getDataModel();
final String code = request.getParameter("code");
final JSONObject verifycode = verifycodeQueryService.getVerifycode(code);
if (null == verifycode) {
dataModel.put(Keys.MSG, langPropsService.get("verifycodeExpiredLabel"));
renderer.setTemplateName("/error/custom.ftl");
} else {
renderer.setTemplateName("verify/reset-pwd.ftl");
final String userId = verifycode.optString(Verifycode.USER_ID);
final JSONObject user = userQueryService.getUser(userId);
dataModel.put(User.USER, user);
}
dataModelService.fillHeaderAndFooter(request, response, dataModel);
}
/**
* Resets password.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws ServletException servlet exception
* @throws IOException io exception
*/
@RequestProcessing(value = "/reset-pwd", method = HTTPRequestMethod.POST)
public void resetPwd(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
context.renderJSON();
final JSONObject requestJSONObject = Requests.parseRequestJSONObject(request, response);
final String password = requestJSONObject.optString(User.USER_PASSWORD); // Hashed
final String userId = requestJSONObject.optString(Common.USER_ID);
String name = null;
String email = null;
try {
final JSONObject user = userQueryService.getUser(userId);
if (null == user) {
context.renderMsg(langPropsService.get("resetPwdLabel") + " - " + "User Not Found");
return;
}
user.put(User.USER_PASSWORD, password);
userMgmtService.updatePassword(user);
context.renderTrueResult();
LOGGER.info("User [email=" + user.optString(User.USER_EMAIL) + "] reseted password");
} catch (final ServiceException e) {
final String msg = langPropsService.get("resetPwdLabel") + " - " + e.getMessage();
LOGGER.log(Level.ERROR, msg + "[name={0}, email={1}]", name, email);
context.renderMsg(msg);
}
}
/**
* Shows registration page.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws Exception exception
*/
@RequestProcessing(value = "/register", method = HTTPRequestMethod.GET)
@Before(adviceClass = StopwatchStartAdvice.class)
@After(adviceClass = {PermissionGrant.class, StopwatchEndAdvice.class})
public void showRegister(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws Exception {
if (null != userQueryService.getCurrentUser(request)
|| userMgmtService.tryLogInWithCookie(request, response)) {
response.sendRedirect(Latkes.getServePath());
return;
}
final AbstractFreeMarkerRenderer renderer = new SkinRenderer(request);
context.setRenderer(renderer);
final Map<String, Object> dataModel = renderer.getDataModel();
dataModel.put(Common.REFERRAL, "");
boolean useInvitationLink = false;
String referral = request.getParameter("r");
if (!UserRegisterValidation.invalidUserName(referral)) {
final JSONObject referralUser = userQueryService.getUserByName(referral);
if (null != referralUser) {
dataModel.put(Common.REFERRAL, referral);
final Map<String, JSONObject> permissions =
roleQueryService.getUserPermissionsGrantMap(referralUser.optString(Keys.OBJECT_ID));
final JSONObject useILPermission =
permissions.get(Permission.PERMISSION_ID_C_COMMON_USE_INVITATION_LINK);
useInvitationLink = useILPermission.optBoolean(Permission.PERMISSION_T_GRANT);
}
}
final String code = request.getParameter("code");
if (Strings.isEmptyOrNull(code)) { // Register Step 1
renderer.setTemplateName("verify/register.ftl");
} else { // Register Step 2
final JSONObject verifycode = verifycodeQueryService.getVerifycode(code);
if (null == verifycode) {
dataModel.put(Keys.MSG, langPropsService.get("verifycodeExpiredLabel"));
renderer.setTemplateName("/error/custom.ftl");
} else {
renderer.setTemplateName("verify/register2.ftl");
final String userId = verifycode.optString(Verifycode.USER_ID);
final JSONObject user = userQueryService.getUser(userId);
dataModel.put(User.USER, user);
if (UserExt.USER_STATUS_C_VALID == user.optInt(UserExt.USER_STATUS)
|| UserExt.NULL_USER_NAME.equals(user.optString(User.USER_NAME))) {
dataModel.put(Keys.MSG, langPropsService.get("userExistLabel"));
renderer.setTemplateName("/error/custom.ftl");
} else {
referral = StringUtils.substringAfter(code, "r=");
if (!Strings.isEmptyOrNull(referral)) {
dataModel.put(Common.REFERRAL, referral);
}
}
}
}
final String allowRegister = optionQueryService.getAllowRegister();
dataModel.put(Option.ID_C_MISC_ALLOW_REGISTER, allowRegister);
if (useInvitationLink && "2".equals(allowRegister)) {
dataModel.put(Option.ID_C_MISC_ALLOW_REGISTER, "1");
}
dataModelService.fillHeaderAndFooter(request, response, dataModel);
}
/**
* Register Step 1.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws ServletException servlet exception
* @throws IOException io exception
*/
@RequestProcessing(value = "/register", method = HTTPRequestMethod.POST)
@Before(adviceClass = UserRegisterValidation.class)
public void register(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
context.renderJSON();
final JSONObject requestJSONObject = (JSONObject) request.getAttribute(Keys.REQUEST);
final String name = requestJSONObject.optString(User.USER_NAME);
final String email = requestJSONObject.optString(User.USER_EMAIL);
final String invitecode = requestJSONObject.optString(Invitecode.INVITECODE);
final String referral = requestJSONObject.optString(Common.REFERRAL);
final JSONObject user = new JSONObject();
user.put(User.USER_NAME, name);
user.put(User.USER_EMAIL, email);
user.put(User.USER_PASSWORD, "");
final Locale locale = Locales.getLocale();
user.put(UserExt.USER_LANGUAGE, locale.getLanguage() + "_" + locale.getCountry());
try {
final String newUserId = userMgmtService.addUser(user);
final JSONObject verifycode = new JSONObject();
verifycode.put(Verifycode.BIZ_TYPE, Verifycode.BIZ_TYPE_C_REGISTER);
String code = RandomStringUtils.randomAlphanumeric(6);
if (!Strings.isEmptyOrNull(referral)) {
code += "r=" + referral;
}
verifycode.put(Verifycode.CODE, code);
verifycode.put(Verifycode.EXPIRED, DateUtils.addDays(new Date(), 1).getTime());
verifycode.put(Verifycode.RECEIVER, email);
verifycode.put(Verifycode.STATUS, Verifycode.STATUS_C_UNSENT);
verifycode.put(Verifycode.TYPE, Verifycode.TYPE_C_EMAIL);
verifycode.put(Verifycode.USER_ID, newUserId);
verifycodeMgmtService.addVerifycode(verifycode);
final String allowRegister = optionQueryService.getAllowRegister();
if ("2".equals(allowRegister) && StringUtils.isNotBlank(invitecode)) {
final JSONObject ic = invitecodeQueryService.getInvitecode(invitecode);
ic.put(Invitecode.USER_ID, newUserId);
ic.put(Invitecode.USE_TIME, System.currentTimeMillis());
final String icId = ic.optString(Keys.OBJECT_ID);
invitecodeMgmtService.updateInvitecode(icId, ic);
}
context.renderTrueResult().renderMsg(langPropsService.get("verifycodeSentLabel"));
} catch (final ServiceException e) {
final String msg = langPropsService.get("registerFailLabel") + " - " + e.getMessage();
LOGGER.log(Level.ERROR, msg + "[name={0}, email={1}]", name, email);
context.renderMsg(msg);
}
}
/**
* Register Step 2.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws ServletException servlet exception
* @throws IOException io exception
*/
@RequestProcessing(value = "/register2", method = HTTPRequestMethod.POST)
@Before(adviceClass = UserRegister2Validation.class)
public void register2(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
context.renderJSON();
final JSONObject requestJSONObject = (JSONObject) request.getAttribute(Keys.REQUEST);
final String password = requestJSONObject.optString(User.USER_PASSWORD); // Hashed
final int appRole = requestJSONObject.optInt(UserExt.USER_APP_ROLE);
final String referral = requestJSONObject.optString(Common.REFERRAL);
final String userId = requestJSONObject.optString(Common.USER_ID);
String name = null;
String email = null;
try {
final JSONObject user = userQueryService.getUser(userId);
if (null == user) {
context.renderMsg(langPropsService.get("registerFailLabel") + " - " + "User Not Found");
return;
}
name = user.optString(User.USER_NAME);
email = user.optString(User.USER_EMAIL);
user.put(UserExt.USER_APP_ROLE, appRole);
user.put(User.USER_PASSWORD, password);
user.put(UserExt.USER_STATUS, UserExt.USER_STATUS_C_VALID);
userMgmtService.addUser(user);
Sessions.login(request, response, user, false);
final String ip = Requests.getRemoteAddr(request);
userMgmtService.updateOnlineStatus(user.optString(Keys.OBJECT_ID), ip, true);
if (!Strings.isEmptyOrNull(referral)) {
final JSONObject referralUser = userQueryService.getUserByName(referral);
if (null != referralUser) {
final String referralId = referralUser.optString(Keys.OBJECT_ID);
// Point
pointtransferMgmtService.transfer(Pointtransfer.ID_C_SYS, userId,
Pointtransfer.TRANSFER_TYPE_C_INVITED_REGISTER,
Pointtransfer.TRANSFER_SUM_C_INVITE_REGISTER, referralId, System.currentTimeMillis());
pointtransferMgmtService.transfer(Pointtransfer.ID_C_SYS, referralId,
Pointtransfer.TRANSFER_TYPE_C_INVITE_REGISTER,
Pointtransfer.TRANSFER_SUM_C_INVITE_REGISTER, userId, System.currentTimeMillis());
final JSONObject notification = new JSONObject();
notification.put(Notification.NOTIFICATION_USER_ID, referralId);
notification.put(Notification.NOTIFICATION_DATA_ID, userId);
notificationMgmtService.addInvitationLinkUsedNotification(notification);
}
}
final JSONObject ic = invitecodeQueryService.getInvitecodeByUserId(userId);
if (null != ic && Invitecode.STATUS_C_UNUSED == ic.optInt(Invitecode.STATUS)) {
ic.put(Invitecode.STATUS, Invitecode.STATUS_C_USED);
ic.put(Invitecode.USER_ID, userId);
ic.put(Invitecode.USE_TIME, System.currentTimeMillis());
final String icId = ic.optString(Keys.OBJECT_ID);
invitecodeMgmtService.updateInvitecode(icId, ic);
final String icGeneratorId = ic.optString(Invitecode.GENERATOR_ID);
if (StringUtils.isNotBlank(icGeneratorId) && !Pointtransfer.ID_C_SYS.equals(icGeneratorId)) {
pointtransferMgmtService.transfer(Pointtransfer.ID_C_SYS, icGeneratorId,
Pointtransfer.TRANSFER_TYPE_C_INVITECODE_USED,
Pointtransfer.TRANSFER_SUM_C_INVITECODE_USED, userId, System.currentTimeMillis());
final JSONObject notification = new JSONObject();
notification.put(Notification.NOTIFICATION_USER_ID, icGeneratorId);
notification.put(Notification.NOTIFICATION_DATA_ID, userId);
notificationMgmtService.addInvitecodeUsedNotification(notification);
}
}
context.renderTrueResult();
LOGGER.log(Level.INFO, "Registered a user [name={0}, email={1}]", name, email);
// Timeline
final JSONObject timeline = new JSONObject();
timeline.put(Common.USER_ID, user.optString(Keys.OBJECT_ID));
timeline.put(Common.TYPE, Common.NEW_USER);
String content = langPropsService.get("timelineNewUserLabel");
content = content.replace("{user}", "<a target='_blank' rel='nofollow' href='" + Latkes.getServePath()
+ "/member/" + name + "'>" + name + "</a>");
timeline.put(Common.CONTENT, content);
timelineMgmtService.addTimeline(timeline);
} catch (final ServiceException e) {
final String msg = langPropsService.get("registerFailLabel") + " - " + e.getMessage();
LOGGER.log(Level.ERROR, msg + "[name={0}, email={1}]", name, email);
context.renderMsg(msg);
}
}
/**
* Logins user.
*
* @param context the specified context
* @param request the specified request
* @param response the specified response
* @throws ServletException servlet exception
* @throws IOException io exception
*/
@RequestProcessing(value = "/login", method = HTTPRequestMethod.POST)
public void login(final HTTPRequestContext context, final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
context.renderJSON().renderMsg(langPropsService.get("loginFailLabel"));
final JSONObject requestJSONObject = Requests.parseRequestJSONObject(request, response);
final String nameOrEmail = requestJSONObject.optString("nameOrEmail");
try {
JSONObject user = userQueryService.getUserByName(nameOrEmail);
if (null == user) {
user = userQueryService.getUserByEmail(nameOrEmail);
}
if (null == user) {
context.renderMsg(langPropsService.get("notFoundUserLabel"));
return;
}
if (UserExt.USER_STATUS_C_INVALID == user.optInt(UserExt.USER_STATUS)) {
userMgmtService.updateOnlineStatus(user.optString(Keys.OBJECT_ID), "", false);
context.renderMsg(langPropsService.get("userBlockLabel"));
return;
}
if (UserExt.USER_STATUS_C_NOT_VERIFIED == user.optInt(UserExt.USER_STATUS)) {
userMgmtService.updateOnlineStatus(user.optString(Keys.OBJECT_ID), "", false);
context.renderMsg(langPropsService.get("notVerifiedLabel"));
return;
}
if (UserExt.USER_STATUS_C_INVALID_LOGIN == user.optInt(UserExt.USER_STATUS)) {
userMgmtService.updateOnlineStatus(user.optString(Keys.OBJECT_ID), "", false);
context.renderMsg(langPropsService.get("invalidLoginLabel"));
return;
}
final String userId = user.optString(Keys.OBJECT_ID);
JSONObject wrong = WRONG_PWD_TRIES.get(userId);
if (null == wrong) {
wrong = new JSONObject();
}
final int wrongCount = wrong.optInt(Common.WRON_COUNT);
if (wrongCount > 3) {
final String captcha = requestJSONObject.optString(CaptchaProcessor.CAPTCHA);
if (!StringUtils.equals(wrong.optString(CaptchaProcessor.CAPTCHA), captcha)) {
context.renderMsg(langPropsService.get("captchaErrorLabel"));
context.renderJSONValue(Common.NEED_CAPTCHA, userId);
return;
}
}
final String userPassword = user.optString(User.USER_PASSWORD);
if (userPassword.equals(requestJSONObject.optString(User.USER_PASSWORD))) {
final String token = Sessions.login(request, response, user, requestJSONObject.optBoolean(Common.REMEMBER_LOGIN));
final String ip = Requests.getRemoteAddr(request);
userMgmtService.updateOnlineStatus(user.optString(Keys.OBJECT_ID), ip, true);
context.renderMsg("").renderTrueResult();
context.renderJSONValue(Common.TOKEN, token);
WRONG_PWD_TRIES.remove(userId);
return;
}
if (wrongCount > 2) {
context.renderJSONValue(Common.NEED_CAPTCHA, userId);
}
wrong.put(Common.WRON_COUNT, wrongCount + 1);
WRONG_PWD_TRIES.put(userId, wrong);
context.renderMsg(langPropsService.get("wrongPwdLabel"));
} catch (final ServiceException e) {
context.renderMsg(langPropsService.get("loginFailLabel"));
}
}
/**
* 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);
}
/**
* Expires invitecodes.
*
* @param request the specified HTTP servlet request
* @param response the specified HTTP servlet response
* @param context the specified HTTP request context
* @throws Exception exception
*/
@RequestProcessing(value = "/cron/invitecode-expire", method = HTTPRequestMethod.GET)
@Before(adviceClass = StopwatchStartAdvice.class)
@After(adviceClass = StopwatchEndAdvice.class)
public void expireInvitecodes(final HttpServletRequest request, final HttpServletResponse response, final HTTPRequestContext context)
throws Exception {
final String key = Symphonys.get("keyOfSymphony");
if (!key.equals(request.getParameter("key"))) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
invitecodeMgmtService.expireInvitecodes();
context.renderJSON().renderTrueResult();
}
}