Skip to content

Commit

Permalink
minimal service side implementation of user registration by email
Browse files Browse the repository at this point in the history
  • Loading branch information
jsavell committed Feb 12, 2019
1 parent 8cf7ea7 commit 192f464
Show file tree
Hide file tree
Showing 10 changed files with 436 additions and 29 deletions.
180 changes: 180 additions & 0 deletions src/main/java/edu/tamu/cap/auth/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package edu.tamu.cap.auth.controller;

import static edu.tamu.weaver.response.ApiStatus.ERROR;
import static edu.tamu.weaver.response.ApiStatus.INVALID;
import static edu.tamu.weaver.response.ApiStatus.SUCCESS;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import edu.tamu.cap.auth.service.AppUserCredentialsService;
import edu.tamu.cap.model.EmailTemplate;
import edu.tamu.cap.model.User;
import edu.tamu.cap.model.repo.UserRepo;
import edu.tamu.cap.service.EmailTemplateService;
import edu.tamu.weaver.auth.controller.WeaverAuthController;
import edu.tamu.weaver.response.ApiResponse;
import edu.tamu.weaver.validation.results.ValidationResults;
import edu.tamu.weaver.validation.utility.ValidationUtility;

@RestController
@RequestMapping("/auth")
public class AuthController extends WeaverAuthController {

private Logger logger = LoggerFactory.getLogger(this.getClass());

private final static String EMAIL_VERIFICATION_TYPE = "EMAIL_VERIFICATION";

public static final String REGISTRATION_TEMPLATE = "SYSTEM New User Registration";

@Value("${app.url}")
private String url;

@Autowired
private UserRepo userRepo;

@Autowired
EmailTemplateService emailTemplateService;

@Autowired
private AppUserCredentialsService appUserCredentialsService;

@RequestMapping(value = "/register", method = { POST, GET })
public ApiResponse registration(@RequestBody(required = false) Map<String, String> data, @RequestParam Map<String, String> parameters) {

if (parameters.get("email") != null) {

String email = parameters.get("email");

if (userRepo.findByEmail(email) != null) {
logger.debug("Account with email " + email + " already exists!");
ValidationResults invalidEmail = new ValidationResults();
invalidEmail.addMessage(ValidationUtility.BUSINESS_MESSAGE_KEY, "verify", "Account with email " + email + " already exists!");
return new ApiResponse(INVALID, invalidEmail);
}

HashMap<String,String> emailData = new HashMap<String,String>();
try {
emailData.put("REGISTRATION_URL", url + "/register?token=" + cryptoService.generateGenericToken(email, EMAIL_VERIFICATION_TYPE));
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException
| BadPaddingException e) {
logger.debug("Unable to generate token! " + email);
return new ApiResponse(ERROR, "Unable to generate token! " + email);
}
EmailTemplate finalEmail = emailTemplateService.buildEmail("user_registration",emailData);

try {
emailSender.sendEmail(email, finalEmail.getSubject(), finalEmail.getMessage());
} catch (javax.mail.MessagingException e) {
logger.debug("Unable to send email! " + email);
return new ApiResponse(ERROR, "Unable to send email! " + email);
}

return new ApiResponse(SUCCESS, "An email has been sent to " + email + ". Please confirm email to continue registration.", parameters);
}

String token = data.get("token");
String firstName = data.get("firstName");
String lastName = data.get("lastName");
String password = data.get("userPassword");
String confirm = data.get("confirm");

if ((firstName == null || firstName.trim().length() == 0) && (lastName == null || lastName.trim().length() == 0)) {
logger.debug("Either a first or last name is required!");
return new ApiResponse(ERROR, "Either a first or last name is required!");
}

if (password == null || password.trim().length() == 0) {
logger.debug("Registration requires a password!");
return new ApiResponse(ERROR, "Registration requires a password!");
}

if (password != null && !password.equals(confirm)) {
logger.debug("The passwords do not match!");
return new ApiResponse(ERROR, "The passwords do not match!");
}

if (password != null && password.trim().length() < 6) {
logger.debug("Password must be greater than 6 characters!");
return new ApiResponse(ERROR, "Password must be greater than 6 characters!");
}

String[] content = null;
try {
content = cryptoService.validateGenericToken(token, EMAIL_VERIFICATION_TYPE);
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
logger.debug("Unable to validate token!");
return new ApiResponse(ERROR, "Unable to generate token!");
}

String tokenCreateTime = content[0];
String email = content[1];

Long tokenDaysOld = TimeUnit.MILLISECONDS.toDays(Long.valueOf(tokenCreateTime) - new Date().getTime());

if (tokenDaysOld >= 2) {
logger.debug("Token has expired!");
return new ApiResponse(ERROR, "Token has expired! Please begin registration again.");
}

User user = appUserCredentialsService.createUserFromRegistration(email, firstName, lastName, cryptoService.encodePassword(password));

return new ApiResponse(SUCCESS, "Registration was successful. Please login.", user);
}

@RequestMapping(value = "/login", method = POST)
public ApiResponse login(@RequestBody Map<String, String> data) {

String email = data.get("email");
String password = data.get("userPassword");

User user = userRepo.findByEmail(email);

if (user == null) {
logger.debug("No user found with email " + email + "!");
ValidationResults invalidEmail = new ValidationResults();
invalidEmail.addMessage(ValidationUtility.BUSINESS_MESSAGE_KEY, "login", "No user found with email " + email + "!");
return new ApiResponse(INVALID, invalidEmail);
}

if (!cryptoService.validatePassword(password, user.getPassword())) {
logger.debug("Authentication failed!");
ValidationResults failedAuthenticationResults = new ValidationResults();
failedAuthenticationResults.addMessage(ValidationUtility.BUSINESS_MESSAGE_KEY, "login", "Authentication failed!");
return new ApiResponse(INVALID, failedAuthenticationResults);
}

try {
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("lastName", user.getLastName());
claims.put("firstName", user.getFirstName());
claims.put("username", user.getUsername());
claims.put("email", user.getEmail());
String subject = user.getEmail();
return new ApiResponse(SUCCESS, "Login successful", tokenService.createToken(subject, claims));
} catch (Exception e) {
logger.debug("Unable to generate token!");
return new ApiResponse(ERROR, "Unable to generate token!");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ public synchronized User updateUserByCredentials(Credentials credentials) {

}

public User createUserFromRegistration(String email, String firstName, String lastName, String password) {
Role role = Role.ROLE_USER;
for (String adminEmail : admins) {
if (adminEmail.equals(email)) {
role = Role.ROLE_ADMIN;
break;
}
}
return userRepo.create(email, firstName, lastName, password, role.toString());
}

@Override
public String getAnonymousRole() {
return Role.ROLE_ANONYMOUS.toString();
Expand Down
72 changes: 72 additions & 0 deletions src/main/java/edu/tamu/cap/model/EmailTemplate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package edu.tamu.cap.model;

public class EmailTemplate {

private String name;

private String subject;

private String message;

/**
* Create a new EmailTemplate
*
* @param name
* The new template's name.
* @param subject
* The new template's subject.
* @param message
* The new template's message
*/
public EmailTemplate(String name, String subject, String message) {
setName(name);
setSubject(subject);
setMessage(message);
}

/**
* @return the name
*/
public String getName() {
return name;
}

/**
* @param name
* the name to set
*/
public void setName(String name) {
this.name = name;
}

/**
* @return the subject
*/
public String getSubject() {
return subject;
}

/**
* @param subject
* the subject to set
*/
public void setSubject(String subject) {
this.subject = subject;
}

/**
* @return the message
*/
public String getMessage() {
return message;
}

/**
* @param message
* the message to set
*/
public void setMessage(String message) {
this.message = message;
}

}
56 changes: 50 additions & 6 deletions src/main/java/edu/tamu/cap/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import edu.tamu.weaver.user.model.IRole;

import edu.tamu.weaver.auth.model.AbstractWeaverUserDetails;
import edu.tamu.weaver.response.ApiView;

/**
* Application User entity.
Expand All @@ -46,6 +48,14 @@ public class User extends AbstractWeaverUserDetails {
@Column(name = "last_name")
private String lastName;

@JsonView(ApiView.Partial.class)
@Column(nullable = false, unique = true)
private String email;

@Column
@JsonIgnore
private String password = null;

/**
* Constructor for the application user
*
Expand Down Expand Up @@ -76,6 +86,14 @@ public User(String uin, String firstName, String lastName, String role) {
setRole(role == null ? null : Role.valueOf(role));
}

public User(String email, String firstName, String lastName, String role, String password) {
this(email);
setFirstName(firstName);
setLastName(lastName);
setRole(role == null ? null : Role.valueOf(role));
setPassword(password);
}

public User(User user) {
this(user.getUsername());
setFirstName(user.getFirstName());
Expand Down Expand Up @@ -137,6 +155,38 @@ public void setLastName(String lastName) {
this.lastName = lastName;
}

/**
* @return the email
*/
public String getEmail() {
return email;
}

/**
* @param email
* the email to set
*/
public void setEmail(String email) {
this.email = email;
}

@Override
@JsonIgnore
public String getPassword() {
return null;
}

/**
* Stores an encoded password
*
* @param password
* the password to set
*/
public void setPassword(String password) {
this.password = password;
}


@Override
@JsonIgnore
public Collection<? extends GrantedAuthority> getAuthorities() {
Expand All @@ -146,10 +196,4 @@ public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}

@Override
@JsonIgnore
public String getPassword() {
return null;
}

}

0 comments on commit 192f464

Please sign in to comment.