From 662d0e569d60156b7b78310a83cf02d0aedc1a7c Mon Sep 17 00:00:00 2001 From: Andreas Date: Wed, 3 Apr 2024 14:49:38 +0200 Subject: [PATCH 1/6] Add `Event` for `EncryptionErrors` This commit adds `trycatch` to the encryption stuff and invokes an event if such a error happens. --- src/MauiSettings/Enums/MauiSettingsResults.cs | 10 ++ .../Events/EncryptionErrorEventArgs.cs | 8 ++ src/MauiSettings/MauiSettingsGeneric.cs | 123 +++++++++++++++--- 3 files changed, 123 insertions(+), 18 deletions(-) create mode 100644 src/MauiSettings/Enums/MauiSettingsResults.cs create mode 100644 src/MauiSettings/Events/EncryptionErrorEventArgs.cs diff --git a/src/MauiSettings/Enums/MauiSettingsResults.cs b/src/MauiSettings/Enums/MauiSettingsResults.cs new file mode 100644 index 0000000..0776591 --- /dev/null +++ b/src/MauiSettings/Enums/MauiSettingsResults.cs @@ -0,0 +1,10 @@ +namespace AndreasReitberger.Maui.Enums +{ + public enum MauiSettingsResults + { + Success, + Skipped, + EncryptionError, + Failed, + } +} diff --git a/src/MauiSettings/Events/EncryptionErrorEventArgs.cs b/src/MauiSettings/Events/EncryptionErrorEventArgs.cs new file mode 100644 index 0000000..797b93f --- /dev/null +++ b/src/MauiSettings/Events/EncryptionErrorEventArgs.cs @@ -0,0 +1,8 @@ +namespace AndreasReitberger.Maui.Events +{ + public partial class EncryptionErrorEventArgs : EventArgs + { + public Exception? Exception { get; set; } + public string Key { get; set; } = string.Empty; + } +} diff --git a/src/MauiSettings/MauiSettingsGeneric.cs b/src/MauiSettings/MauiSettingsGeneric.cs index d5d92d7..bcfb0fa 100644 --- a/src/MauiSettings/MauiSettingsGeneric.cs +++ b/src/MauiSettings/MauiSettingsGeneric.cs @@ -3,6 +3,7 @@ using AndreasReitberger.Maui.Cloud; #endif using AndreasReitberger.Maui.Enums; +using AndreasReitberger.Maui.Events; using AndreasReitberger.Maui.Helper; using AndreasReitberger.Maui.Utilities; using AndreasReitberger.Shared.Core.Utilities; @@ -68,7 +69,7 @@ public MauiSettingsGeneric(SO settingsObject, string settingsKey) public static Task LoadSettingAsync(Expression> value, string? key = null) => Task.Run(async delegate { - await LoadObjectSettingAsync(SettingsObject, value, key: key); + await LoadObjectSettingAsync(SettingsObject, value, key: key); }); public static Task LoadSecureSettingAsync(Expression> value, string? key = null) => Task.Run(async delegate @@ -336,7 +337,8 @@ static async Task GetClassMetaAsync(object settings, MauiSettingsActions mode, M settingsObjectInfo.OrignalSettingsObject = settings; settingsObjectInfo.Info = mInfo; // Handles saving the settings to the Maui.Storage.Preferences - _ = await ProcessSettingsInfoAsync(settingsObjectInfo, settingsInfo, mode, target, secureOnly: secureOnly, key: key); + MauiSettingsResults result = await ProcessSettingsInfoAsync(settingsObjectInfo, settingsInfo, mode, target, secureOnly: secureOnly, key: key); + if (result == MauiSettingsResults.EncryptionError || result == MauiSettingsResults.Failed) { break; } } } static async Task GetMetaFromDictionaryAsync(object settings, Dictionary> dictionary, MauiSettingsActions mode, MauiSettingsTarget target = MauiSettingsTarget.Local, bool secureOnly = false, string? key = null) @@ -371,8 +373,9 @@ static async Task GetMetaFromDictionaryAsync(object settings, Dictionary settingBaseAttributes return true; } - static async Task ProcessSettingsInfoAsync(MauiSettingsMemberInfo settingsObjectInfo, MauiSettingsInfo settingsInfo, MauiSettingsActions mode, MauiSettingsTarget target, bool secureOnly = false, bool useValueFromSettingsInfo = false, string? key = null, bool keepEncrypted = false) + 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; @@ -586,7 +589,7 @@ List settingBaseAttributes if (settingBaseAttributes?.Count == 0) { // If the member has not the needed MauiSettingsAttribute, continue with the search - return false; + return MauiSettingsResults.Skipped; } settingBaseAttribute = settingBaseAttributes?.FirstOrDefault(); settingsInfo.Name = MauiSettingNameFormater.GetFullSettingName(settingsObjectInfo.OrignalSettingsObject.GetType(), settingsObjectInfo.Info, settingBaseAttribute); @@ -605,7 +608,7 @@ List settingBaseAttributes { // If only secure storage should be loaded, stop here. if (secureOnly) - return true; + return MauiSettingsResults.Skipped; // If the value is not used from the passed settingsInfo, load it switch (target) @@ -673,8 +676,23 @@ List settingBaseAttributes if (settingsInfo.Value is string secureString) { // Decrypt string - string decryptedString = EncryptionManager.DecryptStringFromBase64String(secureString, key); - MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, decryptedString, settingsInfo.SettingsType); + try + { + string decryptedString = EncryptionManager.DecryptStringFromBase64String(secureString, key); + // Throw on key missmatch + if (string.IsNullOrEmpty(decryptedString) && !string.IsNullOrEmpty(secureString)) + throw new Exception($"The secure string is not empty, but the decrypted string is. This indicates a key missmatch!"); + MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, decryptedString, settingsInfo.SettingsType); + } + catch(Exception ex) + { + OnEncryptionErrorEvent(new() + { + Exception = ex, + Key = key, + }); + return MauiSettingsResults.EncryptionError; + } break; } } @@ -702,8 +720,20 @@ List settingBaseAttributes if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key)); // Encrypt string - string encryptedString = EncryptionManager.EncryptStringToBase64String(secureString, key); - await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, encryptedString); + try + { + string encryptedString = EncryptionManager.EncryptStringToBase64String(secureString, key); + await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, encryptedString); + } + catch (Exception ex) + { + OnEncryptionErrorEvent(new() + { + Exception = ex, + Key = key, + }); + return MauiSettingsResults.EncryptionError; + } } else await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, secureString); @@ -752,9 +782,21 @@ List settingBaseAttributes { if (settingsInfo.Encrypt && !string.IsNullOrEmpty(key)) { - // Decrypt string - string encryptedString = EncryptionManager.EncryptStringToBase64String(secureString, key); - await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, encryptedString); + // Encrypt string + try + { + string encryptedString = EncryptionManager.EncryptStringToBase64String(secureString, key); + await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, encryptedString); + } + catch (Exception ex) + { + OnEncryptionErrorEvent(new() + { + Exception = ex, + Key = key, + }); + return MauiSettingsResults.EncryptionError; + } } else await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, secureString); @@ -795,8 +837,20 @@ List settingBaseAttributes if (settingsInfo.Encrypt && !string.IsNullOrEmpty(key)) { // Decrypt string - string encryptedString = EncryptionManager.EncryptStringToBase64String(secureString, key); - await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, encryptedString); + try + { + string encryptedString = EncryptionManager.EncryptStringToBase64String(secureString, key); + await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, encryptedString); + } + catch (Exception ex) + { + OnEncryptionErrorEvent(new() + { + Exception = ex, + Key = key, + }); + return MauiSettingsResults.EncryptionError; + } } else await MauiSettingsHelper.SetSecureSettingsValueAsync(settingsInfo.Name, secureString); @@ -816,7 +870,7 @@ List settingBaseAttributes default: break; } - return true; + return MauiSettingsResults.Success; } static async Task ProcessSettingsInfoAsKeyValuePairAsync(MauiSettingsMemberInfo settingsObjectInfo, MauiSettingsInfo settingsInfo, bool secureOnly = false, string? key = null, bool keeyEncrypted = false) @@ -860,8 +914,26 @@ List settingBaseAttributes if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key)); // Decrypt string - string decryptedString = EncryptionManager.DecryptStringFromBase64String(settingsInfo.Value as string, key); - settingsInfo.Value = decryptedString; + if (settingsInfo.Value is string secureString) + { + try + { + string decryptedString = EncryptionManager.DecryptStringFromBase64String(secureString, key); + // Throw on key missmatch + if (string.IsNullOrEmpty(decryptedString) && !string.IsNullOrEmpty(secureString)) + throw new Exception($"The secure string is not empty, but the decrypted string is. This indicates a key missmatch!"); + settingsInfo.Value = decryptedString; + } + catch (Exception ex) + { + OnEncryptionErrorEvent(new() + { + Exception = ex, + Key = key, + }); + return null; + } + } } } else @@ -875,5 +947,20 @@ List settingBaseAttributes #endregion #endregion + + #region Events + + public static event EventHandler? ErrorEvent; + protected static void OnErrorEvent(ErrorEventArgs e) + { + ErrorEvent?.Invoke(typeof(MauiSettingsGeneric), e); + } + + public static event EventHandler? EncryptionErrorEvent; + protected static void OnEncryptionErrorEvent(EncryptionErrorEventArgs e) + { + EncryptionErrorEvent?.Invoke(typeof(MauiSettingsGeneric), e); + } + #endregion } } From 100426f718a5813fa41c24dbef785ab61637b9f2 Mon Sep 17 00:00:00 2001 From: Andreas Date: Thu, 4 Apr 2024 12:44:07 +0200 Subject: [PATCH 2/6] Added `TryLoadSettingsAsync` methods --- src/MauiSettings/MauiSettingsGeneric.cs | 68 ++++++++++++++++++++----- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/src/MauiSettings/MauiSettingsGeneric.cs b/src/MauiSettings/MauiSettingsGeneric.cs index bcfb0fa..d4419ab 100644 --- a/src/MauiSettings/MauiSettingsGeneric.cs +++ b/src/MauiSettings/MauiSettingsGeneric.cs @@ -105,6 +105,18 @@ public static Task LoadSettingsAsync(object settings, string? key = null) await GetClassMetaAsync(settings: settings, mode: MauiSettingsActions.Load, key: key); }); + public static Task TryLoadSettingsAsync(string? key = null) + => Task.Run(async delegate + { + return await TryLoadSettingsAsync(settings: SettingsObject, key: key); + }); + + public static Task TryLoadSettingsAsync(object settings, string? key = null) + => Task.Run(async delegate + { + return await GetClassMetaAsync(settings: settings, mode: MauiSettingsActions.Load, key: key, justTryLoading: true); + }); + public static Task LoadSecureSettingsAsync(string? key = null) => Task.Run(async delegate { @@ -123,12 +135,24 @@ public static Task LoadSettingsAsync(Dictionary> dic await LoadSettingsAsync(settings: SettingsObject, dictionary: dictionary, save: save, key: key); }); + public static Task TryLoadSettingsAsync(Dictionary> dictionary, string? key = null) + => Task.Run(async delegate + { + return await TryLoadSettingsAsync(settings: SettingsObject, dictionary: dictionary, key: key); + }); + public static Task LoadSettingsAsync(string settingsKey, Tuple data, bool save = true, string? key = null) => Task.Run(async delegate { await LoadSettingsAsync(settings: SettingsObject, dictionary: new() { { settingsKey, data } }, save: save, key: key); }); + public static Task TryLoadSettingsAsync(string settingsKey, Tuple data, string? key = null) + => Task.Run(async delegate + { + return await TryLoadSettingsAsync(settings: SettingsObject, dictionary: new() { { settingsKey, data } }, key: key); + }); + public static Task LoadSettingsAsync(object settings, Dictionary> dictionary, bool save = true, string? key = null) => Task.Run(async delegate { @@ -136,6 +160,11 @@ public static Task LoadSettingsAsync(object settings, Dictionary TryLoadSettingsAsync(object settings, Dictionary> dictionary, string? key = null) + => Task.Run(async delegate + { + return await GetMetaFromDictionaryAsync(settings: settings, dictionary: dictionary, mode: MauiSettingsActions.Load, secureOnly: false, key: key, justTryLoading: true); + }); #endregion @@ -324,7 +353,7 @@ static void GetClassMeta(object settings, MauiSettingsActions mode, MauiSettings } } } - static async Task GetClassMetaAsync(object settings, MauiSettingsActions mode, MauiSettingsTarget target = MauiSettingsTarget.Local, bool secureOnly = false, string? key = null) + static async Task GetClassMetaAsync(object settings, MauiSettingsActions mode, MauiSettingsTarget target = MauiSettingsTarget.Local, bool secureOnly = false, string? key = null, bool justTryLoading = false) { // Get all member infos from the passed settingsObject IEnumerable declaredMembers = settings.GetType().GetTypeInfo().DeclaredMembers; @@ -337,11 +366,12 @@ static async Task GetClassMetaAsync(object settings, MauiSettingsActions mode, M settingsObjectInfo.OrignalSettingsObject = settings; settingsObjectInfo.Info = mInfo; // Handles saving the settings to the Maui.Storage.Preferences - MauiSettingsResults result = await ProcessSettingsInfoAsync(settingsObjectInfo, settingsInfo, mode, target, secureOnly: secureOnly, key: key); - if (result == MauiSettingsResults.EncryptionError || result == MauiSettingsResults.Failed) { break; } - } + MauiSettingsResults result = await ProcessSettingsInfoAsync(settingsObjectInfo, settingsInfo, mode, target, secureOnly: secureOnly, key: key, justTryLoading: justTryLoading); + if (result == MauiSettingsResults.EncryptionError || result == MauiSettingsResults.Failed) { return false; } + } + return true; } - static async Task GetMetaFromDictionaryAsync(object settings, Dictionary> dictionary, MauiSettingsActions mode, MauiSettingsTarget target = MauiSettingsTarget.Local, bool secureOnly = false, string? key = null) + static async Task GetMetaFromDictionaryAsync(object settings, Dictionary> dictionary, MauiSettingsActions mode, MauiSettingsTarget target = MauiSettingsTarget.Local, bool secureOnly = false, string? key = null, bool justTryLoading = false) { // Get all member infos from the passed settingsObject IEnumerable declaredMembers = settings.GetType().GetTypeInfo().DeclaredMembers; @@ -374,9 +404,10 @@ static async Task GetMetaFromDictionaryAsync(object settings, Dictionary(object settings, Expression> value, MauiSettingsActions mode, MauiSettingsTarget target = MauiSettingsTarget.Local) @@ -423,7 +454,10 @@ static async Task GetExpressionMetaAsync(object settings, Expression settingBaseAttributes } #else - if (throwOnError) throw new NotSupportedException("SecureStorage is only available in the Async methods!"); + if (throwOnError && mode != MauiSettingsActions.LoadDefaults) throw new NotSupportedException("SecureStorage is only available in the Async methods!"); #endif } else if (settingsInfo.Encrypt) @@ -502,7 +536,8 @@ List settingBaseAttributes object defaultValue = MauiSettingsObjectHelper.GetDefaultValue(settingBaseAttribute, settingsInfo.SettingsType); } // Sets the loaded value back to the settingsObject - MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, settingsInfo.Value, settingsInfo.SettingsType); + if (!justTryLoading) + MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, settingsInfo.Value, settingsInfo.SettingsType); break; case MauiSettingsActions.Save: // Get the value from the settingsObject @@ -577,7 +612,10 @@ 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, bool keepEncrypted = false) + static async Task ProcessSettingsInfoAsync( + MauiSettingsMemberInfo settingsObjectInfo, MauiSettingsInfo settingsInfo, MauiSettingsActions mode, MauiSettingsTarget target, + bool secureOnly = false, bool useValueFromSettingsInfo = false, string? key = null, bool keepEncrypted = false, bool justTryLoading = false + ) { settingsInfo ??= new(); MauiSettingBaseAttribute? settingBaseAttribute = null; @@ -682,7 +720,8 @@ List settingBaseAttributes // Throw on key missmatch if (string.IsNullOrEmpty(decryptedString) && !string.IsNullOrEmpty(secureString)) throw new Exception($"The secure string is not empty, but the decrypted string is. This indicates a key missmatch!"); - MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, decryptedString, settingsInfo.SettingsType); + if (!justTryLoading) + MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, decryptedString, settingsInfo.SettingsType); } catch(Exception ex) { @@ -697,7 +736,8 @@ List settingBaseAttributes } } // Sets the loaded value back to the settingsObject - MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, settingsInfo.Value, settingsInfo.SettingsType); + if (!justTryLoading) + MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, settingsInfo.Value, settingsInfo.SettingsType); break; case MauiSettingsActions.Save: // Get the value from the settingsObject From 9d685d5e41c94390f4bd051a40fe62ab5ea17767 Mon Sep 17 00:00:00 2001 From: Andreas Date: Thu, 4 Apr 2024 15:25:10 +0200 Subject: [PATCH 3/6] Update MauiSettingsGeneric.cs --- src/MauiSettings/MauiSettingsGeneric.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/MauiSettings/MauiSettingsGeneric.cs b/src/MauiSettings/MauiSettingsGeneric.cs index d4419ab..d7e5aff 100644 --- a/src/MauiSettings/MauiSettingsGeneric.cs +++ b/src/MauiSettings/MauiSettingsGeneric.cs @@ -105,16 +105,16 @@ public static Task LoadSettingsAsync(object settings, string? key = null) await GetClassMetaAsync(settings: settings, mode: MauiSettingsActions.Load, key: key); }); - public static Task TryLoadSettingsAsync(string? key = null) + public static Task TryLoadSettingsAsync(string? key = null, bool justTryLoading = true) => Task.Run(async delegate { - return await TryLoadSettingsAsync(settings: SettingsObject, key: key); + return await TryLoadSettingsAsync(settings: SettingsObject, key: key, justTryLoading: justTryLoading); }); - public static Task TryLoadSettingsAsync(object settings, string? key = null) + public static Task TryLoadSettingsAsync(object settings, string? key = null, bool justTryLoading = true) => Task.Run(async delegate { - return await GetClassMetaAsync(settings: settings, mode: MauiSettingsActions.Load, key: key, justTryLoading: true); + return await GetClassMetaAsync(settings: settings, mode: MauiSettingsActions.Load, key: key, justTryLoading: justTryLoading); }); public static Task LoadSecureSettingsAsync(string? key = null) @@ -135,7 +135,7 @@ public static Task LoadSettingsAsync(Dictionary> dic await LoadSettingsAsync(settings: SettingsObject, dictionary: dictionary, save: save, key: key); }); - public static Task TryLoadSettingsAsync(Dictionary> dictionary, string? key = null) + public static Task TryLoadSettingsAsync(Dictionary> dictionary, string? key = null, bool justTryLoading = true) => Task.Run(async delegate { return await TryLoadSettingsAsync(settings: SettingsObject, dictionary: dictionary, key: key); @@ -147,10 +147,10 @@ public static Task LoadSettingsAsync(string settingsKey, Tuple dat await LoadSettingsAsync(settings: SettingsObject, dictionary: new() { { settingsKey, data } }, save: save, key: key); }); - public static Task TryLoadSettingsAsync(string settingsKey, Tuple data, string? key = null) + public static Task TryLoadSettingsAsync(string settingsKey, Tuple data, string? key = null, bool justTryLoading = true) => Task.Run(async delegate { - return await TryLoadSettingsAsync(settings: SettingsObject, dictionary: new() { { settingsKey, data } }, key: key); + return await TryLoadSettingsAsync(settings: SettingsObject, dictionary: new() { { settingsKey, data } }, key: key, justTryLoading: justTryLoading); }); public static Task LoadSettingsAsync(object settings, Dictionary> dictionary, bool save = true, string? key = null) @@ -160,10 +160,11 @@ public static Task LoadSettingsAsync(object settings, Dictionary TryLoadSettingsAsync(object settings, Dictionary> dictionary, string? key = null) + public static Task TryLoadSettingsAsync(object settings, Dictionary> dictionary, string? key = null, bool justTryLoading = true) => Task.Run(async delegate { - return await GetMetaFromDictionaryAsync(settings: settings, dictionary: dictionary, mode: MauiSettingsActions.Load, secureOnly: false, key: key, justTryLoading: true); + return await GetMetaFromDictionaryAsync( + settings: settings, dictionary: dictionary, mode: MauiSettingsActions.Load, secureOnly: false, key: key, justTryLoading: justTryLoading); }); #endregion @@ -718,8 +719,10 @@ List settingBaseAttributes { string decryptedString = EncryptionManager.DecryptStringFromBase64String(secureString, key); // Throw on key missmatch + /* if (string.IsNullOrEmpty(decryptedString) && !string.IsNullOrEmpty(secureString)) throw new Exception($"The secure string is not empty, but the decrypted string is. This indicates a key missmatch!"); + */ if (!justTryLoading) MauiSettingsObjectHelper.SetSettingValue(settingsObjectInfo.Info, settingsObjectInfo.OrignalSettingsObject, decryptedString, settingsInfo.SettingsType); } @@ -960,8 +963,10 @@ List settingBaseAttributes { string decryptedString = EncryptionManager.DecryptStringFromBase64String(secureString, key); // Throw on key missmatch + /* if (string.IsNullOrEmpty(decryptedString) && !string.IsNullOrEmpty(secureString)) throw new Exception($"The secure string is not empty, but the decrypted string is. This indicates a key missmatch!"); + */ settingsInfo.Value = decryptedString; } catch (Exception ex) From 7f4e74af2cd9a15f6da0851bb229642c6cedc563 Mon Sep 17 00:00:00 2001 From: Andreas Date: Thu, 4 Apr 2024 18:44:53 +0200 Subject: [PATCH 4/6] Update MauiSettingsGeneric.cs --- src/MauiSettings/MauiSettingsGeneric.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/MauiSettings/MauiSettingsGeneric.cs b/src/MauiSettings/MauiSettingsGeneric.cs index d7e5aff..bf9d4b2 100644 --- a/src/MauiSettings/MauiSettingsGeneric.cs +++ b/src/MauiSettings/MauiSettingsGeneric.cs @@ -758,7 +758,7 @@ List settingBaseAttributes { if (settingsInfo.Value is string secureString) { - if (settingsInfo.Encrypt) + if (settingsInfo.Encrypt && !string.IsNullOrEmpty(secureString)) { if (string.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key)); @@ -823,8 +823,10 @@ List settingBaseAttributes { if (settingsInfo.Value is string secureString) { - if (settingsInfo.Encrypt && !string.IsNullOrEmpty(key)) + if (settingsInfo.Encrypt && !string.IsNullOrEmpty(secureString)) { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); // Encrypt string try { @@ -877,9 +879,11 @@ List settingBaseAttributes { if (settingsInfo.Value is string secureString) { - if (settingsInfo.Encrypt && !string.IsNullOrEmpty(key)) + if (settingsInfo.Encrypt && !string.IsNullOrEmpty(secureString)) { - // Decrypt string + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + // Encrypt string try { string encryptedString = EncryptionManager.EncryptStringToBase64String(secureString, key); From c46ec2e074be3fbb79ffd2a6567b709f216ed58a Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 7 Apr 2024 19:15:48 +0200 Subject: [PATCH 5/6] Update MauiSettingsGeneric.cs --- src/MauiSettings/MauiSettingsGeneric.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/MauiSettings/MauiSettingsGeneric.cs b/src/MauiSettings/MauiSettingsGeneric.cs index bf9d4b2..b9fd7b0 100644 --- a/src/MauiSettings/MauiSettingsGeneric.cs +++ b/src/MauiSettings/MauiSettingsGeneric.cs @@ -300,22 +300,22 @@ public static async Task>> ToCo return setting; } - public static Task>> ToSettingsTupleAsync(Expression> value) - => ToSettingsTupleAsync(settings: SettingsObject, value: value); + public static Task>> ToSettingsTupleAsync(Expression> value, string? key = null) + => ToSettingsTupleAsync(settings: SettingsObject, value: value, key: key); - public static async Task>> ToSettingsTupleAsync(object? settings, Expression> value) + public static async Task>> ToSettingsTupleAsync(object? settings, Expression> value, string? key = null) { - MauiSettingsInfo? info = await GetExpressionMetaAsKeyValuePairAsync(settings: settings, value: value); + MauiSettingsInfo? info = await GetExpressionMetaAsKeyValuePairAsync(settings: settings, value: value, key: key); return new(info.Name, new(info.Value, info.SettingsType)); } #endregion #region Encryption - public static Task ExhangeKeyAsync(string newKey, string? oldKey = null) + public static Task ExhangeKeyAsync(string newKey, string? oldKey = null, bool reloadSettings = false) => Task.Run(async delegate { - await LoadSecureSettingsAsync(key: oldKey); + if (reloadSettings) await LoadSecureSettingsAsync(key: oldKey); await SaveSettingsAsync(key: newKey); }); @@ -406,7 +406,10 @@ static async Task GetMetaFromDictionaryAsync(object settings, Dictionary(object settings, Expression Date: Mon, 8 Apr 2024 06:34:02 +0200 Subject: [PATCH 6/6] Cleanup --- src/MauiSettings/Helper/MauiSettingsHelper.cs | 9 +++++---- src/MauiSettings/Utilities/MauiSettingNameFormater.cs | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/MauiSettings/Helper/MauiSettingsHelper.cs b/src/MauiSettings/Helper/MauiSettingsHelper.cs index 44fcde6..e131266 100644 --- a/src/MauiSettings/Helper/MauiSettingsHelper.cs +++ b/src/MauiSettings/Helper/MauiSettingsHelper.cs @@ -16,7 +16,7 @@ internal class MauiSettingsHelper * - String * - DateTime */ - public static T GetSettingsValue(string key, T defaultValue) + public static T? GetSettingsValue(string key, T defaultValue) { object? returnValue = null; try @@ -73,17 +73,18 @@ public static T GetSettingsValue(string key, T defaultValue) //return (T)Convert.ChangeType(returnValue, typeof(T)); } - public static T ChangeSettingsType(object settingsValue, T defaultValue) => (T)Convert.ChangeType(settingsValue, typeof(T)); + public static T? ChangeSettingsType(object settingsValue, T defaultValue) => (T)Convert.ChangeType(settingsValue, typeof(T)) ?? default; // Docs: https://docs.microsoft.com/en-us/dotnet/maui/platform-integration/storage/secure-storage?tabs=ios // Only string is allowed for secure storage - public static async Task GetSecureSettingsValueAsync(string key, string defaultValue) + public static async Task GetSecureSettingsValueAsync(string key, string? defaultValue) { + defaultValue ??= string.Empty; string? settingsObject = await SecureStorage.Default.GetAsync(key); return settingsObject == null ? defaultValue : settingsObject; } - public static void SetSettingsValue(string key, object value) + public static void SetSettingsValue(string key, object? value) { switch (value) { diff --git a/src/MauiSettings/Utilities/MauiSettingNameFormater.cs b/src/MauiSettings/Utilities/MauiSettingNameFormater.cs index 3dc046d..c47af35 100644 --- a/src/MauiSettings/Utilities/MauiSettingNameFormater.cs +++ b/src/MauiSettings/Utilities/MauiSettingNameFormater.cs @@ -16,7 +16,9 @@ internal class MauiSettingNameFormater public const string Version = "v1"; public const string NamePrefix = "AR"; #endregion - public static string GetFullSettingName(Type settingsType, MemberInfo mi, MauiSettingBaseAttribute baseSettingAttr) + + #region Methods + public static string GetFullSettingName(Type? settingsType, MemberInfo mi, MauiSettingBaseAttribute? baseSettingAttr) { string name; if (string.IsNullOrEmpty(baseSettingAttr?.Name)) @@ -30,5 +32,7 @@ public static string GetFullSettingName(Type settingsType, MemberInfo mi, MauiSe } return $"{NamePrefix}_{Version}_{name}{(settingsType == null ? "" : $"_{settingsType}")}"; } + public static string GetSettingsNamePrefix() => $"{NamePrefix}_{Version}"; + #endregion } }