Change the references and structure of the code to use Blueprint.Mongo package
This commit is contained in:
		
							
								
								
									
										471
									
								
								Core.Thalos.Provider/Providers/Onboarding/UserProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										471
									
								
								Core.Thalos.Provider/Providers/Onboarding/UserProvider.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,471 @@ | ||||
| // *********************************************************************** | ||||
| // <copyright file="UserService.cs"> | ||||
| //     AgileWebs | ||||
| // </copyright> | ||||
| // *********************************************************************** | ||||
|  | ||||
| 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 | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Handles all services and business rules related to <see cref="UserAdapter"/>. | ||||
|     /// </summary> | ||||
|     public class UserProvider : IUserProvider | ||||
|     { | ||||
|         private readonly CollectionRepository<UserAdapter> repository; | ||||
|         private readonly CacheSettings cacheSettings; | ||||
|         private readonly IRedisCacheProvider cacheProvider; | ||||
|  | ||||
|         public UserProvider(CollectionRepository<UserAdapter> repository, | ||||
|         IRedisCacheProvider cacheProvider, IOptions<CacheSettings> cacheSettings) | ||||
|         { | ||||
|             this.repository = repository; | ||||
|             this.repository.CollectionInitialization(); | ||||
|             this.cacheSettings = cacheSettings.Value; | ||||
|             this.cacheProvider = cacheProvider; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new User. | ||||
|         /// </summary> | ||||
|         /// <param name="newUser">The User to be created.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter> CreateUser(Core.Thalos.Domain.Contexts.Onboarding.Request.UserRequest newUser, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var userCollection = newUser.Adapt<UserAdapter>(); | ||||
|  | ||||
|             await repository.InsertOneAsync(userCollection); | ||||
|  | ||||
|             return userCollection; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets an User by identifier. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The User identifier.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter> GetUserById(string _id, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserById", _id); | ||||
|             var cachedData = await cacheProvider.GetAsync<UserAdapter>(cacheKey); | ||||
|  | ||||
|             if (cachedData is not null) { return cachedData; } | ||||
|  | ||||
|             var user = await repository.FindByIdAsync(_id); | ||||
|  | ||||
|             await cacheProvider.SetAsync(cacheKey, user); | ||||
|  | ||||
|             return user; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets all the users. | ||||
|         /// </summary> | ||||
|         /// <returns>A <see cref="{Task{IEnumerable{UserAdapter}}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<IEnumerable<UserAdapter>> GetAllUsers(CancellationToken cancellationToken) | ||||
|         { | ||||
|             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetAllUsers"); | ||||
|             var cachedData = await cacheProvider.GetAsync<IEnumerable<UserAdapter>>(cacheKey) ?? []; | ||||
|  | ||||
|             if (cachedData.Any()) return cachedData; | ||||
|  | ||||
|             var users = await repository.AsQueryable(); | ||||
|  | ||||
|             await cacheProvider.SetAsync(cacheKey, users); | ||||
|  | ||||
|             return users; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets an User by email. | ||||
|         /// </summary> | ||||
|         /// <param name="email">The User email.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter> GetUserByEmail(string? email, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserByEmail", email); | ||||
|             var cachedData = await cacheProvider.GetAsync<UserAdapter>(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; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Validates if a users exists by email.. | ||||
|         /// </summary> | ||||
|         /// <param name="email">The User email.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter> ValidateUserExistence(string? email, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var cacheKey = CacheKeyHelper.GenerateCacheKey(this, "GetUserByEmail", email); | ||||
|             var cachedData = await cacheProvider.GetAsync<UserAdapter>(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; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Changes the status of the user. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user identifier.</param> | ||||
|         /// <param name="newStatus">The new status of the user.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter> 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; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Updates a User by id. | ||||
|         /// </summary> | ||||
|         /// <param name="entity">The User to be updated.</param> | ||||
|         /// <param name="id">The User identifier.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter> UpdateUser(UserAdapter entity, CancellationToken cancellationToken) | ||||
|         { | ||||
|             await repository.ReplaceOneAsync(entity); | ||||
|  | ||||
|             return entity; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Logs in the user. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The User identifier.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter?> 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; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Logs out the user's session. | ||||
|         /// </summary> | ||||
|         /// <param name="email">The User email.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter?> 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; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a company to the user's list of companies. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The identifier of the user to whom the company will be added.</param> | ||||
|         /// <param name="companyId">The identifier of the company to add.</param> | ||||
|         /// <returns>A <see cref="Task{UserAdapter}"/> representing the asynchronous operation, with the updated user object.</returns> | ||||
|         public async ValueTask<UserAdapter> 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; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Removes a company from the user's list of companies. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The identifier of the user from whom the company will be removed.</param> | ||||
|         /// <param name="companyId">The identifier of the company to remove.</param> | ||||
|         /// <returns>A <see cref="Task{UserAdapter}"/> representing the asynchronous operation, with the updated user object.</returns> | ||||
|         public async ValueTask<UserAdapter> 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; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a project to the user's list of projects. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The identifier of the user to whom the project will be added.</param> | ||||
|         /// <param name="projectId">The identifier of the project to add.</param> | ||||
|         /// <returns>A <see cref="Task{UserAdapter}"/> representing the asynchronous operation, with the updated user object.</returns> | ||||
|         public async ValueTask<UserAdapter> 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.Companies = updatedProjects; | ||||
|  | ||||
|             await repository.ReplaceOneAsync(user); | ||||
|  | ||||
|             return user; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Removes a project from the user's list of projects. | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The identifier of the user from whom the project will be removed.</param> | ||||
|         /// <param name="projectId">The identifier of the project to remove.</param> | ||||
|         /// <returns>A <see cref="Task{UserAdapter}"/> representing the asynchronous operation, with the updated user object.</returns> | ||||
|         public async ValueTask<UserAdapter> 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.Companies = updatedProjects; | ||||
|  | ||||
|             await repository.ReplaceOneAsync(user); | ||||
|  | ||||
|             return user; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the token adapter for a user. | ||||
|         /// </summary> | ||||
|         /// <param name="email">The user's email.</param> | ||||
|         /// <returns>A <see cref="{Task{TokenAdapter}}"/> representing the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<TokenAdapter?> 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<BsonDocument>(pipeline); | ||||
|  | ||||
|                 if (result is null) return null; | ||||
|  | ||||
|                 var tokenAdapter = new TokenAdapter | ||||
|                 { | ||||
|                     User = new UserAdapter | ||||
|                     { | ||||
|                         Id = result["_id"]?.ToString() ?? "", | ||||
|                         Guid = result["guid"].AsString, | ||||
|                         Email = result["email"].AsString, | ||||
|                         Name = result["name"].AsString, | ||||
|                         MiddleName = result["middleName"].AsString, | ||||
|                         LastName = result["lastName"].AsString, | ||||
|                         DisplayName = result["displayName"].AsString, | ||||
|                         RoleId = result["roleId"]?.ToString() ?? "", | ||||
|                         Companies = result["companies"].AsBsonArray | ||||
|                             .Select(c => c.AsString) | ||||
|                             .ToArray(), | ||||
|                         Projects = result["projects"].AsBsonArray | ||||
|                             .Select(c => c.AsString) | ||||
|                             .ToArray(), | ||||
|                         LastLogIn = result["lastLogIn"].ToUniversalTime(), | ||||
|                         LastLogOut = result["lastLogOut"].ToUniversalTime(), | ||||
|                         CreatedAt = result["createdAt"].ToUniversalTime(), | ||||
|                         CreatedBy = result["createdBy"].AsString, | ||||
|                         UpdatedAt = result["updatedAt"].ToUniversalTime(), | ||||
|                         UpdatedBy = result["updatedBy"].AsString, | ||||
|                         Status = (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["status"].AsString), | ||||
|                     }, | ||||
|                     Role = new RoleAdapter | ||||
|                     { | ||||
|                         Id = result["role"]["_id"]?.ToString() ?? "", | ||||
|                         Name = result["role"]["name"].AsString, | ||||
|                         Description = result["role"]["description"].AsString, | ||||
|                         Applications = result["role"]["applications"].AsBsonArray | ||||
|                             .Select(c => (ApplicationsEnum)c.AsInt32) | ||||
|                             .ToArray(), | ||||
|                         Modules = result["role"]["modules"].AsBsonArray | ||||
|                             .Select(c => c.ToString() ?? "") | ||||
|                             .ToArray(), | ||||
|                         Permissions = result["role"]["permissions"].AsBsonArray | ||||
|                             .Select(c => c.ToString() ?? "") | ||||
|                             .ToArray(), | ||||
|                         Status = (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["role"]["status"].AsString), | ||||
|                         CreatedAt = result["role"]["createdAt"].ToUniversalTime(), | ||||
|                         UpdatedAt = result["role"]["updatedAt"].ToUniversalTime(), | ||||
|                         CreatedBy = result["role"]["createdBy"].AsString, | ||||
|                         UpdatedBy = result["role"]["updatedBy"].AsString | ||||
|                     }, | ||||
|                     Permissions = result["permissions"].AsBsonArray | ||||
|                         .Select(permission => BsonSerializer.Deserialize<PermissionAdapter>(permission.AsBsonDocument)) | ||||
|                         .Where(permission => permission.Status == Core.Blueprint.Mongo.StatusEnum.Active) | ||||
|                         .ToList() | ||||
|                 }; | ||||
|  | ||||
|                 return tokenAdapter; | ||||
|  | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 throw new Exception(ex.Message, ex); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Deletes an User by id. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The User identifier.</param> | ||||
|         /// <returns>A <see cref="{Task{UserAdapter}}"/> representing | ||||
|         /// the asynchronous execution of the service.</returns> | ||||
|         public async ValueTask<UserAdapter> DeleteUser(string _id, CancellationToken cancellationToken) | ||||
|         { | ||||
|             var entity = await repository.DeleteOneAsync(doc => doc.Id == _id); | ||||
|  | ||||
|             return entity; | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Oscar Morales
					Oscar Morales