Email Verifcation Works

This commit is contained in:
omenem 2020-02-27 21:39:38 +01:00
parent 990f1bd6d4
commit 2271f4a5b9
10 changed files with 106 additions and 20 deletions

View file

@ -17,6 +17,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'org.springframework.security:spring-security-web' implementation 'org.springframework.security:spring-security-web'
implementation 'org.postgresql:postgresql' implementation 'org.postgresql:postgresql'

View file

@ -54,6 +54,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.permitAll() .permitAll()
.antMatchers("/auth/register") .antMatchers("/auth/register")
.permitAll() .permitAll()
.antMatchers("/register")
.permitAll()
.antMatchers("/register/confirm-account")
.permitAll()
. .
// all other requests need to be authenticated // all other requests need to be authenticated
anyRequest() anyRequest()

View file

@ -42,13 +42,6 @@ public class AuthenticationController {
return new JWTResponse(token); return new JWTResponse(token);
} }
@PostMapping("/register")
public User register(@Valid @RequestBody User user) {
user.setPassword(encoder.encode(user.getPassword()));
users.save(user);
return user;
}
@PatchMapping("/update") @PatchMapping("/update")
public User update(@Valid @RequestBody final UserUpdateRequest u, final Principal principal) { public User update(@Valid @RequestBody final UserUpdateRequest u, final Principal principal) {
final User oldUser = userRepository.findByUsername(principal.getName()); final User oldUser = userRepository.findByUsername(principal.getName());

View file

@ -1,16 +1,24 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller; package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import ch.usi.inf.sa4.sanmarinoes.smarthut.Service.EmailSenderService; import ch.usi.inf.sa4.sanmarinoes.smarthut.Service.EmailSenderService;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.OkResponse;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.DuplicateEmailRegistrationException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.EmailTokenNotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationToken; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationToken;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationTokenRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ConfirmationTokenRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@ -25,6 +33,8 @@ public class UserAccountController {
@Autowired private EmailSenderService emailSenderService; @Autowired private EmailSenderService emailSenderService;
@Autowired private BCryptPasswordEncoder encoder;
@GetMapping @GetMapping
public ModelAndView displayRegistration(ModelAndView modelAndView, User user) { public ModelAndView displayRegistration(ModelAndView modelAndView, User user) {
modelAndView.addObject("user", user); modelAndView.addObject("user", user);
@ -33,14 +43,17 @@ public class UserAccountController {
} }
@PostMapping @PostMapping
public ModelAndView registerUser(ModelAndView modelAndView, User user) { public OkResponse registerUser(@Valid @RequestBody User user)
throws DuplicateEmailRegistrationException {
System.out.println(user);
User existingUser = userRepository.findByEmailIgnoreCase(user.getEmail()); User existingUser = userRepository.findByEmailIgnoreCase(user.getEmail());
// Check if an User with the same email already exists // Check if an User with the same email already exists
if (existingUser != null) { if (existingUser != null) {
modelAndView.addObject("message", "This email already exists!"); throw new DuplicateEmailRegistrationException();
modelAndView.setViewName("error");
} else { } else {
// encode user's password
user.setPassword(encoder.encode(user.getPassword()));
userRepository.save(user); userRepository.save(user);
ConfirmationToken confirmationToken = new ConfirmationToken(user); ConfirmationToken confirmationToken = new ConfirmationToken(user);
@ -53,16 +66,28 @@ public class UserAccountController {
mailMessage.setFrom("smarthut.sm@gmail.com"); mailMessage.setFrom("smarthut.sm@gmail.com");
mailMessage.setText( mailMessage.setText(
"To confirm your account, please click here : " "To confirm your account, please click here : "
+ "http://localhost:8082/confirm-account?token=" + "http://localhost:8080/register/confirm-account?token="
+ confirmationToken.getConfirmationToken()); + confirmationToken.getConfirmationToken());
emailSenderService.sendEmail(mailMessage); emailSenderService.sendEmail(mailMessage);
modelAndView.addObject("emailId", user.getEmail()); return new OkResponse();
modelAndView.setViewName("successfulRegisteration");
} }
}
return modelAndView; @GetMapping(value = "/confirm-account")
public OkResponse confirmUserAccount(@RequestParam("token") @NotNull String confirmationToken)
throws EmailTokenNotFoundException {
final ConfirmationToken token =
confirmationTokenRepository.findByConfirmationToken(confirmationToken);
if (token != null) {
final User user = userRepository.findByEmailIgnoreCase(token.getUser().getEmail());
user.setEnabled(true);
userRepository.save(user);
return new OkResponse();
} else {
throw new EmailTokenNotFoundException();
}
} }
} }

View file

@ -0,0 +1,6 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
/** A dummy DTO to return when there is no data to return */
public class OkResponse {
private boolean success = true;
}

View file

@ -0,0 +1,11 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.error;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class DuplicateEmailRegistrationException extends Exception {
public DuplicateEmailRegistrationException() {
super("Email already belonging to another user");
}
}

View file

@ -0,0 +1,11 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.error;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class EmailTokenNotFoundException extends Exception {
public EmailTokenNotFoundException() {
super("Email verification token not found in DB");
}
}

View file

@ -37,6 +37,9 @@ public class ConfirmationToken {
confirmationToken = UUID.randomUUID().toString(); confirmationToken = UUID.randomUUID().toString();
} }
/** Constructor for hibernate reflective stuff things whatever */
public ConfirmationToken() {}
public Long getId() { public Long getId() {
return id; return id;
} }

View file

@ -3,10 +3,10 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import java.util.Set; import java.util.Set;
import javax.persistence.*; import javax.persistence.*;
import javax.validation.constraints.Email; import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern; import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/** A user of the Smarthut application */ /** A user of the Smarthut application */
@Entity(name = "smarthutuser") @Entity(name = "smarthutuser")
@ -33,7 +33,10 @@ public class User {
@NotNull @NotNull
@Column(nullable = false) @Column(nullable = false)
@NotEmpty(message = "Please provide a password") @NotEmpty(message = "Please provide a password")
@Min(value = 6, message = "Your password should be at least 6 characters long") @Size(
min = 6,
max = 255,
message = "Your password should be at least 6 characters long and up to 255 chars long")
private String password; private String password;
/** /**
@ -51,6 +54,9 @@ public class User {
@OneToMany(mappedBy = "user") @OneToMany(mappedBy = "user")
private Set<Room> rooms; private Set<Room> rooms;
@Column(nullable = false)
private Boolean isEnabled = false;
public Long getId() { public Long getId() {
return id; return id;
} }
@ -95,6 +101,14 @@ public class User {
return rooms; return rooms;
} }
public Boolean getEnabled() {
return isEnabled;
}
public void setEnabled(Boolean enabled) {
isEnabled = enabled;
}
@Override @Override
public String toString() { public String toString() {
return "User{" return "User{"
@ -103,11 +117,17 @@ public class User {
+ ", name='" + ", name='"
+ name + name
+ '\'' + '\''
+ ", username='"
+ username
+ '\''
+ ", password='" + ", password='"
+ password + password
+ '\'' + '\''
+ ", email='" + ", email='"
+ email + email
+ "\'}"; + '\''
+ ", isEnabled="
+ isEnabled
+ '}';
} }
} }

View file

@ -10,4 +10,16 @@ spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.format_sql=true
jwt.secret=thiskeymustbeverylongorthethingcomplainssoiamjustgoingtowritehereabunchofgarbageciaomamma jwt.secret=thiskeymustbeverylongorthethingcomplainssoiamjustgoingtowritehereabunchofgarbageciaomamma
spring.mail.test-connection=true
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.username=smarthut.sm@gmail.com
spring.mail.password=dcadvbagqfkwbfts
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000