First Commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
namespace ADS.Apis.Gps.Infrastructure.Crypto;
|
||||
|
||||
public sealed class LegacyCryptoOptions
|
||||
{
|
||||
public string Mode { get; set; } = "AES"; // "DES" o "AES"
|
||||
public string Key { get; set; } = "";
|
||||
public string IV { get; set; } = ""; // Base64
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using ADS.Apis.Gps.Application.Common.Crypto;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ADS.Apis.Gps.Infrastructure.Crypto;
|
||||
|
||||
public sealed class LegacyPasswordEncryptor : ILegacyPasswordEncryptor
|
||||
{
|
||||
private readonly LegacyCryptoOptions _opt;
|
||||
|
||||
public LegacyPasswordEncryptor(IOptions<LegacyCryptoOptions> opt)
|
||||
=> _opt = opt.Value;
|
||||
|
||||
public string Encrypt(string plainText)
|
||||
{
|
||||
if (string.IsNullOrEmpty(plainText)) return string.Empty;
|
||||
|
||||
var mode = (_opt.Mode ?? "AES").Trim().ToUpperInvariant();
|
||||
var iv = Convert.FromBase64String(_opt.IV ?? "");
|
||||
|
||||
return mode switch
|
||||
{
|
||||
"DES" => EncryptDesBase64(plainText, _opt.Key, iv),
|
||||
"AES" => EncryptAesBase64(plainText, _opt.Key, iv),
|
||||
_ => throw new InvalidOperationException($"Unsupported LegacyCrypto.Mode: {_opt.Mode}")
|
||||
};
|
||||
}
|
||||
|
||||
private static string EncryptDesBase64(string plainText, string keySource, byte[] iv8)
|
||||
{
|
||||
if (iv8.Length != 8) throw new ArgumentException("DES IV must be 8 bytes.", nameof(iv8));
|
||||
|
||||
var key8 = Encoding.UTF8.GetBytes((keySource ?? string.Empty).PadRight(8).Substring(0, 8));
|
||||
|
||||
using var des = new DESCryptoServiceProvider
|
||||
{
|
||||
Mode = CipherMode.CBC,
|
||||
Padding = PaddingMode.PKCS7,
|
||||
Key = key8,
|
||||
IV = iv8
|
||||
};
|
||||
|
||||
var input = Encoding.UTF8.GetBytes(plainText);
|
||||
using var encryptor = des.CreateEncryptor(des.Key, des.IV);
|
||||
var cipher = encryptor.TransformFinalBlock(input, 0, input.Length);
|
||||
|
||||
return Convert.ToBase64String(cipher);
|
||||
}
|
||||
|
||||
private static string EncryptAesBase64(string plainText, string keySource, byte[] iv16)
|
||||
{
|
||||
if (iv16.Length != 16) throw new ArgumentException("AES IV must be 16 bytes.", nameof(iv16));
|
||||
|
||||
var key32 = Encoding.UTF8.GetBytes((keySource ?? string.Empty).PadRight(32).Substring(0, 32));
|
||||
|
||||
using var aes = Aes.Create();
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
aes.Key = key32;
|
||||
aes.IV = iv16;
|
||||
|
||||
var input = Encoding.UTF8.GetBytes(plainText);
|
||||
using var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
|
||||
var cipher = encryptor.TransformFinalBlock(input, 0, input.Length);
|
||||
|
||||
return Convert.ToBase64String(cipher);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Data;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ADS.Apis.Gps.Domain.Models.Sicrep;
|
||||
using ADS.Apis.Gps.Domain.Ports.Sicrep;
|
||||
using ADS.Helpers.Data.Abstractions;
|
||||
using ADS.Helpers.MultiTenant.Abstractions;
|
||||
using ADS.Helpers.MultiTenant.Context;
|
||||
using Dapper;
|
||||
|
||||
namespace ADS.Apis.Gps.Infrastructure.Data.Dapper;
|
||||
|
||||
public sealed class DapperSicrepUserValidationRepository : ISicrepUserValidationRepository
|
||||
{
|
||||
private readonly ITenantDbConnectionFactory _connFactory;
|
||||
private readonly ITenantContextAccessor _tenantAccessor;
|
||||
|
||||
public DapperSicrepUserValidationRepository(
|
||||
ITenantDbConnectionFactory connFactory,
|
||||
ITenantContextAccessor tenantAccessor)
|
||||
{
|
||||
_connFactory = connFactory;
|
||||
_tenantAccessor = tenantAccessor;
|
||||
}
|
||||
|
||||
public async Task<SicrepUserValidationResult?> ValidateUserAsync(
|
||||
string usuario,
|
||||
string contrasena32,
|
||||
int cveEmpresa,
|
||||
string? ip,
|
||||
string? mac,
|
||||
string? grupoEmpresa,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var tenant = _tenantAccessor.Current
|
||||
?? throw new UnauthorizedAccessException("TenantContext not available.");
|
||||
|
||||
// USAMOS TU MÉTODO REAL
|
||||
using var conn = _connFactory.Create();//tenant.Database.ConnectionString);
|
||||
|
||||
var p = new DynamicParameters();
|
||||
p.Add("@Usuario", usuario, DbType.String, size: 32);
|
||||
p.Add("@Contraseña", contrasena32, DbType.String, size: 32);
|
||||
p.Add("@CveEmpresa", cveEmpresa, DbType.Int32);
|
||||
p.Add("@IP", ip ?? string.Empty, DbType.String, size: 20);
|
||||
p.Add("@MAC", mac ?? string.Empty, DbType.String, size: 50);
|
||||
p.Add("@GrupoEmpresa", grupoEmpresa ?? string.Empty, DbType.String, size: 100);
|
||||
const string sp = "[dbo].[PA_Sis_UsuarioValidacionGet]";
|
||||
|
||||
var result = await conn.QueryFirstOrDefaultAsync<SicrepUserValidationResult>(
|
||||
sp,
|
||||
p,
|
||||
commandType: CommandType.StoredProcedure);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using ADS.Apis.Gps.Application.Abstractions.Security;
|
||||
using ADS.Apis.Gps.Application.Common.Crypto;
|
||||
using ADS.Apis.Gps.Application.Contracts.Auth;
|
||||
using ADS.Apis.Gps.Application.UseCases.Auth;
|
||||
using ADS.Apis.Gps.Domain.Ports.Sicrep;
|
||||
using ADS.Apis.Gps.Infrastructure.Crypto;
|
||||
using ADS.Apis.Gps.Infrastructure.Data.Dapper;
|
||||
using ADS.Apis.Gps.Infrastructure.Security;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ADS.Apis.Gps.Infrastructure.DependencyInjection;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddGpsSicrepAuth(this IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<IAdsUserCredentialValidator, AdsUserCredentialValidator>();
|
||||
services.AddScoped<IAdsClientCredentialValidator, AdsClientCredentialValidator>();
|
||||
// Domain Ports -> Infrastructure
|
||||
services.AddScoped<ISicrepUserValidationRepository, DapperSicrepUserValidationRepository>();
|
||||
|
||||
// Application
|
||||
services.AddScoped<ISicrepAuthService, SicrepAuthService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
public static IServiceCollection AddGpsInfrastructure(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.Configure<LegacyCryptoOptions>(configuration.GetSection("LegacyCrypto"));
|
||||
services.AddSingleton<ILegacyPasswordEncryptor, LegacyPasswordEncryptor>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Data;
|
||||
using Dapper;
|
||||
using ADS.Apis.Gps.Application.Abstractions.Security;
|
||||
using ADS.Helpers.Data.Abstractions;
|
||||
|
||||
namespace ADS.Apis.Gps.Infrastructure.Security;
|
||||
|
||||
public sealed class AdsClientCredentialValidator : IAdsClientCredentialValidator
|
||||
{
|
||||
private readonly ITenantDbConnectionFactory _db;
|
||||
|
||||
public AdsClientCredentialValidator(ITenantDbConnectionFactory db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public async Task<AdsClientCredentialResult> ValidateAsync(string clientId, string clientSecret, CancellationToken ct = default)
|
||||
{
|
||||
// using var conn = await _db.OpenAsync(ct);
|
||||
|
||||
// var p = new DynamicParameters();
|
||||
// p.Add("@ClientId", clientId, DbType.String);
|
||||
// p.Add("@ClientSecret", clientSecret, DbType.String);
|
||||
|
||||
// var row = await conn.QueryFirstOrDefaultAsync<ClientRow>(
|
||||
// sql: "PA_Sicrep_ValidateClient",
|
||||
// param: p,
|
||||
// commandType: CommandType.StoredProcedure
|
||||
// );
|
||||
|
||||
// if (row is null || row.IsValid == 0)
|
||||
// return new AdsClientCredentialResult(false, null, null, null);
|
||||
|
||||
// return new AdsClientCredentialResult(true, row.ClientId, row.ClientKey, row.ClientName);
|
||||
return null;
|
||||
}
|
||||
|
||||
private sealed class ClientRow
|
||||
{
|
||||
public int IsValid { get; init; }
|
||||
public int ClientId { get; init; }
|
||||
public string ClientKey { get; init; } = string.Empty;
|
||||
public string ClientName { get; init; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.Data;
|
||||
using Dapper;
|
||||
using ADS.Apis.Gps.Application.Abstractions.Security;
|
||||
using ADS.Helpers.Data.Abstractions;
|
||||
|
||||
namespace ADS.Apis.Gps.Infrastructure.Security;
|
||||
|
||||
public sealed class AdsUserCredentialValidator : IAdsUserCredentialValidator
|
||||
{
|
||||
private readonly ITenantDbConnectionFactory _db;
|
||||
|
||||
public AdsUserCredentialValidator(ITenantDbConnectionFactory db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public async Task<AdsUserCredentialResult> ValidateAsync(string username, string password, CancellationToken ct = default)
|
||||
{
|
||||
// using var conn = await _db.OpenAsync(ct);
|
||||
|
||||
// // EJEMPLO: si validas con SP
|
||||
// // Cambia el nombre del SP y los nombres de parámetros a tus reales.
|
||||
// var p = new DynamicParameters();
|
||||
// p.Add("@Usuario", username, DbType.String);
|
||||
// p.Add("@Password", password, DbType.String);
|
||||
|
||||
// var row = await conn.QueryFirstOrDefaultAsync<UserRow>(
|
||||
// sql: "PA_Sicrep_ValidateUser",
|
||||
// param: p,
|
||||
// commandType: CommandType.StoredProcedure
|
||||
// );
|
||||
|
||||
// if (row is null || row.IsValid == 0)
|
||||
// return new AdsUserCredentialResult(false, null, null, null);
|
||||
|
||||
// return new AdsUserCredentialResult(true, row.UserId, row.Username, row.DisplayName);
|
||||
return null;
|
||||
}
|
||||
|
||||
private sealed class UserRow
|
||||
{
|
||||
public int IsValid { get; init; }
|
||||
public int UserId { get; init; }
|
||||
public string Username { get; init; } = string.Empty;
|
||||
public string DisplayName { get; init; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Data;
|
||||
using ADS.Apis.Gps.Application.Units;
|
||||
using ADS.Helpers.Data;
|
||||
using ADS.Helpers.Data.Abstractions;
|
||||
using Dapper;
|
||||
|
||||
namespace ADS.Apis.Gps.Infrastructure.Units;
|
||||
|
||||
public sealed class UnitLocationQueryService : IUnitLocationQueryService
|
||||
{
|
||||
private readonly ITenantDbConnectionFactory _connectionFactory;
|
||||
|
||||
public UnitLocationQueryService(ITenantDbConnectionFactory connectionFactory)
|
||||
{
|
||||
_connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
public async Task<UnitLastLocationResponse?> GetLastLocationByNoEconomicoAsync(
|
||||
int cveUsuario,
|
||||
string noEconomico,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
using var connection = _connectionFactory.Create();
|
||||
|
||||
var command = new CommandDefinition(
|
||||
commandText: "dbo.PA_GPS_DispositovoUbicacionByNoEconomicoGet",
|
||||
parameters: new
|
||||
{
|
||||
CveUsuario = cveUsuario,
|
||||
NoEconomico = noEconomico
|
||||
},
|
||||
commandType: CommandType.StoredProcedure,
|
||||
cancellationToken: ct
|
||||
);
|
||||
|
||||
return await connection.QueryFirstOrDefaultAsync<UnitLastLocationResponse>(command);
|
||||
}
|
||||
public async Task<IReadOnlyList<UnitClientLocationResponse>> GetLocationsByClientAsync(
|
||||
int cveUsuario,
|
||||
int cveCliente,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
using var connection = _connectionFactory.Create();
|
||||
|
||||
var command = new CommandDefinition(
|
||||
commandText: "dbo.PA_GPS_DispositovoUbicacionPorClienteGet",
|
||||
parameters: new
|
||||
{
|
||||
CveUsuario = cveUsuario,
|
||||
CveCliente = cveCliente
|
||||
},
|
||||
commandType: CommandType.StoredProcedure,
|
||||
cancellationToken: ct
|
||||
);
|
||||
|
||||
var result = await connection.QueryAsync<UnitClientLocationResponse>(command);
|
||||
|
||||
return result.AsList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user