155 lines
5.0 KiB
Java

package com.banesco.common.infraestructure.helpers;
import com.banesco.common.domain.dto.bian.device.BianDevice;
import com.banesco.common.domain.model.Device;
import com.banesco.common.infraestructure.config.DeviceTypeValues;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DeviceHelper {
private boolean readDeviceFromRequest;
private final String DESKTOP = "Desktop";
private static final Logger logger = Logger.getLogger(DeviceHelper.class.getName());
/**
* Nombres de cabeceras HTTP que pueden contener la dirección IP del
* cliente. Se revisan en orden para encontrar la IP real considerando
* proxies y balanceadores.
*/
private final String[] IP_HEADER_NAMES = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"REMOTE_ADDR"
};
public DeviceHelper() {
// Lee la propiedad del sistema. Si no existe, asume false por defecto.
String readDeviceProperty = System.getProperty("api.server-request.read-device");
this.readDeviceFromRequest = readDeviceProperty == null ? false : Boolean.parseBoolean(readDeviceProperty);
}
/**
* Obtiene la dirección IP remota del cliente a partir de la solicitud HTTP.
* Revisa varias cabeceras HTTP que podrían contener la IP real del cliente
* considerando proxies y balanceadores de carga.
*
* @param request La solicitud HTTP
* @return La dirección IP remota del cliente, o "0.0.0.0" si la solicitud
* es nula
*/
public String getRemoteIP(HttpServletRequest request) {
if (request == null) {
return "0.0.0.0";
}
for (String header : IP_HEADER_NAMES) {
String ipList = request.getHeader(header);
if (!StringHelper.isEmpty(ipList) && !"unknown".equalsIgnoreCase(ipList)) {
return ipList.split(",")[0];
}
}
return request.getRemoteAddr();
}
/**
* Llena la información del dispositivo remoto del cliente en el objeto
* Device. Si se configura readDeviceFromRequest como true, siempre se
* obtendrá la información del dispositivo desde la solicitud HTTP,
* independientemente de si ya existe.
*
* @param servletRequest La solicitud HTTP
* @param device El objeto Device existente a actualizar o null para crear
* uno nuevo
* @return El objeto Device con la información del cliente actualizada
*/
public Device fillRemoteDevice(HttpServletRequest servletRequest, Device device) {
if (device == null) {
device = new Device();
}
if (StringHelper.isEmpty(device.getIpAddress()) || readDeviceFromRequest) {
device.setIpAddress(getRemoteIP(servletRequest));
String userAgent = servletRequest.getHeader("user-agent");
if (userAgent == null) {
device.setType(DESKTOP);
device.setDescription(DESKTOP);
} else {
device.setDescription(userAgent);
if (userAgent.toLowerCase().contains("mobi")) {
device.setType("Mobile");
} else {
device.setType(DESKTOP);
}
}
}
return device;
}
/**
* Mapea el tipo de dispositivo desde el objeto BianDevice al enum DeviceTypeValues.
*
* @param device
* @return
*/
public static DeviceTypeValues getDeviceTypeValue(
BianDevice device
) {
var deviceTypeValue = DeviceTypeValues.Unknown;
if (!Objects.isNull(device) && !StringHelper.isEmpty(device.getDeviceType())) {
try {
deviceTypeValue = DeviceTypeValues.valueOf(device.getDeviceType());
} catch (Exception e) {
logger.log(Level.WARNING, "Error Mapping Device Type: %s -> %s".formatted(device.getDeviceType(), e.getMessage()));
}
}
return deviceTypeValue;
}
/**
* Valida si el tipo de dispositivo es válido según el enum DeviceTypeValues.
*
* @param type
* @return
*/
public static boolean isValidDeviceType(String type) {
for (DeviceTypeValues deviceType : DeviceTypeValues.values()) {
if (deviceType.name().equals(type)) {
return true;
}
}
return false;
}
/**
* Obtiene una cadena con todos los tipos de dispositivos válidos.
*
* @return
*/
public static String getDeviceTypes() {
return Stream.of(DeviceTypeValues.values()).map(Enum::name).collect(
Collectors.joining(", ")
);
}
}