Added logging mechanism for user actions.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package net.gepafin.tendermanagement.util;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class IpAddressUtils {
|
||||
|
||||
private static final Pattern IPV4_PATTERN = Pattern.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
|
||||
|
||||
private static final Pattern IPV6_PATTERN = Pattern.compile(
|
||||
"([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|" + "([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" + "([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" + "([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" + ":((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|" + "::(ffff(:0{1,4}){0,1}:){0,1}(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3,3}" + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|([0-9a-fA-F]{1,4}:){1,4}:" + "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3,3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])");
|
||||
|
||||
public static String getClientIp(HttpServletRequest request) {
|
||||
|
||||
String ipAddress = null;
|
||||
|
||||
String[] headers = { "X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR" };
|
||||
|
||||
for (String header : headers) {
|
||||
ipAddress = request.getHeader(header);
|
||||
if (ipAddress != null && !ipAddress.isEmpty() && !"unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = ipAddress.split(",")[0].trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getRemoteAddr();
|
||||
}
|
||||
if ("0:0:0:0:0:0:0:1".equals(ipAddress) || "127.0.0.1".equals(ipAddress)) {
|
||||
ipAddress = "127.0.0.1";
|
||||
}
|
||||
if (isValidIpAddress(ipAddress)) {
|
||||
return ipAddress;
|
||||
} else {
|
||||
return "Invalid IP";
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isValidIpAddress(String ipAddress) {
|
||||
|
||||
return IPV4_PATTERN.matcher(ipAddress).matches() || IPV6_PATTERN.matcher(ipAddress).matches();
|
||||
}
|
||||
}
|
||||
|
||||
149
src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java
Normal file
149
src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java
Normal file
@@ -0,0 +1,149 @@
|
||||
package net.gepafin.tendermanagement.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.gepafin.tendermanagement.config.CachedBodyHttpServletRequest;
|
||||
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
|
||||
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.model.request.UserActionRequest;
|
||||
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
|
||||
import net.gepafin.tendermanagement.model.util.LogResponse;
|
||||
import net.gepafin.tendermanagement.repositories.UserActionsRepository;
|
||||
import net.gepafin.tendermanagement.repositories.VersionHistoryRepository;
|
||||
import net.gepafin.tendermanagement.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.context.annotation.RequestScope;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequestScope
|
||||
public class LoggingUtil {
|
||||
|
||||
@Autowired
|
||||
private UserActionsRepository userActionsRepository;
|
||||
|
||||
@Autowired
|
||||
private VersionHistoryRepository versionHistoryRepository;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
TokenProvider tokenProvider;
|
||||
|
||||
public UserActionEntity logUserAction(UserActionRequest userActionRequest) {
|
||||
UserActionEntity userAction = new UserActionEntity();
|
||||
try {
|
||||
String token = tokenProvider.extractTokenFromRequest(userActionRequest.getRequest());
|
||||
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);
|
||||
|
||||
String requestBody = null;
|
||||
if (userActionRequest.getRequest() instanceof CachedBodyHttpServletRequest cachedRequest) {
|
||||
requestBody = cachedRequest.getCachedBodyAsString();
|
||||
}
|
||||
userAction.setActionType(userActionRequest.getActionType().getValue());
|
||||
userAction.setUserId(userId);
|
||||
userAction.setActionContext(userActionRequest.getActionContext());
|
||||
userAction.setMethodType(userActionRequest.getRequest().getMethod());
|
||||
userAction.setHubId(userEntity.getHub().getId());
|
||||
userAction.setUrl(userActionRequest.getRequest().getRequestURI());
|
||||
userAction.setLoginAttemptId(loginAttemptId);
|
||||
userAction.setIpAddress(IpAddressUtils.getClientIp(userActionRequest.getRequest()));
|
||||
userAction.setRequestBody(requestBody);
|
||||
userAction.setResponse(null);
|
||||
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;
|
||||
}
|
||||
|
||||
// @Transactional
|
||||
// public UserActionEntity updateUserAction(HttpServletResponse response, UserActionEntity userAction) {
|
||||
// try {
|
||||
// String requestBody = null;
|
||||
// if (userAction. instanceof CachedBodyHttpServletRequest cachedRequest) {
|
||||
// requestBody = cachedRequest.getCachedBodyAsString();
|
||||
// }
|
||||
//
|
||||
// LogResponse<String> logResponse = new LogResponse<>();
|
||||
// logResponse.setStatus(response.getStatus());
|
||||
// logResponse.setStatusCode(String.valueOf(response.getStatus()));
|
||||
// logResponse.setMessage("SUCCESS");
|
||||
//
|
||||
// String serializedResponse;
|
||||
// try {
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
// serializedResponse = objectMapper.writeValueAsString(logResponse);
|
||||
// } catch (Exception e) {
|
||||
// serializedResponse = "Error serializing LogResponse: " + e.getMessage();
|
||||
// }
|
||||
//
|
||||
// userAction.setResponse(serializedResponse);
|
||||
// userActionsRepository.save(userAction);
|
||||
// } catch (Exception e) {
|
||||
// log.error("Error updating user action: {}", e.getMessage(), e);
|
||||
// }
|
||||
// return userAction;
|
||||
// }
|
||||
|
||||
public void logVersionHistory(VersionHistoryRequest versionHistoryRequest) {
|
||||
try {
|
||||
VersionHistoryEntity history = new VersionHistoryEntity();
|
||||
String token = tokenProvider.extractTokenFromRequest(versionHistoryRequest.getRequest());
|
||||
Claims claims = tokenProvider.getClaimsFromToken(token);
|
||||
Long userId = claims.get(GepafinConstant.USER_ID, Long.class);
|
||||
String oldData = Utils.convertEntityToJsonForLogging(versionHistoryRequest.getOldData());
|
||||
String newData = Utils.convertEntityToJsonForLogging(versionHistoryRequest.getNewData());
|
||||
history.setUserActionId(versionHistoryRequest.getUserActionId());
|
||||
history.setActionType(versionHistoryRequest.getActionType().getValue());
|
||||
history.setOldData(oldData);
|
||||
history.setNewData(newData);
|
||||
history.setRecordId(versionHistoryRequest.getRecordId());
|
||||
history.setTableName(versionHistoryRequest.getTableName());
|
||||
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)) {
|
||||
Table tableAnnotation = entityClass.getAnnotation(Table.class);
|
||||
return tableAnnotation.name();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error retrieving table name: {}", e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addVersionHistory(VersionHistoryRequest versionHistoryRequest) {
|
||||
try {
|
||||
Long userActionId = (Long) versionHistoryRequest.getRequest().getAttribute(GepafinConstant.USER_ACTION_ID);
|
||||
Long recordId = versionHistoryRequest.getNewData().getId();
|
||||
String tableName = getTableName(versionHistoryRequest.getNewData().getClass());
|
||||
versionHistoryRequest.setRecordId(recordId);
|
||||
versionHistoryRequest.setUserActionId(userActionId);
|
||||
versionHistoryRequest.setTableName(tableName);
|
||||
logVersionHistory(versionHistoryRequest);
|
||||
} catch (Exception e) {
|
||||
log.error("Error adding version history: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,19 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.itextpdf.styledxmlparser.jsoup.Jsoup;
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
@@ -515,4 +514,36 @@ public class Utils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String convertEntityToJsonForLogging(Object entity) {
|
||||
|
||||
if(entity == null){
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return mapper.writeValueAsString(entity);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties({ "childEntities", "relatedData", "otherRelations" })
|
||||
private abstract static class IgnoreChildEntities {
|
||||
}
|
||||
|
||||
public static <T> T getClonedEntityForData(T entity) {
|
||||
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String json = mapper.writeValueAsString(entity);
|
||||
@SuppressWarnings("unchecked") T clonedEntity = (T) mapper.readValue(json, entity.getClass());
|
||||
return clonedEntity;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Failed to clone entity", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user