From 4aa5ee44cea3ae22430bb611ef8aab1a45d022e0 Mon Sep 17 00:00:00 2001 From: ddangelorb Date: Mon, 23 Aug 2021 11:47:27 -0300 Subject: [PATCH] Adding ForgotPwd v1 structure --- db/ddl.sql | 9 +- pom.xml | 6 ++ .../controller/ForgotPasswordController.java | 42 ++++++++++ .../wpdauth/model/ForgotPasswordKeys.java | 30 +++++++ .../wpdauth/model/Users.java | 2 +- .../ForgotPasswordKeysRepository.java | 10 +++ .../wpdauth/repository/UsersRepository.java | 4 + .../service/ForgotPasswordService.java | 83 +++++++++++++++++++ .../wpdauth/service/UsersService.java | 14 ++-- 9 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java create mode 100644 src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordKeys.java create mode 100644 src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordKeysRepository.java create mode 100644 src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java diff --git a/db/ddl.sql b/db/ddl.sql index 57e5359..b9469d4 100644 --- a/db/ddl.sql +++ b/db/ddl.sql @@ -2,13 +2,20 @@ CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, - email VARCHAR(255) UNIQUE NULL, + email VARCHAR(255) UNIQUE NOT NULL, firstname VARCHAR(100) NULL, surname VARCHAR(100) NULL, avatar VARCHAR(100) NULL, active INT NOT NULL ); +CREATE TABLE IF NOT EXISTS forgotpassword_keys ( + id SERIAL PRIMARY KEY, + email VARCHAR(255) NOT NULL, + key VARCHAR(4) NOT NULL, + created_at TIMESTAMP DEFAULT NOW() +); + CREATE TABLE IF NOT EXISTS roles ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, diff --git a/pom.xml b/pom.xml index ae6b313..b95d9bb 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,12 @@ modelmapper 2.3.5 + + + org.springframework.boot + spring-boot-starter-mail + + diff --git a/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java b/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java new file mode 100644 index 0000000..af43636 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/controller/ForgotPasswordController.java @@ -0,0 +1,42 @@ +package org.waterproofingdata.wpdauth.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.waterproofingdata.wpdauth.service.ForgotPasswordService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +@RestController +@RequestMapping("/forgotpassword") +@Api(tags = "forgotpassword") +public class ForgotPasswordController { + @Autowired + private ForgotPasswordService forgotPasswordService; + + @PostMapping("/sendkey") + @ApiOperation(value = "${ForgotPasswordController.sendkey}") + @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); + } + + @PostMapping("/login") + @ApiOperation(value = "${UserController.login}") + @ApiResponses(value = {// + @ApiResponse(code = 400, message = "Something went wrong"), // + @ApiResponse(code = 422, message = "Invalid username/password supplied")}) + public String login(// + @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/ForgotPasswordKeys.java b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordKeys.java new file mode 100644 index 0000000..28e7881 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/model/ForgotPasswordKeys.java @@ -0,0 +1,30 @@ +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_keys") +@Getter +@Setter +@NoArgsConstructor +public class ForgotPasswordKeys { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + private String email; + + @Column(nullable = false) + private String key; + + @Column(nullable = false) + private String created_at; +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/model/Users.java b/src/main/java/org/waterproofingdata/wpdauth/model/Users.java index cefcdc9..3275976 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/model/Users.java +++ b/src/main/java/org/waterproofingdata/wpdauth/model/Users.java @@ -35,7 +35,7 @@ public class Users { @Column(nullable = false) private String password; - @Column(unique = true, nullable = true) + @Column(unique = true, nullable = false) private String email; @Size(min = 4, max = 255, message = "Minimum firstname length: 4 characters") diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordKeysRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordKeysRepository.java new file mode 100644 index 0000000..c5c4aee --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/ForgotPasswordKeysRepository.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.ForgotPasswordKeys; + +public interface ForgotPasswordKeysRepository extends JpaRepository { + @Query(value = "SELECT f.* FROM forgotpassword_keys f WHERE f.email = ?1 AND f.key = ?2 AND f.created_at >= current_date::timestamp AND f.created_at < current_date::timestamp + interval '1 day' ORDER BY f.id DESC LIMIT 1", nativeQuery = true) + ForgotPasswordKeys findTodayRecordByEmailANDKey(String email, String key); +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java index a1ab469..1d41e30 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java +++ b/src/main/java/org/waterproofingdata/wpdauth/repository/UsersRepository.java @@ -11,6 +11,10 @@ public interface UsersRepository extends JpaRepository { boolean existsByUsername(String username); Users findByUsername(String username); + + boolean existsByEmail(String email); + + Users findByEmail(String email); @Transactional @Query(value = "UPDATE users SET active = ?2 WHERE username = ?1", nativeQuery = true) diff --git a/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java b/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java new file mode 100644 index 0000000..12c2d93 --- /dev/null +++ b/src/main/java/org/waterproofingdata/wpdauth/service/ForgotPasswordService.java @@ -0,0 +1,83 @@ +package org.waterproofingdata.wpdauth.service; + +import java.util.Random; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +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.Users; +import org.waterproofingdata.wpdauth.repository.ForgotPasswordKeysRepository; +import org.waterproofingdata.wpdauth.repository.UsersRepository; +import org.waterproofingdata.wpdauth.security.JwtTokenProvider; + +@Service +public class ForgotPasswordService { + @Autowired + private ForgotPasswordKeysRepository forgotPasswordKeysRepository; + + @Autowired + private UsersRepository usersRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private JavaMailSender mailSender; + + @Autowired + private JwtTokenProvider jwtTokenProvider; + + public void sendkey(String email) { + Users user = usersRepository.findByEmail(email); + if (user == null) { + throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); + } + + Random rand = new Random(); + String key = String.format("%04d", rand.nextInt(10000)); + //System.out.printf("%04d%n", rand.nextInt(10000)); + + ForgotPasswordKeys entity = new ForgotPasswordKeys(); + entity.setEmail(email); + entity.setKey(key); + forgotPasswordKeysRepository.save(entity); + + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom("noreply@wp6.com"); + message.setTo(email); + message.setSubject("Envio de código para alteração de senha"); + message.setText(String.format("Olá! Segue o código para alterar sua senha:'%s'. Informe esse código no aplicativo para prosseguir.", key)); + mailSender.send(message); + } + + public String loginByEmailAndKey(String email, String key) { + ForgotPasswordKeys entity = forgotPasswordKeysRepository.findTodayRecordByEmailANDKey(email, key); + if (entity == null) { + throw new CustomException("The email and forgot key don't exist", HttpStatus.NOT_FOUND); + } + + Users user = usersRepository.findByEmail(email); + if (user == null) { + throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); + } + + String username = user.getUsername(); + return jwtTokenProvider.createToken(username, usersRepository.findByUsername(username).getRoles()); + } + + //public String loginByEmailAndAnswers(String email, List passwordAnswers) + + public void passwordUpdate(String email, String newPassword) { + Users user = usersRepository.findByEmail(email); + if (user == null) { + throw new CustomException("The user email doesn't exist", HttpStatus.NOT_FOUND); + } + user.setPassword(passwordEncoder.encode(newPassword)); + usersRepository.save(user); + } +} diff --git a/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java b/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java index eb9e082..7020838 100644 --- a/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java +++ b/src/main/java/org/waterproofingdata/wpdauth/service/UsersService.java @@ -24,7 +24,7 @@ import org.waterproofingdata.wpdauth.security.JwtTokenProvider; @Service public class UsersService { @Autowired - private UsersRepository userRepository; + private UsersRepository usersRepository; @Autowired private EduCemadenOrganizationsRepository eduCemadenOrganizationsRepository; @@ -42,13 +42,13 @@ public class UsersService { private AuthenticationManager authenticationManager; public boolean existsByUsername(String username) { - return userRepository.existsByUsername(username); + return usersRepository.existsByUsername(username); } public String login(String username, String password) { try { authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); - return jwtTokenProvider.createToken(username, userRepository.findByUsername(username).getRoles()); + return jwtTokenProvider.createToken(username, usersRepository.findByUsername(username).getRoles()); } catch (AuthenticationException e) { throw new CustomException("Invalid username/password supplied", HttpStatus.UNPROCESSABLE_ENTITY); @@ -59,7 +59,7 @@ public class UsersService { if (!existsByUsername(user.getUsername())) { user.setPassword(passwordEncoder.encode(user.getPassword())); user.setActive(0); - userRepository.save(user); + usersRepository.save(user); return jwtTokenProvider.createToken(user.getUsername(), user.getRoles()); } else { @@ -73,7 +73,7 @@ public class UsersService { } public Users search(String username) { - Users user = userRepository.findByUsername(username); + Users user = usersRepository.findByUsername(username); if (user == null) { throw new CustomException("The user doesn't exist", HttpStatus.NOT_FOUND); } @@ -81,7 +81,7 @@ public class UsersService { } public Users whoami(HttpServletRequest req) { - return userRepository.findByUsername(jwtTokenProvider.getUsername(jwtTokenProvider.resolveToken(req))); + return usersRepository.findByUsername(jwtTokenProvider.getUsername(jwtTokenProvider.resolveToken(req))); } public EduCemadenOrganizations findEduCemadenOrganizationById(Integer userid) { @@ -93,6 +93,6 @@ public class UsersService { } public String refresh(String username) { - return jwtTokenProvider.createToken(username, userRepository.findByUsername(username).getRoles()); + return jwtTokenProvider.createToken(username, usersRepository.findByUsername(username).getRoles()); } }