From ef62b7bfea9bf196aa36e57cfdd92c727b38e381 Mon Sep 17 00:00:00 2001 From: jrojas Date: Mon, 6 Jul 2026 13:50:16 +0200 Subject: [PATCH] se agrego rc102 --- .../adas-core.Application.csproj | 25 +- .../adas-core.Authentication.csproj | 17 +- adas-core.Domain/adas-core.Domain.csproj | 10 +- .../Repositories/MasterListRepository.cs | 1 - .../adas-core.Infrastructure.csproj | 11 +- adas-core.LdapLogin/LdapLoginService.cs | 247 +++++++----------- .../adas-core.LdapLogin.csproj | 7 +- .../adas-core.LocalLogin.csproj | 10 +- adas-core.Test/adas-core.Test.csproj | 8 +- .../adas-core.module.LightBeacons.csproj | 6 +- .../adas-core.module.ProxyDevices.csproj | 6 +- .../adas-core.module.Relays.csproj | 1 - adas-core/Program.cs | 4 +- adas-core/adas-core.csproj | 27 +- adas-core/appsettings.NursePlan.json | 2 +- 15 files changed, 170 insertions(+), 212 deletions(-) diff --git a/adas-core.Application/adas-core.Application.csproj b/adas-core.Application/adas-core.Application.csproj index ede1a4b1..5bac7ce2 100644 --- a/adas-core.Application/adas-core.Application.csproj +++ b/adas-core.Application/adas-core.Application.csproj @@ -21,23 +21,20 @@ - + - - - - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + - - - - - - - ..\..\..\..\..\..\..\Program Files\dotnet\shared\Microsoft.AspNetCore.App\7.0.10\Microsoft.AspNetCore.Http.Features.dll - + diff --git a/adas-core.Authentication/adas-core.Authentication.csproj b/adas-core.Authentication/adas-core.Authentication.csproj index 8af44874..98e372c3 100644 --- a/adas-core.Authentication/adas-core.Authentication.csproj +++ b/adas-core.Authentication/adas-core.Authentication.csproj @@ -9,12 +9,17 @@ - - - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/adas-core.Domain/adas-core.Domain.csproj b/adas-core.Domain/adas-core.Domain.csproj index f36d59dc..c8a2ac16 100644 --- a/adas-core.Domain/adas-core.Domain.csproj +++ b/adas-core.Domain/adas-core.Domain.csproj @@ -10,17 +10,13 @@ - - - + - - - - + + diff --git a/adas-core.Infrastructure/Repositories/MasterListRepository.cs b/adas-core.Infrastructure/Repositories/MasterListRepository.cs index 5526f8aa..8f412baf 100644 --- a/adas-core.Infrastructure/Repositories/MasterListRepository.cs +++ b/adas-core.Infrastructure/Repositories/MasterListRepository.cs @@ -1117,7 +1117,6 @@ public class MasterListRepository : MongoRepository, IMasterListRepository // Normaliza el texto de búsqueda a minúsculas var normalizedTextSearch = textSearch.ToLowerInvariant(); - // Construye la expresión regular dinámica para tener en cuenta la acentuación en las vocales var regexPattern = BuildRegexPattern(normalizedTextSearch); // foreach (var c in normalizedTextSearch) // { diff --git a/adas-core.Infrastructure/adas-core.Infrastructure.csproj b/adas-core.Infrastructure/adas-core.Infrastructure.csproj index 186f0b92..08f01dd9 100644 --- a/adas-core.Infrastructure/adas-core.Infrastructure.csproj +++ b/adas-core.Infrastructure/adas-core.Infrastructure.csproj @@ -9,11 +9,14 @@ - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - + diff --git a/adas-core.LdapLogin/LdapLoginService.cs b/adas-core.LdapLogin/LdapLoginService.cs index 7876c840..8bd3f0ca 100644 --- a/adas-core.LdapLogin/LdapLoginService.cs +++ b/adas-core.LdapLogin/LdapLoginService.cs @@ -5,11 +5,12 @@ using adas_core.Domain.Models.MongoModels; using adas_core.LdapLogin.Configuration; using FluentValidation; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MongoDB.Bson; -using Novell.Directory.Ldap; +using System.DirectoryServices.Protocols; +using System.Net; +using Authorization = adas_core.Domain.Models.MongoModels.Authorization; namespace adas_core.LdapLogin; @@ -39,157 +40,128 @@ public class LdapLoginService : ILoginService public async Task Login(string username, string password) { - // Check for LDAP config - if (_ldapConfig.Server == null) throw new LoginServicesException("LDAP Config not found"); - var conn = new LdapConnection(); + if (_ldapConfig.Server == null) + throw new LoginServicesException("LDAP Config not found"); + + var identifier = new LdapDirectoryIdentifier(_ldapConfig.Server, _ldapConfig.Port ?? 389); + var connection = new LdapConnection(identifier); + try { - await conn.ConnectAsync(_ldapConfig.Server, _ldapConfig.Port ?? 389); - } - catch (Exception e) - { - _logger.LogError("[LDAP] Error connecting to {server}, port {port}, Exception: {e}", _ldapConfig.Server, - _ldapConfig.Port, e.Message); - throw; - } - - if (_ldapConfig.LdapUser != null) - { - _logger.LogInformation("[LDAP] _ldapConfig.LdapUser is enabled with {LdapUser}", _ldapConfig.LdapUser); - await conn.BindAsync(_ldapConfig.LdapUser, _ldapConfig.LdapPassword); - } - else - { - var ldapUser = (!string.IsNullOrEmpty(_ldapConfig.UserDomainName) - ? _ldapConfig.UserDomainName + @"\" - : "") + username; - - try + if (_ldapConfig.LdapUser != null) { - await conn.BindAsync(ldapUser, password); + _logger.LogInformation("[LDAP] Using configured LDAP user {LdapUser}", _ldapConfig.LdapUser); + connection.Credential = new NetworkCredential(_ldapConfig.LdapUser, _ldapConfig.LdapPassword); } - catch (LdapException e) + else { - _logger.LogError("[LDAP] Error binding ldapUser: {LdapUser} and password", ldapUser); + var ldapUser = (!string.IsNullOrEmpty(_ldapConfig.UserDomainName) + ? _ldapConfig.UserDomainName + @"\" + : "") + username; - throw new UserNotFoundException(username, e); - } - } - - var results = await conn.SearchAsync( - _ldapConfig.SearchBase, - LdapConnection.ScopeSub, - $"({_ldapConfig.UserNameProperty}={username})", - null, - false); - - - LdapEntry? entry = null; - - while (await results.HasMoreAsync()) - { - LdapEntry? current = null; - - try - { - current = await results.NextAsync(); - } - catch (LdapException ex) - { - _logger.LogWarning("[LDAP] Skipping invalid entry: {error}", ex.Message); - continue; + connection.Credential = new NetworkCredential(ldapUser, password); } - if (current != null) + connection.AuthType = AuthType.Basic; + connection.Bind(); + } + catch (LdapException e) + { + _logger.LogError("[LDAP] Error binding user {username}", username); + throw new UserNotFoundException(username, e); + } + + SearchResultEntry? entry = null; + + try + { + var request = new SearchRequest( + _ldapConfig.SearchBase, + $"({_ldapConfig.UserNameProperty}={username})", + SearchScope.Subtree + ); + + var response = (SearchResponse)connection.SendRequest(request); + + foreach (SearchResultEntry current in response.Entries) { entry = current; break; } } + catch (Exception e) + { + _logger.LogError("[LDAP] Search error for user {username}: {error}", username, e.Message); + throw; + } + if (entry == null) + throw new LoginServicesException("LDAP User not found"); - if (entry == null) throw new LoginServicesException("LDAP User not found"); var userEntryLdap = GetUser(entry); var user = await GetOrCreateUser(userEntryLdap, entry); - _logger.LogInformation("[LDAP] entry is {entry} and user {user}", entry, user); - // user.Authorization.AddRange(GetAuthorities(entry)); - conn.Disconnect(); + + _logger.LogInformation("[LDAP] entry found and user {user}", user); + + connection.Dispose(); + return user ?? throw new LoginServicesException("LDAP User not found"); } public Task Login(HttpContext context) - { - throw new LoginServicesException("Not implemented"); - } + => throw new LoginServicesException("Not implemented"); public Task Authenticate(string username, string password) - { - throw new LoginServicesException("Not implemented"); - } + => throw new LoginServicesException("Not implemented"); public Task GetById(ObjectId id) - { - throw new LoginServicesException("Not implemented"); - } + => throw new LoginServicesException("Not implemented"); public Task GetByEmail(string email) - { - throw new LoginServicesException("Not implemented"); - } + => throw new LoginServicesException("Not implemented"); public Task GetByUsername(string username) - { - throw new LoginServicesException("Not implemented"); - } + => throw new LoginServicesException("Not implemented"); public Task> GetAllUsers() - { - throw new LoginServicesException("Not implemented"); - } + => throw new LoginServicesException("Not implemented"); - private async Task GetOrCreateUser(User userEntryLdap, LdapEntry entry) + private async Task GetOrCreateUser(User userEntryLdap, SearchResultEntry entry) { var userToReturn = (await _userService.Value.GetUserByUserName(userEntryLdap.UserName) ?? await _userService.Value.GetUserByName(userEntryLdap.Name)) ?? await _userService.Value.CreateUser(userEntryLdap); if (userToReturn == null) return userToReturn; + userToReturn.Authorization = []; var authorities = await CheckAuthorities(userToReturn, entry); - userToReturn.Authorization.AddRange(authorities); - //foreach (var authorization in userToReturn.Authorization) - //{ - // Enum.TryParse(authorization.Rol, out var compareRole); - // if (compareRole == RolesType.Admin) userToReturn.Rol = RolesType.Admin; - //} + return userToReturn; } - private async Task> CheckAuthorities(User user, LdapEntry entry) + private async Task> CheckAuthorities(User user, SearchResultEntry entry) { try { var authorizationMap = GetAuthoritiesMap(entry, user); var authorizationWhiteList = GetAuthoritiesWhiteList(entry, user); - _logger.LogInformation( - "[LDAP] user {user} authorizationMap count is {authorizationMap}, authorizationWhiteList count is {authorizationWhiteList}", - user.UserName, authorizationMap.Count, authorizationWhiteList.Count); - // Primero, creamos un HashSet con los DisplayID de la lista blanca para búsqueda eficiente var whiteListDisplayIds = new HashSet(authorizationWhiteList.Select(a => a.DisplayId)); - // Filtramos los elementos de authorizationMap que no están en la lista blanca, basándonos en DisplayID - var uniqueMapAuthorizations = authorizationMap.Where(a => !whiteListDisplayIds.Contains(a.DisplayId)); + var uniqueMapAuthorizations = authorizationMap + .Where(a => !whiteListDisplayIds.Contains(a.DisplayId)); - // Finalmente, combinamos los elementos únicos de authorizationMap con los de authorizationWhiteList var combinedList = authorizationWhiteList.Concat(uniqueMapAuthorizations).ToList(); var userAuthorities = await _authorityService.GetUserAuthorities(user.Id); + foreach (var auth in combinedList) { var authFound = userAuthorities.Find(c => c.DisplayId == auth.DisplayId); + if (authFound is { CanUpdate: true }) { authFound.Rol = auth.Rol; @@ -205,36 +177,32 @@ public class LdapLoginService : ILoginService } catch (Exception e) { - _logger.LogError("[LDAP] CheckAuthorities for user {user} has exception {ex}", user.UserName, e.Message); + _logger.LogError("[LDAP] CheckAuthorities error for user {user}: {error}", + user.UserName, e.Message); return []; } } - private List GetAuthoritiesWhiteList(LdapEntry entry, User user) + private List GetAuthoritiesWhiteList(SearchResultEntry entry, User user) { try { - var userWhiteList = new List(); - var userNameProperty = _ldapConfig.UserNameProperty; + var result = new List(); var whiteList = _ldapConfig.WhiteList.FindAll(u => - (u.Name != null && entry.Dn.Contains(u.Name, StringComparison.CurrentCultureIgnoreCase)) || + (u.Name != null && entry.DistinguishedName.Contains(u.Name, StringComparison.CurrentCultureIgnoreCase)) || (u.Username != null && - userNameProperty != null && - entry.GetAttributeSet().TryGetValue(userNameProperty, out var attr) && - attr.StringValue != null && - attr.StringValue.Equals(u.Username, StringComparison.CurrentCultureIgnoreCase)) + entry.Attributes[_ldapConfig.UserNameProperty]?[0]?.ToString() + ?.Equals(u.Username, StringComparison.CurrentCultureIgnoreCase) == true) ); - if (whiteList.Count == 0) return userWhiteList; - foreach (var authorityMap in whiteList) { if (!Enum.TryParse(authorityMap.Rol, out _)) continue; - userWhiteList.Add(new Authorization + result.Add(new Authorization { UserId = user.Id, DisplayId = authorityMap.DisplayId, @@ -242,59 +210,42 @@ public class LdapLoginService : ILoginService }); } - return userWhiteList; + return result; } catch (Exception e) { - _logger.LogError("[LDAP] GetAuthoritiesWhiteList for user {user} has exception {ex}", user.UserName, - e.Message); - + _logger.LogError("[LDAP] GetAuthoritiesWhiteList error: {error}", e.Message); return []; } } - private User GetUser(LdapEntry ldapEntry) + private User GetUser(SearchResultEntry entry) { - var attributes = ldapEntry.GetAttributeSet(); - - var user = new User(); - - // UserName - if (!string.IsNullOrWhiteSpace(_ldapConfig.UserNameProperty) && - attributes.TryGetValue(_ldapConfig.UserNameProperty, out var userAttr) && - userAttr?.StringValue != null) + var user = new User { - user.UserName = userAttr.StringValue; - } - else + UserName = entry.Attributes[_ldapConfig.UserNameProperty]?[0]?.ToString() ?? "" + }; + + if (!string.IsNullOrWhiteSpace(_ldapConfig.FirstNameProperty)) { - user.UserName = ""; + var first = entry.Attributes[_ldapConfig.FirstNameProperty]?[0]?.ToString(); + if (first != null) + user.Name = first; } - _logger.LogInformation("[LDAP] GetUser UserName is {UserName} ", user.UserName); - - // First name - if (!string.IsNullOrWhiteSpace(_ldapConfig.FirstNameProperty) && - attributes.TryGetValue(_ldapConfig.FirstNameProperty, out var firstNameAttr) && - firstNameAttr?.StringValue != null) + if (!string.IsNullOrWhiteSpace(_ldapConfig.LastNameProperty)) { - user.Name = firstNameAttr.StringValue; - } - - // Last name - if (!string.IsNullOrWhiteSpace(_ldapConfig.LastNameProperty) && - attributes.TryGetValue(_ldapConfig.LastNameProperty, out var lastNameAttr) && - lastNameAttr?.StringValue != null) - { - user.Name = string.IsNullOrEmpty(user.Name) - ? lastNameAttr.StringValue - : $"{user.Name} {lastNameAttr.StringValue}"; + var last = entry.Attributes[_ldapConfig.LastNameProperty]?[0]?.ToString(); + if (last != null) + user.Name = string.IsNullOrEmpty(user.Name) + ? last + : $"{user.Name} {last}"; } return user; } - private List GetAuthoritiesMap(LdapEntry ldapEntry, User user) + private List GetAuthoritiesMap(SearchResultEntry entry, User user) { try { @@ -303,16 +254,14 @@ public class LdapLoginService : ILoginService if (!_ldapConfig.AuthoritiesMap.Any()) return authorities; - var attributes = ldapEntry.GetAttributeSet(); + var groupAttr = entry.Attributes[_ldapConfig.GroupsProperty]; - if (!string.IsNullOrWhiteSpace(_ldapConfig.GroupsProperty) || - !attributes.TryGetValue(_ldapConfig.GroupsProperty!, out var groupsAttr) || - groupsAttr?.StringValueArray == null) - { + if (groupAttr == null) return authorities; - } - var groups = groupsAttr.StringValueArray.ToList(); + var groups = groupAttr.GetValues(typeof(string)) + .Cast() + .ToList(); foreach (var authorityMap in _ldapConfig.AuthoritiesMap) { @@ -335,8 +284,8 @@ public class LdapLoginService : ILoginService } catch (Exception e) { - _logger.LogError("Error getting Authorities Map. Return new empty list. Exception: {e}", e); + _logger.LogError("[LDAP] GetAuthoritiesMap error: {error}", e.Message); return []; } } -} \ No newline at end of file +} diff --git a/adas-core.LdapLogin/adas-core.LdapLogin.csproj b/adas-core.LdapLogin/adas-core.LdapLogin.csproj index 7666248e..9219e722 100644 --- a/adas-core.LdapLogin/adas-core.LdapLogin.csproj +++ b/adas-core.LdapLogin/adas-core.LdapLogin.csproj @@ -14,7 +14,12 @@ - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/adas-core.LocalLogin/adas-core.LocalLogin.csproj b/adas-core.LocalLogin/adas-core.LocalLogin.csproj index 27c0080b..4cab6978 100644 --- a/adas-core.LocalLogin/adas-core.LocalLogin.csproj +++ b/adas-core.LocalLogin/adas-core.LocalLogin.csproj @@ -8,13 +8,17 @@ - - + + - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/adas-core.Test/adas-core.Test.csproj b/adas-core.Test/adas-core.Test.csproj index 5a88c1b4..33fb1a10 100644 --- a/adas-core.Test/adas-core.Test.csproj +++ b/adas-core.Test/adas-core.Test.csproj @@ -21,14 +21,18 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/adas-core.module.LightBeacons/adas-core.module.LightBeacons.csproj b/adas-core.module.LightBeacons/adas-core.module.LightBeacons.csproj index 01a7e2dd..c14d7cb3 100644 --- a/adas-core.module.LightBeacons/adas-core.module.LightBeacons.csproj +++ b/adas-core.module.LightBeacons/adas-core.module.LightBeacons.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -14,6 +14,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/adas-core.module.ProxyDevices/adas-core.module.ProxyDevices.csproj b/adas-core.module.ProxyDevices/adas-core.module.ProxyDevices.csproj index 0c44716c..6bb63cf3 100644 --- a/adas-core.module.ProxyDevices/adas-core.module.ProxyDevices.csproj +++ b/adas-core.module.ProxyDevices/adas-core.module.ProxyDevices.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -15,11 +15,7 @@ - - - - diff --git a/adas-core.module.Relays/adas-core.module.Relays.csproj b/adas-core.module.Relays/adas-core.module.Relays.csproj index 6ad62b26..74cf94a9 100644 --- a/adas-core.module.Relays/adas-core.module.Relays.csproj +++ b/adas-core.module.Relays/adas-core.module.Relays.csproj @@ -9,7 +9,6 @@ - diff --git a/adas-core/Program.cs b/adas-core/Program.cs index 091629eb..d8817b12 100644 --- a/adas-core/Program.cs +++ b/adas-core/Program.cs @@ -21,7 +21,7 @@ using adas_core.WebSocket; using adas_core.WebSocket.Hubs; using audit_logs.Extensions; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MongoDB.Bson; using MongoDB.Driver; using Newtonsoft.Json; @@ -120,7 +120,7 @@ builder.Services.AddSwaggerGen(c => c.MapType(() => new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, Format = "objectid" }); }); diff --git a/adas-core/adas-core.csproj b/adas-core/adas-core.csproj index 40769239..54b2062d 100644 --- a/adas-core/adas-core.csproj +++ b/adas-core/adas-core.csproj @@ -13,7 +13,7 @@ Epigram Technologies ADAS Core - + True @@ -24,15 +24,17 @@ - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - @@ -42,18 +44,13 @@ - - - - - - - - + + + diff --git a/adas-core/appsettings.NursePlan.json b/adas-core/appsettings.NursePlan.json index daab64e9..ba7e65e7 100644 --- a/adas-core/appsettings.NursePlan.json +++ b/adas-core/appsettings.NursePlan.json @@ -20,7 +20,7 @@ //"ConnectionString": "mongodb://smartuci:!H12o2020@localhost:27017/?authSource=smartuci", //"ConnectionString": "mongodb://admin:4q*pHca@10.0.20.78:22007", //"ConnectionString": "mongodb://smacsuci:2(R*aQpu2r@sumo.julianrojas.xyz:27017/?authSource=admin", - "DatabaseName": "adasDevNewStandard" + "DatabaseName": "adas" }, "DatabaseConfigurationAudit": { "ConnectionString": "mongodb://smacsuci:2(R*aQpu2r@julianrojas.xyz:27017/?authSource=admin",