diff --git a/aconnect/src/main/java/com/mfsys/aconnect/security/controller/AuthenticationController.java b/aconnect/src/main/java/com/mfsys/aconnect/security/controller/AuthenticationController.java index 8ca6b0c..aa5544d 100644 --- a/aconnect/src/main/java/com/mfsys/aconnect/security/controller/AuthenticationController.java +++ b/aconnect/src/main/java/com/mfsys/aconnect/security/controller/AuthenticationController.java @@ -1,6 +1,7 @@ package com.mfsys.aconnect.security.controller; import com.mfsys.aconnect.security.constant.SecurityURI; +import com.mfsys.aconnect.security.dto.ChangePasswordDTO; import com.mfsys.aconnect.security.dto.LoginRequest; import com.mfsys.aconnect.security.dto.LoginResponse; import com.mfsys.aconnect.security.service.AuthenticationService; @@ -15,6 +16,9 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.HashMap; +import java.util.Map; + @RestController @RequestMapping(SecurityURI.AUTHENTICATION) public class AuthenticationController { @@ -46,9 +50,12 @@ public class AuthenticationController { } @PostMapping(SecurityURI.CHANGE_PASSWORD) - public ResponseEntity changePassword(@RequestBody UserDTOs.UserRequest request) { - UserDTOs.UserResponse response = userService.createUser(request); - return new ResponseEntity<>(response, HttpStatus.CREATED); + public ResponseEntity> changePassword(@RequestBody ChangePasswordDTO request) { + String message = userService.changePassword(request); + Map response = new HashMap<>(); + response.put("message", message); + + return new ResponseEntity<>(response, HttpStatus.OK); } } diff --git a/aconnect/src/main/java/com/mfsys/aconnect/security/dto/ChangePasswordDTO.java b/aconnect/src/main/java/com/mfsys/aconnect/security/dto/ChangePasswordDTO.java new file mode 100644 index 0000000..a4444f1 --- /dev/null +++ b/aconnect/src/main/java/com/mfsys/aconnect/security/dto/ChangePasswordDTO.java @@ -0,0 +1,11 @@ +package com.mfsys.aconnect.security.dto; + +import lombok.Data; + +@Data +public class ChangePasswordDTO { + private String userId; + private String porOrgacode; + private String oldPassword; + private String newPassword; +} diff --git a/aconnect/src/main/java/com/mfsys/aconnect/security/service/AuthenticationService.java b/aconnect/src/main/java/com/mfsys/aconnect/security/service/AuthenticationService.java index b90ec02..4efce05 100644 --- a/aconnect/src/main/java/com/mfsys/aconnect/security/service/AuthenticationService.java +++ b/aconnect/src/main/java/com/mfsys/aconnect/security/service/AuthenticationService.java @@ -36,7 +36,7 @@ public class AuthenticationService { String token = jwtService.generateToken(loginRequest.getUserId()); - return new LoginResponse(user, false, user.getIsFirstLogin(), token); + return new LoginResponse(user, false, user.isFirstLogin(), token); } } diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/dto/UserDTOs.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/dto/UserDTOs.java index b4d1651..2a37c97 100644 --- a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/dto/UserDTOs.java +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/dto/UserDTOs.java @@ -16,6 +16,7 @@ public class UserDTOs { @NoArgsConstructor public static class UserRequest { private String userId; + private String porOrgacode; private String userFullname; private String password; private String email; @@ -26,6 +27,7 @@ public class UserDTOs { @NoArgsConstructor public static class UserResponse { private String userId; + private String porOrgacode; private String userFullname; private String email; private Role role; diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/EmailAlreadyExistException.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/EmailAlreadyExistException.java new file mode 100644 index 0000000..4ed9cb7 --- /dev/null +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/EmailAlreadyExistException.java @@ -0,0 +1,11 @@ +package com.mfsys.aconnect.usermanagement.exceptions; + +import com.mfsys.common.configuration.constant.ERRCode; +import com.mfsys.common.configuration.exception.ApplicationException; + +public class EmailAlreadyExistException extends ApplicationException { + public EmailAlreadyExistException(String porOrgacode) { + super(porOrgacode, ERRCode.EMAIL_ALREADY_EXIST); + } +} + diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/OldPasswordNotMatch.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/OldPasswordNotMatch.java new file mode 100644 index 0000000..8187c8b --- /dev/null +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/OldPasswordNotMatch.java @@ -0,0 +1,12 @@ +package com.mfsys.aconnect.usermanagement.exceptions; + +import com.mfsys.common.configuration.constant.ERRCode; +import com.mfsys.common.configuration.exception.ResourceNotFoundException; + +public class OldPasswordNotMatch extends ResourceNotFoundException { + + public OldPasswordNotMatch(String porOrgacode) { + super(porOrgacode, ERRCode.PASSWORD_ALREADY_EXIST); + } +} + diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/UsernameAlreadyExistException.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/UsernameAlreadyExistException.java new file mode 100644 index 0000000..9accee6 --- /dev/null +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/exceptions/UsernameAlreadyExistException.java @@ -0,0 +1,10 @@ +package com.mfsys.aconnect.usermanagement.exceptions; + +import com.mfsys.common.configuration.constant.ERRCode; +import com.mfsys.common.configuration.exception.ApplicationException; + +public class UsernameAlreadyExistException extends ApplicationException { + public UsernameAlreadyExistException(String porOrgacode) { + super(porOrgacode, ERRCode.USERNAME_ALREADY_EXIST); + } +} \ No newline at end of file diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/model/User.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/model/User.java index 34a03e7..2402c6a 100644 --- a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/model/User.java +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/model/User.java @@ -1,5 +1,6 @@ package com.mfsys.aconnect.usermanagement.model; +import com.mfsys.common.configuration.constant.FieldNameLength; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Data; @@ -11,7 +12,7 @@ import java.time.LocalDateTime; import java.util.HashSet; import java.util.Set; -@Entity +@Entity(name = "users") @Table(name = "users") @Data @NoArgsConstructor @@ -22,6 +23,9 @@ public class User { @Column(name = "user_id", unique = true, nullable = false) private String userId; + @Column(name = "POR_ORGACODE", nullable = false, updatable = false, columnDefinition = FieldNameLength.POR_ORGACODE) + private String porOrgacode; + @Column(name = "user_fullname", nullable = false) private String userFullname; @@ -38,11 +42,11 @@ public class User { @Column(name = "permissions", columnDefinition = "TEXT") private String permissions; - @Column(name = "is_first_login") - private Boolean isFirstLogin = true; + @Column(name = "is_first_login", columnDefinition = FieldNameLength.BOOLEAN_BIT) + private boolean isFirstLogin = true; - @Column(name = "is_active") - private Boolean isActive = true; + @Column(name = "is_active", columnDefinition = FieldNameLength.BOOLEAN_BIT) + private boolean isActive = true; @CreationTimestamp @Column(name = "created_at", updatable = false) diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/repository/UserRepository.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/repository/UserRepository.java index a379e55..b04fa1d 100644 --- a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/repository/UserRepository.java +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/repository/UserRepository.java @@ -9,4 +9,6 @@ import java.util.Optional; @Repository public interface UserRepository extends JpaRepository { Optional findByUserIdAndIsActiveTrue(String userId); + boolean existsByUserId(String userId); + boolean existsByEmail(String email); } diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/PermissionService.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/PermissionService.java index 6e8b494..8daaa4b 100644 --- a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/PermissionService.java +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/PermissionService.java @@ -61,8 +61,8 @@ public class PermissionService { response.setUserFullname(user.getUserFullname()); response.setEmail(user.getEmail()); response.setRole(user.getRole()); - response.setIsFirstLogin(user.getIsFirstLogin()); - response.setIsActive(user.getIsActive()); + response.setIsFirstLogin(user.isFirstLogin()); + response.setIsActive(user.isActive()); response.setCreatedAt(user.getCreatedAt()); response.setUpdatedAt(user.getUpdatedAt()); return response; diff --git a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/UserService.java b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/UserService.java index f5ad9eb..7fe0bf5 100644 --- a/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/UserService.java +++ b/aconnect/src/main/java/com/mfsys/aconnect/usermanagement/service/UserService.java @@ -1,8 +1,11 @@ package com.mfsys.aconnect.usermanagement.service; +import com.mfsys.aconnect.security.dto.ChangePasswordDTO; +import com.mfsys.aconnect.usermanagement.exceptions.EmailAlreadyExistException; +import com.mfsys.aconnect.usermanagement.exceptions.OldPasswordNotMatch; +import com.mfsys.aconnect.usermanagement.exceptions.UsernameAlreadyExistException; import com.mfsys.common.configuration.service.PasswordEncryptionService; import com.mfsys.aconnect.usermanagement.dto.UserDTOs; -import com.mfsys.aconnect.usermanagement.dto.PermissionDTO; import com.mfsys.aconnect.usermanagement.model.User; import com.mfsys.aconnect.usermanagement.repository.UserRepository; import jakarta.persistence.EntityNotFoundException; @@ -10,7 +13,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; @Service @@ -26,8 +28,15 @@ public class UserService { @Transactional public UserDTOs.UserResponse createUser(UserDTOs.UserRequest request) { + if (userRepository.existsByUserId(request.getUserId())) { + throw new UsernameAlreadyExistException(request.getPorOrgacode()); + } + if (userRepository.existsByEmail(request.getEmail())) { + throw new EmailAlreadyExistException(request.getPorOrgacode()); + } User user = new User(); user.setUserId(request.getUserId()); + user.setPorOrgacode(request.getPorOrgacode()); user.setUserFullname(request.getUserFullname()); user.setEmail(request.getEmail()); user.setRole(request.getRole()); @@ -36,6 +45,20 @@ public class UserService { return mapToResponseDTO(savedUser); } + @Transactional + public String changePassword(ChangePasswordDTO request) { + User user = userRepository.findById(request.getUserId()) + .orElseThrow(() -> new EntityNotFoundException("User not found with ID: " + request.getUserId())); + + boolean isPasswordValid = PasswordEncryptionService.verifyPassword(request.getOldPassword(), request.getNewPassword()); + if(!isPasswordValid) { + throw new OldPasswordNotMatch(request.getPorOrgacode()); + } + user.setPassword(passwordEncryptionService.hashPassword(request.getNewPassword())); + userRepository.save(user); + return "Password changed successfully"; + } + public List getAllUsers() { return userRepository.findAll().stream() .map(this::mapToResponseDTO) @@ -68,9 +91,6 @@ public class UserService { userRepository.deleteById(userId); } - public Optional findActiveUserById(String userId) { - return userRepository.findByUserIdAndIsActiveTrue(userId); - } private UserDTOs.UserResponse mapToResponseDTO(User user) { UserDTOs.UserResponse response = new UserDTOs.UserResponse(); @@ -78,8 +98,8 @@ public class UserService { response.setUserFullname(user.getUserFullname()); response.setEmail(user.getEmail()); response.setRole(user.getRole()); - response.setIsFirstLogin(user.getIsFirstLogin()); - response.setIsActive(user.getIsActive()); + response.setIsFirstLogin(user.isFirstLogin()); + response.setIsActive(user.isActive()); response.setCreatedAt(user.getCreatedAt()); response.setUpdatedAt(user.getUpdatedAt()); return response; diff --git a/common/src/main/java/com/mfsys/common/configuration/constant/ERRCode.java b/common/src/main/java/com/mfsys/common/configuration/constant/ERRCode.java index 423ae36..01ffc07 100644 --- a/common/src/main/java/com/mfsys/common/configuration/constant/ERRCode.java +++ b/common/src/main/java/com/mfsys/common/configuration/constant/ERRCode.java @@ -2,7 +2,12 @@ package com.mfsys.common.configuration.constant; import com.mfsys.common.configuration.exception.ErrorMessage; -public enum ERRCode implements ErrorMessage {; +public enum ERRCode implements ErrorMessage { + EMAIL_ALREADY_EXIST("ERR_SEC_0001", "Email already exists"), + USERNAME_ALREADY_EXIST("ERR_SEC_0002", "Username already exists"), + PASSWORD_ALREADY_EXIST("ERR_SEC_0003", "Old Password is not correct"); + + private String code; private String description; diff --git a/common/src/main/java/com/mfsys/common/configuration/exception/ErrorMessage.java b/common/src/main/java/com/mfsys/common/configuration/exception/ErrorMessage.java index 0c082a8..d6cab4e 100644 --- a/common/src/main/java/com/mfsys/common/configuration/exception/ErrorMessage.java +++ b/common/src/main/java/com/mfsys/common/configuration/exception/ErrorMessage.java @@ -2,6 +2,5 @@ package com.mfsys.common.configuration.exception; public interface ErrorMessage { public String getCode(); - public String getDescription(); }