// *********************************************************************** // // AgileWebs // // *********************************************************************** using Core.Thalos.Adapters; using Core.Thalos.Adapters.Common.Enums; using Core.Blueprint.Mongo; //using Core.Blueprint.Redis; //using Core.Blueprint.Redis.Helpers; using Mapster; using Microsoft.Extensions.Options; using MongoDB.Driver; using Core.Thalos.Provider.Contracts; using MongoDB.Bson; using System.Text.RegularExpressions; using MongoDB.Bson.Serialization; namespace Core.Thalos.Provider.Providers.Onboarding { /// /// Handles all services and business rules related to . /// public class UserProvider : IUserProvider { private readonly CollectionRepository repository; //private readonly CacheSettings cacheSettings; //private readonly IRedisCacheProvider cacheProvider; public UserProvider(CollectionRepository repository //IRedisCacheProvider cacheProvider, //IOptions cacheSettings ) { this.repository = repository; this.repository.CollectionInitialization(); //this.cacheSettings = cacheSettings.Value; //this.cacheProvider = cacheProvider; } /// /// Creates a new User. /// /// The User to be created. /// A representing /// the asynchronous execution of the service. public async ValueTask CreateUser(Core.Thalos.Domain.Contexts.Onboarding.Request.UserRequest newUser, CancellationToken cancellationToken) { var userCollection = newUser.Adapt(); await repository.InsertOneAsync(userCollection); return userCollection; } /// /// Gets an User by identifier. /// /// The User identifier. /// A representing /// the asynchronous execution of the service. public async ValueTask GetUserById(string _id, CancellationToken cancellationToken) { //var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserById", _id); //var cachedData = await cacheProvider.GetAsync(cacheKey); //if (cachedData is not null) { return cachedData; } var user = await repository.FindByIdAsync(_id); //await cacheProvider.SetAsync(cacheKey, user); return user; } /// /// Gets all the users. /// /// A representing /// the asynchronous execution of the service. public async ValueTask> GetAllUsers(CancellationToken cancellationToken) { //var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllUsers"); //var cachedData = await cacheProvider.GetAsync>(cacheKey) ?? []; //if (cachedData.Any()) return cachedData; var users = await repository.AsQueryable(); //await cacheProvider.SetAsync(cacheKey, users); return users; } /// /// Gets an User by email. /// /// The User email. /// A representing /// the asynchronous execution of the service. public async ValueTask GetUserByEmail(string? email, CancellationToken cancellationToken) { //var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserByEmail", email); //var cachedData = await cacheProvider.GetAsync(cacheKey); //if (cachedData is not null) { return cachedData; } var user = await repository.FindOneAsync( u => u.Email == email && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); //await cacheProvider.SetAsync(cacheKey, user); return user; } /// /// Validates if a users exists by email.. /// /// The User email. /// A representing /// the asynchronous execution of the service. public async ValueTask ValidateUserExistence(string? email, CancellationToken cancellationToken) { //var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserByEmail", email); //var cachedData = await cacheProvider.GetAsync(cacheKey); //if (cachedData is not null) { return cachedData; } var user = await repository.FindOneAsync( u => u.Email == email && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); //await cacheProvider.SetAsync(cacheKey, user); return user; } /// /// Changes the status of the user. /// /// The user identifier. /// The new status of the user. /// A representing /// the asynchronous execution of the service. public async ValueTask ChangeUserStatus(string id, Core.Blueprint.Mongo.StatusEnum newStatus, CancellationToken cancellationToken) { var entity = await repository.FindByIdAsync(id); entity.Status = newStatus; await repository.ReplaceOneAsync(entity); return entity; } /// /// Updates a User by id. /// /// The User to be updated. /// The User identifier. /// A representing /// the asynchronous execution of the service. public async ValueTask UpdateUser(UserAdapter entity, CancellationToken cancellationToken) { await repository.ReplaceOneAsync(entity); return entity; } /// /// Logs in the user. /// /// The User identifier. /// A representing /// the asynchronous execution of the service. public async ValueTask LogInUser(string email, CancellationToken cancellationToken) { var user = await repository.FindOneAsync( u => u.Email == email && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); user.LastLogIn = DateTime.UtcNow; await repository.ReplaceOneAsync(user); return user; } /// /// Logs out the user's session. /// /// The User email. /// A representing /// the asynchronous execution of the service. public async ValueTask LogOutUserSession(string email, CancellationToken cancellationToken) { var user = await repository.FindOneAsync( u => u.Email == email && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); user.LastLogOut = DateTime.UtcNow; await repository.ReplaceOneAsync(user); return user; } /// /// Adds a company to the user's list of companies. /// /// The identifier of the user to whom the company will be added. /// The identifier of the company to add. /// A representing the asynchronous operation, with the updated user object. public async ValueTask AddCompanyToUser(string userId, string companyId, CancellationToken cancellationToken) { var user = await repository.FindOneAsync( u => u._Id == userId && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); var updatedCompanies = user.Companies.Append(companyId).Distinct().ToArray(); user.Companies = updatedCompanies; await repository.ReplaceOneAsync(user); return user; } /// /// Removes a company from the user's list of companies. /// /// The identifier of the user from whom the company will be removed. /// The identifier of the company to remove. /// A representing the asynchronous operation, with the updated user object. public async ValueTask RemoveCompanyFromUser(string userId, string companyId, CancellationToken cancellationToken) { var user = await repository.FindOneAsync( u => u._Id == userId && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); var updatedCompanies = user.Companies ?.Where(c => c != companyId) .ToArray(); user.Companies = updatedCompanies; await repository.ReplaceOneAsync(user); return user; } /// /// Adds a project to the user's list of projects. /// /// The identifier of the user to whom the project will be added. /// The identifier of the project to add. /// A representing the asynchronous operation, with the updated user object. public async ValueTask AddProjectToUser(string userId, string projectId, CancellationToken cancellationToken) { var user = await repository.FindOneAsync( u => u._Id == userId && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); var updatedProjects = user.Projects.Append(projectId).Distinct().ToArray(); user.Projects = updatedProjects; await repository.ReplaceOneAsync(user); return user; } /// /// Removes a project from the user's list of projects. /// /// The identifier of the user from whom the project will be removed. /// The identifier of the project to remove. /// A representing the asynchronous operation, with the updated user object. public async ValueTask RemoveProjectFromUser(string userId, string projectId, CancellationToken cancellationToken) { var user = await repository.FindOneAsync( u => u._Id == userId && u.Status == Core.Blueprint.Mongo.StatusEnum.Active); var updatedProjects = user.Projects ?.Where(c => c != projectId) .ToArray(); user.Projects = updatedProjects; await repository.ReplaceOneAsync(user); return user; } /// /// Gets the token adapter for a user. /// /// The user's email. /// A representing the asynchronous execution of the service. public async ValueTask GetToken(string email, CancellationToken cancellationToken) { try { var pipeline = new[] { new BsonDocument("$match", new BsonDocument { { "email", new BsonDocument { { "$regex", $"^{Regex.Escape(email)}$" }, { "$options", "i" } } }, { "status", Core.Blueprint.Mongo.StatusEnum.Active.ToString() } }), new BsonDocument("$lookup", new BsonDocument { { "from", "Roles" }, { "localField", "roleId" }, { "foreignField", "_id" }, { "as", "role" } }), new BsonDocument("$unwind", "$role"), new BsonDocument("$match", new BsonDocument("role.status", Core.Blueprint.Mongo.StatusEnum.Active.ToString())), new BsonDocument("$addFields", new BsonDocument { { "role.permissions", new BsonDocument("$map", new BsonDocument { { "input", "$role.permissions" }, { "as", "perm" }, { "in", new BsonDocument("$toObjectId", "$$perm") } }) }, { "role.modules", new BsonDocument("$map", new BsonDocument { { "input", "$role.modules" }, { "as", "mod" }, { "in", new BsonDocument("$toObjectId", "$$mod") } }) } }), new BsonDocument("$lookup", new BsonDocument { { "from", "Permissions" }, { "localField", "role.permissions" }, { "foreignField", "_id" }, { "as", "permissions" } }), new BsonDocument("$lookup", new BsonDocument { { "from", "Modules" }, { "localField", "role.modules" }, { "foreignField", "_id" }, { "as", "modules" } }), new BsonDocument("$project", new BsonDocument { { "_id", 1 }, { "guid", 1 }, { "email", 1 }, { "name", 1 }, { "middleName", 1 }, { "lastName", 1 }, { "displayName", 1 }, { "roleId", 1 }, { "companies", 1 }, { "projects", 1 }, { "lastLogIn", 1 }, { "lastLogOut", 1 }, { "createdBy", 1 }, { "updatedBy", 1 }, { "status", 1 }, { "createdAt", 1 }, { "updatedAt", 1 }, { "role._id", 1 }, { "role.name", 1 }, { "role.description", 1 }, { "role.applications", 1 }, { "role.permissions", 1 }, { "role.modules", 1 }, { "role.status", 1 }, { "role.createdAt", 1 }, { "role.updatedAt", 1 }, { "role.createdBy", 1 }, { "role.updatedBy", 1 }, { "permissions", 1 }, { "modules", 1 } }) }; var result = await repository.FindOnePipelineAsync(pipeline); if (result is null) return null; var tokenAdapter = new TokenAdapter { User = new UserAdapter { Id = result["_id"]?.ToString() ?? "", Guid = result.Contains("guid") && !result["guid"].IsBsonNull ? result["guid"].AsString : "", Email = result.Contains("email") && !result["email"].IsBsonNull ? result["email"].AsString : "", Name = result.Contains("name") && !result["name"].IsBsonNull ? result["name"].AsString : "", MiddleName = result.Contains("middleName") && !result["middleName"].IsBsonNull ? result["middleName"].AsString : "", LastName = result.Contains("lastName") && !result["lastName"].IsBsonNull ? result["lastName"].AsString : "", DisplayName = result.Contains("displayName") && !result["displayName"].IsBsonNull ? result["displayName"].AsString : "", RoleId = result.Contains("roleId") && !result["roleId"].IsBsonNull ? result["roleId"].ToString() : "", Companies = result.Contains("companies") && result["companies"].IsBsonArray ? result["companies"].AsBsonArray .Where(c => c != null && !c.IsBsonNull) .Select(c => c.AsString) .ToArray() : Array.Empty(), Projects = result.Contains("projects") && result["projects"].IsBsonArray ? result["projects"].AsBsonArray .Where(p => p != null && !p.IsBsonNull) .Select(p => p.AsString) .ToArray() : Array.Empty(), LastLogIn = result.Contains("lastLogIn") && !result["lastLogIn"].IsBsonNull ? result["lastLogIn"].ToUniversalTime() : DateTime.MinValue, LastLogOut = result.Contains("lastLogOut") && !result["lastLogOut"].IsBsonNull ? result["lastLogOut"].ToUniversalTime() : DateTime.MinValue, CreatedAt = result.Contains("createdAt") && !result["createdAt"].IsBsonNull ? result["createdAt"].ToUniversalTime() : DateTime.MinValue, CreatedBy = result.Contains("createdBy") && !result["createdBy"].IsBsonNull ? result["createdBy"].AsString : "", UpdatedAt = result.Contains("updatedAt") && !result["updatedAt"].IsBsonNull ? result["updatedAt"].ToUniversalTime() : DateTime.MinValue, UpdatedBy = result.Contains("updatedBy") && !result["updatedBy"].IsBsonNull ? result["updatedBy"].AsString : "", Status = result.Contains("status") && !result["status"].IsBsonNull ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["status"].AsString) : Core.Blueprint.Mongo.StatusEnum.Inactive }, Role = new RoleAdapter { Id = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("_id") ? result["role"]["_id"]?.ToString() ?? "" : "", Name = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("name") ? result["role"]["name"]?.AsString ?? "" : "", Description = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("description") ? result["role"]["description"]?.AsString ?? "" : "", Applications = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("applications") && result["role"]["applications"].IsBsonArray ? result["role"]["applications"].AsBsonArray .Where(app => app != null && app.IsInt32) .Select(app => (ApplicationsEnum)app.AsInt32) .ToArray() : Array.Empty(), Modules = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("modules") && result["role"]["modules"].IsBsonArray ? result["role"]["modules"].AsBsonArray .Where(m => m != null) .Select(m => m.ToString() ?? "") .ToArray() : Array.Empty(), Permissions = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("permissions") && result["role"]["permissions"].IsBsonArray ? result["role"]["permissions"].AsBsonArray .Where(p => p != null) .Select(p => p.ToString() ?? "") .ToArray() : Array.Empty(), Status = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("status") && !result["role"]["status"].IsBsonNull ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["role"]["status"].AsString) : Core.Blueprint.Mongo.StatusEnum.Inactive, CreatedAt = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("createdAt") && !result["role"]["createdAt"].IsBsonNull ? result["role"]["createdAt"].ToUniversalTime() : DateTime.MinValue, UpdatedAt = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("updatedAt") && !result["role"]["updatedAt"].IsBsonNull ? result["role"]["updatedAt"].ToUniversalTime() : DateTime.MinValue, CreatedBy = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("createdBy") && !result["role"]["createdBy"].IsBsonNull ? result["role"]["createdBy"].AsString : "", UpdatedBy = result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("updatedBy") && !result["role"]["updatedBy"].IsBsonNull ? result["role"]["updatedBy"].AsString : "" }, Permissions = result.Contains("permissions") && result["permissions"].IsBsonArray ? result["permissions"].AsBsonArray .Where(p => p != null && p.IsBsonDocument) .Select(p => BsonSerializer.Deserialize(p.AsBsonDocument)) .Where(p => p.Status == Core.Blueprint.Mongo.StatusEnum.Active) .ToList() : new List() }; return tokenAdapter; } catch (Exception ex) { throw new Exception(ex.Message, ex); } } /// /// Deletes an User by id. /// /// The User identifier. /// A representing /// the asynchronous execution of the service. public async ValueTask DeleteUser(string _id, CancellationToken cancellationToken) { var entity = await repository.DeleteOneAsync(doc => doc.Id == _id); return entity; } } }