From 8c3f8f6402855ff2d8c059d1d6825253b22edf13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20White?= Date: Wed, 3 Sep 2025 01:14:31 -0600 Subject: [PATCH] fix: bsondocuments with time - added validation --- .../Providers/Onboarding/UserProvider.cs | 273 +++++++++--------- 1 file changed, 133 insertions(+), 140 deletions(-) diff --git a/Core.Thalos.Provider/Providers/Onboarding/UserProvider.cs b/Core.Thalos.Provider/Providers/Onboarding/UserProvider.cs index 8a7adb0..e10a5c5 100644 --- a/Core.Thalos.Provider/Providers/Onboarding/UserProvider.cs +++ b/Core.Thalos.Provider/Providers/Onboarding/UserProvider.cs @@ -221,128 +221,128 @@ namespace Core.Thalos.Provider.Providers.Onboarding { var pipeline = new[] { - new BsonDocument("$match", new BsonDocument + new BsonDocument("$match", new BsonDocument + { + { "email", new BsonDocument { - { "email", new BsonDocument - { - { "$regex", $"^{Regex.Escape(email)}$" }, - { "$options", "i" } - } - }, - { "status", Core.Blueprint.Mongo.StatusEnum.Active.ToString() } - }), - - new BsonDocument("$lookup", 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("$lookup", new BsonDocument + { + { "from", "Tenants" }, + { "localField", "tenantId" }, + { "foreignField", "_id" }, + { "as", "tenant" } + }), + new BsonDocument("$unwind", "$tenant"), + new BsonDocument("$addFields", new BsonDocument + { + { "role.permissions", new BsonDocument("$map", 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())), - - // Tenant lookup - new BsonDocument("$lookup", new BsonDocument - { - { "from", "Tenants" }, - { "localField", "tenantId" }, - { "foreignField", "_id" }, - { "as", "tenant" } - }), - new BsonDocument("$unwind", "$tenant"), - - 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 }, - { "tenant._id", 1 }, - { "tenant.name", 1 }, - { "tenant.taxIdentifier", 1 }, - { "tenant.addressLine1", 1 }, - { "tenant.addressLine2", 1 }, - { "tenant.city", 1 }, - { "tenant.state", 1 }, - { "tenant.country", 1 }, - { "tenant.postalCode", 1 }, - { "tenant.contactEmail", 1 }, - { "tenant.contactPhone", 1 }, - { "tenant.website", 1 }, - { "tenant.connectionString", 1 }, - { "tenant.isolated", 1 }, - { "tenant.status", 1 }, - { "tenant.createdAt", 1 }, - { "tenant.updatedAt", 1 }, - { "tenant.createdBy", 1 }, - { "tenant.updatedBy", 1 }, - { "permissions", 1 }, - { "modules", 1 } + { "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 }, + { "tenant._id", 1 }, + { "tenant.name", 1 }, + { "tenant.taxIdentifier", 1 }, + { "tenant.addressLine1", 1 }, + { "tenant.addressLine2", 1 }, + { "tenant.city", 1 }, + { "tenant.state", 1 }, + { "tenant.country", 1 }, + { "tenant.postalCode", 1 }, + { "tenant.contactEmail", 1 }, + { "tenant.contactPhone", 1 }, + { "tenant.website", 1 }, + { "tenant.connectionString", 1 }, + { "tenant.isolated", 1 }, + { "tenant.status", 1 }, + { "tenant.createdAt", 1 }, + { "tenant.updatedAt", 1 }, + { "tenant.createdBy", 1 }, + { "tenant.updatedBy", 1 }, + { "permissions", 1 }, + { "modules", 1 } + }) + }; var result = await repository.FindOnePipelineAsync(pipeline); if (result is null) return null; + DateTime SafeToUtc(BsonValue value) + { + if (value == null || value.IsBsonNull) return DateTime.MinValue; + return value.IsBsonDateTime ? value.ToUniversalTime() : DateTime.MinValue; + } + var tokenAdapter = new TokenAdapter { User = new UserAdapter @@ -354,11 +354,11 @@ namespace Core.Thalos.Provider.Providers.Onboarding LastName = result.Contains("lastName") && !result["lastName"].IsBsonNull ? result["lastName"].AsString : string.Empty, DisplayName = result.Contains("displayName") && !result["displayName"].IsBsonNull ? result["displayName"].AsString : string.Empty, RoleId = result.Contains("roleId") && !result["roleId"].IsBsonNull ? result["roleId"].ToString() : string.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, + LastLogIn = SafeToUtc(result.Contains("lastLogIn") ? result["lastLogIn"] : null), + LastLogOut = SafeToUtc(result.Contains("lastLogOut") ? result["lastLogOut"] : null), + CreatedAt = SafeToUtc(result.Contains("createdAt") ? result["createdAt"] : null), + UpdatedAt = SafeToUtc(result.Contains("updatedAt") ? result["updatedAt"] : null), CreatedBy = result.Contains("createdBy") && !result["createdBy"].IsBsonNull ? result["createdBy"].AsString : string.Empty, - UpdatedAt = result.Contains("updatedAt") && !result["updatedAt"].IsBsonNull ? result["updatedAt"].ToUniversalTime() : DateTime.MinValue, UpdatedBy = result.Contains("updatedBy") && !result["updatedBy"].IsBsonNull ? result["updatedBy"].AsString : string.Empty, Status = result.Contains("status") && !result["status"].IsBsonNull ? (Core.Blueprint.Mongo.StatusEnum)Enum.Parse(typeof(Core.Blueprint.Mongo.StatusEnum), result["status"].AsString) @@ -404,24 +404,18 @@ namespace Core.Thalos.Provider.Providers.Onboarding !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, + CreatedAt = SafeToUtc(result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("createdAt") + ? result["role"]["createdAt"] + : null), + UpdatedAt = SafeToUtc(result.Contains("role") && result["role"].IsBsonDocument && result["role"].AsBsonDocument.Contains("updatedAt") + ? result["role"]["updatedAt"] + : null), CreatedBy = result.Contains("role") && result["role"].IsBsonDocument && - result["role"].AsBsonDocument.Contains("createdBy") && - !result["role"]["createdBy"].IsBsonNull + result["role"].AsBsonDocument.Contains("createdBy") && !result["role"]["createdBy"].IsBsonNull ? result["role"]["createdBy"].AsString : string.Empty, UpdatedBy = result.Contains("role") && result["role"].IsBsonDocument && - result["role"].AsBsonDocument.Contains("updatedBy") && - !result["role"]["updatedBy"].IsBsonNull + result["role"].AsBsonDocument.Contains("updatedBy") && !result["role"]["updatedBy"].IsBsonNull ? result["role"]["updatedBy"].AsString : string.Empty }, @@ -470,12 +464,12 @@ namespace Core.Thalos.Provider.Providers.Onboarding Isolated = result["tenant"].AsBsonDocument.Contains("isolated") && !result["tenant"]["isolated"].IsBsonNull ? result["tenant"]["isolated"].ToBoolean() : false, - CreatedAt = result["tenant"].AsBsonDocument.Contains("createdAt") && !result["tenant"]["createdAt"].IsBsonNull - ? result["tenant"]["createdAt"].ToUniversalTime() - : DateTime.MinValue, - UpdatedAt = result["tenant"].AsBsonDocument.Contains("updatedAt") && !result["tenant"]["updatedAt"].IsBsonNull - ? result["tenant"]["updatedAt"].ToUniversalTime() - : DateTime.MinValue, + CreatedAt = SafeToUtc(result.Contains("tenant") && result["tenant"].IsBsonDocument && result["tenant"].AsBsonDocument.Contains("createdAt") + ? result["tenant"]["createdAt"] + : null), + UpdatedAt = SafeToUtc(result.Contains("tenant") && result["tenant"].IsBsonDocument && result["tenant"].AsBsonDocument.Contains("updatedAt") + ? result["tenant"]["updatedAt"] + : null), CreatedBy = result["tenant"].AsBsonDocument.Contains("createdBy") && !result["tenant"]["createdBy"].IsBsonNull ? result["tenant"]["createdBy"].AsString : string.Empty, @@ -503,9 +497,7 @@ namespace Core.Thalos.Provider.Providers.Onboarding : new List() }; - return tokenAdapter; - } catch (Exception ex) { @@ -513,6 +505,7 @@ namespace Core.Thalos.Provider.Providers.Onboarding } } + /// /// Deletes an User by _id. ///