diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs index f025276b5e..d0ef3247f4 100644 --- a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs +++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs @@ -2,15 +2,46 @@ { public class SettingDefinition { + /// + /// Unique name of the setting. + /// public string Name { get; } + /// + /// Default value of the setting. + /// public string DefaultValue { get; set; } - public SettingDefinition(string name, string defaultValue = null) + /// + /// Can clients see this setting and it's value. + /// It maybe dangerous for some settings to be visible to clients (such as email server password). + /// Default: false. + /// + public bool IsVisibleToClients { get; set; } + + /// + /// Is this setting inherited from parent scopes. + /// Default: True. + /// + public bool IsInherited { get; set; } + + /// + /// Can be used to store a custom object related to this setting. + /// + public object CustomData { get; set; } + + public SettingDefinition( + string name, + string defaultValue = null, + bool isVisibleToClients = false, + bool isInherited = true, + object customData = null) { Name = name; - DefaultValue = defaultValue; + IsVisibleToClients = isVisibleToClients; + IsInherited = isInherited; + CustomData = customData; } } } \ No newline at end of file diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs index ca4108f554..23fff238fc 100644 --- a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs +++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs @@ -48,7 +48,7 @@ namespace Volo.Abp.Settings { Check.NotNull(name, nameof(name)); Check.NotNull(entityType, nameof(entityType)); - + return GetOrNullInternalAsync(name, entityType, entityId, fallback); } @@ -63,7 +63,7 @@ namespace Volo.Abp.Settings providers = providers.SkipWhile(c => c.EntityType != entityType); } - if (!fallback) + if (!fallback || !setting.IsInherited) { providers = providers.TakeWhile(c => c.EntityType == entityType); } @@ -114,16 +114,29 @@ namespace Volo.Abp.Settings providers = providers.TakeWhile(c => c.EntityType == entityType); } - providers = providers.Reverse(); + var providerList = providers.Reverse().ToList(); - foreach (var provider in providers) + if (providerList.Any()) { foreach (var setting in settingDefinitions) { - var value = await provider.GetOrNullAsync(setting, entityId); - if (value != null) + if (setting.IsInherited) { - settingValues[setting.Name] = new SettingValue(setting.Name, value); + foreach (var provider in providerList) + { + var value = await provider.GetOrNullAsync(setting, entityId); + if (value != null) + { + settingValues[setting.Name] = new SettingValue(setting.Name, value); + } + } + } + else + { + settingValues[setting.Name] = new SettingValue( + setting.Name, + await providerList[0].GetOrNullAsync(setting, entityId) + ); } } } @@ -148,9 +161,9 @@ namespace Volo.Abp.Settings return; } - //Clear the value if it's same as it's fallback value - if (providers.Count > 1 && !forceToSet && value != null) + if (providers.Count > 1 && !forceToSet && setting.IsInherited && value != null) { + //Clear the value if it's same as it's fallback value var fallbackValue = await GetOrNullInternalAsync(name, providers[1].EntityType, entityId); if (fallbackValue == value) { @@ -160,7 +173,7 @@ namespace Volo.Abp.Settings providers = providers .TakeWhile(p => p.EntityType == entityType) - .ToList(); + .ToList(); //Getting list for case of there are more than one provider with same EntityType if (value == null) { diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs new file mode 100644 index 0000000000..f9fa53ea4c --- /dev/null +++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManagerSyncExtensions.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.Settings +{ + public static class SettingManagerSyncExtensions + { + //TODO: Add sync extension methods for all setting manager methods. + //TODO: Also add sync extension methods for all value provider extensions (like GlobalSettingManagerExtensions). + } +} diff --git a/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/AbpIdentityTestDataBuilder.cs b/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/AbpIdentityTestDataBuilder.cs index 06b54bbbd3..5405edf567 100644 --- a/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/AbpIdentityTestDataBuilder.cs +++ b/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/AbpIdentityTestDataBuilder.cs @@ -26,6 +26,9 @@ namespace Volo.Abp.Settings _settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySetting2", "default-store-value", GlobalSettingValueProvider.DefaultEntityType)); _settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySetting2", "user1-store-value", UserSettingValueProvider.DefaultEntityType, User1Id.ToString())); _settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySetting2", "user2-store-value", UserSettingValueProvider.DefaultEntityType, User2Id.ToString())); + + _settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySettingWithoutInherit", "default-store-value", GlobalSettingValueProvider.DefaultEntityType)); + _settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySettingWithoutInherit", "user1-store-value", UserSettingValueProvider.DefaultEntityType, User1Id.ToString())); } } } \ No newline at end of file diff --git a/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingManager_User_Tests.cs b/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingManager_User_Tests.cs index 49e5201562..621c31f0a9 100644 --- a/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingManager_User_Tests.cs +++ b/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/SettingManager_User_Tests.cs @@ -100,8 +100,9 @@ namespace Volo.Abp.Settings public async Task Should_Get_All_From_Store_For_Given_User_Without_Fallback() { var settingValues = await _settingManager.GetAllForUserAsync(AbpIdentityTestDataBuilder.User1Id, fallback: false); - settingValues.Count.ShouldBe(1); settingValues.ShouldContain(sv => sv.Name == "MySetting2" && sv.Value == "user1-store-value"); + settingValues.ShouldContain(sv => sv.Name == "MySettingWithoutInherit" && sv.Value == "user1-store-value"); + settingValues.ShouldNotContain(sv => sv.Name == "MySetting1"); } [Fact] @@ -172,5 +173,13 @@ namespace Volo.Abp.Settings (await _settingManager.GetOrNullForUserAsync("MySetting2", AbpIdentityTestDataBuilder.User1Id)) .ShouldBe("default-store-value"); } + + [Fact] + public async Task Should_Get_For_Given_User_For_Non_Inherited_Setting() + { + (await _settingManager.GetOrNullForUserAsync("MySettingWithoutInherit", AbpIdentityTestDataBuilder.User1Id)).ShouldBe("user1-store-value"); + (await _settingManager.GetOrNullForUserAsync("MySettingWithoutInherit", AbpIdentityTestDataBuilder.User2Id)).ShouldBeNull(); //Does not inherit! + (await _settingManager.GetOrNullGlobalAsync("MySettingWithoutInherit")).ShouldBe("default-store-value"); + } } } \ No newline at end of file diff --git a/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/TestSettingDefinitionProvider.cs b/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/TestSettingDefinitionProvider.cs index 8d26340096..761b383448 100644 --- a/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/TestSettingDefinitionProvider.cs +++ b/test/Volo.Abp.Settings.Tests/Volo/Abp/Settings/TestSettingDefinitionProvider.cs @@ -6,6 +6,7 @@ { context.Add(new SettingDefinition("MySetting1")); context.Add(new SettingDefinition("MySetting2")); + context.Add(new SettingDefinition("MySettingWithoutInherit", isInherited: false)); context.Add(new SettingDefinition("SettingNotSetInStore", defaultValue: "default-value")); } }