Files

240 lines
8.3 KiB
C#

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<User>, IUserRepository
{
private readonly ApiSettings _apiSettings;
public UserRepository(IOptions<ApiSettings> 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<User?> GetUser(string username, string password)
{
var filter = Builders<User>
.Filter.Eq(p => p.UserName, username) & Builders<User>
.Filter.Eq(p => p.Password, password);
var result = await Collection.FindAsync(filter);
return await result.FirstOrDefaultAsync();
}
public async Task<User?> GetById(ObjectId id)
{
var filter = Builders<User>
.Filter.Eq(p => p.Id, id);
var result = await Collection.FindAsync(filter);
return await result.FirstOrDefaultAsync();
}
public async Task<User?> GetByUserName(string name)
{
var filter = Builders<User>
.Filter.Eq(p => p.UserName, name);
var result = await Collection.FindAsync(filter);
return await result.FirstOrDefaultAsync();
}
public async Task<User?> 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<User>(pipeline, options);
var bsonResult = await result.FirstOrDefaultAsync();
return bsonResult;
}
public async Task<User?> GetByName(string name)
{
var filter = Builders<User>
.Filter.Eq(p => p.Name, name);
var result = await Collection.FindAsync(filter);
return await result.FirstOrDefaultAsync();
}
public async Task<User?> UpdateUser(User user, bool updatePass)
{
var filter = Builders<User>
.Filter.Eq(p => p.Id, user.Id);
var update = Builders<User>.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<User, User> GetPaginatedUsers(PaginationFilter filteredRequest)
{
// Crear variable con la clase que construye los filtros que necesitamos
var filterBuilder = Builders<User>.Filter;
var sort = Builders<User>.Sort.Ascending("userName");
// Crear una lista de filtros que pueden venir de tu servicio
var filters = new List<FilterDefinition<User>>();
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<FilterDefinition<User>>
{
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<User> 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<User, User> CreateFindFluent(List<FilterDefinition<User>> filters, SortDefinition<User> sort)
{
var combinedFilter = filters.Any()
? Builders<User>.Filter.And(filters)
: Builders<User>.Filter.Empty; // Filtra todo si no hay filtros
return Collection.Find(combinedFilter).Sort(sort);
}
private List<FilterDefinition<User>> GetUserTypeFilter(UserEnum.Type? type)
{
var filters = new List<FilterDefinition<User>>();
var filterBuilder = Builders<User>.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<FilterDefinition<User>> GetUserStatusFilter(StatusEnum.User? status)
{
var filters = new List<FilterDefinition<User>>();
var filterBuilder = Builders<User>.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;
}
}