package net.gepafin.tendermanagement.util; import com.amazonaws.services.alexaforbusiness.model.UnauthorizedException; import jakarta.persistence.EntityNotFoundException; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.server.ResponseStatusException; import java.lang.reflect.InvocationTargetException; import java.nio.file.AccessDeniedException; import java.util.LinkedHashMap; import java.util.Map; @Aspect @Component @Slf4j public class UserActionAspect { @Autowired private LoggingUtil loggingUtil; @Around("execution(public * net.gepafin.tendermanagement.web.rest.api.impl..*(..))") public Object logApiResponse(ProceedingJoinPoint joinPoint) throws Throwable { Object result; HttpServletRequest request = getRequestFromContext(); try { Long userActionId = getUserActionIdFromRequest(request); if (userActionId != null) { request.setAttribute(GepafinConstant.USER_ACTION_ID, userActionId); log.info("Stored userActionId in RequestContext: {}", userActionId); } else { userActionId = loggingUtil.getUserActionId(); if (userActionId != null) { request.setAttribute(GepafinConstant.USER_ACTION_ID, userActionId); } } result = joinPoint.proceed(); if (result instanceof ResponseEntity) { Long storedUserActionId = (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID); handleSuccessResponse((ResponseEntity) result, storedUserActionId == null ? userActionId : storedUserActionId); } } catch (Exception ex) { log.error("Exception occurred: ", ex); handleError(ex, getUserActionIdFromRequest(request)); throw ex; } finally { loggingUtil.clearUserActionId(); } return result; } private void handleSuccessResponse(ResponseEntity responseEntity, Long userActionId) { if (userActionId != null) { Map responseWithUserAction = new LinkedHashMap<>(); responseWithUserAction.put(GepafinConstant.STATUS_CODE_STRING, responseEntity.getStatusCode().value()); // Log and update user action loggingUtil.updateUserActionWithResponse(userActionId, Utils.convertMapIntoJsonString(responseWithUserAction)); log.info("Updated userActionId with response: {}", userActionId); } } private void handleError(Throwable ex, Long userActionId) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { HttpStatus status = getStatusCodeFromException(ex); log.info("Status Code received from exception : {}", status); String errorMessage = ex.getMessage(); Map errorResponse = new LinkedHashMap<>(); errorResponse.put(GepafinConstant.STATUS_CODE_STRING, status.value()); errorResponse.put(GepafinConstant.GET_STATUS_CODE_STRING, status); errorResponse.put(GepafinConstant.MESSAGE_STRING, errorMessage); if (userActionId != null) { String errorDetails = Utils.convertMapIntoJsonString(errorResponse); loggingUtil.updateUserActionWithError(userActionId, errorDetails); log.info("Updated userActionId with error details: {}", userActionId); } } private HttpServletRequest getRequestFromContext() { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return attributes != null ? attributes.getRequest() : null; } private Long getUserActionIdFromRequest(HttpServletRequest request) { if (request != null) { Object userActionIdAttr = request.getAttribute(GepafinConstant.USER_ACTION_ID); return userActionIdAttr != null ? Long.valueOf(userActionIdAttr.toString()) : null; } return null; } private HttpStatus getStatusCodeFromException(Throwable ex) { if (ex instanceof ResourceNotFoundException) { return HttpStatus.NOT_FOUND; } if (ex instanceof ResponseStatusException responseStatusException) { return (HttpStatus) responseStatusException.getStatusCode(); } if (ex instanceof CustomValidationException) { return HttpStatus.BAD_REQUEST; } if (ex instanceof EntityNotFoundException) { return HttpStatus.NOT_FOUND; } if (ex instanceof IllegalArgumentException || ex instanceof MissingServletRequestParameterException || ex instanceof MethodArgumentNotValidException) { return HttpStatus.BAD_REQUEST; } if (ex instanceof AccessDeniedException) { return HttpStatus.FORBIDDEN; } if (ex instanceof UnauthorizedException) { return HttpStatus.UNAUTHORIZED; } return HttpStatus.INTERNAL_SERVER_ERROR; } }