From a6269d01646cb03ee6b460256953ef5cb09e525b Mon Sep 17 00:00:00 2001 From: Andreas Date: Wed, 20 Mar 2024 07:13:03 +0100 Subject: [PATCH] Keep encryption for `Dictionary` exports Fixed #28 --- src/MauiSettings.Example/MainPage.xaml | 24 +++++- .../Models/Settings/SettingsItem.cs | 13 ++++ .../ViewModels/MainPageViewModel.cs | 17 +++- .../Helper/MauiSettingsMemberInfo.cs | 6 +- src/MauiSettings/MauiSettings.csproj | 3 +- src/MauiSettings/MauiSettingsGeneric.cs | 77 +++++++------------ 6 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 src/MauiSettings.Example/Models/Settings/SettingsItem.cs diff --git a/src/MauiSettings.Example/MainPage.xaml b/src/MauiSettings.Example/MainPage.xaml index 1b391b2..bdb2999 100644 --- a/src/MauiSettings.Example/MainPage.xaml +++ b/src/MauiSettings.Example/MainPage.xaml @@ -4,7 +4,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MauiSettings.Example.MainPage" xmlns:viewModels="clr-namespace:MauiSettings.Example.ViewModels" - + xmlns:settings="clr-namespace:MauiSettings.Example.Models.Settings" x:DataType="viewModels:MainPageViewModel" > @@ -59,6 +59,28 @@ Text="To dictionary" Command="{Binding ToDictionaryCommand}" HorizontalOptions="Fill" /> + + + + + + + + + diff --git a/src/MauiSettings.Example/Models/Settings/SettingsItem.cs b/src/MauiSettings.Example/Models/Settings/SettingsItem.cs new file mode 100644 index 0000000..78bfa57 --- /dev/null +++ b/src/MauiSettings.Example/Models/Settings/SettingsItem.cs @@ -0,0 +1,13 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace MauiSettings.Example.Models.Settings +{ + public partial class SettingsItem : ObservableObject + { + [ObservableProperty] + string key = string.Empty; + + [ObservableProperty] + string value = string.Empty; + } +} diff --git a/src/MauiSettings.Example/ViewModels/MainPageViewModel.cs b/src/MauiSettings.Example/ViewModels/MainPageViewModel.cs index 34f32d3..17f9ffe 100644 --- a/src/MauiSettings.Example/ViewModels/MainPageViewModel.cs +++ b/src/MauiSettings.Example/ViewModels/MainPageViewModel.cs @@ -2,6 +2,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using MauiSettings.Example.Models.Settings; +using System.Collections.ObjectModel; namespace MauiSettings.Example.ViewModels { @@ -25,6 +26,8 @@ partial void OnLicenseInfoChanged(string value) } } + [ObservableProperty] + ObservableCollection settings = []; #endregion #region Ctor @@ -52,8 +55,15 @@ void LoadSettings() [RelayCommand] async Task LoadSettingsFromDevice() { - await SettingsApp.LoadSettingsAsync(key: App.Hash); - LoadSettings(); + try + { + await SettingsApp.LoadSettingsAsync(key: App.Hash); + LoadSettings(); + } + catch(Exception) + { + // Throus if the key missmatches + } } [RelayCommand] @@ -69,7 +79,8 @@ async Task ExchangeHashKey() async Task ToDictionary() { // All "SkipForExport" should be missing here. - var dict = await SettingsApp.ToDictionaryAsync(); + Dictionary> dict = await SettingsApp.ToDictionaryAsync(); + Settings = [.. dict.Select(kp => new SettingsItem() { Key = kp.Key, Value = kp.Value.Item1.ToString() })]; } #endregion } diff --git a/src/MauiSettings/Helper/MauiSettingsMemberInfo.cs b/src/MauiSettings/Helper/MauiSettingsMemberInfo.cs index 08ee79a..a121457 100644 --- a/src/MauiSettings/Helper/MauiSettingsMemberInfo.cs +++ b/src/MauiSettings/Helper/MauiSettingsMemberInfo.cs @@ -12,9 +12,9 @@ namespace AndreasReitberger.Maui.Helper internal class MauiSettingsMemberInfo { #region Properties - public object OrignalSettingsObject { get; set; } - public MemberInfo Info { get; set; } - public Type SettingsType { get; set; } + public object? OrignalSettingsObject { get; set; } + public MemberInfo? Info { get; set; } + public Type? SettingsType { get; set; } #endregion } } diff --git a/src/MauiSettings/MauiSettings.csproj b/src/MauiSettings/MauiSettings.csproj index 2f03dd4..e6c59b1 100644 --- a/src/MauiSettings/MauiSettings.csproj +++ b/src/MauiSettings/MauiSettings.csproj @@ -10,13 +10,14 @@ enable false enable - + 14.2 14.0 21.0 10.0.17763.0 10.0.17763.0 6.5 + AndreasReitberger.Maui Andreas Reitberger https://github.com/AndreasReitberger/MauiSettings diff --git a/src/MauiSettings/MauiSettingsGeneric.cs b/src/MauiSettings/MauiSettingsGeneric.cs index fbdf92b..42ae269 100644 --- a/src/MauiSettings/MauiSettingsGeneric.cs +++ b/src/MauiSettings/MauiSettingsGeneric.cs @@ -222,83 +222,66 @@ public static void LoadObjectDefaultSetting(object settings, Expression>> ToDictionaryAsync() => ToDictionaryAsync(settings: SettingsObject); - public static async Task>> ToDictionaryAsync(object settings) + public static Task>> ToDictionaryAsync(bool secureOnly = false, string? key = null) + => ToDictionaryAsync(settings: SettingsObject, secureOnly: secureOnly, key: key); + + public static async Task>> ToDictionaryAsync(object? settings, bool secureOnly = false, string? key = null) { if (true) { Dictionary> setting = []; - IEnumerable declaredMembers = settings.GetType().GetTypeInfo().DeclaredMembers; + IEnumerable? declaredMembers = settings?.GetType().GetTypeInfo().DeclaredMembers; MauiSettingsMemberInfo settingsObjectInfo = new(); MauiSettingsInfo settingsInfo = new(); + if (declaredMembers is null) return setting; foreach (MemberInfo mInfo in declaredMembers) { settingsObjectInfo.OrignalSettingsObject = settings; settingsObjectInfo.Info = mInfo; // Handles saving the settings to the Maui.Storage.Preferences - MauiSettingsInfo settingsPair = await ProcessSettingsInfoAsKeyValuePairAsync(settingsObjectInfo, settingsInfo); + MauiSettingsInfo? settingsPair = await ProcessSettingsInfoAsKeyValuePairAsync(settingsObjectInfo, settingsInfo, secureOnly: secureOnly, key: key, keeyEncrypted: true); if (settingsPair != null && !settingsPair.SkipForExport) { setting.TryAdd(settingsPair.Name, new Tuple(settingsPair.Value ?? settingsPair.Default, settingsPair.SettingsType)); } } - /* - members?.ForEach(member => - { - settingsObjectInfo.OrignalSettingsObject = settings; - settingsObjectInfo.Info = member; - var settingsPair = ProcessSettingsInfoAsKeyValuePair(settingsObjectInfo, settingsInfo); - if (settingsPair != null) - { - setting.TryAdd(settingsPair.Name, new Tuple(settingsPair.Value ?? settingsPair.Default, settingsPair.SettingsType)); - } - }); - */ return setting; } } public static Task>> ToConcurrentDictionaryAsync() => ToConcurrentDictionaryAsync(settings: SettingsObject); + public static Task>> ToConcurrentDictionaryAsync(bool secureOnly = false, string? key = null) + => ToConcurrentDictionaryAsync(settings: SettingsObject, secureOnly: secureOnly, key: key); - public static async Task>> ToConcurrentDictionaryAsync(object settings) + public static async Task>> ToConcurrentDictionaryAsync(object? settings, bool secureOnly = false, string? key = null) { ConcurrentDictionary> setting = new(); - List members = GetClassMetaAsList(settings); + List? members = GetClassMetaAsList(settings); MauiSettingsMemberInfo settingsObjectInfo = new(); MauiSettingsInfo settingsInfo = new(); + if (members is null) return setting; foreach (MemberInfo mInfo in members) { settingsObjectInfo.OrignalSettingsObject = settings; settingsObjectInfo.Info = mInfo; // Handles saving the settings to the Maui.Storage.Preferences - MauiSettingsInfo settingsPair = await ProcessSettingsInfoAsKeyValuePairAsync(settingsObjectInfo, settingsInfo); + MauiSettingsInfo? settingsPair = await ProcessSettingsInfoAsKeyValuePairAsync(settingsObjectInfo, settingsInfo, secureOnly: secureOnly, key: key, keeyEncrypted: true); if (settingsPair != null && !settingsPair.SkipForExport) { setting.TryAdd(settingsPair.Name, new Tuple(settingsPair.Value ?? settingsPair.Default, settingsPair.SettingsType)); } } - /* - members?.ForEach(member => - { - settingsObjectInfo.OrignalSettingsObject = settings; - settingsObjectInfo.Info = member; - var settingsPair = ProcessSettingsInfoAsKeyValuePair(settingsObjectInfo, settingsInfo); - if(settingsPair != null) - { - setting.TryAdd(settingsPair.Name, new Tuple(settingsPair.Value ?? settingsPair.Default, settingsPair.SettingsType)); - } - }); - */ return setting; } public static Task>> ToSettingsTupleAsync(Expression> value) => ToSettingsTupleAsync(settings: SettingsObject, value: value); - public static async Task>> ToSettingsTupleAsync(object settings, Expression> value) + public static async Task>> ToSettingsTupleAsync(object? settings, Expression> value) { MauiSettingsInfo? info = await GetExpressionMetaAsKeyValuePairAsync(settings: settings, value: value); return new(info.Name, new(info.Value, info.SettingsType)); @@ -317,12 +300,13 @@ public static Task ExhangeKeyAsync(string? newKey = null, string? oldKey = null) #endregion #region Private - static List? GetClassMetaAsList(object settings) + static List? GetClassMetaAsList(object? settings) { + if (settings is null) return null; lock (lockObject) { // Get all member infos from the passed settingsObject - IEnumerable declaredMembers = settings.GetType().GetTypeInfo().DeclaredMembers; + IEnumerable? declaredMembers = settings?.GetType().GetTypeInfo().DeclaredMembers; MauiSettingsMemberInfo settingsObjectInfo = new(); MauiSettingsInfo settingsInfo = new(); @@ -439,7 +423,7 @@ static async Task GetExpressionMetaAsync(object settings, Expression GetExpressionMetaAsKeyValuePairAsync(object settings, Expression> value, string? key = null) + static async Task GetExpressionMetaAsKeyValuePairAsync(object? settings, Expression> value, string? key = null) { if (value.Body is MemberExpression memberExpression) { @@ -608,7 +592,7 @@ List settingBaseAttributes return true; } - static async Task ProcessSettingsInfoAsync(MauiSettingsMemberInfo settingsObjectInfo, MauiSettingsInfo settingsInfo, MauiSettingsActions mode, MauiSettingsTarget target, bool secureOnly = false, bool useValueFromSettingsInfo = false, string? key = null) + static async Task ProcessSettingsInfoAsync(MauiSettingsMemberInfo settingsObjectInfo, MauiSettingsInfo settingsInfo, MauiSettingsActions mode, MauiSettingsTarget target, bool secureOnly = false, bool useValueFromSettingsInfo = false, string? key = null, bool keepEncrypted = false) { settingsInfo ??= new(); MauiSettingBaseAttribute? settingBaseAttribute = null; @@ -623,9 +607,9 @@ List settingBaseAttributes return false; } settingBaseAttribute = settingBaseAttributes?.FirstOrDefault(); - } - if (settingsObjectInfo.Info is not null) - { + //} + //if (settingsObjectInfo.Info is not null) + //{ settingsInfo.Name = MauiSettingNameFormater.GetFullSettingName(settingsObjectInfo.OrignalSettingsObject.GetType(), settingsObjectInfo.Info, settingBaseAttribute); settingsInfo.SettingsType = (settingsInfo.SettingsType = MauiSettingsObjectHelper.GetSettingType(settingsObjectInfo.Info)); settingsInfo.Default = MauiSettingsObjectHelper.GetDefaultValue(settingBaseAttribute, settingsInfo.SettingsType); @@ -704,7 +688,7 @@ List settingBaseAttributes { object defaultValue = MauiSettingsObjectHelper.GetDefaultValue(settingBaseAttribute, settingsInfo.SettingsType); } - if (secure && settingsInfo.Encrypt && !string.IsNullOrEmpty(key)) + if (secure && settingsInfo.Encrypt && !string.IsNullOrEmpty(key) && !keepEncrypted) { if (settingsInfo.Value is string secureString) { @@ -716,7 +700,6 @@ List settingBaseAttributes } // Sets the loaded value back to the settingsObject MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, settingsInfo.Value, settingsInfo.SettingsType); - break; case MauiSettingsActions.Save: // Get the value from the settingsObject @@ -854,7 +837,7 @@ List settingBaseAttributes return true; } - static async Task ProcessSettingsInfoAsKeyValuePairAsync(MauiSettingsMemberInfo settingsObjectInfo, MauiSettingsInfo settingsInfo, bool secureOnly = false, string? key = null) + static async Task ProcessSettingsInfoAsKeyValuePairAsync(MauiSettingsMemberInfo settingsObjectInfo, MauiSettingsInfo settingsInfo, bool secureOnly = false, string? key = null, bool keeyEncrypted = false) { settingsInfo ??= new(); MauiSettingBaseAttribute? settingBaseAttribute = null; @@ -869,16 +852,12 @@ List settingBaseAttributes return null; } settingBaseAttribute = settingBaseAttributes?.FirstOrDefault(); - } - if (settingsObjectInfo.Info is not null) - { + //} + //if (settingsObjectInfo.Info is not null) + //{ settingsInfo.Name = MauiSettingNameFormater.GetFullSettingName(settingsObjectInfo.OrignalSettingsObject.GetType(), settingsObjectInfo.Info, settingBaseAttribute); settingsInfo.SettingsType = (settingsInfo.SettingsType = MauiSettingsObjectHelper.GetSettingType(settingsObjectInfo.Info)); - settingsInfo.Default = MauiSettingsObjectHelper.GetDefaultValue(settingBaseAttribute, settingsInfo.SettingsType); - //Type type = (settingsInfo.SettingsType = MauiSettingsObjectHelper.GetSettingType(settingsObjectInfo.Info)); - //settingsInfo.Value = MauiSettingsObjectHelper.GetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject); - //settingsInfo.Value = MauiSettingsHelper.GetSettingsValue(settingsInfo.Name, settingsInfo.Default); } if (settingBaseAttribute is MauiSettingAttribute settingAttribute) { @@ -897,7 +876,7 @@ List settingBaseAttributes else if (settingsInfo.SettingsType == typeof(string)) { settingsInfo.Value = await MauiSettingsHelper.GetSecureSettingsValueAsync(settingsInfo.Name, settingsInfo.Default as string); - if (settingsInfo.Encrypt && !string.IsNullOrEmpty(key)) + if (settingsInfo.Encrypt && !string.IsNullOrEmpty(key) && !keeyEncrypted) { // Decrypt string string decryptedString = EncryptionManager.DecryptStringFromBase64String(settingsInfo.Value as string, key);