package edu.gatech.oad.rocket.findmythings.server.web;
import com.google.appengine.api.datastore.PhoneNumber;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import edu.gatech.oad.rocket.findmythings.server.TemplateServlet;
import edu.gatech.oad.rocket.findmythings.server.db.DatabaseService;
import edu.gatech.oad.rocket.findmythings.server.db.model.DBMember;
import edu.gatech.oad.rocket.findmythings.server.model.AppMember;
import edu.gatech.oad.rocket.findmythings.server.model.MessageBean;
import edu.gatech.oad.rocket.findmythings.server.util.Config;
import edu.gatech.oad.rocket.findmythings.server.util.Messages;
import edu.gatech.oad.rocket.findmythings.shared.util.validation.EmailValidator;
import edu.gatech.oad.rocket.findmythings.shared.util.validation.RegexValidator;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Logger;
public class RegisterServlet extends TemplateServlet {
@SuppressWarnings("unused")
private static final Logger LOGGER = Logger.getLogger(RegisterServlet.class.getName());
private static final String REAL_NAME = "name";
private static final String PASSWORD_CONFIRM = "password_alt";
private static final String PHONE = "phone";
private static final String ADDRESS = "address";
private static final long serialVersionUID = -7032016092040490069L;
// register workflow
// GET register -> POST register -> validate for errors
// - if errors, set attr so addParametersToMap picks it up, call doGet
// - if no errors, create user in DB, create auth ticket
// email link with token to user
// user clicks link, GET on activate with URL param, activates user
// fun fact: password recovery is almost identical
private static final RegexValidator PHONE_VALIDATOR = new RegexValidator("[0-9]-([0-9]{3})-[0-9]{3}-[0-9]{4}", false);
public static RegexValidator getPhoneNumberValidator() {
return PHONE_VALIDATOR;
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
try {
String email = WebUtils.getCleanParam(request, Config.USERNAME_PARAM);
if (emailIsInvalid(email)) {
sendError(request, response, Messages.Register.BAD_EMAIL_ADDRESS);
return;
}
AppMember user = memberWithEmail(email);
if (user != null && user.isRegistered()) {
sendError(request, response, Messages.Register.ALREADY_USER);
return;
}
String password = WebUtils.getCleanParam(request, Config.PASSWORD_PARAM);
String passwordAlt = WebUtils.getCleanParam(request, PASSWORD_CONFIRM);
if (password == null || password.length() < 3 || passwordAlt == null || passwordAlt.length() < 3) {
sendError(request, response, Messages.Register.BAD_PASSWORD);
return;
}
if (!password.equals(passwordAlt)) {
sendError(request, response, Messages.Register.PASSWORDS_MATCH);
return;
}
String phoneString = WebUtils.getCleanParam(request, PHONE);
if (!getPhoneNumberValidator().isValid(phoneString)) {
sendError(request, response, Messages.Register.INVALID_PHONE);
return;
}
String name = WebUtils.getCleanParam(request, REAL_NAME);
PhoneNumber phone = new PhoneNumber(phoneString);
String address = WebUtils.getCleanParam(request, ADDRESS);
DBMember newUser = (DBMember)user;
if (newUser == null) {
newUser = new DBMember(email, password, null, null, true);
newUser.setPhone(phone);
newUser.setName(name);
newUser.setAddress(address);
} else {
if (phone != null) newUser.setPhone(phone);
if (name != null) newUser.setName(name);
if (address != null) newUser.setAddress(address);
}
newUser.setAdmin(false);
DatabaseService.ofy().save().entity(newUser);
mailAuthenticationTokenSendOK(request, response, email, false);
} catch (Exception e) {
sendError(request, response, Messages.Register.INVALID_DATA);
}
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
writeDocument(response, getDefaultTemplateURI(request), getParameterMap(request));
}
@Override
protected void addParametersToMap(HttpServletRequest request, Map<String, Object> params) {
super.addParametersToMap(request, params);
params.put(Config.FORGOT_PASSWORD_PARAM, false);
}
void sendError(HttpServletRequest request, HttpServletResponse response, Messages.Register message) {
request.setAttribute(MessageBean.FAILURE_REASON, message.toString());
try {
doGet(request, response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void sendOK(HttpServletRequest request, HttpServletResponse response) {
try {
writeDocument(response, "registerSubmitted.ftl", getParameterMap(request));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
boolean emailIsInvalid(String email) {
return email == null || email.length() == 0 || !EmailValidator.getInstance().isValid(email);
}
void mailAuthenticationTokenSendOK(HttpServletRequest request, HttpServletResponse response, String email, boolean isForgot) {
String registrationToken = DatabaseService.ofy().createRegistrationTicket(email);
// send email with registrationToken
Queue queue = QueueFactory.getDefaultQueue();
queue.add(TaskOptions.Builder.withUrl("/sendMail")
.param(Config.USERNAME_PARAM, email)
.param(Config.FORGOT_PASSWORD_PARAM, Boolean.toString(isForgot))
.param(Config.TICKET_PARAM, registrationToken));
sendOK(request, response);
}
}