From 4fed3d6abd0dde161e9877eda5261af36b578a2b Mon Sep 17 00:00:00 2001 From: ManishKumarKeshri Date: Sat, 27 Mar 2021 13:08:14 -0700 Subject: [PATCH 1/6] Updating. Signed-off-by: ManishKumarKeshri --- .idea/compiler.xml | 2 +- .idea/misc.xml | 2 +- build.gradle | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 34d5ccd..609a421 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -11,6 +11,6 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 81c302f..62b6423 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index a7709bc..b4bbb6b 100644 --- a/build.gradle +++ b/build.gradle @@ -55,6 +55,7 @@ dependencies { compile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: springBootVersion compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-sleuth', version: springSleuthVersion compile group: 'org.springframework.data', name: 'spring-data-mongodb', version: springMongoDataVersion + compile group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: springBootVersion compile group: 'org.mongodb', name: 'mongodb-driver-sync', version: javaMongoDriverVersion compile group: 'com.google.code.gson', name: 'gson', version: gsonVersion compile group: 'com.google.guava', name: 'guava', version: guavaVersion From 56cda9fea68a1e1f3b7f4b099d8b7266b37807e0 Mon Sep 17 00:00:00 2001 From: ManishKumarKeshri Date: Sat, 27 Mar 2021 16:35:05 -0700 Subject: [PATCH 2/6] Updating. Signed-off-by: ManishKumarKeshri --- .../TechVault/services/User/EmailService.java | 18 ++ .../TechVault/services/User/UserService.java | 32 +++ .../services/User/UserServiceImpl.java | 196 ++++++++++++++++++ .../User/controller/UserController.java | 108 ++++++++++ .../exception/InvalidArgumentException.java | 23 ++ .../exception/ResourceNotFoundException.java | 22 ++ .../TechVault/services/User/model/User.java | 35 ++++ .../User/persistence/UserRepository.java | 20 ++ .../User/request/ChangePasswordRequest.java | 22 ++ .../User/request/PasswordForgotRequest.java | 15 ++ .../User/request/RegisterUserRequest.java | 26 +++ .../User/request/UserLoginRequest.java | 21 ++ .../services/User/response/UserResponse.java | 10 + src/main/resources/application.properties | 14 +- 14 files changed, 561 insertions(+), 1 deletion(-) create mode 100644 src/main/java/TechVault/services/User/EmailService.java create mode 100644 src/main/java/TechVault/services/User/UserService.java create mode 100644 src/main/java/TechVault/services/User/UserServiceImpl.java create mode 100644 src/main/java/TechVault/services/User/controller/UserController.java create mode 100644 src/main/java/TechVault/services/User/exception/InvalidArgumentException.java create mode 100644 src/main/java/TechVault/services/User/exception/ResourceNotFoundException.java create mode 100644 src/main/java/TechVault/services/User/model/User.java create mode 100644 src/main/java/TechVault/services/User/persistence/UserRepository.java create mode 100644 src/main/java/TechVault/services/User/request/ChangePasswordRequest.java create mode 100644 src/main/java/TechVault/services/User/request/PasswordForgotRequest.java create mode 100644 src/main/java/TechVault/services/User/request/RegisterUserRequest.java create mode 100644 src/main/java/TechVault/services/User/request/UserLoginRequest.java create mode 100644 src/main/java/TechVault/services/User/response/UserResponse.java diff --git a/src/main/java/TechVault/services/User/EmailService.java b/src/main/java/TechVault/services/User/EmailService.java new file mode 100644 index 0000000..bd490b0 --- /dev/null +++ b/src/main/java/TechVault/services/User/EmailService.java @@ -0,0 +1,18 @@ +package TechVault.services.User; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +@Service +public class EmailService { + @Autowired + private JavaMailSender mailSender; + + @Async + public void sendEmail(SimpleMailMessage email) { + mailSender.send(email); + } +} \ No newline at end of file diff --git a/src/main/java/TechVault/services/User/UserService.java b/src/main/java/TechVault/services/User/UserService.java new file mode 100644 index 0000000..f936f4b --- /dev/null +++ b/src/main/java/TechVault/services/User/UserService.java @@ -0,0 +1,32 @@ +package TechVault.services.User; + +import TechVault.services.User.model.User; +import TechVault.services.User.request.ChangePasswordRequest; +import TechVault.services.User.request.PasswordForgotRequest; +import TechVault.services.User.request.UserLoginRequest; + +import java.nio.file.AccessDeniedException; + +public interface UserService { + boolean register(User user); + + User fetchUser(String email) throws AccessDeniedException; + + User saveUser(User user); + + User resetUser(PasswordForgotRequest passwordForgotRequest); + + void changeUserPassword(ChangePasswordRequest changePasswordRequest); + + void confirmUser(String token); + + User findByEmail(String email); + + boolean loginUser(UserLoginRequest userLoginRequest) ; + + boolean userExistsByEmail(String email); + + boolean userExistsByUserName(String userName); + + Boolean getVerificationStatus(User user) throws AccessDeniedException; +} diff --git a/src/main/java/TechVault/services/User/UserServiceImpl.java b/src/main/java/TechVault/services/User/UserServiceImpl.java new file mode 100644 index 0000000..ccfeb3b --- /dev/null +++ b/src/main/java/TechVault/services/User/UserServiceImpl.java @@ -0,0 +1,196 @@ +package TechVault.services.User; + +import TechVault.services.User.exception.InvalidArgumentException; +import TechVault.services.User.exception.ResourceNotFoundException; +import TechVault.services.User.model.User; +import TechVault.services.User.persistence.UserRepository; +import TechVault.services.User.request.ChangePasswordRequest; +import TechVault.services.User.request.PasswordForgotRequest; +import TechVault.services.User.request.UserLoginRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.nio.file.AccessDeniedException; +import java.security.SecureRandom; +import java.util.Objects; +import java.util.Optional; +import java.util.Random; +import java.util.UUID; + +@Service +public class UserServiceImpl implements UserService { + @Autowired + private UserRepository userRepository; + + private static final Random RANDOM = new SecureRandom(); + private static final String ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + @Override + public boolean register(User user) throws InvalidArgumentException { + String password = user.getPassword(); + if (password.isEmpty()) { + throw new InvalidArgumentException("Invalid password."); + } + + if (user.getUserName().isEmpty()) { + user.setUserName(user.getEmail()); + } + + User userExists = userRepository.findByUserName(user.getUserName()); + + if (userExists != null) { + throw new InvalidArgumentException(user.getUserName() + " already registered."); + } + + if (userRepository.findByEmail(user.getEmail()).get() != null) { + throw new InvalidArgumentException(user.getEmail() + " already registered."); + } + + // Disable user until they click on confirmation link in email + user.setEmailVerified(0); + user.setId(RANDOM.nextLong()); + // Generate random 36-character string token for confirmation link + user.setConfirmationToken(UUID.randomUUID().toString()); + + userRepository.save(user); + + return true; + } + + @Override + public User resetUser(PasswordForgotRequest passwordForgotRequest) { + + User userExists = userRepository.findByEmail(passwordForgotRequest.getEmail()).get(); + + if (userExists == null) { + throw new InvalidArgumentException(passwordForgotRequest.getEmail() + " is not registered."); + } + + String password = generatePassword(10); + userExists.setPassword(password); + userExists.setTempPassword(true); + + userRepository.save(userExists); + + // return the user with plain password so that we can send it to the user's email. + userExists.setPassword(password); + + return userExists; + } + + @Override + public void changeUserPassword(ChangePasswordRequest changePasswordRequest) { + User userExists = userRepository.findByUserName(changePasswordRequest.getUserName()); + + if (userExists == null) { + throw new InvalidArgumentException(changePasswordRequest.getUserName() + " is not registered."); + } + + if (userExists.getEmailVerified() == 0) { + throw new InvalidArgumentException("The user is not enabled."); + } + + userExists.setPassword(changePasswordRequest.getPassword()); + + userRepository.save(userExists); + } + + @Override + public void confirmUser(String token) { + User user = userRepository.findByConfirmationToken(token); + + if (user == null) { + throw new InvalidArgumentException("Invalid token."); + } + // Token found + user.setEmailVerified(1); + user.setConfirmationToken(""); + + // Save user + userRepository.save(user); + } + + @Override + public boolean loginUser(UserLoginRequest userLoginRequest) { + if (userLoginRequest.getEmail() == null && userLoginRequest.getUserName() == null) { + throw new InvalidArgumentException("Required either email or user name."); + } + User userExists = null; + if (userLoginRequest.getUserName() != null) { + userExists = userRepository.findByUserName(userExists.getUserName()); + } else { + userExists = userRepository.findByEmail(userExists.getEmail()).get(); + } + + if (userExists == null) { + throw new InvalidArgumentException("Invalid user name."); + } + + String password = userLoginRequest.getPassword(); + if (!password.equals(userExists.getPassword())) { + throw new InvalidArgumentException("Invalid user name and password combination."); + } + + if (userExists.getEmailVerified() == 0) { + throw new InvalidArgumentException("The user is not enabled."); + } + + userExists.setPassword(""); + userExists.setId(0L); + return true; + } + + @Override + public User fetchUser(String email) throws AccessDeniedException { + if (Objects.isNull(email)) { + throw new AccessDeniedException("Invalid access"); + } + + Optional user = userRepository.findByEmail(email); + if (!user.isPresent()) { + throw new ResourceNotFoundException("User not found"); + } + return user.get(); + } + + @Override + public User saveUser(User user) { + if (Objects.isNull(user)) { + throw new InvalidArgumentException("Null user"); + } + + return userRepository.save(user); + } + + @Override + public User findByEmail(String email) { + if (Objects.isNull(email)) { + throw new InvalidArgumentException("Null email"); + } + + return userRepository.findByEmail(email).orElse(null); + } + + @Override + public boolean userExistsByEmail(String email) { + return userRepository.existsByEmail(email); + } + + @Override + public boolean userExistsByUserName(String userName) { + return userRepository.existsByUserName(userName); + } + + @Override + public Boolean getVerificationStatus(User user) throws AccessDeniedException { + return user.getEmailVerified() == 1; + } + + public static String generatePassword(int length) { + StringBuilder returnValue = new StringBuilder(length); + for (int i = 0; i < length; i++) { + returnValue.append(ALPHABET.charAt(RANDOM.nextInt(ALPHABET.length()))); + } + return new String(returnValue); + } +} diff --git a/src/main/java/TechVault/services/User/controller/UserController.java b/src/main/java/TechVault/services/User/controller/UserController.java new file mode 100644 index 0000000..c6db5c0 --- /dev/null +++ b/src/main/java/TechVault/services/User/controller/UserController.java @@ -0,0 +1,108 @@ +package TechVault.services.User.controller; + +import TechVault.services.User.EmailService; +import TechVault.services.User.UserService; +import TechVault.services.User.model.User; +import TechVault.services.User.request.ChangePasswordRequest; +import TechVault.services.User.request.PasswordForgotRequest; +import TechVault.services.User.request.RegisterUserRequest; +import TechVault.services.User.request.UserLoginRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +@Slf4j +@Validated +@RestController +@RequestMapping("user") +public class UserController { + + @Autowired + private UserService userService; + @Autowired + private EmailService emailService; + @Value("${webServerUrl}") + private String webServerUrl; + + + @PostMapping(value = "/register") + public ResponseEntity registerUser(@RequestBody @Valid RegisterUserRequest registerUserRequest) { + User user = new User(); + user.setEmail(registerUserRequest.getEmail()); + user.setPassword(registerUserRequest.getPassword()); + user.setUserName(registerUserRequest.getUserName()); + try { + if (userService.register(user)) { + SimpleMailMessage registrationEmail = new SimpleMailMessage(); + registrationEmail.setTo(user.getEmail()); + registrationEmail.setSubject("Registration Confirmation"); + registrationEmail.setText("To confirm your e-mail address, please click the link below:\n" + webServerUrl + + "/users/confirm?token=" + user.getConfirmationToken()); + registrationEmail.setFrom("noreply@domain.com"); + + emailService.sendEmail(registrationEmail); + } + return new ResponseEntity<>("Registered.", HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @GetMapping(path = "/confirm") + public ResponseEntity confirm(@RequestParam("token") String token) { + try { + userService.confirmUser(token); + return new ResponseEntity<>("Confirmed.", HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @PostMapping(path = "/login") + public ResponseEntity login(@Valid @RequestBody UserLoginRequest userLoginRequest) { + try { + userService.loginUser(userLoginRequest); + return new ResponseEntity<>("Successful.", HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @PostMapping(path = "/reset") + public ResponseEntity forgotPasswordRequest(@Valid @RequestBody PasswordForgotRequest passwordForgotRequest) { + try { + User resetUser = userService.resetUser(passwordForgotRequest); + if (resetUser != null) { + SimpleMailMessage registrationEmail = new SimpleMailMessage(); + registrationEmail.setTo(passwordForgotRequest.getEmail()); + registrationEmail.setSubject("Temporary Password Sent From " + webServerUrl); + registrationEmail + .setText("To access your account, please use this temporary password: " + resetUser.getPassword() + + ".\r\nNOTE: This email was sent from an automated system. Please do not reply."); + registrationEmail.setFrom("noreply@domain.com"); + emailService.sendEmail(registrationEmail); + } + return new ResponseEntity<>("Check your email.", HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @PostMapping(path = "/changepwd") + public ResponseEntity changePassword(@Valid @RequestBody ChangePasswordRequest changePasswordRequest) { + userService.changeUserPassword(changePasswordRequest); + return new ResponseEntity<>("Changed.", HttpStatus.OK); + } +} diff --git a/src/main/java/TechVault/services/User/exception/InvalidArgumentException.java b/src/main/java/TechVault/services/User/exception/InvalidArgumentException.java new file mode 100644 index 0000000..9185e0c --- /dev/null +++ b/src/main/java/TechVault/services/User/exception/InvalidArgumentException.java @@ -0,0 +1,23 @@ +package TechVault.services.User.exception; + +public class InvalidArgumentException extends RuntimeException { + + private static final long serialVersionUID = -1262173968380116559L; + + public InvalidArgumentException() { + super(); + } + + public InvalidArgumentException(String s) { + super(s); + } + + public InvalidArgumentException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidArgumentException(Throwable cause) { + super(cause); + } + +} \ No newline at end of file diff --git a/src/main/java/TechVault/services/User/exception/ResourceNotFoundException.java b/src/main/java/TechVault/services/User/exception/ResourceNotFoundException.java new file mode 100644 index 0000000..ec369fa --- /dev/null +++ b/src/main/java/TechVault/services/User/exception/ResourceNotFoundException.java @@ -0,0 +1,22 @@ +package TechVault.services.User.exception; + +public class ResourceNotFoundException extends RuntimeException { + private static final long serialVersionUID = 1177491237661223459L; + + public ResourceNotFoundException() { + super(); + } + + public ResourceNotFoundException(String s) { + super(s); + } + + public ResourceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/TechVault/services/User/model/User.java b/src/main/java/TechVault/services/User/model/User.java new file mode 100644 index 0000000..0c09758 --- /dev/null +++ b/src/main/java/TechVault/services/User/model/User.java @@ -0,0 +1,35 @@ +package TechVault.services.User.model; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +@Document(collection = "user") +@Getter +@Setter +@NoArgsConstructor +public class User { + + @Id + @Field(name = "id") + private Long id; + + @Field(name = "email") + private String email; + + @Field(name = "password") + private String password; + + @Field(name = "user_name") + private String userName; + + @Field(name = "email_verified") + private Integer emailVerified; + + private String confirmationToken; + + private boolean isTempPassword; +} diff --git a/src/main/java/TechVault/services/User/persistence/UserRepository.java b/src/main/java/TechVault/services/User/persistence/UserRepository.java new file mode 100644 index 0000000..1da7af3 --- /dev/null +++ b/src/main/java/TechVault/services/User/persistence/UserRepository.java @@ -0,0 +1,20 @@ +package TechVault.services.User.persistence; + +import TechVault.services.User.model.User; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface UserRepository extends MongoRepository { + Optional findByEmail(String email); + + Boolean existsByEmail(String email); + + Boolean existsByUserName(String userName); + + User findByUserName(String username); + + User findByConfirmationToken(String confirmationToken); +} \ No newline at end of file diff --git a/src/main/java/TechVault/services/User/request/ChangePasswordRequest.java b/src/main/java/TechVault/services/User/request/ChangePasswordRequest.java new file mode 100644 index 0000000..3253eb7 --- /dev/null +++ b/src/main/java/TechVault/services/User/request/ChangePasswordRequest.java @@ -0,0 +1,22 @@ +package TechVault.services.User.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@Data +public class ChangePasswordRequest { + + @NotBlank + @Size(min = 3, max = 52) + private String userName; + + @NotBlank + @Size(min = 6, max = 52) + private String password; + + @NotBlank + @Size(min = 6, max = 52) + private String passwordRepeat; +} diff --git a/src/main/java/TechVault/services/User/request/PasswordForgotRequest.java b/src/main/java/TechVault/services/User/request/PasswordForgotRequest.java new file mode 100644 index 0000000..e1c1f6b --- /dev/null +++ b/src/main/java/TechVault/services/User/request/PasswordForgotRequest.java @@ -0,0 +1,15 @@ +package TechVault.services.User.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@Data +public class PasswordForgotRequest { + + @NotBlank + @Size(min = 3, max = 52) + private String email; +} + diff --git a/src/main/java/TechVault/services/User/request/RegisterUserRequest.java b/src/main/java/TechVault/services/User/request/RegisterUserRequest.java new file mode 100644 index 0000000..b96e570 --- /dev/null +++ b/src/main/java/TechVault/services/User/request/RegisterUserRequest.java @@ -0,0 +1,26 @@ +package TechVault.services.User.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@Data +public class RegisterUserRequest { + + @NotBlank + @Size(min = 3, max = 52) + private String email; + + @NotBlank + @Size(min = 3, max = 52) + private String userName; + + @NotBlank + @Size(min = 6, max = 52) + private String password; + + @NotBlank + @Size(min = 6, max = 52) + private String passwordRepeat; +} diff --git a/src/main/java/TechVault/services/User/request/UserLoginRequest.java b/src/main/java/TechVault/services/User/request/UserLoginRequest.java new file mode 100644 index 0000000..1df5833 --- /dev/null +++ b/src/main/java/TechVault/services/User/request/UserLoginRequest.java @@ -0,0 +1,21 @@ +package TechVault.services.User.request; + + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@Data +public class UserLoginRequest { + + @Size(min = 3, max = 52) + private String email; + + @Size(min = 3, max = 52) + private String userName; + + @NotBlank + @Size(min = 6, max = 52) + private String password; +} diff --git a/src/main/java/TechVault/services/User/response/UserResponse.java b/src/main/java/TechVault/services/User/response/UserResponse.java new file mode 100644 index 0000000..fa036a7 --- /dev/null +++ b/src/main/java/TechVault/services/User/response/UserResponse.java @@ -0,0 +1,10 @@ +package TechVault.services.User.response; + +import lombok.Data; + +@Data +public class UserResponse { + private String email; + private String userName; + private Integer emailVerified; +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 29d097e..1fa6d91 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,4 +1,16 @@ #spring.application.name: TechVault server.port= 8080 spring.data.mongodb.uri=mongodb+srv://prateek:p@cluster0.kf3n4.mongodb.net/TechVault?retryWrites=true&w=majority -spring.data.mongodb.database=TechVault \ No newline at end of file +spring.data.mongodb.database=TechVault + + +spring.mail.host=smtp.gmail.com +spring.mail.username=techvaulttech@gmail.com +spring.mail.password=wediscusstech +spring.mail.port=587 +spring.mail.properties.mail.smtp.starttls.enable=true +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.required=true + +#Used in the emails sent to users +webServerUrl=http://localhost:9000 \ No newline at end of file From f5a92de5183e7c499bb050b9d12f32eaf6cacf1f Mon Sep 17 00:00:00 2001 From: ManishKumarKeshri Date: Sat, 27 Mar 2021 17:08:09 -0700 Subject: [PATCH 3/6] Login sign up. Signed-off-by: ManishKumarKeshri --- .../TechVault/services/User/UserService.java | 2 -- .../services/User/UserServiceImpl.java | 34 +++++-------------- .../User/controller/UserController.java | 2 +- .../User/persistence/UserRepository.java | 2 +- src/main/resources/application.properties | 2 +- 5 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/main/java/TechVault/services/User/UserService.java b/src/main/java/TechVault/services/User/UserService.java index f936f4b..2fc604d 100644 --- a/src/main/java/TechVault/services/User/UserService.java +++ b/src/main/java/TechVault/services/User/UserService.java @@ -20,8 +20,6 @@ public interface UserService { void confirmUser(String token); - User findByEmail(String email); - boolean loginUser(UserLoginRequest userLoginRequest) ; boolean userExistsByEmail(String email); diff --git a/src/main/java/TechVault/services/User/UserServiceImpl.java b/src/main/java/TechVault/services/User/UserServiceImpl.java index ccfeb3b..118b5e6 100644 --- a/src/main/java/TechVault/services/User/UserServiceImpl.java +++ b/src/main/java/TechVault/services/User/UserServiceImpl.java @@ -7,6 +7,7 @@ import TechVault.services.User.request.ChangePasswordRequest; import TechVault.services.User.request.PasswordForgotRequest; import TechVault.services.User.request.UserLoginRequest; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -17,6 +18,7 @@ import java.util.Random; import java.util.UUID; +@Slf4j @Service public class UserServiceImpl implements UserService { @Autowired @@ -31,7 +33,6 @@ public boolean register(User user) throws InvalidArgumentException { if (password.isEmpty()) { throw new InvalidArgumentException("Invalid password."); } - if (user.getUserName().isEmpty()) { user.setUserName(user.getEmail()); } @@ -42,7 +43,7 @@ public boolean register(User user) throws InvalidArgumentException { throw new InvalidArgumentException(user.getUserName() + " already registered."); } - if (userRepository.findByEmail(user.getEmail()).get() != null) { + if (userRepository.findByEmail(user.getEmail()) != null) { throw new InvalidArgumentException(user.getEmail() + " already registered."); } @@ -51,7 +52,6 @@ public boolean register(User user) throws InvalidArgumentException { user.setId(RANDOM.nextLong()); // Generate random 36-character string token for confirmation link user.setConfirmationToken(UUID.randomUUID().toString()); - userRepository.save(user); return true; @@ -60,7 +60,7 @@ public boolean register(User user) throws InvalidArgumentException { @Override public User resetUser(PasswordForgotRequest passwordForgotRequest) { - User userExists = userRepository.findByEmail(passwordForgotRequest.getEmail()).get(); + User userExists = userRepository.findByEmail(passwordForgotRequest.getEmail()); if (userExists == null) { throw new InvalidArgumentException(passwordForgotRequest.getEmail() + " is not registered."); @@ -117,26 +117,20 @@ public boolean loginUser(UserLoginRequest userLoginRequest) { } User userExists = null; if (userLoginRequest.getUserName() != null) { - userExists = userRepository.findByUserName(userExists.getUserName()); + userExists = userRepository.findByUserName(userLoginRequest.getUserName()); } else { - userExists = userRepository.findByEmail(userExists.getEmail()).get(); + userExists = userRepository.findByEmail(userLoginRequest.getEmail()); } - if (userExists == null) { throw new InvalidArgumentException("Invalid user name."); } - String password = userLoginRequest.getPassword(); if (!password.equals(userExists.getPassword())) { throw new InvalidArgumentException("Invalid user name and password combination."); } - if (userExists.getEmailVerified() == 0) { throw new InvalidArgumentException("The user is not enabled."); } - - userExists.setPassword(""); - userExists.setId(0L); return true; } @@ -145,12 +139,11 @@ public User fetchUser(String email) throws AccessDeniedException { if (Objects.isNull(email)) { throw new AccessDeniedException("Invalid access"); } - - Optional user = userRepository.findByEmail(email); - if (!user.isPresent()) { + User user = userRepository.findByEmail(email); + if (user == null) { throw new ResourceNotFoundException("User not found"); } - return user.get(); + return user; } @Override @@ -162,15 +155,6 @@ public User saveUser(User user) { return userRepository.save(user); } - @Override - public User findByEmail(String email) { - if (Objects.isNull(email)) { - throw new InvalidArgumentException("Null email"); - } - - return userRepository.findByEmail(email).orElse(null); - } - @Override public boolean userExistsByEmail(String email) { return userRepository.existsByEmail(email); diff --git a/src/main/java/TechVault/services/User/controller/UserController.java b/src/main/java/TechVault/services/User/controller/UserController.java index c6db5c0..9c370db 100644 --- a/src/main/java/TechVault/services/User/controller/UserController.java +++ b/src/main/java/TechVault/services/User/controller/UserController.java @@ -49,7 +49,7 @@ public ResponseEntity registerUser(@RequestBody @Valid RegisterUserRequest re registrationEmail.setTo(user.getEmail()); registrationEmail.setSubject("Registration Confirmation"); registrationEmail.setText("To confirm your e-mail address, please click the link below:\n" + webServerUrl - + "/users/confirm?token=" + user.getConfirmationToken()); + + "/user/confirm?token=" + user.getConfirmationToken()); registrationEmail.setFrom("noreply@domain.com"); emailService.sendEmail(registrationEmail); diff --git a/src/main/java/TechVault/services/User/persistence/UserRepository.java b/src/main/java/TechVault/services/User/persistence/UserRepository.java index 1da7af3..dc0e7b7 100644 --- a/src/main/java/TechVault/services/User/persistence/UserRepository.java +++ b/src/main/java/TechVault/services/User/persistence/UserRepository.java @@ -8,7 +8,7 @@ @Repository public interface UserRepository extends MongoRepository { - Optional findByEmail(String email); + User findByEmail(String email); Boolean existsByEmail(String email); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1fa6d91..3d017ae 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -13,4 +13,4 @@ spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.required=true #Used in the emails sent to users -webServerUrl=http://localhost:9000 \ No newline at end of file +webServerUrl=http://localhost:8080 \ No newline at end of file From 06bd61affab03872bb5a1dd5119118f78ae4a46d Mon Sep 17 00:00:00 2001 From: ManishKumarKeshri Date: Sat, 27 Mar 2021 17:19:10 -0700 Subject: [PATCH 4/6] Updating. Signed-off-by: ManishKumarKeshri --- .../java/TechVault/services/User/controller/UserController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/TechVault/services/User/controller/UserController.java b/src/main/java/TechVault/services/User/controller/UserController.java index 9c370db..03cb491 100644 --- a/src/main/java/TechVault/services/User/controller/UserController.java +++ b/src/main/java/TechVault/services/User/controller/UserController.java @@ -87,7 +87,7 @@ public ResponseEntity forgotPasswordRequest(@Valid @RequestBody PasswordForgo if (resetUser != null) { SimpleMailMessage registrationEmail = new SimpleMailMessage(); registrationEmail.setTo(passwordForgotRequest.getEmail()); - registrationEmail.setSubject("Temporary Password Sent From " + webServerUrl); + registrationEmail.setSubject("Temporary Password Sent From TechVault"); registrationEmail .setText("To access your account, please use this temporary password: " + resetUser.getPassword() + ".\r\nNOTE: This email was sent from an automated system. Please do not reply."); From 81dd56476d5aed5d1f8d6d6e11accba8514bebc5 Mon Sep 17 00:00:00 2001 From: ManishKumarKeshri Date: Sat, 22 May 2021 19:44:56 -0700 Subject: [PATCH 5/6] adding session. Signed-off-by: ManishKumarKeshri --- .idea/modules.xml | 8 ----- .../TechVault/services/User/UserService.java | 7 ++++- .../services/User/UserServiceImpl.java | 30 +++++++++++++++++-- .../User/controller/UserController.java | 24 +++++++++++++-- .../services/User/model/Session.java | 22 ++++++++++++++ .../User/persistence/SessionRepository.java | 12 ++++++++ .../User/persistence/UserRepository.java | 2 ++ .../services/User/response/UserResponse.java | 6 +++- 8 files changed, 97 insertions(+), 14 deletions(-) delete mode 100644 .idea/modules.xml create mode 100644 src/main/java/TechVault/services/User/model/Session.java create mode 100644 src/main/java/TechVault/services/User/persistence/SessionRepository.java diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 969f6be..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/main/java/TechVault/services/User/UserService.java b/src/main/java/TechVault/services/User/UserService.java index 2fc604d..58982ec 100644 --- a/src/main/java/TechVault/services/User/UserService.java +++ b/src/main/java/TechVault/services/User/UserService.java @@ -4,6 +4,7 @@ import TechVault.services.User.request.ChangePasswordRequest; import TechVault.services.User.request.PasswordForgotRequest; import TechVault.services.User.request.UserLoginRequest; +import TechVault.services.User.response.UserResponse; import java.nio.file.AccessDeniedException; @@ -20,7 +21,11 @@ public interface UserService { void confirmUser(String token); - boolean loginUser(UserLoginRequest userLoginRequest) ; + String loginUser(UserLoginRequest userLoginRequest); + + void logoutUser(String sessionId); + + UserResponse getUser(String sessionId); boolean userExistsByEmail(String email); diff --git a/src/main/java/TechVault/services/User/UserServiceImpl.java b/src/main/java/TechVault/services/User/UserServiceImpl.java index 118b5e6..d3736c7 100644 --- a/src/main/java/TechVault/services/User/UserServiceImpl.java +++ b/src/main/java/TechVault/services/User/UserServiceImpl.java @@ -2,11 +2,14 @@ import TechVault.services.User.exception.InvalidArgumentException; import TechVault.services.User.exception.ResourceNotFoundException; +import TechVault.services.User.model.Session; import TechVault.services.User.model.User; +import TechVault.services.User.persistence.SessionRepository; import TechVault.services.User.persistence.UserRepository; import TechVault.services.User.request.ChangePasswordRequest; import TechVault.services.User.request.PasswordForgotRequest; import TechVault.services.User.request.UserLoginRequest; +import TechVault.services.User.response.UserResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -24,6 +27,9 @@ public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; + @Autowired + private SessionRepository sessionRepository; + private static final Random RANDOM = new SecureRandom(); private static final String ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; @@ -111,7 +117,7 @@ public void confirmUser(String token) { } @Override - public boolean loginUser(UserLoginRequest userLoginRequest) { + public String loginUser(UserLoginRequest userLoginRequest) { if (userLoginRequest.getEmail() == null && userLoginRequest.getUserName() == null) { throw new InvalidArgumentException("Required either email or user name."); } @@ -131,7 +137,27 @@ public boolean loginUser(UserLoginRequest userLoginRequest) { if (userExists.getEmailVerified() == 0) { throw new InvalidArgumentException("The user is not enabled."); } - return true; + + Long user_id = userExists.getId(); + String sessionId = UUID.randomUUID().toString(); + Session session = new Session(); + session.setId(sessionId); + session.setUser_id(user_id); + sessionRepository.save(session); + return sessionId; + } + + @Override + public void logoutUser(String sessionId) { + Session session = sessionRepository.findById(sessionId).get(); + sessionRepository.delete(session); + } + + @Override + public UserResponse getUser(String sessionId) { + Session session = sessionRepository.findById(sessionId).get(); + User user = userRepository.findById(session.getUser_id()).get(); + return new UserResponse(user.getUserName(), user.getEmailVerified()); } @Override diff --git a/src/main/java/TechVault/services/User/controller/UserController.java b/src/main/java/TechVault/services/User/controller/UserController.java index 03cb491..cee2ebf 100644 --- a/src/main/java/TechVault/services/User/controller/UserController.java +++ b/src/main/java/TechVault/services/User/controller/UserController.java @@ -7,6 +7,7 @@ import TechVault.services.User.request.PasswordForgotRequest; import TechVault.services.User.request.RegisterUserRequest; import TechVault.services.User.request.UserLoginRequest; +import TechVault.services.User.response.UserResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -73,8 +74,27 @@ public ResponseEntity confirm(@RequestParam("token") String token) { @PostMapping(path = "/login") public ResponseEntity login(@Valid @RequestBody UserLoginRequest userLoginRequest) { try { - userService.loginUser(userLoginRequest); - return new ResponseEntity<>("Successful.", HttpStatus.OK); + return new ResponseEntity<>(userService.loginUser(userLoginRequest), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @PostMapping(path = "/logout") + public ResponseEntity login(@RequestParam("sessionId") String sessionId) { + try { + userService.logoutUser(sessionId); + return new ResponseEntity<>("Successful", HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + } + + @PostMapping(path = "/session") + public ResponseEntity getUser(@RequestParam("sessionId") String sessionId) { + try { + UserResponse userResponse = userService.getUser(sessionId); + return new ResponseEntity<>(userResponse, HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); } diff --git a/src/main/java/TechVault/services/User/model/Session.java b/src/main/java/TechVault/services/User/model/Session.java new file mode 100644 index 0000000..8f047fb --- /dev/null +++ b/src/main/java/TechVault/services/User/model/Session.java @@ -0,0 +1,22 @@ +package TechVault.services.User.model; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +@Document(collection = "session_token") +@Getter +@Setter +@NoArgsConstructor +public class Session { + + @Id + @Field(name = "_id") + private String id; + + @Field(name = "user_id") + private Long user_id; +} diff --git a/src/main/java/TechVault/services/User/persistence/SessionRepository.java b/src/main/java/TechVault/services/User/persistence/SessionRepository.java new file mode 100644 index 0000000..ab74b30 --- /dev/null +++ b/src/main/java/TechVault/services/User/persistence/SessionRepository.java @@ -0,0 +1,12 @@ +package TechVault.services.User.persistence; + +import TechVault.services.User.model.Session; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface SessionRepository extends MongoRepository { + Optional findById(String id); +} \ No newline at end of file diff --git a/src/main/java/TechVault/services/User/persistence/UserRepository.java b/src/main/java/TechVault/services/User/persistence/UserRepository.java index dc0e7b7..e53a6e4 100644 --- a/src/main/java/TechVault/services/User/persistence/UserRepository.java +++ b/src/main/java/TechVault/services/User/persistence/UserRepository.java @@ -16,5 +16,7 @@ public interface UserRepository extends MongoRepository { User findByUserName(String username); + Optional findById(Long id); + User findByConfirmationToken(String confirmationToken); } \ No newline at end of file diff --git a/src/main/java/TechVault/services/User/response/UserResponse.java b/src/main/java/TechVault/services/User/response/UserResponse.java index fa036a7..bb383f4 100644 --- a/src/main/java/TechVault/services/User/response/UserResponse.java +++ b/src/main/java/TechVault/services/User/response/UserResponse.java @@ -4,7 +4,11 @@ @Data public class UserResponse { - private String email; private String userName; private Integer emailVerified; + + public UserResponse(String userName, Integer emailVerified) { + this.userName = userName; + this.emailVerified = emailVerified; + } } From c2c4b1c437a9296653d4a1f84903810bc1356fab Mon Sep 17 00:00:00 2001 From: ManishKumarKeshri Date: Sat, 22 May 2021 20:01:12 -0700 Subject: [PATCH 6/6] Updating. Signed-off-by: ManishKumarKeshri --- .../java/TechVault/services/User/controller/UserController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/TechVault/services/User/controller/UserController.java b/src/main/java/TechVault/services/User/controller/UserController.java index cee2ebf..aab4777 100644 --- a/src/main/java/TechVault/services/User/controller/UserController.java +++ b/src/main/java/TechVault/services/User/controller/UserController.java @@ -81,7 +81,7 @@ public ResponseEntity login(@Valid @RequestBody UserLoginRequest userLoginReq } @PostMapping(path = "/logout") - public ResponseEntity login(@RequestParam("sessionId") String sessionId) { + public ResponseEntity logout(@RequestParam("sessionId") String sessionId) { try { userService.logoutUser(sessionId); return new ResponseEntity<>("Successful", HttpStatus.OK);