add girIgnore
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
using audit_logs.Models;
|
||||
using audit.Model;
|
||||
|
||||
namespace audit_logs.Utils;
|
||||
|
||||
public static class AuditRecordMapper
|
||||
{
|
||||
public static AuditRecordDto ToDto(this AuditRecord record)
|
||||
{
|
||||
return new AuditRecordDto
|
||||
{
|
||||
Id = record.Id.ToString(),
|
||||
EntityType = record.EntityType,
|
||||
RecordId = record.RecordId,
|
||||
UserId = record.UserId,
|
||||
ActionType = record.ActionType,
|
||||
ActionTime = record.ActionTime,
|
||||
Reason = record.Reason,
|
||||
UserIpAddress = record.UserIpAddress,
|
||||
Changes = record.Changes?.Select(c => new ChangeDto
|
||||
{
|
||||
Field = c.Field,
|
||||
OldValue = AuditRecord.Change.ConvertBsonValue(c.OldValue),
|
||||
NewValue = AuditRecord.Change.ConvertBsonValue(c.NewValue),
|
||||
ValueType = c.ValueType
|
||||
}).ToList() ?? new List<ChangeDto>()
|
||||
};
|
||||
}
|
||||
}
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace audit_logs.Utils;
|
||||
|
||||
public static class JsonClean
|
||||
{
|
||||
public static JObject CleanJObject(JObject obj)
|
||||
{
|
||||
var properties = obj.Properties().ToList();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
if (property.Value.Type == JTokenType.Null)
|
||||
{
|
||||
// Eliminar la propiedad si el valor es null
|
||||
property.Remove();
|
||||
}
|
||||
else if (property.Value.Type == JTokenType.Object)
|
||||
{
|
||||
// Limpieza para objetos anidados
|
||||
property.Value = CleanJObject((JObject)property.Value);
|
||||
}
|
||||
else if (property.Value.Type == JTokenType.Array)
|
||||
{
|
||||
// Limpieza para arrays, aplicando limpieza a cada objeto dentro del array
|
||||
property.Value = CleanJArray((JArray)property.Value);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static JArray CleanJArray(JArray array)
|
||||
{
|
||||
var cleanedArray = new JArray();
|
||||
foreach (var item in array)
|
||||
{
|
||||
if (item.Type == JTokenType.Object)
|
||||
{
|
||||
cleanedArray.Add(CleanJObject((JObject)item));
|
||||
}
|
||||
else if (item.Type != JTokenType.Null)
|
||||
{
|
||||
cleanedArray.Add(item);
|
||||
}
|
||||
}
|
||||
return cleanedArray;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+197
@@ -0,0 +1,197 @@
|
||||
using audit.Model;
|
||||
|
||||
namespace audit_logs.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MongoDB.Bson;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Utils;
|
||||
|
||||
public class JsonComparer
|
||||
{
|
||||
public List<AuditRecord.Change> GetDifferences(object? originalJson, object? modifiedJson)
|
||||
{
|
||||
var changes = new List<AuditRecord.Change>();
|
||||
|
||||
// Convertir los objetos a cadenas JSON; usar "{}" si el objeto es null
|
||||
var originalJsonString = originalJson != null
|
||||
? JsonConverter.ConvertObjectToJson(originalJson)
|
||||
: "{}";
|
||||
var modifiedJsonString = modifiedJson != null
|
||||
? JsonConverter.ConvertObjectToJson(modifiedJson)
|
||||
: "{}";
|
||||
|
||||
// Intentar parsear a JObject solo si el JSON es un objeto
|
||||
var originalObj = ParseAsJObject(originalJsonString);
|
||||
var modifiedObj = ParseAsJObject(modifiedJsonString);
|
||||
//eliminamos aquellas claves que contengan null, por ejemplo "allergies": [
|
||||
// {
|
||||
// "optionType": null,
|
||||
// "name": "Sí",
|
||||
// "iconDefault": "icCheck",
|
||||
// "iconLight": null,
|
||||
// "iconDark": null,
|
||||
// "color": null,
|
||||
// "bgColor": null,
|
||||
// "description": null,
|
||||
// "initDate": null,
|
||||
// "endDate": null
|
||||
// }
|
||||
// ]
|
||||
|
||||
if (originalObj != null)
|
||||
{
|
||||
originalObj = JsonClean.CleanJObject(originalObj);
|
||||
}
|
||||
if (modifiedObj != null)
|
||||
{
|
||||
modifiedObj = JsonClean.CleanJObject(modifiedObj);
|
||||
}
|
||||
// Comparar los objetos JSON
|
||||
CompareJTokens(originalObj, modifiedObj, changes, string.Empty);
|
||||
return changes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intenta parsear una cadena JSON como JObject. Devuelve null si no es un objeto.
|
||||
/// </summary>
|
||||
/// <param name="json">La cadena JSON a validar.</param>
|
||||
/// <returns>Un JObject si es válido, de lo contrario null.</returns>
|
||||
private static JObject? ParseAsJObject(string json)
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = JToken.Parse(json);
|
||||
return token as JObject; // Devuelve null si no es un JObject
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null; // Si ocurre un error, no es un JSON válido
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CompareJTokens(JToken original, JToken modified, List<AuditRecord.Change> changes, string path)
|
||||
{
|
||||
foreach (var property in modified.Children<JProperty>())
|
||||
{
|
||||
var fieldPath = string.IsNullOrEmpty(path) ? property.Name : $"{path}.{property.Name}";
|
||||
var originalValue = original[property.Name];
|
||||
var modifiedValue = property.Value;
|
||||
// Ignorar campos donde ambos valores son null
|
||||
if (originalValue == null && modifiedValue.Type == JTokenType.Null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (originalValue == null)
|
||||
{
|
||||
// Campo nuevo
|
||||
changes.Add(new AuditRecord.Change
|
||||
{
|
||||
Field = fieldPath,
|
||||
OldValue = BsonNull.Value,
|
||||
NewValue = ConvertToBsonValue(modifiedValue),
|
||||
ValueType = GetBsonType(modifiedValue)
|
||||
});
|
||||
}
|
||||
else if (!JToken.DeepEquals(originalValue, modifiedValue))
|
||||
{
|
||||
if (originalValue.Type == JTokenType.Object && modifiedValue.Type == JTokenType.Object)
|
||||
{
|
||||
// Comparar objetos anidados
|
||||
CompareJTokens(originalValue, modifiedValue, changes, fieldPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Campo modificado
|
||||
changes.Add(new AuditRecord.Change
|
||||
{
|
||||
Field = fieldPath,
|
||||
OldValue = ConvertToBsonValue(originalValue),
|
||||
NewValue = ConvertToBsonValue(modifiedValue),
|
||||
ValueType = GetBsonType(modifiedValue)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Campos eliminados
|
||||
foreach (var property in original.Children<JProperty>())
|
||||
{
|
||||
var fieldPath = string.IsNullOrEmpty(path) ? property.Name : $"{path}.{property.Name}";
|
||||
if (modified[property.Name] == null)
|
||||
{
|
||||
changes.Add(new AuditRecord.Change
|
||||
{
|
||||
Field = fieldPath,
|
||||
OldValue = ConvertToBsonValue(property.Value),
|
||||
NewValue = BsonNull.Value,
|
||||
ValueType = GetBsonType(property.Value)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*private BsonValue ConvertToBsonValue(JToken token)
|
||||
{
|
||||
return token.Type switch
|
||||
{
|
||||
JTokenType.String => new BsonString(token.ToString()),
|
||||
JTokenType.Integer => new BsonInt32(token.ToObject<int>()),
|
||||
JTokenType.Float => new BsonDouble(token.ToObject<double>()),
|
||||
JTokenType.Boolean => new BsonBoolean(token.ToObject<bool>()),
|
||||
JTokenType.Date => new BsonDateTime(token.ToObject<DateTime>()),
|
||||
JTokenType.Null => BsonNull.Value,
|
||||
JTokenType.Object => BsonDocument.Parse(token.ToString()),
|
||||
JTokenType.Array => new BsonArray(token.ToObject<List<BsonValue>>()),
|
||||
_ => new BsonString(token.ToString())
|
||||
};
|
||||
}*/
|
||||
private BsonValue ConvertToBsonValue(JToken token)
|
||||
{
|
||||
switch (token.Type)
|
||||
{
|
||||
case JTokenType.String:
|
||||
return new BsonString(token.ToString());
|
||||
case JTokenType.Integer:
|
||||
return BsonValue.Create(token.ToObject<int>());
|
||||
case JTokenType.Float:
|
||||
return BsonValue.Create(token.ToObject<double>());
|
||||
case JTokenType.Boolean:
|
||||
return new BsonBoolean(token.ToObject<bool>());
|
||||
case JTokenType.Date:
|
||||
return new BsonDateTime(token.ToObject<DateTime>());
|
||||
case JTokenType.Null:
|
||||
return BsonNull.Value;
|
||||
case JTokenType.Object:
|
||||
return BsonDocument.Parse(token.ToString());
|
||||
case JTokenType.Array:
|
||||
var array = new BsonArray();
|
||||
foreach (var item in token.Children())
|
||||
{
|
||||
array.Add(ConvertToBsonValue(item));
|
||||
}
|
||||
return array;
|
||||
default:
|
||||
return new BsonString(token.ToString()); // Trata cualquier otro tipo como string
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string GetBsonType(JToken token)
|
||||
{
|
||||
return token.Type switch
|
||||
{
|
||||
JTokenType.String => "string",
|
||||
JTokenType.Integer => "int",
|
||||
JTokenType.Float => "double",
|
||||
JTokenType.Boolean => "bool",
|
||||
JTokenType.Date => "date",
|
||||
JTokenType.Null => "null",
|
||||
JTokenType.Object => "object",
|
||||
JTokenType.Array => "array",
|
||||
_ => "unknown"
|
||||
};
|
||||
}
|
||||
}
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace audit_logs.Utils;
|
||||
using System.Text.Json;
|
||||
|
||||
public static class JsonConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an object to a JSON string.
|
||||
/// </summary>
|
||||
/// <param name="obj">the object to be converted</param>
|
||||
/// <returns>A JSON string representing the object</returns>
|
||||
public static string ConvertObjectToJson(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Si el objeto es una cadena, asumimos que ya es JSON
|
||||
if (obj is string jsonString && IsValidJson(jsonString))
|
||||
{
|
||||
return jsonString; // No volver a serializar
|
||||
}
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
};
|
||||
var json = JsonSerializer.Serialize(obj);
|
||||
return json;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"Error converting object to JSON: {ex.Message}";
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Valida si una cadena es un JSON válido.
|
||||
/// </summary>
|
||||
private static bool IsValidJson(string jsonString)
|
||||
{
|
||||
try
|
||||
{
|
||||
JToken.Parse(jsonString);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
|
||||
using audit_logs.Models.AppSettings;
|
||||
using MongoDB.Driver;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization;
|
||||
using MongoDB.Bson.Serialization.Conventions;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
using MongoDB.Bson.Serialization.Serializers;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace audit_logs.Utils;
|
||||
|
||||
public static class MongoDbHostBuilderExtension
|
||||
{
|
||||
#region MongoDB
|
||||
private static MongoDB.Driver.MongoClient? _mongoClient;
|
||||
private static IMongoDatabase? _mongoDb;
|
||||
#endregion
|
||||
public static IHostBuilder UseMongo(this IHostBuilder hostBuilder)
|
||||
{
|
||||
ConfigureMongoDbConventions();
|
||||
|
||||
// ConfigureRegisterMapClass();
|
||||
|
||||
return hostBuilder;
|
||||
}
|
||||
public static IMongoDatabase GetMongoDB(IOptions<MongoDbSettingsAudit> dbSettings)
|
||||
{
|
||||
_mongoDb ??= ConfigureMongoDbConnection(dbSettings);
|
||||
return _mongoDb;
|
||||
}
|
||||
private static IMongoDatabase ConfigureMongoDbConnection(IOptions<MongoDbSettingsAudit> dbSettings)
|
||||
{
|
||||
var connectionString = dbSettings.Value.ConnectionString;
|
||||
|
||||
var databaseName = dbSettings.Value.DatabaseName;
|
||||
|
||||
if (string.IsNullOrEmpty(connectionString) || string.IsNullOrEmpty(databaseName))
|
||||
{
|
||||
throw new Exception("DataBase connection string and name is requiered");
|
||||
}
|
||||
|
||||
_mongoClient = new MongoDB.Driver.MongoClient(connectionString);
|
||||
|
||||
var mongoDb = _mongoClient.GetDatabase(databaseName);
|
||||
return mongoDb;
|
||||
}
|
||||
public static void ConfigureMongoDbConventions()
|
||||
{
|
||||
var _pack = new ConventionPack
|
||||
{
|
||||
new IgnoreExtraElementsConvention(true),
|
||||
new CamelCaseElementNameConvention()
|
||||
};
|
||||
|
||||
ConventionRegistry.Register(
|
||||
"Ignore Extra Elements Convention",
|
||||
_pack,
|
||||
t => true);
|
||||
|
||||
ConventionRegistry.Register(
|
||||
"Camel Case Convention",
|
||||
_pack,
|
||||
t => true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user