AuthController.java 7.05 KB
package com.sigem.gis.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import com.sigem.gis.service.FdwService;

import java.util.Base64;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    @Qualifier("masterJdbcTemplate")
    private JdbcTemplate masterJdbcTemplate;

    @Autowired
    @Qualifier("gisJdbcTemplate")
    private JdbcTemplate gisJdbcTemplate;

    @Autowired
    private FdwService fdwService;

    @GetMapping("/entidades")
    public ResponseEntity<?> getEntidadesActivas() {
        try {
            String sql = "select entidad, nombre, entidad_logo, responsable, eslogan from public.entidades WHERE activo = TRUE ORDER BY entidad ASC";
            List<Map<String, Object>> entidades = masterJdbcTemplate.queryForList(sql);
            return ResponseEntity.ok(entidades);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error al cargar entidades");
        }
    }

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody AuthRequest request) {
        try {
            // 1. Validar existencia de entidad en directorio maestro (en el .254)
            String sqlEntidades = "SELECT sigem_site, sigem_dbname, lat, lng, zoom, minzoom, maxzoom, mapa_base, boundno, boundse, nombre, eslogan, entidad_logo, responsable FROM public.entidades WHERE activo= TRUE AND entidad = ?";
            List<Map<String, Object>> entidades = masterJdbcTemplate.queryForList(sqlEntidades, Integer.parseInt(request.getEntidad()));
            
            if (entidades.isEmpty()) {
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new AuthResponse(null, null, "La MUNICIPALIDAD con código " + request.getEntidad() + " no existe o está inactiva."));
            }

            Map<String, Object> entidadData = entidades.get(0);
            String nombreEntidad = convertObjectToString(entidadData.get("nombre"));
            String eslogan = convertObjectToString(entidadData.get("eslogan"));
            
            // Tratamiento especial para el logo (Binario -> Base64)
            Object logoObj = entidadData.get("entidad_logo");
            String logo = (logoObj instanceof byte[]) ? Base64.getEncoder().encodeToString((byte[]) logoObj) : convertObjectToString(logoObj);
            
            String responsable = convertObjectToString(entidadData.get("responsable"));

            // 2. Asegurar Infraestructura FDW (Regla 16: Solo crea si no existe)
            fdwService.setupFdw(request.getEntidad(), false);
            String schemaName = "fdw_" + request.getEntidad();
            
            System.out.println("Validando usuario vía FDW local para entidad: " + request.getEntidad());
            
            // 3. Buscar Usuario en el esquema FDW local (en el .123)
            String sqlUser = "SELECT usu_nom, usu_ape, activo, entidad, " +
                             "pgp_sym_decrypt(usu_clave_a::bytea, '510580', 'compress-algo=0, cipher-algo=aes256')::text as clave_desencriptada " +
                             "FROM " + schemaName + ".usuarios " +
                             "WHERE usu_alias = ? AND ejer_fisca = date_part('year', now())";

            List<Map<String, Object>> usuarios = gisJdbcTemplate.queryForList(sqlUser, request.getUsername());

            if (!usuarios.isEmpty()) {
                Map<String, Object> userData = usuarios.get(0);
                boolean isActivo = (boolean) userData.get("activo");
                String claveDesencriptada = convertObjectToString(userData.get("clave_desencriptada"));
                
                // 4. Validación Final y Generación de Token
                if (isActivo && request.getPassword().equals(claveDesencriptada)) {
                    // Extraer la Entidad oficial desde el FDW ( character varying 8 )
                    String entidadOficial = convertObjectToString(userData.get("entidad"));
                    if (entidadOficial == null || entidadOficial.trim().isEmpty()) {
                        entidadOficial = request.getEntidad(); // Fallback si el campo está vacío, aunque no debería
                    }
                    
                    String token = jwtUtil.generateToken(request.getUsername(), entidadOficial);
                    String nombreCompleto = convertObjectToString(userData.get("usu_nom")) + " " + convertObjectToString(userData.get("usu_ape"));
                    
                    // Metadatos georreferenciados de la entidad
                    Double lat = parseDouble(entidadData.get("lat"), -25.456443);
                    Double lng = parseDouble(entidadData.get("lng"), -56.446949);
                    Integer zoom = parseInteger(entidadData.get("zoom"), 14);
                    Integer minZoom = parseInteger(entidadData.get("minzoom"), 5);
                    Integer maxZoom = parseInteger(entidadData.get("maxzoom"), 20);
                    String mapaBase = convertObjectToString(entidadData.getOrDefault("mapa_base", "osm"));
                    String bounds = convertObjectToString(entidadData.getOrDefault("boundno", "")) + "|" +
                                    convertObjectToString(entidadData.getOrDefault("boundse", ""));

                    return ResponseEntity.ok(new AuthResponse(token, nombreCompleto, "Login Exitoso", 
                                             lat, lng, zoom, minZoom, maxZoom, mapaBase, bounds, 
                                             nombreEntidad, eslogan, logo, responsable, entidadOficial));
                }
            }

            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new AuthResponse(null, null, "Credenciales Inválidas o Cuenta de Baja"));

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new AuthResponse(null, null, "Fallo interno en el Microservicio SaaS: " + e.toString()));
        }
    }
    
    private String convertObjectToString(Object val) {
        if (val == null) return null;
        if (val instanceof byte[]) {
            return new String((byte[]) val);
        }
        return String.valueOf(val);
    }

    private Double parseDouble(Object val, Double def) {
        if (val == null) return def;
        try {
            String str = convertObjectToString(val);
            return Double.parseDouble(str.trim());
        } catch (Exception e) {
            return def;
        }
    }

    private Integer parseInteger(Object val, Integer def) {
        if (val == null) return def;
        try {
            String str = convertObjectToString(val);
            return Integer.parseInt(str.trim());
        } catch (Exception e) {
            return def;
        }
    }
}
GitLab Appliance - Powered by TurnKey Linux