Add password change and user uniqueness validation

Introduced ChangePasswordDTO and implemented password change functionality in UserService and AuthenticationController. Added custom exceptions for existing email, username, and incorrect old password. Updated User entity and DTOs to include porOrgacode, and enforced uniqueness checks for userId and email. Enhanced ERRCode with new error codes and improved boolean field handling in User entity.
dev-pending-01-01-2026
Naeem Ullah 4 weeks ago
parent a1f993bfd4
commit 5e85a32f61

@ -1,6 +1,7 @@
package com.mfsys.aconnect.security.controller; package com.mfsys.aconnect.security.controller;
import com.mfsys.aconnect.security.constant.SecurityURI; 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.LoginRequest;
import com.mfsys.aconnect.security.dto.LoginResponse; import com.mfsys.aconnect.security.dto.LoginResponse;
import com.mfsys.aconnect.security.service.AuthenticationService; 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.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController @RestController
@RequestMapping(SecurityURI.AUTHENTICATION) @RequestMapping(SecurityURI.AUTHENTICATION)
public class AuthenticationController { public class AuthenticationController {
@ -46,9 +50,12 @@ public class AuthenticationController {
} }
@PostMapping(SecurityURI.CHANGE_PASSWORD) @PostMapping(SecurityURI.CHANGE_PASSWORD)
public ResponseEntity<UserDTOs.UserResponse> changePassword(@RequestBody UserDTOs.UserRequest request) { public ResponseEntity<Map<String, String>> changePassword(@RequestBody ChangePasswordDTO request) {
UserDTOs.UserResponse response = userService.createUser(request); String message = userService.changePassword(request);
return new ResponseEntity<>(response, HttpStatus.CREATED); Map<String, String> response = new HashMap<>();
response.put("message", message);
return new ResponseEntity<>(response, HttpStatus.OK);
} }
} }

@ -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;
}

@ -36,7 +36,7 @@ public class AuthenticationService {
String token = jwtService.generateToken(loginRequest.getUserId()); String token = jwtService.generateToken(loginRequest.getUserId());
return new LoginResponse(user, false, user.getIsFirstLogin(), token); return new LoginResponse(user, false, user.isFirstLogin(), token);
} }
} }

@ -16,6 +16,7 @@ public class UserDTOs {
@NoArgsConstructor @NoArgsConstructor
public static class UserRequest { public static class UserRequest {
private String userId; private String userId;
private String porOrgacode;
private String userFullname; private String userFullname;
private String password; private String password;
private String email; private String email;
@ -26,6 +27,7 @@ public class UserDTOs {
@NoArgsConstructor @NoArgsConstructor
public static class UserResponse { public static class UserResponse {
private String userId; private String userId;
private String porOrgacode;
private String userFullname; private String userFullname;
private String email; private String email;
private Role role; private Role role;

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

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

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

@ -1,5 +1,6 @@
package com.mfsys.aconnect.usermanagement.model; package com.mfsys.aconnect.usermanagement.model;
import com.mfsys.common.configuration.constant.FieldNameLength;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@ -11,7 +12,7 @@ import java.time.LocalDateTime;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@Entity @Entity(name = "users")
@Table(name = "users") @Table(name = "users")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -22,6 +23,9 @@ public class User {
@Column(name = "user_id", unique = true, nullable = false) @Column(name = "user_id", unique = true, nullable = false)
private String userId; private String userId;
@Column(name = "POR_ORGACODE", nullable = false, updatable = false, columnDefinition = FieldNameLength.POR_ORGACODE)
private String porOrgacode;
@Column(name = "user_fullname", nullable = false) @Column(name = "user_fullname", nullable = false)
private String userFullname; private String userFullname;
@ -38,11 +42,11 @@ public class User {
@Column(name = "permissions", columnDefinition = "TEXT") @Column(name = "permissions", columnDefinition = "TEXT")
private String permissions; private String permissions;
@Column(name = "is_first_login") @Column(name = "is_first_login", columnDefinition = FieldNameLength.BOOLEAN_BIT)
private Boolean isFirstLogin = true; private boolean isFirstLogin = true;
@Column(name = "is_active") @Column(name = "is_active", columnDefinition = FieldNameLength.BOOLEAN_BIT)
private Boolean isActive = true; private boolean isActive = true;
@CreationTimestamp @CreationTimestamp
@Column(name = "created_at", updatable = false) @Column(name = "created_at", updatable = false)

@ -9,4 +9,6 @@ import java.util.Optional;
@Repository @Repository
public interface UserRepository extends JpaRepository<User, String> { public interface UserRepository extends JpaRepository<User, String> {
Optional<User> findByUserIdAndIsActiveTrue(String userId); Optional<User> findByUserIdAndIsActiveTrue(String userId);
boolean existsByUserId(String userId);
boolean existsByEmail(String email);
} }

@ -61,8 +61,8 @@ public class PermissionService {
response.setUserFullname(user.getUserFullname()); response.setUserFullname(user.getUserFullname());
response.setEmail(user.getEmail()); response.setEmail(user.getEmail());
response.setRole(user.getRole()); response.setRole(user.getRole());
response.setIsFirstLogin(user.getIsFirstLogin()); response.setIsFirstLogin(user.isFirstLogin());
response.setIsActive(user.getIsActive()); response.setIsActive(user.isActive());
response.setCreatedAt(user.getCreatedAt()); response.setCreatedAt(user.getCreatedAt());
response.setUpdatedAt(user.getUpdatedAt()); response.setUpdatedAt(user.getUpdatedAt());
return response; return response;

@ -1,8 +1,11 @@
package com.mfsys.aconnect.usermanagement.service; 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.common.configuration.service.PasswordEncryptionService;
import com.mfsys.aconnect.usermanagement.dto.UserDTOs; 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.model.User;
import com.mfsys.aconnect.usermanagement.repository.UserRepository; import com.mfsys.aconnect.usermanagement.repository.UserRepository;
import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.EntityNotFoundException;
@ -10,7 +13,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -26,8 +28,15 @@ public class UserService {
@Transactional @Transactional
public UserDTOs.UserResponse createUser(UserDTOs.UserRequest request) { 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 user = new User();
user.setUserId(request.getUserId()); user.setUserId(request.getUserId());
user.setPorOrgacode(request.getPorOrgacode());
user.setUserFullname(request.getUserFullname()); user.setUserFullname(request.getUserFullname());
user.setEmail(request.getEmail()); user.setEmail(request.getEmail());
user.setRole(request.getRole()); user.setRole(request.getRole());
@ -36,6 +45,20 @@ public class UserService {
return mapToResponseDTO(savedUser); 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<UserDTOs.UserResponse> getAllUsers() { public List<UserDTOs.UserResponse> getAllUsers() {
return userRepository.findAll().stream() return userRepository.findAll().stream()
.map(this::mapToResponseDTO) .map(this::mapToResponseDTO)
@ -68,9 +91,6 @@ public class UserService {
userRepository.deleteById(userId); userRepository.deleteById(userId);
} }
public Optional<User> findActiveUserById(String userId) {
return userRepository.findByUserIdAndIsActiveTrue(userId);
}
private UserDTOs.UserResponse mapToResponseDTO(User user) { private UserDTOs.UserResponse mapToResponseDTO(User user) {
UserDTOs.UserResponse response = new UserDTOs.UserResponse(); UserDTOs.UserResponse response = new UserDTOs.UserResponse();
@ -78,8 +98,8 @@ public class UserService {
response.setUserFullname(user.getUserFullname()); response.setUserFullname(user.getUserFullname());
response.setEmail(user.getEmail()); response.setEmail(user.getEmail());
response.setRole(user.getRole()); response.setRole(user.getRole());
response.setIsFirstLogin(user.getIsFirstLogin()); response.setIsFirstLogin(user.isFirstLogin());
response.setIsActive(user.getIsActive()); response.setIsActive(user.isActive());
response.setCreatedAt(user.getCreatedAt()); response.setCreatedAt(user.getCreatedAt());
response.setUpdatedAt(user.getUpdatedAt()); response.setUpdatedAt(user.getUpdatedAt());
return response; return response;

@ -2,7 +2,12 @@ package com.mfsys.common.configuration.constant;
import com.mfsys.common.configuration.exception.ErrorMessage; 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 code;
private String description; private String description;

@ -2,6 +2,5 @@ package com.mfsys.common.configuration.exception;
public interface ErrorMessage { public interface ErrorMessage {
public String getCode(); public String getCode();
public String getDescription(); public String getDescription();
} }

Loading…
Cancel
Save