using adas_core.Application.Repositories.Interfaces; using adas_core.Domain.Enums; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.Filter; using adas_core.Domain.Models.MongoModels; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; using System.Text.RegularExpressions; namespace adas_core.Infrastructure.Repositories; public class UserRepository : MongoRepository, IUserRepository { private readonly ApiSettings _apiSettings; public UserRepository(IOptions apiSettings, IMongoDatabase database) : base(database) { if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings)); _apiSettings = apiSettings.Value; } public override string GetCollectionName() { return _apiSettings.Users; } public async Task GetUser(string username, string password) { var filter = Builders .Filter.Eq(p => p.UserName, username) & Builders .Filter.Eq(p => p.Password, password); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } public async Task GetById(ObjectId id) { var filter = Builders .Filter.Eq(p => p.Id, id); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } public async Task GetByUserName(string name) { var filter = Builders .Filter.Eq(p => p.UserName, name); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } public async Task GetByUserAndAuthoritesName(string name) { var matchStage = new BsonDocument("$match", new BsonDocument("userName", name)); var lookupStage = new BsonDocument("$lookup", new BsonDocument { { "from", "authorizations" }, { "localField", "_id" }, { "foreignField", "userId" }, { "as", "Authorization" } }); var projectStage = new BsonDocument("$project", new BsonDocument { { "_id", 1 }, { "userName", 1 }, { "email", 1 }, { "name", 1 }, { "Authorization", "$Authorization" }, { "rol", new BsonDocument("$cond", new BsonArray { new BsonDocument("$eq", new BsonArray { "$Authorization.rol", "Admin" }), "$rol", "Some" }) } }); var pipeline = new[] { matchStage, lookupStage, projectStage }; var options = new AggregateOptions { AllowDiskUse = true }; var result = await Collection.AggregateAsync(pipeline, options); var bsonResult = await result.FirstOrDefaultAsync(); return bsonResult; } public async Task GetByName(string name) { var filter = Builders .Filter.Eq(p => p.Name, name); var result = await Collection.FindAsync(filter); return await result.FirstOrDefaultAsync(); } public async Task UpdateUser(User user, bool updatePass) { var filter = Builders .Filter.Eq(p => p.Id, user.Id); var update = Builders.Update .Set(u => u.UserName, user.UserName) .Set(u => u.Name, user.Name) .Set(u => u.Email, user.Email) .Set(u => u.LockExpirationDate, user.LockExpirationDate) .Set(u => u.LastLogin, user.LastLogin) .Set(u => u.IsEnabled, user.IsEnabled); if (updatePass) update = update.Set(u => u.Password, user.Password); await Collection.UpdateOneAsync(filter, update); var result = await Collection.Find(filter).FirstOrDefaultAsync(); return result; } public IFindFluent GetPaginatedUsers(PaginationFilter filteredRequest) { // Crear variable con la clase que construye los filtros que necesitamos var filterBuilder = Builders.Filter; var sort = Builders.Sort.Ascending("userName"); // Crear una lista de filtros que pueden venir de tu servicio var filters = new List>(); if (filteredRequest.FilteredRequest == null) return CreateFindFluent(filters, sort); var textFilter = filteredRequest.FilteredRequest?.Text; if (!string.IsNullOrEmpty(textFilter)) { var textFilterEscaped = Regex.Escape(textFilter); var orFilters = new List> { filterBuilder.Regex(p => p.Name, new BsonRegularExpression(textFilterEscaped, "i")), filterBuilder.Regex(p => p.Email, new BsonRegularExpression(textFilterEscaped, "i")), filterBuilder.Regex(p => p.UserName, new BsonRegularExpression(textFilterEscaped, "i")) }; filters.Add(filterBuilder.Or(orFilters)); } var userStatus = filteredRequest.FilteredRequest?.UserStatus; filters.Add(filterBuilder.And(GetUserStatusFilter(userStatus))); if (Enum.TryParse(filteredRequest.FilteredRequest?.UserType, out UserEnum.Type userType)) { GetUserTypeFilter(userType); filters.Add(filterBuilder.And(GetUserTypeFilter(userType))); } return CreateFindFluent(filters, sort); } public async Task GetOrCreateSystemUser() { var user = await GetByUserName("System"); if (user == null) { var userToInsert = new User { UserName = "System", Name = "System", Password = "$2a$12$crWa3EN1izcZBXNc81RzmOlfaYW2TPr2NdDQEWI7RzLTnA0Dd68WG" }; await Collection.InsertOneAsync(userToInsert); return userToInsert; } return user; } public sealed override async Task InsertInitialLoad() { await GetOrCreateSystemUser(); } private IFindFluent CreateFindFluent(List> filters, SortDefinition sort) { var combinedFilter = filters.Any() ? Builders.Filter.And(filters) : Builders.Filter.Empty; // Filtra todo si no hay filtros return Collection.Find(combinedFilter).Sort(sort); } private List> GetUserTypeFilter(UserEnum.Type? type) { var filters = new List>(); var filterBuilder = Builders.Filter; switch (type) { case UserEnum.Type.Local: filters.Add(filterBuilder.Eq(u => u.Type, UserEnum.Type.Local)); break; case UserEnum.Type.Ldap: filters.Add(filterBuilder.Eq(u => u.Type, UserEnum.Type.Ldap)); break; } return filters; } private List> GetUserStatusFilter(StatusEnum.User? status) { var filters = new List>(); var filterBuilder = Builders.Filter; switch (status) { case StatusEnum.User.Enabled: filters.Add(filterBuilder.Or( filterBuilder.Eq(u => u.IsEnabled, true), filterBuilder.Exists(u => u.IsEnabled, false) )); break; case StatusEnum.User.EnabledUnlocked: filters.Add(filterBuilder.Or( filterBuilder.Eq(u => u.IsEnabled, true), filterBuilder.Exists(u => u.IsEnabled, false) )); filters.Add(filterBuilder.Ne(u => u.LockExpirationDate, null)); break; case StatusEnum.User.EnabledLocked: filters.Add(filterBuilder.Or( filterBuilder.Eq(u => u.IsEnabled, true), filterBuilder.Exists(u => u.IsEnabled, false) )); filters.Add(filterBuilder.Eq(u => u.LockExpirationDate, null)); break; case StatusEnum.User.Disabled: filters.Add(filterBuilder.Eq(u => u.IsEnabled, false)); break; } return filters; } }