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());
}
}