Merge pull request #9 from Kitzanos/feature/GEPAFINBE-6

GEPAFINBE-6(User related api)
This commit is contained in:
rbonazzo-KZ
2024-08-27 10:36:49 +02:00
committed by GitHub
18 changed files with 398 additions and 35 deletions

View File

@@ -54,7 +54,7 @@ public class SecurityConfig {
}
@Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
public MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
return new MvcRequestMatcher.Builder(introspector);
}
@@ -87,6 +87,7 @@ public class SecurityConfig {
return new CorsFilter(source);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
http

View File

@@ -48,6 +48,7 @@ public class TokenProvider {
public static final String INVALID_USER = "invalid_user";
static final String AUTH_SECRET = "X-Api-Secret";
private final Set<String> invalidatedTokens = new HashSet<>();
@PostConstruct
public void init() {
@@ -113,6 +114,10 @@ public class TokenProvider {
public boolean validateToken(String authToken) {
try {
if (isTokenInvalid(authToken)) {
log.warn("Token is invalidated.");
return false;
}
Jwts.parserBuilder()
.setSigningKey(key)
.build()
@@ -124,6 +129,15 @@ public class TokenProvider {
return false;
}
}
public void invalidateToken(String token) {
invalidatedTokens.add(token);
log.info("Token invalidated: {}", token);
}
public boolean isTokenInvalid(String token) {
return invalidatedTokens.contains(token);
}
public Map<String, Object> getUserInfoAndUserIdFromToken(HttpServletRequest request) {
Map<String, Object> userInfo = new HashMap<>();
String authSecretHeader=request.getHeader(AUTH_SECRET);
@@ -196,4 +210,12 @@ public class TokenProvider {
Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
return claims.getSubject();
}
public String extractTokenFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7); // Remove "Bearer " prefix
}
return null; // Return null if token is not found or not in Bearer format
}
}

View File

@@ -44,5 +44,13 @@ public class GepafinConstant {
public static final String DOCUMENT_ID_NOT_FOUND="document.id.not.found";
public static final String INVALID_DATE_MSG = "call.invalid.date";
public static final String RESET_PASSWORD_INITIATED = "password.reset.initiated";
public static final String PASSWORD_RESET_SUCCESS = "password.reset.success";
public static final String INVALID_TOKEN_MSG = "invalid.token.msg";
public static final String CURRENT_PASSWORD_INCORRECT = "current.password.incorrect";
public static final String LOGOUT_SUCCESSFUL_MSG = "logout.successful.msg";
public static final String SUCCESS_PASSWORD_CHANGED = "success.password.changed";
public static final String UPDATE_USER_STATUS_SUCCESS_MSG = "update.user.status.success";
}

View File

@@ -1,13 +1,13 @@
package net.gepafin.tendermanagement.dao;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.RoleEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.response.RoleResponseBean;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
@@ -23,6 +23,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Optional;
import static net.gepafin.tendermanagement.util.ObjectUtils.setIfUpdated;
@Repository
@@ -149,4 +153,82 @@ public class UserDao {
log.info("Login successful for email: {}", loginReq.getEmail());
return jwtToken;
}
public String generateSecureToken() {
SecureRandom secureRandom = new SecureRandom();
byte[] tokenBytes = new byte[24];
secureRandom.nextBytes(tokenBytes);
String token = Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes);
log.debug("Generated secure token: {}", token);
return token;
}
public String initiatePasswordReset(InitiatePasswordResetReq resetReq) {
UserEntity user = userRepository.findByEmail(resetReq.getEmail());
if (user == null) {
log.info("Password reset attempt for non-existent user: {}", resetReq.getEmail());
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG));
}
String token = generateSecureToken();
user.setResetPasswordToken(token);
userRepository.save(user);
log.info("Password reset token generated for user: {}", resetReq.getEmail());
return token;
}
public Boolean resetPassword(ResetPasswordReq resetPasswordReq) {
UserEntity user = userRepository.findByEmail(resetPasswordReq.getEmail());
if (user == null) {
log.info("Password reset attempt for non-existent user: {}", resetPasswordReq.getEmail());
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG));
}
if (!resetPasswordReq.getNewPassword().equals(resetPasswordReq.getConfirmPassword())) {
log.info("User creation failed: Passwords do not match for email {}", user.getEmail());
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH));
}
String dbToken = user.getResetPasswordToken();
if (dbToken == null || !dbToken.equals(resetPasswordReq.getToken())) {
log.info("Invalid password reset token for user: {}", resetPasswordReq.getEmail());
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG));
}
user.setPassword(passwordEncoder.encode(resetPasswordReq.getNewPassword()));
user.setResetPasswordToken(null);
userRepository.save(user);
log.info("Password successfully reset for user: {}", resetPasswordReq.getEmail());
return true;
}
public Boolean changePassword(ChangePasswordRequest request) {
UserEntity user = userRepository.findByEmail(request.getEmail());
if (user == null) {
log.info("Password reset attempt for non-existent user: {}", request.getEmail());
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG));
}
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.CURRENT_PASSWORD_INCORRECT));
}
if (!request.getNewPassword().equals(request.getConfirmPassword())) {
log.info("User creation failed: Passwords do not match for email {}", user.getEmail());
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH));
}
user.setPassword(passwordEncoder.encode(request.getNewPassword()));
userRepository.save(user);
return true;
}
public void logout(HttpServletRequest request, HttpServletResponse response) {
authService.logout(request, response);
log.info("User successfully logged out.");
}
public UserResponseBean updateUserStatus(Long userId, UserStatusEnum statusReq) {
log.info("Updating status for user with ID: {}", userId);
UserEntity userEntity = userRepository.findById(userId)
.orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)));
userEntity.setStatus(statusReq.getValue());
userEntity = userRepository.save(userEntity);
log.info("User status updated to {} for user ID: {}", statusReq, userId);
return convertUserEntityToUserResponse(userEntity);
}
}

View File

@@ -58,4 +58,6 @@ public class UserEntity extends BaseEntity {
@Column(name = "COUNTRY", length = 50, nullable = true)
private String country;
@Column(name = "RESET_PASSWORD_TOKEN", length = 255, nullable = true)
private String resetPasswordToken;
}

View File

@@ -0,0 +1,16 @@
package net.gepafin.tendermanagement.model.request;
import lombok.Data;
@Data
public class ChangePasswordRequest {
private String email;
private String password;
private String newPassword;
private String confirmPassword;
}

View File

@@ -0,0 +1,8 @@
package net.gepafin.tendermanagement.model.request;
import lombok.Data;
@Data
public class InitiatePasswordResetReq {
private String email;
}

View File

@@ -0,0 +1,10 @@
package net.gepafin.tendermanagement.model.request;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
@Data
public class LogoutReq {
private String email;
}

View File

@@ -0,0 +1,13 @@
package net.gepafin.tendermanagement.model.request;
import lombok.Data;
@Data
public class ResetPasswordReq {
private String email;
private String token;
private String newPassword;
private String confirmPassword;
}

View File

@@ -8,4 +8,5 @@ import java.util.Optional;
public interface UserRepository extends JpaRepository<UserEntity, Long> {
Optional<UserEntity> findByEmailIgnoreCase(String email);
boolean existsByEmailIgnoreCase(String email);
UserEntity findByEmail(String email);
}

View File

@@ -1,8 +1,9 @@
package net.gepafin.tendermanagement.service;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
@@ -16,4 +17,15 @@ public interface UserService {
void deleteUser(Long userId);
JWTToken login(LoginReq loginReq);
String initiatePasswordReset(InitiatePasswordResetReq resetReq);
Boolean resetPassword(ResetPasswordReq resetPasswordReq);
Boolean changePassword(ChangePasswordRequest request);
void logoutUser(HttpServletRequest request, HttpServletResponse response);
UserResponseBean updateUserStatus(Long userId, UserStatusEnum statusReq);
}

View File

@@ -1,5 +1,7 @@
package net.gepafin.tendermanagement.service.impl;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
import net.gepafin.tendermanagement.constants.GepafinConstant;
@@ -7,6 +9,7 @@ import net.gepafin.tendermanagement.dao.RoleDao;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.LogoutReq;
import net.gepafin.tendermanagement.model.response.LoginResponse;
import net.gepafin.tendermanagement.model.response.RoleResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
@@ -21,7 +24,9 @@ import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service
@@ -54,7 +59,7 @@ public class AuthenticationService {
UserEntity user = userRepository.findByEmailIgnoreCase(loginReq.getEmail()).orElseThrow(()-> new CustomValidationException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)));
if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) {
new CustomValidationException(Status.NOT_FOUND,
throw new CustomValidationException(Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG));
}
user.setLastLogin(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
@@ -88,6 +93,16 @@ public class AuthenticationService {
loginResponse.setCreatedDate(user.getCreatedDate());
loginResponse.setUpdatedDate(user.getUpdatedDate());
return loginResponse;
}
public void logout(HttpServletRequest request, HttpServletResponse response)
{ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
String token = tokenProvider.extractTokenFromRequest(request);
tokenProvider.invalidateToken(token);
new SecurityContextLogoutHandler().logout(request, response, auth);
}
SecurityContextHolder.getContext().setAuthentication(null);
SecurityContextHolder.clearContext();
}
}

View File

@@ -1,9 +1,10 @@
package net.gepafin.tendermanagement.service.impl;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.dao.UserDao;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.response.LoginResponse;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
@@ -50,4 +51,27 @@ public class UserServiceImpl implements UserService {
}
@Override
public String initiatePasswordReset(InitiatePasswordResetReq resetReq) {
return userDao.initiatePasswordReset(resetReq);
}
@Override
public Boolean resetPassword(ResetPasswordReq resetPasswordReq) {
return userDao.resetPassword(resetPasswordReq);
}
@Override
public Boolean changePassword(ChangePasswordRequest request){
return userDao.changePassword(request);
}
@Override
public void logoutUser(HttpServletRequest request, HttpServletResponse response) {
userDao.logout(request,response);
}
@Override
@Transactional(rollbackFor = Exception.class)
public UserResponseBean updateUserStatus(Long userId, UserStatusEnum statusReq) {
return userDao.updateUserStatus(userId, statusReq);
}
}

View File

@@ -5,10 +5,12 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
import net.gepafin.tendermanagement.model.util.Response;
@@ -18,10 +20,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.*;
@Validated
public interface UserApi {
@@ -105,4 +104,77 @@ public interface UserApi {
method = RequestMethod.POST)
ResponseEntity<Response<JWTToken>> login(
@Parameter(description = "Login request object", required = true) @Valid @RequestBody LoginReq loginReq);
@Operation(summary = "Api to initiate password reset request",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "/reset-password/initiate",
produces = {"application/json"},
method = RequestMethod.POST)
ResponseEntity<Response<String>> initiatePasswordReset(
@Parameter(description = "Initiate password reset request object", required = true) @Valid @RequestBody InitiatePasswordResetReq initiatePasswordResetReq);
@Operation(summary = "Api to reset password",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "/reset-password",
produces = {"application/json"},
method = RequestMethod.POST)
ResponseEntity<Response<Boolean>> resetPassword(
@Parameter(description = "Reset password request object", required = true) @Valid @RequestBody ResetPasswordReq resetPasswordReq);
@Operation(summary = "Api to change user password",
responses = {
@ApiResponse(responseCode = "200", description = "Password Changed Successfully", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = "{ \"message\": \"Password changed successfully.\" }")})),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "/change-password",
produces = {"application/json"},
method = RequestMethod.POST)
ResponseEntity<Response<Boolean>> changePassword(
@Parameter(description = "Change password request object", required = true) @Valid @RequestBody ChangePasswordRequest changePasswordRequest); @Operation(summary = "Api to logout user",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
@RequestMapping(value = "/logout",
method = RequestMethod.POST)
ResponseEntity<Response<Void>> logoutUser(
@Parameter(description = "The request object is not needed for logout", required = false) HttpServletRequest request,
@Parameter(description = "The response object is not needed for logout", required = false) HttpServletResponse response);
@Operation(summary = "Api to update user active/deactive status",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))
})
@RequestMapping(value = "/{userId}/status",
produces = {"application/json"},
method = RequestMethod.PUT)
@PreAuthorize("hasRole('ROLE_SUPER_ADMIN')")
default ResponseEntity<Response<UserResponseBean>> updateUserStatus(
@Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId,
@Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) UserStatusEnum status) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
}

View File

@@ -1,17 +1,19 @@
package net.gepafin.tendermanagement.web.rest.api.impl;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.service.UserService;
import net.gepafin.tendermanagement.web.rest.api.UserApi;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,7 +29,8 @@ import org.springframework.web.bind.annotation.*;
public class UserApiController implements UserApi {
private final Logger log = LoggerFactory.getLogger(UserApiController.class);
@Autowired
private TokenProvider tokenProvider;
@Autowired
private UserService userService;
@@ -74,4 +77,46 @@ public class UserApiController implements UserApi {
JWTToken jwtToken = userService.login(loginReq);
return ResponseEntity.ok(new Response<>(jwtToken, Status.SUCCESS, Translator.toLocale(GepafinConstant.LOGIN_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<Boolean>> changePassword(@Valid @RequestBody ChangePasswordRequest request) {
log.info("Change Password attempt for email: {}", request.getEmail());
userService.changePassword(request);
return ResponseEntity.ok(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.SUCCESS_PASSWORD_CHANGED)));
}
@Override
public ResponseEntity<Response<String>> initiatePasswordReset(InitiatePasswordResetReq request) {
log.info("Initiating password reset for email: {}", request.getEmail());
String resetToken = userService.initiatePasswordReset(request);
log.info("Password reset token generated for email: {}", request.getEmail());
return ResponseEntity.ok(new Response<>(resetToken, Status.SUCCESS, Translator.toLocale(GepafinConstant.RESET_PASSWORD_INITIATED)));
}
@Override
public ResponseEntity<Response<Boolean>> resetPassword(ResetPasswordReq request) {
log.info("Resetting password for username: {}", request.getEmail());
Boolean success = userService.resetPassword(request);
if (success) {
log.info("Password reset successfully for username: {}", request.getEmail());
} else {
log.error("Password reset failed for username: {}", request.getEmail());
}
return ResponseEntity.ok(new Response<>(success, Status.SUCCESS, Translator.toLocale(GepafinConstant.PASSWORD_RESET_SUCCESS)));
}
@Override
public ResponseEntity<Response<Void>> logoutUser(HttpServletRequest request, HttpServletResponse response) {
userService.logoutUser(request, response);
log.info("User has successfully logged");
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.LOGOUT_SUCCESSFUL_MSG)));
}
@Override
public ResponseEntity<Response<UserResponseBean>> updateUserStatus(@PathVariable Long userId, @RequestParam UserStatusEnum status) {
log.info("Update User Status for- User ID: {}, Request Body: {}", userId, status);
UserResponseBean updatedUser = userService.updateUserStatus(userId, status);
return ResponseEntity.ok(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.UPDATE_USER_STATUS_SUCCESS_MSG)));
}
}

View File

@@ -395,4 +395,12 @@
<column name="country" value="Italy"/>
</insert>
</changeSet>
<changeSet id="23-08-2024_1" author="Harish Bagora">
<addColumn tableName="gepafin_user">
<column name="reset_password_token" type="VARCHAR(255)">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>

View File

@@ -57,6 +57,20 @@ invalid_signature=Invalid token.
invalid_login=Invalid username or password.
req_validation_er=Request Validation Error
# Password reset messages
password.reset.initiated=Password reset initiated.
password.reset.success=Password has been successfully reset.
#Change Password
invalid.token.msg=The token provided is invalid or expired. Please request a new token.
current.password.incorrect = Current password is incorrect.
success.password.changed=Password changed successfully.
#Logout
logout.successful.msg=Logout successful. You have been logged out successfully.
#Update user Active or Deactive status
update.user.status.success=User status has been successfully updated.

View File

@@ -55,3 +55,13 @@ common_message=qualcosa é andato storto. Per favore riprova
invalid_signature=Gettone non valido.
invalid_login=Nome utente o password errati
req_validation_er=Errore di convalida
# Password reset messages
password.reset.initiated=Reimpostazione della password avviata.
password.reset.success=La password è stata reimpostata con successo.
invalid.token.msg=Il token fornito è invalido o scaduto. Si prega di richiedere un nuovo token.
current.password.incorrect = La password attuale non è corretta.
success.password.changed=Password cambiata con successo.
logout.successful.msg=Logout riuscito. Sei stato disconnesso con successo.
update.user.status.success=Lo stato dell'utente è stato aggiornato con successo.