package controllers; import com.fasterxml.jackson.databind.JsonNode; import models.User; import play.Logger; import play.mvc.Http; import play.mvc.Result; import utils.Authentication; import utils.ImageUtil; import javax.persistence.PersistenceException; import java.io.File; import java.io.IOException; import java.util.List; public class UserController extends OJController { public static Result userListPage() { List<User> users = User.find.all(); return ok(views.html.user.list.render(users)); } public static Result registerPage() { return ok(views.html.user.register.render()); } public static Result loginPage() { return ok(views.html.user.login.render()); } public static Result forgetPasswordPage() { return ok(views.html.user.forgetPassword.render()); } public static Result logoutRedirect() { session().remove("user"); return redirect(routes.UserController.loginPage()); } public static Result verifyEmail(String username, String verificationPass) { User user = User.find.where().eq("name", username).findUnique(); if (user == null) { String message = "The account \"" + username + "\" you want to verify is not found on our system. " + "This might be because you have did verify your email within 24 hours and " + " your account has been deleted automatically."; return badRequest(views.html.info.message.render("Account Not Found", message)); } if (user.getVerificationPass().equals(verificationPass)) { user.isEmailVerified = true; user.save(); String message = "This account \"" + username + "\" has been successfully verified. " + "Thank you for your support."; return badRequest(views.html.info.message.render("Email Verified", message)); } else { String message = "Sorry. This account \"" + username + "\" could not be verified. " + " The verification link is not valid."; return badRequest(views.html.info.message.render("Invalid Verification Link", message)); } } public static Result resetPassWordPage(String username, String token) { User user = User.find.where().eq("name", username).findUnique(); if (user == null) { String message = "The account \"" + username + "\" you want to reset password for " + "is not found on our system. "; return badRequest(views.html.info.message.render("Account Not Found", message)); } if (user.getResetPasswordToken() != null && user.getResetPasswordToken().equals(token)) { return ok(views.html.user.resetPassword.render(user)); } else { String message = "Sorry. You can not create password for \"" + username + "\". " + " The token is not valid. <br />" + " You may request anther reset password request."; return badRequest(views.html.info.message.render("Invalid Reset Password Request", message)); } } public static User currentUser() { User user = (User) ctx().args.get("user"); if (user == null) { Logger.info("User not exist in context. Try to read from session."); user = User.find.where().eq("name", session("user")).findUnique(); if (user != null) { ctx().args.put("user", user); } } return user; } public static Result getSolvedProblems(String username) { User user = User.find.where().eq("name", username).findUnique(); if (user == null) { return notFound(jsonResponse(1, "User not found")); } return ok(jsonResponse(0, user.getSolvedProblems())); } public static Result getSolvedProblemsPage(String username) { User user = User.find.where().eq("name", username).findUnique(); if (user == null) { return notFound("User not found"); } return ProblemController.problemListPage(user); } @Authentication public static Result getMySolvedProblemsPage() { User user = (User) ctx().args.get("user"); return redirect(routes.UserController.getSolvedProblemsPage(user.name)); } @Authentication public static Result myProfilePage() { User user = (User) ctx().args.get("user"); return redirect(routes.UserController.profilePage(user.name)); } public static Result profilePage(String username) { User user = User.find.where().eq("name", username).findUnique(); if (user == null) { return notFound("User Not Found."); } return ok(views.html.user.profile.render(user)); } public static Result profileImage(String username) { int maxWidth = 96; int maxHeight = 96; try { if (request().queryString().containsKey("x")) { maxWidth = Integer.parseInt(request().queryString().get("x")[0]); } if (request().queryString().containsKey("y")) { maxHeight = Integer.parseInt(request().queryString().get("y")[0]); } } catch (Exception e) { return badRequest(jsonResponse(2, "Invalid request parameters: " + e.toString())); } User user = User.find.where().eq("name", username).findUnique(); if (user == null) { return notFound(jsonResponse(1, "User Not Found.")); } try { return ok(user.getProfileImage(maxWidth, maxHeight)).as("image/jpg"); } catch (IOException e) { return redirect(routes.Assets.versioned(new Assets.Asset("images/avatar.jpg"))); } } public static Result userProfile(String username) { User user = User.find.where().eq("name", username).findUnique(); if (user == null) { return notFound(jsonResponse(1, "User not found")); } return ok(jsonResponse(0, user)); } @Authentication public static Result editProfilePage() { return ok(views.html.user.profileEdit.render()); } @Authentication public static Result mySolutionListRedirect() { User user = (User) ctx().args.get("user"); return redirect(routes.SolutionController.solutionListPage() + "?user=" + user.name); } public static Result userSolutionListRedirect(String username) { User user = User.find.where().eq("name", username).findUnique(); if (user == null) { return notFound(jsonResponse(1, "User not found")); } return redirect(routes.SolutionController.solutionListPage() + "?user=" + user.name); } public static Result register() { JsonNode in = request().body().asJson(); if (in == null) { return formSubmitResponse(1, null, "Expecting Json data."); } try { User user = new User(); String username = in.get("username").textValue(); if (username == null) { return formSubmitResponse(1, "username", "Username cannot be empty."); } if (username.length() < 4 || username.length() > 32) { return formSubmitResponse(1, "username", "The length of username should be between 4 and 32."); } if (!username.matches("^(\\w+)$")) { return formSubmitResponse(1, "username", "Username contains illegal characters."); } if (User.find.where().eq("name", username).findRowCount() > 0) { return formSubmitResponse(1, "username", "Username is taken."); } user.name = username; String email = in.get("email").textValue(); user.email = email; String emailException = user.setEmail(email); if (emailException != null) { return formSubmitResponse(1, "email", emailException); } user.displayName = in.get("displayName").textValue().trim(); user.school = in.get("school").textValue().trim(); user.country = in.get("country").textValue().trim(); user.gender = in.get("gender").booleanValue(); String password = in.get("password").textValue(); user.setPassword(password); user.save(); user.sendVerifyEmail(); } catch (PersistenceException e) { // Database change after checking. return formSubmitResponse(1, null, "Server encountered a problem, please try again."); } catch (NullPointerException npe) { return formSubmitResponse(2, null, "Please check your input."); } catch (Exception e) { return formSubmitResponse(3, null, e.toString()); } return formSubmitResponse(0, null, null); } public static Result login() { JsonNode in = request().body().asJson(); if (in == null) { return formSubmitResponse(1, null, "Expecting Json data."); } User.updateStatus(); String username = in.get("username").textValue(); String password = in.get("password").textValue(); User user; if (username.contains("@")) { user = User.find.where().eq("email", username).findUnique(); } else { user = User.find.where().eq("name", username).findUnique(); } if (user == null) { return formSubmitResponse(1, "username", "No such account found."); } if (!user.verifyPassword(password)) { return formSubmitResponse(2, "password", "Password is incorrect."); } if (user.status > 0) { return formSubmitResponse(3, null, "The user has been deleted."); } session("user", user.name); return formSubmitResponse(0, null, null); } @Authentication(json = true) public static Result uploadProfileImage() { Logger.info("Handle upload profile image."); User user = (User) ctx().args.get("user"); Http.MultipartFormData body = request().body().asMultipartFormData(); Http.MultipartFormData.FilePart uploadFile = body.getFile("file"); File file = uploadFile.getFile(); Logger.debug("File type: " + uploadFile.getContentType()); try { switch (uploadFile.getContentType()) { case "image/jpeg": user.setProfileImage(file); break; case "image/png": byte[] converted = ImageUtil.convert(file, "jpg"); user.setProfileImage(converted); break; default: return badRequest(jsonResponse(1, "Unsupported file format.")); } } catch (Exception e) { return internalServerError(jsonResponse(2, e.toString())); } return ok(jsonResponse(0, null)); } @Authentication(json = true) public static Result editBasicProfile() { JsonNode in = request().body().asJson(); if (in == null) { return formSubmitResponse(1, null, "Expecting Json data."); } User user = (User) ctx().args.get("user"); try { String email = in.get("email").textValue(); if (!user.email.equals(email)) { String emailException = user.setEmail(email); if (emailException != null) { return formSubmitResponse(1, "email", emailException); } user.sendVerifyEmail(); } user.displayName = in.get("displayName").textValue().trim(); String country = in.get("country").textValue(); if (country != null) { country = country.trim(); // TODO: check if country code is valid. } user.country = country; user.school = in.get("school").textValue().trim(); user.gender = in.get("gender").booleanValue(); user.save(); } catch (NullPointerException npe) { return formSubmitResponse(3, null, "Invalid input data."); } catch (Exception e) { return formSubmitResponse(4, null, e.toString()); } return formSubmitResponse(0, null, null); } @Authentication(json = true) public static Result changePassword() { JsonNode in = request().body().asJson(); if (in == null) { return formSubmitResponse(1, null, "Expecting Json data."); } User user = (User) ctx().args.get("user"); String oldPassword = in.get("passwordOld").textValue(); if (!user.verifyPassword(oldPassword)) { return formSubmitResponse(2, "password", "Current password is not correct."); } String newPassword = in.get("password").textValue(); // TODO: Check if password is valid. user.setPassword(newPassword); user.save(); return formSubmitResponse(0, null, null); } public static Result resetPassword() { JsonNode in = request().body().asJson(); if (in == null) { return formSubmitResponse(1, null, "Expecting Json data."); } User user = User.find.where().eq("name", in.get("username").asText()).findUnique(); if (user == null) { return formSubmitResponse(4, null, "User not found"); } if (!user.getResetPasswordToken().equals(in.get("token").asText())) { return formSubmitResponse(2, null, "Incorrect token."); } // TODO: Check if password is valid. user.setPassword(in.get("password").asText()); user.resetPasswordRequestedTime = null; user.save(); return formSubmitResponse(0, null, null); } @Authentication(json = true) public static Result requestVerificationEmail() { User user = (User) ctx().args.get("user"); try { user.sendVerifyEmail(); } catch (Exception e) { return ok(jsonResponse(1, e.getMessage())); } return ok(jsonResponse(0, null)); } public static Result requestResetPassword() { JsonNode in = request().body().asJson(); String email = in.get("email").asText(); if (email == null) { return badRequest(jsonResponse(2, "Please provide an valid email address.")); } User user = User.find.where().eq("email", email).findUnique(); if (user == null) { return ok(jsonResponse(3, "User not found with email address " + email + ".")); } try { user.sendResetPasswordEmail(); } catch (Exception e) { return ok(jsonResponse(1, e.getMessage())); } return ok(jsonResponse(0, null)); } }