diff --git a/db/ddl.sql b/db/ddl.sql index b9469d4..2066019 100644 --- a/db/ddl.sql +++ b/db/ddl.sql @@ -16,6 +16,21 @@ CREATE TABLE IF NOT EXISTS forgotpassword_keys ( created_at TIMESTAMP DEFAULT NOW() ); +CREATE TABLE IF NOT EXISTS forgotpassword_questions ( + id SERIAL PRIMARY KEY, + question VARCHAR(255) NOT NULL, + active INT NOT NULL +); + +CREATE TABLE IF NOT EXISTS forgotpassword_questions_users_answers ( + id SERIAL PRIMARY KEY, + forgotpassword_questions_id INT NOT NULL, + users_id INT NOT NULL, + answer VARCHAR(255) NOT NULL, + FOREIGN KEY (forgotpassword_questions_id) REFERENCES forgotpassword_questions (id), + FOREIGN KEY (users_id) REFERENCES users (id) +); + CREATE TABLE IF NOT EXISTS roles ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, diff --git a/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java b/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java index af43636..036e2b0 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java +++ b/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java @@ -20,21 +20,21 @@ public class ForgotPasswordController { @Autowired private ForgotPasswordService forgotPasswordService; - @PostMapping("/sendkey") - @ApiOperation(value = "${ForgotPasswordController.sendkey}") + @PostMapping("/sendkeybyemail") + @ApiOperation(value = "${ForgotPasswordController.sendkeybyemail}") @ApiResponses(value = {// @ApiResponse(code = 400, message = "Something went wrong"), // @ApiResponse(code = 422, message = "Invalid email supplied")}) - public void sendkey(@ApiParam("Email") @RequestParam String email) { - forgotPasswordService.sendkey(email); + public void sendkeybyemail(@ApiParam("Email") @RequestParam String email) { + forgotPasswordService.sendKeyByEmail(email); } - @PostMapping("/login") - @ApiOperation(value = "${UserController.login}") + @PostMapping("/loginbyemailandkey") + @ApiOperation(value = "${ForgotPasswordController.loginbyemailandkey}") @ApiResponses(value = {// @ApiResponse(code = 400, message = "Something went wrong"), // @ApiResponse(code = 422, message = "Invalid username/password supplied")}) - public String login(// + public String loginbyemailandkey(// @ApiParam("Email") @RequestParam String email, // @ApiParam("Key") @RequestParam String key) { return forgotPasswordService.loginByEmailAndKey(email, key); diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordQuestions.java b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordQuestions.java new file mode 100644 index 0000000..f000311 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordQuestions.java @@ -0,0 +1,27 @@ +package org.waterproofingdata.wpdauth.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity(name = "forgotpassword_questions") +@Getter +@Setter +@NoArgsConstructor +public class ForgotPasswordQuestions { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + private String question; + + @Column(nullable = false) + private Integer active; +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordQuestionsUsersAnswers.java b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordQuestionsUsersAnswers.java new file mode 100644 index 0000000..908d5e4 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordQuestionsUsersAnswers.java @@ -0,0 +1,31 @@ +package org.waterproofingdata.wpdauth.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity(name = "forgotpassword_questions_users_answers") +@Getter +@Setter +@NoArgsConstructor +public class ForgotPasswordQuestionsUsersAnswers { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false, name="forgotpassword_questions_id") + private Integer forgotpasswordquestionsid; + + @Column(nullable = false, name="users_id") + private Integer usersid; + + @Column(nullable = false) + private String answer; + +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordQuestionsRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordQuestionsRepository.java new file mode 100644 index 0000000..9f123a2 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordQuestionsRepository.java @@ -0,0 +1,7 @@ +package org.waterproofingdata.wpdauth.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.waterproofingdata.wpdauth.model.ForgotPasswordQuestions; + +public interface ForgotPasswordQuestionsRepository extends JpaRepository { +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordQuestionsUsersAnswersRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordQuestionsUsersAnswersRepository.java new file mode 100644 index 0000000..b23cd44 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordQuestionsUsersAnswersRepository.java @@ -0,0 +1,10 @@ +package org.waterproofingdata.wpdauth.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.waterproofingdata.wpdauth.model.ForgotPasswordQuestionsUsersAnswers; + +public interface ForgotPasswordQuestionsUsersAnswersRepository extends JpaRepository { + @Query(value = "SELECT fqua.* FROM forgotpassword_questions_users_answers fqua WHERE fqua.forgotpassword_questions_id = ?1 AND fqua.users_id = ?2", nativeQuery = true) + ForgotPasswordQuestionsUsersAnswers findByForgotPasswordQuestionsAndUserid(Integer forgotpasswordquestionsid, Integer usersid); +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java b/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java index 12c2d93..fb150e5 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java +++ b/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java @@ -1,5 +1,6 @@ package org.waterproofingdata.wpdauth.service; +import java.util.List; import java.util.Random; import org.springframework.beans.factory.annotation.Autowired; @@ -10,8 +11,12 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.waterproofingdata.wpdauth.exception.CustomException; import org.waterproofingdata.wpdauth.model.ForgotPasswordKeys; +import org.waterproofingdata.wpdauth.model.ForgotPasswordQuestions; +import org.waterproofingdata.wpdauth.model.ForgotPasswordQuestionsUsersAnswers; import org.waterproofingdata.wpdauth.model.Users; import org.waterproofingdata.wpdauth.repository.ForgotPasswordKeysRepository; +import org.waterproofingdata.wpdauth.repository.ForgotPasswordQuestionsRepository; +import org.waterproofingdata.wpdauth.repository.ForgotPasswordQuestionsUsersAnswersRepository; import org.waterproofingdata.wpdauth.repository.UsersRepository; import org.waterproofingdata.wpdauth.security.JwtTokenProvider; @@ -20,6 +25,12 @@ public class ForgotPasswordService { @Autowired private ForgotPasswordKeysRepository forgotPasswordKeysRepository; + @Autowired + private ForgotPasswordQuestionsRepository forgotPasswordQuestionsRepository; + + @Autowired + private ForgotPasswordQuestionsUsersAnswersRepository forgotPasswordQuestionsUsersAnswersRepository; + @Autowired private UsersRepository usersRepository; @@ -32,7 +43,7 @@ public class ForgotPasswordService { @Autowired private JwtTokenProvider jwtTokenProvider; - public void sendkey(String email) { + public void sendKeyByEmail(String email) { Users user = usersRepository.findByEmail(email); if (user == null) { throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); @@ -70,9 +81,7 @@ public class ForgotPasswordService { return jwtTokenProvider.createToken(username, usersRepository.findByUsername(username).getRoles()); } - //public String loginByEmailAndAnswers(String email, List passwordAnswers) - - public void passwordUpdate(String email, String newPassword) { + public void passwordUpdateByEmail(String email, String newPassword) { Users user = usersRepository.findByEmail(email); if (user == null) { throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); @@ -80,4 +89,45 @@ public class ForgotPasswordService { user.setPassword(passwordEncoder.encode(newPassword)); usersRepository.save(user); } + + public List findAllForgotPasswordQuestions() { + return forgotPasswordQuestionsRepository.findAll(); + } + + public void saveForgotPasswordQuestionsUsersAnswers(ForgotPasswordQuestionsUsersAnswers forgotPasswordQuestionsUsersAnswer) { + if (!forgotPasswordQuestionsRepository.existsById(forgotPasswordQuestionsUsersAnswer.getForgotpasswordquestionsid())) { + throw new CustomException("The Forgot Password Questions provided doesn't exist", HttpStatus.NOT_FOUND); + } + + if (!usersRepository.existsById(forgotPasswordQuestionsUsersAnswer.getUsersid())) { + throw new CustomException("The User provided doesn't exist", HttpStatus.NOT_FOUND); + } + + forgotPasswordQuestionsUsersAnswersRepository.save(forgotPasswordQuestionsUsersAnswer); + } + + public String loginByEmailAndAnswers(String email, List answers) { + Users user = usersRepository.findByEmail(email); + if (user == null) { + throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); + } + + int correctAnswers = 0; + for (ForgotPasswordQuestionsUsersAnswers answer : answers) { + ForgotPasswordQuestionsUsersAnswers answerComparison = forgotPasswordQuestionsUsersAnswersRepository.findByForgotPasswordQuestionsAndUserid(answer.getForgotpasswordquestionsid(), answer.getUsersid()); + if (answerComparison == null) { + throw new CustomException("The comparison answer doesn't exist", HttpStatus.NOT_FOUND); + } + + if (answer.getAnswer().equalsIgnoreCase(answerComparison.getAnswer())) { + correctAnswers++; + } + } + if (correctAnswers < 2) { + throw new CustomException("Invalid answers supplied to login. Must have at least 2 correct ones.", HttpStatus.UNPROCESSABLE_ENTITY); + } + + String username = user.getUsername(); + return jwtTokenProvider.createToken(username, usersRepository.findByUsername(username).getRoles()); + } }