no funciona el bearer
This commit is contained in:
@@ -23,7 +23,8 @@ namespace bdEmtusa.dbcontext
|
|||||||
public static List<Conexion> ListaConexiones()
|
public static List<Conexion> ListaConexiones()
|
||||||
{
|
{
|
||||||
List<Conexion> lc = new List<Conexion>();
|
List<Conexion> lc = new List<Conexion>();
|
||||||
lc.Add(new Conexion() { Nombre = "Producción", Puerto = 3306, Servidor = "192.168.41.56", Usuario = "root", Contraseña = "0êmF/e#g/*6pZÛLWqölLvPp", Database = "gestionemtusa" });
|
lc.Add(new Conexion() { Nombre = "Producción", Puerto = 3306, Servidor = "192.168.41.56", Usuario = "tecnosis", Contraseña = "0êmF/e#g/*6pZÛLWqölLvPp", Database = "gestionemtusa" });
|
||||||
|
lc.Add(new Conexion() { Nombre = "sololectura", Puerto = 3306, Servidor = "192.168.41.56", Usuario = "sololectura", Contraseña = "ÁÔ,mâ1üeqzHbû", Database = "gestionemtusa" });
|
||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
internal static string ObtieneConexionDefecto(string NombreConexion="Producción")
|
internal static string ObtieneConexionDefecto(string NombreConexion="Producción")
|
||||||
|
|||||||
8
swEmtusa/Clases/DatosAuth.cs
Normal file
8
swEmtusa/Clases/DatosAuth.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace SwaggerAutenticacion.Clases
|
||||||
|
{
|
||||||
|
public class DatosAuth
|
||||||
|
{
|
||||||
|
public string nombreExterno { get; set; }
|
||||||
|
public string pwExterno { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,128 +1,104 @@
|
|||||||
using bdCOAS.db;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using System.Net;
|
||||||
using SwaggerAutenticacion.Clases;
|
|
||||||
using System.Linq.Dynamic.Core;
|
|
||||||
using tsUtilidades;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using bdEmtusa;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using SwaggerAutenticacion.Clases;
|
||||||
|
|
||||||
|
namespace SwaggerAntifraude.Controllers
|
||||||
namespace SwaggerAutenticacion.Controllers
|
|
||||||
{
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("[controller]")]
|
public class AuthController : ControllerBase
|
||||||
public class AuthController : Controller
|
|
||||||
{
|
{
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
private readonly IConfiguration jwtSettings;
|
|
||||||
|
|
||||||
public AuthController(IConfiguration configuration)
|
public AuthController(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
|
_configuration = configuration;
|
||||||
jwtSettings = configuration.GetSection("Jwt");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("ComprobarUser")]
|
[AllowAnonymous]
|
||||||
public ActionResult<string> PostComprobarUser([FromBody] DatosAuth model)
|
[HttpPost("login")]
|
||||||
|
public IActionResult Login([FromBody] DatosAuth datos)
|
||||||
{
|
{
|
||||||
var bd = bdCOAS.tsCOAS.NuevoContextoDirecto();
|
if (!ModelState.IsValid)
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
|
||||||
|
var token = AuthenticateUser(datos);
|
||||||
|
|
||||||
|
if (token == null)
|
||||||
|
return Unauthorized("Nombre de usuario o contraseña incorrectos.");
|
||||||
|
|
||||||
|
if (token.Equals("no autorizado"))
|
||||||
try
|
|
||||||
{
|
{
|
||||||
autorizacionesexternas externo = bd.autorizacionesexternas.FirstOrDefault(x => x.Codigo == model.nombreExterno);
|
return Unauthorized("Usuario no autorizado");
|
||||||
|
|
||||||
//var externo = bd.autorizacionesexternas.FirstOrDefault(x => x.Nombre == model.nombreExterno);
|
|
||||||
|
|
||||||
if (externo != null)
|
|
||||||
{
|
|
||||||
var pwEmpresaEncrypt = tsUtilidades.crypt.SHA1("M3Soft." + model.pwExterno);
|
|
||||||
|
|
||||||
if (pwEmpresaEncrypt != externo.HashPassword) throw new Exception("PassWord Incorrecta");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Autorización no encontrada.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var token = "";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var sContraseñaenc = tsUtilidades.crypt.SHA1("M3Soft." + model.pwColegiado);
|
|
||||||
Exception ex = null;
|
|
||||||
accesoswebcoas nac = null;
|
|
||||||
var col = bd.Colegiados.First(x => x.NumeroColegiado == model.identificacionColegiado || x.NIF == model.identificacionColegiado);
|
|
||||||
clavesacceso.LoginCoas(bd, col.NumeroColegiado, sContraseñaenc, "", clavesacceso.TipoLoginEnum.EXTERNOS_1, ref ex, ref nac);
|
|
||||||
if (ex != null) throw ex;
|
|
||||||
|
|
||||||
externo.FechaUltimaConexion = DateTime.Now;
|
|
||||||
bd.Update(externo);
|
|
||||||
bd.SaveChanges();
|
|
||||||
|
|
||||||
token = AuthHandler.GenerateJwtToken(jwtSettings, col.idColegiado.ToString());
|
|
||||||
return Ok(new { token });
|
|
||||||
}
|
|
||||||
catch (tsExcepcion e)
|
|
||||||
{
|
|
||||||
return Unauthorized("Credenciales Colegiado no válidas. " + e.Message);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return BadRequest($"Ha ocurrido un error. Mensaje de error: {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return Unauthorized("Credenciales Empresa no válidas. " + e.Message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Ok(BuildLoginResponse(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateJwtToken(DatosAuth auth)
|
||||||
[HttpPost("LoginExterno")]
|
|
||||||
public ActionResult<object> PostLoginExterno([FromBody] DatosAuthEmail model)
|
|
||||||
{
|
{
|
||||||
var bd = bdCOAS.tsCOAS.NuevoContextoDirecto();
|
var jwtSettings = _configuration.GetSection("Jwt");
|
||||||
// string ip = HttpContext.Connection.RemoteIpAddress?.ToString();
|
var key = Encoding.UTF8.GetBytes(jwtSettings["Key"]!);
|
||||||
try
|
|
||||||
|
var claims = new[]
|
||||||
{
|
{
|
||||||
var externo = bd.autorizacionesexternas
|
new Claim(JwtRegisteredClaimNames.Sub, auth.nombreExterno),
|
||||||
.FirstOrDefault(x => x.Codigo == model.nombreExterno)
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
||||||
?? throw new Exception("Autorización no encontrada.");
|
//new Claim(ClaimTypes.Role, persona.ADMINISTRARPTYREGISTRO == true ? "Supervisor" : "Lectura")
|
||||||
|
};
|
||||||
|
|
||||||
var pwEncrypt = tsUtilidades.crypt.SHA1("M3Soft." + model.pwExterno);
|
var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
if (pwEncrypt != externo.HashPassword)
|
|
||||||
throw new Exception("Password Incorrecta.");
|
|
||||||
|
|
||||||
// Solo guardamos nombreExterno + tipo en el token
|
|
||||||
var claims = new List<Claim>
|
|
||||||
{
|
|
||||||
new Claim(ClaimTypes.Name, model.nombreExterno),
|
|
||||||
new Claim("AuthType", "EmailOnly")
|
|
||||||
};
|
|
||||||
|
|
||||||
var token = AuthHandler.GenerateJwtToken(jwtSettings, claims);
|
|
||||||
|
|
||||||
externo.FechaUltimaConexion = DateTime.Now;
|
|
||||||
bd.Update(externo);
|
|
||||||
bd.SaveChanges();
|
|
||||||
// if (externo.Codigo!="GCOAS") tsUtilidades.TsNotificacionesClient.RegistrarAsync("LoginExterno", "Login Externo " + externo.Nombre + " - IP: " + ip, TsNotificacionesClient.TipoNotificacionEnum.INFO);
|
|
||||||
return Ok(new { token });
|
|
||||||
}
|
|
||||||
catch (Exception e) when (
|
|
||||||
e.Message.Contains("no encontrada") ||
|
|
||||||
e.Message.Contains("Incorrecta"))
|
|
||||||
{
|
{
|
||||||
tsUtilidades.TsNotificacionesClient.RegistrarAsync("Credenciales LoginExterno incorrectas", e.Message,TsNotificacionesClient.TipoNotificacionEnum.CRÍTICO);
|
Subject = new ClaimsIdentity(claims),
|
||||||
return Unauthorized("Credenciales Empresa no válidas. " + e.Message);
|
Expires = DateTime.UtcNow.AddMinutes(double.Parse(jwtSettings["ExpiresInMinutes"]!)),
|
||||||
}
|
Issuer = jwtSettings["Issuer"],
|
||||||
catch (Exception e)
|
Audience = jwtSettings["Audience"],
|
||||||
{
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||||
tsUtilidades.TsNotificacionesClient.RegistrarAsync("Error en LoginExterno", e.Message, TsNotificacionesClient.TipoNotificacionEnum.ERROR);
|
};
|
||||||
return BadRequest($"Ha ocurrido un error: {e.Message}");
|
|
||||||
}
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
|
return tokenHandler.WriteToken(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static object BuildLoginResponse( string token)
|
||||||
|
{
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
Token = token,
|
||||||
|
//User = new
|
||||||
|
//{
|
||||||
|
// persona.NIF,
|
||||||
|
// persona.NOMBRE,
|
||||||
|
// persona.APELLIDOS,
|
||||||
|
// persona.ADMINISTRARPTYREGISTRO
|
||||||
|
//}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string AuthenticateUser(DatosAuth datos)
|
||||||
|
{
|
||||||
|
using (var context = tscEmtusa.NuevoContexto(SoloLectura: true))
|
||||||
|
{
|
||||||
|
var login = context.configuracion.First(x => x.codigo == "auth.login").valor;
|
||||||
|
var pass = context.configuracion.First(x => x.codigo == "auth.pass").valor;
|
||||||
|
|
||||||
|
if (datos.nombreExterno != "emtusanot" || datos.pwExterno != "tsemt2026#..")
|
||||||
|
{
|
||||||
|
return ("Credenciales incorrectas");
|
||||||
|
}
|
||||||
|
|
||||||
|
var jwtToken = GenerateJwtToken(datos);
|
||||||
|
return jwtToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
486
swEmtusa/Controllers/GenericoController.cs
Normal file
486
swEmtusa/Controllers/GenericoController.cs
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Linq.Dynamic.Core;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Serialize.Linq.Serializers;
|
||||||
|
namespace SwaggerColegiados.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public abstract class GenericoController<TEntity, TKey> : ControllerBase where TEntity : class
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Obtiene todos los registros de la entidad (Solo Lectura).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Lista de entidades.</returns>
|
||||||
|
[Authorize]
|
||||||
|
[HttpGet]
|
||||||
|
public virtual async Task<IActionResult> GetAll()
|
||||||
|
{
|
||||||
|
|
||||||
|
string operacion = nameof(GetAll);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Asegúrate de pasar UseLazyLoadingProxies: false para desactivar Lazy Loading
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var entities = await dbSet.AsNoTracking().ToListAsync();
|
||||||
|
//string jsonString = JsonSerializer.Serialize(entities);
|
||||||
|
|
||||||
|
//RegistrarActividad(operacion, usuario, "Sin parámetros", $"Registros obtenidos: {entities.Count}");
|
||||||
|
|
||||||
|
return Ok(entities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Obtiene un registro específico por ID (Solo Lectura).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">ID de la entidad.</param>
|
||||||
|
/// <returns>Entidad encontrada.</returns>
|
||||||
|
[Authorize]
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public virtual IActionResult GetById(TKey id)
|
||||||
|
{
|
||||||
|
string operacion = nameof(GetById);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var entity = dbSet.Find(id);
|
||||||
|
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, $"ID: {id}", null, "Entidad no encontrada");
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
//RegistrarActividad(operacion, usuario, $"ID: {id}", "Entidad encontrada");
|
||||||
|
return Ok(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, $"ID: {id}", null, ex.Message);
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
[HttpPost("filtrar")]
|
||||||
|
public virtual async Task<IActionResult> Filtrar([FromBody] ExpressionWrapper request)
|
||||||
|
{
|
||||||
|
string operacion = nameof(Filtrar);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
string parametros = request.Expression;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
// Crear el deserializador
|
||||||
|
var serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
|
||||||
|
|
||||||
|
// Deserializar la expresión
|
||||||
|
var deserializedExpression = serializer.DeserializeText(request.Expression) as Expression<Func<TEntity, bool>>;
|
||||||
|
if (deserializedExpression == null)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, "Expresión inválida");
|
||||||
|
|
||||||
|
return BadRequest("La expresión deserializada es nula o incorrecta.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplicar el filtro en la consulta
|
||||||
|
var query = context.Set<TEntity>().Where(deserializedExpression);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Agregar un log para verificar el SQL generado y la consulta
|
||||||
|
Console.WriteLine(query.ToQueryString()); // Esto imprime la consulta SQL generada por EF Core
|
||||||
|
|
||||||
|
var res = await query.AsNoTracking().ToListAsync();
|
||||||
|
|
||||||
|
// Verificar si el resultado es vacío
|
||||||
|
if (res.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("La consulta no devolvió resultados.");
|
||||||
|
}
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, $"Registros encontrados: {res.Count}");
|
||||||
|
|
||||||
|
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, ex.Message);
|
||||||
|
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
[HttpPost("filtrar-entidad")]
|
||||||
|
public virtual async Task<IActionResult> FiltrarEntidad([FromBody] ExpressionWrapper request)
|
||||||
|
{
|
||||||
|
string operacion = nameof(FiltrarEntidad);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
string parametros = request.Expression;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
var serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
|
||||||
|
var deserializedExpression = serializer.DeserializeText(request.Expression) as Expression<Func<TEntity, bool>>;
|
||||||
|
|
||||||
|
if (deserializedExpression == null)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, "Expresión deserializada es nula o incorrecta.");
|
||||||
|
return BadRequest("La expresión deserializada es nula o incorrecta.");
|
||||||
|
}
|
||||||
|
var entity = await context.Set<TEntity>()
|
||||||
|
.Where(deserializedExpression)
|
||||||
|
.AsNoTracking()
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, "No se encontró ninguna entidad que coincida con el filtro.");
|
||||||
|
return NotFound("No se encontró ninguna entidad que coincida con el filtro.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, "Entidad encontrada.");
|
||||||
|
|
||||||
|
return Ok(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, ex.Message);
|
||||||
|
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
[HttpPost("filtrar-Atributo")]
|
||||||
|
public virtual async Task<IActionResult> FiltrarAtributoDinamico([FromBody] ExpressionWrapperAtributo request)
|
||||||
|
{
|
||||||
|
|
||||||
|
string operacion = nameof(FiltrarAtributoDinamico);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
string parametros = $"Expresión: {request.Expression}, Atributo: {request.AttributeName}";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
var serializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
|
||||||
|
var expression = serializer.DeserializeText(request.Expression) as Expression<Func<TEntity, bool>>;
|
||||||
|
if (expression == null)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, "La expresión deserializada es nula o incorrecta.");
|
||||||
|
return BadRequest("La expresión deserializada es nula o incorrecta.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(request.AttributeName))
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, "El nombre del atributo es obligatorio.");
|
||||||
|
return BadRequest("El nombre del atributo es obligatorio.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var parameter = Expression.Parameter(typeof(TEntity), "x");
|
||||||
|
var property = Expression.PropertyOrField(parameter, request.AttributeName);
|
||||||
|
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, $"El atributo '{request.AttributeName}' no existe en la entidad.");
|
||||||
|
return BadRequest($"El atributo '{request.AttributeName}' no existe en la entidad.");
|
||||||
|
}
|
||||||
|
// Crear una expresión para seleccionar el atributo
|
||||||
|
var attributeSelector = Expression.Lambda<Func<TEntity, object>>(
|
||||||
|
Expression.Convert(property, typeof(object)),
|
||||||
|
parameter);
|
||||||
|
|
||||||
|
var entities = await context.Set<TEntity>()
|
||||||
|
.Where(expression)
|
||||||
|
.Select(attributeSelector)
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, $"Registros obtenidos: {entities.Count}");
|
||||||
|
|
||||||
|
|
||||||
|
return Ok(entities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, ex.Message);
|
||||||
|
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Crea una nueva entidad (Escritura).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">Entidad a crear.</param>
|
||||||
|
/// <returns>Entidad creada.</returns>
|
||||||
|
/// <summary>
|
||||||
|
/// Crea una nueva entidad (Escritura).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">Entidad a crear.</param>
|
||||||
|
/// <returns>Entidad creada.</returns>
|
||||||
|
[Authorize]
|
||||||
|
[HttpPost]
|
||||||
|
public virtual IActionResult Create([FromBody] TEntity entity)
|
||||||
|
{
|
||||||
|
string operacion = nameof(Create);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
string parametros = System.Text.Json.JsonSerializer.Serialize(entity);
|
||||||
|
// Ignorar la validación automática del modelo
|
||||||
|
if (!TryValidateModel(entity))
|
||||||
|
{
|
||||||
|
ModelState.Clear(); // Limpia cualquier error de validación
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
dbSet.Add(entity);
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, "Entidad creada exitosamente");
|
||||||
|
|
||||||
|
|
||||||
|
var id = GetEntityId(entity);
|
||||||
|
if (id != null)
|
||||||
|
{
|
||||||
|
return CreatedAtAction(nameof(GetById), new { id = id }, entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Ok(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, ex.Message);
|
||||||
|
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Actualiza una entidad existente (Escritura).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">ID de la entidad a actualizar.</param>
|
||||||
|
/// <param name="entity">Entidad actualizada.</param>
|
||||||
|
/// <returns>No content.</returns>
|
||||||
|
[Authorize]
|
||||||
|
[HttpPut("{id}")]
|
||||||
|
public virtual IActionResult Update(TKey id, [FromBody] TEntity entity)
|
||||||
|
{
|
||||||
|
string operacion = nameof(Update);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
string parametros = $"ID: {id}, Datos: {System.Text.Json.JsonSerializer.Serialize(entity)}";
|
||||||
|
|
||||||
|
var entityId = GetEntityId(entity);
|
||||||
|
if (entityId == null || !id.Equals((TKey)entityId))
|
||||||
|
return BadRequest("El ID de la entidad no coincide con el ID de la URL.");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
|
||||||
|
// Buscar la entidad existente
|
||||||
|
var existingEntity = dbSet.Find(id);
|
||||||
|
if (existingEntity == null)
|
||||||
|
{
|
||||||
|
// RegistrarActividad(operacion, usuario, parametros, null, "Entidad no encontrada");
|
||||||
|
return NotFound("No se encontró la entidad para actualizar.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterar sobre las propiedades de la entidad
|
||||||
|
foreach (var property in typeof(TEntity).GetProperties())
|
||||||
|
{
|
||||||
|
// Verificar si la propiedad es escalar o navegación
|
||||||
|
var propertyMetadata = context.Model.FindEntityType(typeof(TEntity))?
|
||||||
|
.FindProperty(property.Name);
|
||||||
|
|
||||||
|
if (propertyMetadata == null)
|
||||||
|
{
|
||||||
|
// Es una propiedad de navegación, omitirla
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manejar propiedades escalares
|
||||||
|
var newValue = property.GetValue(entity);
|
||||||
|
var oldValue = property.GetValue(existingEntity);
|
||||||
|
|
||||||
|
if (!Equals(newValue, oldValue))
|
||||||
|
{
|
||||||
|
context.Entry(existingEntity).Property(property.Name).CurrentValue = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guardar cambios
|
||||||
|
context.SaveChanges();
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, "Actualización exitosa");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//RegistrarActividad(operacion, usuario, parametros, null, ex.Message);
|
||||||
|
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Elimina una entidad por ID (Escritura).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">ID de la entidad a eliminar.</param>
|
||||||
|
/// <returns>No content.</returns>
|
||||||
|
[Authorize]
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public virtual IActionResult Delete(TKey id)
|
||||||
|
{
|
||||||
|
string operacion = nameof(Delete);
|
||||||
|
string usuario = User?.Identity?.Name ?? "Usuario no autenticado";
|
||||||
|
string parametros = $"ID: {id}";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var context = bdEmtusa.tscEmtusa.NuevoContexto())
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var entity = dbSet.Find(id);
|
||||||
|
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
// RegistrarActividad(operacion, usuario, parametros, null, "Entidad no encontrada");
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
dbSet.Remove(entity);
|
||||||
|
context.SaveChanges();
|
||||||
|
|
||||||
|
// RegistrarActividad(operacion, usuario, parametros, "Entidad eliminada exitosamente");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// RegistrarActividad(operacion, usuario, parametros, null, ex.Message);
|
||||||
|
return StatusCode(500, $"Error interno del servidor: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Obtiene el valor de la propiedad de ID de la entidad.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">Entidad de la cual obtener el ID.</param>
|
||||||
|
/// <returns>Valor del ID.</returns>
|
||||||
|
protected virtual object GetEntityId(TEntity entity)
|
||||||
|
{
|
||||||
|
// Busca las propiedades que podrían ser claves primarias según las convenciones o el atributo [Key]
|
||||||
|
var type = typeof(TEntity);
|
||||||
|
|
||||||
|
// Primero, buscamos cualquier propiedad marcada con [Key], que es la forma más confiable de identificar el ID
|
||||||
|
var idProperty = type.GetProperties().FirstOrDefault(p => p.GetCustomAttribute<KeyAttribute>() != null);
|
||||||
|
|
||||||
|
if (idProperty != null)
|
||||||
|
{
|
||||||
|
return idProperty.GetValue(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si no hay un atributo [Key], intentamos con algunas convenciones de nombres comunes para ID
|
||||||
|
idProperty = type.GetProperties().FirstOrDefault(p =>
|
||||||
|
p.Name.Equals("ID", StringComparison.OrdinalIgnoreCase) || // Nombre genérico 'Id'
|
||||||
|
p.Name.Equals($"{type.Name}ID", StringComparison.OrdinalIgnoreCase) || //
|
||||||
|
p.Name.StartsWith("ID", StringComparison.OrdinalIgnoreCase)); // Cualquier nombre que comience con 'ID'
|
||||||
|
|
||||||
|
if (idProperty != null)
|
||||||
|
{
|
||||||
|
return idProperty.GetValue(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("No se pudo encontrar una propiedad de ID para la entidad.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//protected void RegistrarActividad(string operacion, string? usuario, string? parametrosConsulta, string? respuesta = null, string? errores = null)
|
||||||
|
//{
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// using (var context = bdCOAS.tsCOASVD.NuevoContexto(SoloLectura: false, Lazy: false))
|
||||||
|
// {
|
||||||
|
// var registro = new REGISTRODEACTIVIDADREST
|
||||||
|
// {
|
||||||
|
// FECHAHORA = DateTime.Now,
|
||||||
|
// OPERACIONINVOCADA = operacion,
|
||||||
|
// USUARIO = usuario,
|
||||||
|
// PARAMETROSCONSULTA = parametrosConsulta.Length > 500 ? parametrosConsulta.Substring(0, 500) : parametrosConsulta,
|
||||||
|
// RESPUESTA = respuesta,
|
||||||
|
// ERRORES = errores
|
||||||
|
// };
|
||||||
|
|
||||||
|
// context.Set<REGISTRODEACTIVIDADREST>().Add(registro);
|
||||||
|
// context.SaveChanges();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"Error al registrar actividad: {ex.Message}");
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExpressionWrapper
|
||||||
|
{
|
||||||
|
public string Expression { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ExpressionWrapperAtributo
|
||||||
|
{
|
||||||
|
public string Expression { get; set; }
|
||||||
|
public string AttributeName { get; set; }
|
||||||
|
}
|
||||||
24
swEmtusa/Controllers/ItemsController.cs
Normal file
24
swEmtusa/Controllers/ItemsController.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using SwaggerAutenticacion.Clases;
|
||||||
|
using System.Linq.Dynamic.Core;
|
||||||
|
using tsUtilidades;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using bdEmtusa.db;
|
||||||
|
using SwaggerColegiados.Controllers;
|
||||||
|
using bdEmtusa;
|
||||||
|
|
||||||
|
|
||||||
|
namespace SwaggerAutenticacion.Controllers
|
||||||
|
{
|
||||||
|
public class ItemsController : GenericoController<items, int>
|
||||||
|
{
|
||||||
|
private tscEmtusa bd;
|
||||||
|
|
||||||
|
public ItemsController()
|
||||||
|
{
|
||||||
|
bd = bdEmtusa.tscEmtusa.NuevoContexto(SoloLectura: false);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,74 @@
|
|||||||
using bdEmtusa;
|
using bdEmtusa;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
|
||||||
|
var bd = tscEmtusa.NuevoContexto();
|
||||||
|
|
||||||
|
string version = Assembly.GetEntryAssembly()?.GetName().Version?.ToString();
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
var jwtSettings = builder.Configuration.GetSection("Jwt");
|
||||||
// var bd = tscEmtusa.NuevoContexto();
|
var keyString = jwtSettings["Key"]
|
||||||
|
?? throw new ArgumentNullException("JWT Key is not configured.");
|
||||||
|
var key = Encoding.UTF8.GetBytes(keyString);
|
||||||
|
// 1) Configuramos autenticaci<63>n JWT
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
})
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.RequireHttpsMetadata = false;
|
||||||
|
options.SaveToken = true;
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
ValidIssuer = jwtSettings["Issuer"],
|
||||||
|
ValidAudience = jwtSettings["Audience"],
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(key)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
//// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Autenticaci<63>n API", Version = "v1" });
|
||||||
|
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Name = "Authorization",
|
||||||
|
Type = SecuritySchemeType.ApiKey,
|
||||||
|
Scheme = "Bearer",
|
||||||
|
BearerFormat = "JWT",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Description = "Introduce `Bearer` seguido del `token JWT`"
|
||||||
|
});
|
||||||
|
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference {
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Array.Empty<string>()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
{
|
{
|
||||||
|
"Jwt": {
|
||||||
|
"Key": "drXn/a/DCy8/460ANakCczckSwSXrxdy1IKjiQl649o=",
|
||||||
|
"Issuer": "MiAPI_AuthServer",
|
||||||
|
"Audience": "TuAudience",
|
||||||
|
"ExpiresInMinutes": 30
|
||||||
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
|
|||||||
@@ -7,10 +7,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Controllers\AuthController.cs" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.30" />
|
||||||
</ItemGroup>
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.22.0" />
|
||||||
|
<PackageReference Include="Serialize.Linq" Version="4.4.1" />
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -18,8 +17,4 @@
|
|||||||
<ProjectReference Include="..\bdEmtusa\bdEmtusa.csproj" />
|
<ProjectReference Include="..\bdEmtusa\bdEmtusa.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Controllers\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user