Added action logs for user api's.

This commit is contained in:
piyushkag
2024-11-22 09:05:21 +05:30
parent 531738f82f
commit dd148c0ebf
18 changed files with 404 additions and 73 deletions

View File

@@ -156,7 +156,7 @@ public class GepafinConstant {
public static final String IS_PIVA = "isPIVA";
public static final String FAILED_RETAIN_FIELD = "failed.retain.field";
public static final String USER_ALREADY_EXIST_MSG = "user.already.exist.msg";
public static final String TOKEN_VALIDATE_SUCCESS_MSE = "token.validate.success";
public static final String TOKEN_VALIDATE_SUCCESS_MSG = "token.validate.success";
public static final String INVALID_REQUEST = "invalid.request";
public static final String CODICE_FISCALE_EXISTS = "codice.fiscale.exists";
public static final String TOTAL_STEPS_NOT_BE_ZERO = "total.steps.not.zero";

View File

@@ -1,12 +1,17 @@
package net.gepafin.tendermanagement.dao;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.model.response.LoginAttemptPageableResponseBean;
import net.gepafin.tendermanagement.repositories.LoginAttemptRepository;
import net.gepafin.tendermanagement.util.DateTimeUtil;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
@@ -24,10 +29,29 @@ public class LoginAttemptDao {
@Autowired
LoginAttemptRepository loginAttemptRepository;
public void createLoginAttempt(LoginAttemptEntity loginAttemptEntity) {
loginAttemptEntity.setAttemptDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
@Autowired
private LoggingUtil loggingUtil;
loginAttemptRepository.save(loginAttemptEntity);
@Autowired
private HttpServletRequest request;
public LoginAttemptEntity createLoginAttempt(LoginAttemptEntity loginAttemptEntity) {
VersionActionTypeEnum actionType;
LoginAttemptEntity oldLoginAttemptEntity = Utils.getClonedEntityForData(loginAttemptEntity);
loginAttemptEntity.setAttemptDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
if(loginAttemptEntity.getId() != null ) {
actionType = VersionActionTypeEnum.UPDATE;
}else{
actionType = VersionActionTypeEnum.INSERT;
oldLoginAttemptEntity = null;
}
loginAttemptEntity = loginAttemptRepository.save(loginAttemptEntity);
/** This code is responsible for adding a version history log for "Create Login Attempt" operation. **/
loggingUtil.addVersionHistoryWithoutToken(VersionHistoryRequest.builder().actionType(actionType).request(request).oldData(oldLoginAttemptEntity).newData(loginAttemptEntity).build());
return loginAttemptEntity;
}
public LoginAttemptPageableResponseBean<List<LoginAttemptEntity>> getLoginAttemptsList(UserEntity userEntity, Integer pageNo, Integer pageLimit) {

View File

@@ -7,7 +7,10 @@ import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.enums.RoleStatusEnum;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.response.CompanyResponse;
import net.gepafin.tendermanagement.model.response.RoleResponseBean;
@@ -19,6 +22,7 @@ import net.gepafin.tendermanagement.repositories.UserRepository;
import net.gepafin.tendermanagement.service.HubService;
import net.gepafin.tendermanagement.service.RoleService;
import net.gepafin.tendermanagement.service.impl.AuthenticationService;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.util.Validator;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
@@ -80,28 +84,43 @@ public class UserDao {
@Autowired
private AuthenticationService authenticationService;
@Autowired
private LoggingUtil loggingUtil;
@Autowired
private HttpServletRequest request;
public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) {
if(StringUtils.isEmpty(userReq.getHubUuid())) {
userReq.setHubUuid(defaultHubUuid);
}
HubEntity hub = hubService.getHubByUuid(userReq.getHubUuid());
validateUserRequest(request, tempToken, userReq, hub);
validatePassword(userReq.getPassword(), userReq.getConfPassword(), tempToken);
RoleEntity roleEntity = getRoleEntity(userReq.getRoleId());
BeneficiaryEntity beneficiary = createBeneficiary(roleEntity, userReq, hub);
if (StringUtils.isEmpty(userReq.getHubUuid())) {
userReq.setHubUuid(defaultHubUuid);
}
HubEntity hub = hubService.getHubByUuid(userReq.getHubUuid());
validateUserRequest(request, tempToken, userReq, hub);
validatePassword(userReq.getPassword(), userReq.getConfPassword(), tempToken);
RoleEntity roleEntity = getRoleEntity(userReq.getRoleId());
BeneficiaryEntity beneficiary = createBeneficiary(roleEntity, userReq, hub);
UserEntity userEntity = convertUserRequestToUserEntity(beneficiary, roleEntity, userReq, hub);
log.info("User created with ID: {}", userEntity.getId());
LoginReq loginReq=new LoginReq();
LoginReq loginReq = new LoginReq();
loginReq.setEmail(userEntity.getEmail());
LoginAttemptEntity loginAttemptEntity = null;
if(userEntity!=null){
if (userEntity != null) {
loginAttemptEntity = authenticationService.prepareLoginAttemptEntity(loginReq, request);
log.info("Authentication failed for email: {}", loginReq.getEmail());
loginAttemptEntity.setUserId(userEntity.getId());
authenticationService.createSuccessLoginAttempt(loginAttemptEntity);
authenticationService.createSuccessLoginAttempt(loginAttemptEntity);
}
return authService.getJWTTokenBean(userEntity, Boolean.TRUE, loginAttemptEntity.getId());
JWTToken token = authService.getJWTTokenBean(userEntity, Boolean.TRUE, loginAttemptEntity.getId());
/** This code is responsible for adding a version history log for the "Create beneficiary" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).newData(beneficiary).build());
/** This code is responsible for adding a version history log for the "Create user" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).newData(userEntity).build());
return token;
}
private BeneficiaryEntity createBeneficiary(RoleEntity roleEntity, UserReq userReq, HubEntity hub) {
@@ -196,6 +215,7 @@ public class UserDao {
public UserResponseBean updateUser(Long userId, UpdateUserReq userReq) {
log.info("Updating user with ID: {}", userId);
UserEntity userEntity=validateUser(userId);
UserEntity oldUserEntity = Utils.getClonedEntityForData(userEntity);
log.info("Current user details: {}", userEntity);
log.info("New user details: {}", userReq);
String newStatus = userReq.getStatus() != null ? userReq.getStatus().getValue() : null;
@@ -218,6 +238,10 @@ public class UserDao {
}
setIfUpdated(userEntity.getBeneficiary()::getEmailPec, userEntity.getBeneficiary()::setEmailPec, userReq.getEmailPec());
userEntity = userRepository.save(userEntity);
/** This code is responsible for adding a version history log for the "Update user details" operation **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(oldUserEntity).newData(userEntity).build());
log.info("User updated with ID: {}", userEntity.getId());
return convertUserEntityToUserResponse(userEntity);
}
@@ -305,7 +329,11 @@ public class UserDao {
public void deleteUser(Long id) {
log.info("Deleting user with ID: {}", id);
validateUser(id);
UserEntity oldUserData = validateUser(id);
/** This code is responsible for adding a version history log for the "Delete user" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.DELETE).oldData(oldUserData).build());
userRepository.deleteById(id);
log.info("User deleted with ID: {}", id);
}

View File

@@ -1,21 +1,14 @@
package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.Data;
import java.time.LocalDateTime;
@Entity
@Table(name = "LOGIN_ATTEMPT")
@Getter
@Setter
public class LoginAttemptEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true)
private Long id;
@Data
public class LoginAttemptEntity extends BaseEntity{
@Column(name = "USERNAME")
private String username;

View File

@@ -38,6 +38,6 @@ public class UserActionEntity extends BaseEntity {
private String actionContext;
@Column(name = "RESPONSE")
private Object response;
private String response;
}

View File

@@ -3,7 +3,7 @@ package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum UserActionContextEnum {
/** call action context **/
CREATE_CALL_STEP_1("CREATE_CALL_STEP_1"),
UPDATE_CALL_STEP_1("UPDATE_CALL_STEP_1"),
@@ -12,10 +12,17 @@ public enum UserActionContextEnum {
UPDATE_CALL_STATUS("UPDATE_CALL_STATUS"),
GET_CALL("GET_CALL"),
DOWNLOAD_CALL_DOCUMENT("DOWNLOAD_CALL_DOCUMENT"),
/** user action context **/
CREATE_USER("CREATE_USER");
CREATE_USER("CREATE_USER"),
USER_LOGIN("USER_LOGIN"),
LOGOUT_USER("LOGOUT_USER"),
GET_USER("GET_USER"),
UPDATE_USER_DETAILS("UPDATE_USER_DETAILS"),
DELETE_USER("DELETE_USER"),
VALIDATE_NEW_USER_WITH_SPID_TOKEN("VALIDATE_NEW_USER_WITH_SPID_TOKEN"),
VALIDATE_EXISTING_USER_WITH_SPID_TOKEN("VALIDATE_EXISTING_USER_WITH_SPID_TOKEN"),
GET_VALID_USER_DETAILS("GET_VALID_USER_DETAILS");
private final String value;

View File

@@ -3,7 +3,14 @@ package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum UserActionLogsEnum {
LOGIN("LOGIN"), LOGOUT("LOGOUT"), UPDATE("UPDATE"), DELETE("DELETE"), VIEW("VIEW"), INSERT("INSERT"), DOWNLOAD("DOWNLOAD"), UPLOAD("UPLOAD");
LOGIN("LOGIN"),
LOGOUT("LOGOUT"),
UPDATE("UPDATE"),
DELETE("DELETE"),
VIEW("VIEW"),
INSERT("INSERT"),
DOWNLOAD("DOWNLOAD"),
UPLOAD("UPLOAD");
private final String value;

View File

@@ -3,7 +3,10 @@ package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum VersionActionTypeEnum {
UPDATE("UPDATE"), DELETE("DELETE"), SOFT_DELETE("SOFT_DELETE"), INSERT("INSERT");
UPDATE("UPDATE"),
DELETE("DELETE"),
SOFT_DELETE("SOFT_DELETE"),
INSERT("INSERT");
private final String value;

View File

@@ -1,6 +1,7 @@
package net.gepafin.tendermanagement.model.request;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Builder;
import lombok.Data;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
@@ -12,4 +13,5 @@ public class UserActionRequest {
private HttpServletRequest request;
private UserActionLogsEnum actionType;
private UserActionContextEnum actionContext;
private Object response;
}

View File

@@ -6,4 +6,5 @@ import org.springframework.stereotype.Repository;
@Repository
public interface UserActionsRepository extends JpaRepository<UserActionEntity, Long> {
UserActionEntity findUserActionById(Long id);
}

View File

@@ -4,6 +4,13 @@ import net.gepafin.tendermanagement.entities.VersionHistoryEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface VersionHistoryRepository extends JpaRepository<VersionHistoryEntity, Long> {
List<VersionHistoryEntity> findVersionHistoryById(Long id);
List<VersionHistoryEntity> findVersionHistoryByUserActionIdAndUserIdNull(Long id);
List<VersionHistoryEntity> findVersionHistoryByUserActionId(Long id);
}

View File

@@ -15,16 +15,20 @@ import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.LoginAttemptResultEnum;
import net.gepafin.tendermanagement.enums.LoginAttemptTypeEnum;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.model.response.CompanyResponse;
import net.gepafin.tendermanagement.model.response.LoginResponse;
import net.gepafin.tendermanagement.model.response.RoleResponseBean;
import net.gepafin.tendermanagement.model.response.UserSamlResponse;
import net.gepafin.tendermanagement.model.util.JWTToken;
import net.gepafin.tendermanagement.repositories.LoginAttemptRepository;
import net.gepafin.tendermanagement.repositories.SamlResponseRepository;
import net.gepafin.tendermanagement.repositories.UserRepository;
import net.gepafin.tendermanagement.service.HubService;
import net.gepafin.tendermanagement.util.DateTimeUtil;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
@@ -51,6 +55,7 @@ public class AuthenticationService {
private final TokenProvider tokenProvider;
private final AuthenticationManager authenticationManager;
@Autowired
private CompanyDao companyDao;
@@ -69,6 +74,15 @@ public class AuthenticationService {
@Autowired
private HubService hubService;
@Autowired
private HttpServletRequest request;
@Autowired
private LoggingUtil loggingUtil;
@Autowired
LoginAttemptRepository loginAttemptRepository;
@Autowired
public AuthenticationService(TokenProvider tokenProvider, AuthenticationManager authenticationManager) {
this.tokenProvider = tokenProvider;
@@ -117,9 +131,9 @@ public class AuthenticationService {
return loginAttemptEntity;
}
public void createSuccessLoginAttempt(LoginAttemptEntity loginAttemptEntity) {
public LoginAttemptEntity createSuccessLoginAttempt(LoginAttemptEntity loginAttemptEntity) {
loginAttemptEntity.setResult(LoginAttemptResultEnum.SUCCESS.getValue());
loginAttemptDao.createLoginAttempt(loginAttemptEntity);
return loginAttemptDao.createLoginAttempt(loginAttemptEntity);
}
public void createFailedLoginAttempt(LoginAttemptEntity loginAttemptEntity, String errorMsg) {
loginAttemptEntity.setResult(LoginAttemptResultEnum.FAILED.getValue());
@@ -127,9 +141,11 @@ public class AuthenticationService {
loginAttemptDao.createLoginAttempt(loginAttemptEntity);
}
public JWTToken getJWTTokenBean(UserEntity user, Boolean rememberMe, Long loginAttemptId) {
UserEntity oldUserEntity = Utils.getClonedEntityForData(user);
user.setLastLogin(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
user = userRepository.save(user);
String token = tokenProvider.createToken(rememberMe, user, loginAttemptId);
log.info("JWT token generated for email: {}", user.getEmail());
RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(user.getRoleEntity());
@@ -137,6 +153,9 @@ public class AuthenticationService {
JWTToken jwtToken = new JWTToken(token, loginResponse);
/** This code is responsible for adding a version history log for the "Create user Or Update user" operation. **/
loggingUtil.addVersionHistoryWithoutToken(VersionHistoryRequest.builder().request(request).oldData(oldUserEntity).newData(user).actionType(VersionActionTypeEnum.UPDATE).build());
log.info("Login successful for email: {}", user.getEmail());
return jwtToken;
}
@@ -215,7 +234,8 @@ public class AuthenticationService {
loginReq.setEmail(userEntity.getEmail());
loginAttemptEntity = prepareLoginAttemptEntity(loginReq, request);
loginAttemptEntity.setUserId(userEntity.getId());
return getJWTTokenBean(userEntity, Boolean.TRUE, loginAttemptEntity.getId());
LoginAttemptEntity loginAttempt = createSuccessLoginAttempt(loginAttemptEntity);
return getJWTTokenBean(userEntity, Boolean.TRUE, loginAttempt.getId());
} catch (Exception e) {
log.info("Authentication login failed for email: {}",e.getMessage());
loginAttemptEntity.setUserId(userId);

View File

@@ -4,6 +4,8 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.dao.UserDao;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.request.UpdateUserReq;
import net.gepafin.tendermanagement.model.request.UserReq;
@@ -13,6 +15,7 @@ import net.gepafin.tendermanagement.model.response.UserSamlResponse;
import net.gepafin.tendermanagement.model.response.UserResponseBean;
import net.gepafin.tendermanagement.model.util.JWTToken;
import net.gepafin.tendermanagement.service.UserService;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.util.Validator;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +34,9 @@ public class UserServiceImpl implements UserService {
@Autowired
private Validator validator;
@Autowired
private LoggingUtil loggingUtil;
@Override
@Transactional(rollbackFor = Exception.class)
public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) {

View File

@@ -9,6 +9,7 @@ import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.UserActionEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.entities.VersionHistoryEntity;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
import net.gepafin.tendermanagement.model.request.UserActionRequest;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.repositories.UserActionsRepository;
@@ -18,6 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@Slf4j
@Component
@RequestScope
@@ -33,13 +38,15 @@ public class LoggingUtil {
private UserService userService;
@Autowired
TokenProvider tokenProvider;
private TokenProvider tokenProvider;
public UserActionEntity logUserAction(UserActionRequest userActionRequest) {
UserActionEntity userAction = new UserActionEntity();
try {
String token = tokenProvider.extractTokenFromRequest(userActionRequest.getRequest());
Claims claims = tokenProvider.getClaimsFromToken(token);
Map<String, String[]> parameters = userActionRequest.getRequest().getParameterMap();
parameters.forEach((key, value) -> log.info("Query Parameter: {} = {}", key, Arrays.toString(value)));
Long userId = claims.get(GepafinConstant.USER_ID, Long.class);
Long loginAttemptId = claims.get(GepafinConstant.LOGIN_ATTEMPT_ID, Long.class);
UserEntity userEntity = userService.validateUser(userId);
@@ -57,7 +64,8 @@ public class LoggingUtil {
userAction.setLoginAttemptId(loginAttemptId);
userAction.setIpAddress(IpAddressUtils.getClientIp(userActionRequest.getRequest()));
userAction.setRequestBody(requestBody);
userAction.setResponse(null);
String response = Utils.convertEntityToJsonForLogging(userActionRequest.getResponse());
userAction.setResponse(response);
userActionsRepository.save(userAction);
userActionRequest.getRequest().setAttribute(GepafinConstant.USER_ACTION_ID, userAction.getId());
} catch (Exception e) {
@@ -116,6 +124,31 @@ public class LoggingUtil {
}
}
public void logVersionHistoryWithoutToken(VersionHistoryRequest versionHistoryRequest, Long recordId, Long userActionId, String tableName) {
try {
VersionHistoryEntity history = new VersionHistoryEntity();
Long userId = null;
String token = tokenProvider.extractTokenFromRequest(versionHistoryRequest.getRequest());
if(versionHistoryRequest.getRequest() != null && token != null)
{
Claims claims = tokenProvider.getClaimsFromToken(token);
userId = claims.get(GepafinConstant.USER_ID, Long.class);
}
String oldData = Utils.convertEntityToJsonForLogging(versionHistoryRequest.getOldData());
String newData = Utils.convertEntityToJsonForLogging(versionHistoryRequest.getNewData());
history.setUserActionId(userActionId);
history.setActionType(versionHistoryRequest.getActionType().getValue());
history.setOldData(oldData);
history.setNewData(newData);
history.setRecordId(recordId);
history.setTableName(tableName);
history.setUserId(userId);
versionHistoryRepository.save(history);
} catch (Exception e) {
log.error("Error logging version history: {}", e.getMessage(), e);
}
}
public String getTableName(Class<?> entityClass) {
try {
if (entityClass.isAnnotationPresent(Table.class)) {
@@ -132,15 +165,138 @@ public class LoggingUtil {
try {
Long userActionId = (Long) versionHistoryRequest.getRequest().getAttribute(GepafinConstant.USER_ACTION_ID);
Long recordId = null;
String tableName = null;
if(versionHistoryRequest.getNewData() != null) {
recordId = versionHistoryRequest.getNewData().getId();
recordId = versionHistoryRequest.getNewData().getId();
tableName = getTableName(versionHistoryRequest.getNewData().getClass());
} else if(versionHistoryRequest.getOldData() != null){
recordId = versionHistoryRequest.getOldData().getId();
recordId = versionHistoryRequest.getOldData().getId();
}
String tableName = getTableName(versionHistoryRequest.getNewData().getClass());
logVersionHistory(versionHistoryRequest, recordId, userActionId, tableName);
} catch (Exception e) {
log.error("Error adding version history: {}", e.getMessage(), e);
}
}
public void addVersionHistoryWithoutToken(VersionHistoryRequest versionHistoryRequest) {
try {
Long userActionId = (Long) versionHistoryRequest.getRequest().getAttribute(GepafinConstant.USER_ACTION_ID);
Long recordId = null;
String tableName = null;
if(versionHistoryRequest.getNewData() != null) {
recordId = versionHistoryRequest.getNewData().getId();
tableName = getTableName(versionHistoryRequest.getNewData().getClass());
} else if(versionHistoryRequest.getOldData() != null){
recordId = versionHistoryRequest.getOldData().getId();
tableName = getTableName(versionHistoryRequest.getOldData().getClass());
}
versionHistoryRequest.setNewData(versionHistoryRequest.getNewData());
versionHistoryRequest.setRequest(versionHistoryRequest.getRequest());
logVersionHistoryWithoutToken(versionHistoryRequest, recordId, userActionId, tableName);
} catch (Exception e) {
log.error("Error adding version history: {}", e.getMessage(), e);
}
}
public UserActionEntity logUserActionWithoutToken(UserActionRequest userActionRequest) {
UserActionEntity userAction = new UserActionEntity();
try {
Long userId = null;
Long loginAttemptId = null;
Long hubId = null;
String token = tokenProvider.extractTokenFromRequest(userActionRequest.getRequest());
Map<String, String[]> parameters = userActionRequest.getRequest().getParameterMap();
parameters.forEach((key, value) -> log.info("Query Parameter : {} = {}", key, Arrays.toString(value)));
if(userActionRequest.getRequest() != null && token != null)
{
Claims claims = tokenProvider.getClaimsFromToken(token);
userId = claims.get(GepafinConstant.USER_ID, Long.class);
loginAttemptId = claims.get(GepafinConstant.LOGIN_ATTEMPT_ID, Long.class);
UserEntity userEntity = userService.validateUser(userId);
hubId = userEntity.getHub().getId();
}
String requestBody = null;
if (userActionRequest.getRequest() instanceof CachedBodyHttpServletRequest cachedRequest) {
requestBody = cachedRequest.getCachedBodyAsString();
}
userAction.setActionType(userActionRequest.getActionType().getValue());
userAction.setUserId(userId);
userAction.setActionContext(userActionRequest.getActionContext().getValue());
userAction.setMethodType(userActionRequest.getRequest().getMethod());
userAction.setHubId(hubId);
userAction.setUrl(userActionRequest.getRequest().getRequestURI());
userAction.setLoginAttemptId(loginAttemptId);
userAction.setIpAddress(IpAddressUtils.getClientIp(userActionRequest.getRequest()));
userAction.setRequestBody(requestBody);
String response = Utils.convertEntityToJsonForLogging(userActionRequest.getResponse());
userAction.setResponse(response);
userActionsRepository.save(userAction);
userActionRequest.getRequest().setAttribute(GepafinConstant.USER_ACTION_ID, userAction.getId());
} catch (Exception e) {
log.error("Error logging user action: {}", e.getMessage(), e);
}
return userAction;
}
public void updateUserActionWithTokenDetails(Long actionId, String token, Object response) {
try {
UserActionEntity userAction = getUserActionLogById(actionId);
if (userAction != null && token != null) {
Claims claims = tokenProvider.getClaimsFromToken(token);
Long userId = claims.get(GepafinConstant.USER_ID, Long.class);
Long loginAttemptId = claims.get(GepafinConstant.LOGIN_ATTEMPT_ID, Long.class);
UserEntity userEntity = userService.validateUser(userId);
userAction.setUserId(userId);
String responseData = Utils.convertEntityToJsonForLogging(response);
userAction.setResponse(responseData);
userAction.setLoginAttemptId(loginAttemptId);
userAction.setHubId(userEntity.getHub().getId());
// Save updated entity
userActionsRepository.save(userAction);
log.info("User action log updated with token details: {}", userAction.getId());
}
} catch (Exception e) {
log.error("Failed to update user action with token details: {}", e.getMessage(), e);
}
}
public void updateVersionHistoriesWithTokenDetails(Long userActionId, String token) {
try {
// Fetch version history entities for the given user action ID
List<VersionHistoryEntity> versionHistoryEntities = getVersionHistoryLogById(userActionId);
if (versionHistoryEntities != null && !versionHistoryEntities.isEmpty() && token != null) {
// Extract claims from the token
Claims claims = tokenProvider.getClaimsFromToken(token);
Long userId = claims.get(GepafinConstant.USER_ID, Long.class);
// Update each version history entity with the user ID
for (VersionHistoryEntity versionHistoryEntity : versionHistoryEntities) {
versionHistoryEntity.setUserId(userId);
}
// Save all updated entities
versionHistoryRepository.saveAll(versionHistoryEntities);
log.info("Version History logs updated with userId: {}", userId);
} else {
log.warn("No version history or token provided for userActionId: {}", userActionId);
}
} catch (Exception e) {
log.error("Failed to update version histories with token details: {}", e.getMessage(), e);
}
}
public UserActionEntity getUserActionLogById(Long id) {
return userActionsRepository.findUserActionById(id);
}
public List<VersionHistoryEntity> getVersionHistoryLogById(Long id) {
return versionHistoryRepository.findVersionHistoryByUserActionId(id);
}
}

View File

@@ -56,9 +56,8 @@ public class Utils {
public static final Logger log = LoggerFactory.getLogger(Utils.class);
private static final ObjectMapper mapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
private static final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(new JavaTimeModule()).disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
public static <T, U> U convertObject(T source, Class<U> destinationClass) {
try {
@@ -527,17 +526,14 @@ public class Utils {
}
try {
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
JsonNode entityNode = mapper.valueToTree(entity);
ObjectNode objectNode = (ObjectNode) entityNode;
Field[] fields = entity.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(ManyToOne.class) || field.isAnnotationPresent(OneToMany.class) || field
.isAnnotationPresent(OneToOne.class) || field.isAnnotationPresent(ManyToMany.class)) {
if (field.isAnnotationPresent(ManyToOne.class) || field.isAnnotationPresent(OneToMany.class) || field.isAnnotationPresent(
OneToOne.class) || field.isAnnotationPresent(ManyToMany.class)) {
objectNode.remove(field.getName());
}
}

View File

@@ -76,7 +76,7 @@ public class CallApiController implements CallApi {
.body(new Response<>(createCallResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.CALL_UPDATE_SUCCESSFULLY_MSG)));
}
@Override
@Transactional(readOnly = true)
@Transactional
public ResponseEntity<Response<CallResponse>> getCallById(HttpServletRequest request, Long callId,Long companyId) {
/** This code is responsible for creating user action logs for the "get Call by id" operation. **/

View File

@@ -4,7 +4,11 @@ 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.entities.UserActionEntity;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.*;
import net.gepafin.tendermanagement.model.response.UserSamlResponse;
@@ -12,6 +16,7 @@ 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.util.LoggingUtil;
import net.gepafin.tendermanagement.web.rest.api.UserApi;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.slf4j.Logger;
@@ -35,12 +40,27 @@ public class UserApiController implements UserApi {
@Autowired
private UserService userService;
@Autowired
private LoggingUtil loggingUtil;
@Autowired
private TokenProvider tokenProvider;
@Override
public ResponseEntity<Response<JWTToken>> createUser(HttpServletRequest request, String tempToken, @RequestBody UserReq userReq) {
log.info("Create User with - Request Body: {}", userReq);
/** This code is responsible for creating user action logs for the "Create User" operation, even tempToken and userToken is present or not**/
UserActionEntity userAction = loggingUtil.logUserActionWithoutToken(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.INSERT).actionContext(UserActionContextEnum.CREATE_USER).build());
JWTToken createdUser = userService.createUser(request, tempToken, userReq);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG)));
/** This code is responsible for updating the user action log with new data after token generation.**/
if (userAction != null) {
loggingUtil.updateUserActionWithTokenDetails(userAction.getId(), createdUser.getToken(), null );
}
return ResponseEntity.status(HttpStatus.CREATED).body(new Response<>(createdUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_CREATED_SUCCESS_MSG)));
}
@Override
@@ -48,34 +68,58 @@ public class UserApiController implements UserApi {
@PathVariable("userId") Long userId,
@Valid @RequestBody UpdateUserReq userReq) {
log.info("Update User - User ID: {}, Request Body: {}", userId, userReq);
/** This code is responsible for "Updating user details" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPDATE)
.actionContext(UserActionContextEnum.UPDATE_USER_DETAILS).build());
UserResponseBean updatedUser = userService.updateUser(request, userId, userReq);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_UPDATED_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<UserResponseBean>> getUserById(HttpServletRequest request,
@PathVariable("userId") Long userId) {
public ResponseEntity<Response<UserResponseBean>> getUserById(HttpServletRequest request, @PathVariable("userId") Long userId) {
log.info("Get User by ID - User ID: {}", userId);
/** This code is responsible for creating user action logs for the "Get user" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.GET_USER).build());
UserResponseBean user = userService.getUserById(request, userId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG)));
return ResponseEntity.status(HttpStatus.OK).body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<Void>> deleteUser(HttpServletRequest request,
@PathVariable("userId") Long userId) {
public ResponseEntity<Response<Void>> deleteUser(HttpServletRequest request, @PathVariable("userId") Long userId) {
log.info("Delete User - User ID: {}", userId);
/** This code is responsible for creating user action logs for the "Delete user" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.DELETE).actionContext(UserActionContextEnum.DELETE_USER).build());
userService.deleteUser(request, userId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_DELETED_SUCCESS_MSG)));
return ResponseEntity.status(HttpStatus.OK).body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_DELETED_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<JWTToken>> login(HttpServletRequest request,
@Valid @RequestBody LoginReq loginReq) {
public ResponseEntity<Response<JWTToken>> login(HttpServletRequest request, @Valid @RequestBody LoginReq loginReq) {
log.info("User login attempt ");
JWTToken jwtToken = userService.login(loginReq,request);
/** This code is responsible for creating user action logs for the "LOGIN" operation. **/
UserActionEntity userAction = loggingUtil.logUserActionWithoutToken(
UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.INSERT).actionContext(UserActionContextEnum.USER_LOGIN).build());
JWTToken jwtToken = userService.login(loginReq, request);
/** This code is responsible for updating the action and version log with new data after token generation.**/
if (userAction != null) {
loggingUtil.updateUserActionWithTokenDetails(userAction.getId(), jwtToken.getToken(), null);
loggingUtil.updateVersionHistoriesWithTokenDetails(userAction.getId(), jwtToken.getToken());
}
return ResponseEntity.ok(new Response<>(jwtToken, Status.SUCCESS, Translator.toLocale(GepafinConstant.LOGIN_SUCCESS_MSG)));
}
@Override
@@ -106,6 +150,10 @@ public class UserApiController implements UserApi {
@Override
public ResponseEntity<Response<Void>> logoutUser(HttpServletRequest request, HttpServletResponse response) {
/** This code is responsible for creating user action logs for the "Logout" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.LOGOUT).actionContext(UserActionContextEnum.LOGOUT_USER).build());
userService.logoutUser(request, response);
log.info("User has successfully logged");
@@ -123,24 +171,50 @@ public class UserApiController implements UserApi {
public ResponseEntity<Response<UserResponseBean>> getValidUser(HttpServletRequest request) {
log.info("Get Valid User Detail");
UserResponseBean user = userService.getValidUser(request);
/** This code is responsible for creating user action logs for the "Get valid user details." operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.GET_VALID_USER_DETAILS).build());
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(user, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USER_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<JWTToken>> validateExistingUserToken(HttpServletRequest request, String token) {
log.info("User login attempt via spid token");
JWTToken data = userService.validateExistingUserToken(request, token);
return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSE)));
log.info("User login attempt via spid token");
/** This code is responsible for creating user action logs for the "Validating existing user from spid token" operation. **/
UserActionEntity userAction = loggingUtil.logUserActionWithoutToken(
UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.VALIDATE_EXISTING_USER_WITH_SPID_TOKEN)
.build());
JWTToken data = userService.validateExistingUserToken(request, token);
/** This code is responsible for updating the action and version log with new data.**/
if (userAction != null) {
loggingUtil.updateUserActionWithTokenDetails(userAction.getId(), data.getToken(), data);
loggingUtil.updateVersionHistoriesWithTokenDetails(userAction.getId(), data.getToken());
}
return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<UserSamlResponse>> validateNewUserToken(HttpServletRequest request, String token) {
log.info("User validating spid token");
UserSamlResponse data = userService.validateNewUserToken(request,token);
return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSE)));
log.info("User validating spid token");
/** This code is responsible for creating user action logs for the "Validating new user from spid token" operation. **/
loggingUtil.logUserActionWithoutToken(
UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.VALIDATE_NEW_USER_WITH_SPID_TOKEN).build());
UserSamlResponse data = userService.validateNewUserToken(request, token);
return ResponseEntity.ok(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.TOKEN_VALIDATE_SUCCESS_MSG)));
}
@Override
public ResponseEntity<Response<List<UserResponseBean>>> getAllUsers(HttpServletRequest request,
Long roleId) {

View File

@@ -1779,4 +1779,11 @@
constraintName="fk_version_history_user_action"/>
</changeSet>
<changeSet id="20-11-2024_3" author="Piyush">
<addColumn tableName="login_attempt">
<column name="created_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
<column name="updated_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
</addColumn>
</changeSet>
</databaseChangeLog>