diff options
author | Emma [it/its]@Rory& <root@rory.gay> | 2024-05-30 21:39:12 +0200 |
---|---|---|
committer | Emma [it/its]@Rory& <root@rory.gay> | 2024-05-30 21:39:12 +0200 |
commit | 4bdea63982dae9c17b7a5fbda38d505655b8d4b3 (patch) | |
tree | 8ca9c6bad5f9526c5b36d707f08406fc3bbe2848 /Utilities | |
parent | Log warning if registering a duplicate type (diff) | |
download | LibMatrix-4bdea63982dae9c17b7a5fbda38d505655b8d4b3.tar.xz |
Diffstat (limited to 'Utilities')
5 files changed, 219 insertions, 72 deletions
diff --git a/Utilities/LibMatrix.DebugDataValidationApi/JsonElementExtensions.cs b/Utilities/LibMatrix.DebugDataValidationApi/JsonElementExtensions.cs new file mode 100644 index 0000000..c4ed743 --- /dev/null +++ b/Utilities/LibMatrix.DebugDataValidationApi/JsonElementExtensions.cs @@ -0,0 +1,147 @@ +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace LibMatrix.Extensions; + +public static class JsonElementExtensions { + public static bool FindExtraJsonElementFields(this JsonElement obj, Type objectType, string objectPropertyName) { + if (objectPropertyName == "content" && objectType == typeof(JsonObject)) + objectType = typeof(StateEventResponse); + // if (t == typeof(JsonNode)) + // return false; + + Console.WriteLine($"{objectType.Name} {objectPropertyName}"); + var unknownPropertyFound = false; + var mappedPropsDict = objectType.GetProperties() + .Where(x => x.GetCustomAttribute<JsonPropertyNameAttribute>() is not null) + .ToDictionary(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()!.Name, x => x); + objectType.GetProperties().Where(x => !mappedPropsDict.ContainsKey(x.Name)) + .ToList().ForEach(x => mappedPropsDict.TryAdd(x.Name, x)); + + foreach (var field in obj.EnumerateObject()) { + if (mappedPropsDict.TryGetValue(field.Name, out var mappedProperty)) { + //dictionary + if (mappedProperty.PropertyType.IsGenericType && + mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { + unknownPropertyFound |= _checkDictionary(field, objectType, mappedProperty.PropertyType); + continue; + } + + if (mappedProperty.PropertyType.IsGenericType && + mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) { + unknownPropertyFound |= _checkList(field, objectType, mappedProperty.PropertyType); + continue; + } + + if (field.Name == "content" && (objectType == typeof(StateEventResponse) || objectType == typeof(StateEvent))) { + unknownPropertyFound |= field.FindExtraJsonPropertyFieldsByValueKind( + StateEvent.GetStateEventType(obj.GetProperty("type").GetString()!), // We expect type to always be present + mappedProperty.PropertyType); + continue; + } + + unknownPropertyFound |= + field.FindExtraJsonPropertyFieldsByValueKind(objectType, mappedProperty.PropertyType); + continue; + } + + Console.WriteLine($"[!!] Unknown property {field.Name} in {objectType.Name}!"); + unknownPropertyFound = true; + } + + return unknownPropertyFound; + } + + private static bool FindExtraJsonPropertyFieldsByValueKind(this JsonProperty field, Type containerType, + Type propertyType) { + if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) propertyType = propertyType.GetGenericArguments()[0]; + + var switchResult = false; + switch (field.Value.ValueKind) { + case JsonValueKind.Array: + switchResult = field.Value.EnumerateArray().Aggregate(switchResult, + (current, element) => current | element.FindExtraJsonElementFields(propertyType, field.Name)); + break; + case JsonValueKind.Object: + switchResult |= field.Value.FindExtraJsonElementFields(propertyType, field.Name); + break; + case JsonValueKind.True: + case JsonValueKind.False: + return _checkBool(field, containerType, propertyType); + case JsonValueKind.String: + return _checkString(field, containerType, propertyType); + case JsonValueKind.Number: + return _checkNumber(field, containerType, propertyType); + case JsonValueKind.Undefined: + case JsonValueKind.Null: + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return switchResult; + } + + private static bool _checkBool(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(bool)) return true; + Console.WriteLine( + $"[!!] Encountered bool for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkString(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(string)) return true; + // ReSharper disable once BuiltInTypeReferenceStyle + if (propertyType == typeof(String)) return true; + Console.WriteLine( + $"[!!] Encountered string for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkNumber(this JsonProperty field, Type containerType, Type propertyType) { + if (propertyType == typeof(int) || + propertyType == typeof(double) || + propertyType == typeof(float) || + propertyType == typeof(decimal) || + propertyType == typeof(long) || + propertyType == typeof(short) || + propertyType == typeof(uint) || + propertyType == typeof(ulong) || + propertyType == typeof(ushort) || + propertyType == typeof(byte) || + propertyType == typeof(sbyte)) + return true; + Console.WriteLine( + $"[!!] Encountered number for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!"); + return false; + } + + private static bool _checkDictionary(this JsonProperty field, Type containerType, Type propertyType) { + var keyType = propertyType.GetGenericArguments()[0]; + var valueType = propertyType.GetGenericArguments()[1]; + valueType = Nullable.GetUnderlyingType(valueType) ?? valueType; + Console.WriteLine( + $"Encountered dictionary {field.Name} with key type {keyType.Name} and value type {valueType.Name}!"); + + return field.Value.EnumerateObject() + .Where(key => !valueType.IsPrimitive && valueType != typeof(string)) + .Aggregate(false, (current, key) => + current | key.FindExtraJsonPropertyFieldsByValueKind(containerType, valueType) + ); + } + + private static bool _checkList(this JsonProperty field, Type containerType, Type propertyType) { + var valueType = propertyType.GetGenericArguments()[0]; + valueType = Nullable.GetUnderlyingType(valueType) ?? valueType; + Console.WriteLine( + $"Encountered list {field.Name} with value type {valueType.Name}!"); + + return field.Value.EnumerateArray() + .Where(key => !valueType.IsPrimitive && valueType != typeof(string)) + .Aggregate(false, (current, key) => + current | key.FindExtraJsonElementFields(valueType, field.Name) + ); + } +} \ No newline at end of file diff --git a/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj b/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj index 24fd617..3466fb1 100644 --- a/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj +++ b/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj @@ -9,8 +9,8 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0"/> - <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0"/> + <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.5" /> + <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" /> </ItemGroup> <ItemGroup> diff --git a/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs b/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs index cc866e6..05b357e 100644 --- a/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs +++ b/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs @@ -1,36 +1,36 @@ -using System.Text.Json; -using ArcaneLibs.Extensions; -using LibMatrix.Interfaces.Services; -using Microsoft.Extensions.Logging; - -namespace LibMatrix.ExampleBot.Bot; - -public class FileStorageProvider : IStorageProvider { - private readonly ILogger<FileStorageProvider> _logger; - - public string TargetPath { get; } - - /// <summary> - /// Creates a new instance of <see cref="FileStorageProvider" />. - /// </summary> - /// <param name="targetPath"></param> - public FileStorageProvider(string targetPath) { - new Logger<FileStorageProvider>(new LoggerFactory()).LogInformation("test"); - Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}"); - TargetPath = targetPath; - if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath); - } - - public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson()); - - public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key))); - - public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key))); - - public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList()); - - public Task DeleteObjectAsync(string key) { - File.Delete(Path.Join(TargetPath, key)); - return Task.CompletedTask; - } -} \ No newline at end of file +// using System.Text.Json; +// using ArcaneLibs.Extensions; +// using LibMatrix.Interfaces.Services; +// using Microsoft.Extensions.Logging; +// +// namespace LibMatrix.ExampleBot.Bot; +// +// public class FileStorageProvider : IStorageProvider { +// private readonly ILogger<FileStorageProvider> _logger; +// +// public string TargetPath { get; } +// +// /// <summary> +// /// Creates a new instance of <see cref="FileStorageProvider" />. +// /// </summary> +// /// <param name="targetPath"></param> +// public FileStorageProvider(string targetPath) { +// new Logger<FileStorageProvider>(new LoggerFactory()).LogInformation("test"); +// Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}"); +// TargetPath = targetPath; +// if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath); +// } +// +// public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson()); +// +// public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key))); +// +// public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key))); +// +// public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList()); +// +// public Task DeleteObjectAsync(string key) { +// File.Delete(Path.Join(TargetPath, key)); +// return Task.CompletedTask; +// } +// } \ No newline at end of file diff --git a/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs b/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs index b762937..f723c57 100644 --- a/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs +++ b/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs @@ -1,32 +1,32 @@ -using System.Text.Json; -using ArcaneLibs.Extensions; -using LibMatrix.Interfaces.Services; - -namespace LibMatrix.Utilities.Bot; - -public class FileStorageProvider : IStorageProvider { - public string TargetPath { get; } - - /// <summary> - /// Creates a new instance of <see cref="FileStorageProvider" />. - /// </summary> - /// <param name="targetPath"></param> - public FileStorageProvider(string targetPath) { - Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}"); - TargetPath = targetPath; - if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath); - } - - public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson()); - - public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key))); - - public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key))); - - public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList()); - - public Task DeleteObjectAsync(string key) { - File.Delete(Path.Join(TargetPath, key)); - return Task.CompletedTask; - } -} \ No newline at end of file +// using System.Text.Json; +// using ArcaneLibs.Extensions; +// using LibMatrix.Interfaces.Services; +// +// namespace LibMatrix.Utilities.Bot; +// +// public class FileStorageProvider : IStorageProvider { +// public string TargetPath { get; } +// +// /// <summary> +// /// Creates a new instance of <see cref="FileStorageProvider" />. +// /// </summary> +// /// <param name="targetPath"></param> +// public FileStorageProvider(string targetPath) { +// Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}"); +// TargetPath = targetPath; +// if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath); +// } +// +// public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson()); +// +// public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key))); +// +// public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key))); +// +// public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList()); +// +// public Task DeleteObjectAsync(string key) { +// File.Delete(Path.Join(TargetPath, key)); +// return Task.CompletedTask; +// } +// } \ No newline at end of file diff --git a/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj b/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj index 89ea5af..6e67373 100644 --- a/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj +++ b/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj @@ -12,9 +12,9 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0"/> + <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/> - <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0"/> + <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" /> </ItemGroup> |