diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs new file mode 100644 index 0000000000..9205f375dc --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionContext.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.Authorization.Permissions +{ + public interface IPermissionDefinitionContext + { + PermissionDefinition GetOrNull(string name); + + void Add(params PermissionDefinition[] definitions); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs new file mode 100644 index 0000000000..6ba0d29276 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionManager.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using JetBrains.Annotations; + +namespace Volo.Abp.Authorization.Permissions +{ + public interface IPermissionDefinitionManager + { + [NotNull] + PermissionDefinition Get([NotNull] string name); + + IReadOnlyList GetAll(); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionProvider.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionProvider.cs new file mode 100644 index 0000000000..ef92125595 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionDefinitionProvider.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Authorization.Permissions +{ + public interface IPermissionDefinitionProvider + { + void Define(IPermissionDefinitionContext context); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionManager.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionManager.cs new file mode 100644 index 0000000000..7e587f7cd0 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionManager.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.Authorization.Permissions +{ + //TODO: Change fallback to inherit? + + public interface IPermissionManager + { + Task IsGrantedAsync([NotNull]string name); + + Task IsGrantedAsync([NotNull]string name, [NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true); + + Task> GetAllAsync(); + + Task> GetAllAsync([NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true); + + Task SetAsync([NotNull] string name, bool? isGranted, [NotNull] string providerName, [CanBeNull] string providerKey, bool forceToSet = false); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionStore.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionStore.cs new file mode 100644 index 0000000000..46fa9c3b8e --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionStore.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.Authorization.Permissions +{ + public interface IPermissionStore + { + Task GetOrNullAsync([NotNull] string name, [CanBeNull] string providerName, [CanBeNull] string providerKey); + + Task SetAsync([NotNull] string name, bool isGranted, [CanBeNull] string providerName, [CanBeNull] string providerKey); + + Task> GetListAsync([CanBeNull] string providerName, [CanBeNull] string providerKey); + + Task DeleteAsync([NotNull] string name, [CanBeNull]string providerName, [CanBeNull]string providerKey); + } +} diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs new file mode 100644 index 0000000000..282f3d59cf --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/IPermissionValueProvider.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace Volo.Abp.Authorization.Permissions +{ + public interface IPermissionValueProvider + { + string Name { get; } + + Task IsGrantedAsync([NotNull] PermissionDefinition permission, [CanBeNull] string providerKey); + + Task SetAsync([NotNull] PermissionDefinition permission, bool isGranted, [CanBeNull] string providerKey); + + Task ClearAsync([NotNull] PermissionDefinition permission, [CanBeNull] string providerKey); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullPermissionStore.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullPermissionStore.cs new file mode 100644 index 0000000000..6aab68c7d3 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/NullPermissionStore.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.Permissions +{ + public class NullPermissionStore : IPermissionStore, ISingletonDependency + { + public ILogger Logger { get; set; } + + public NullPermissionStore() + { + Logger = NullLogger.Instance; + } + + public Task GetOrNullAsync(string name, string providerName, string providerKey) + { + return Task.FromResult((bool?)null); + } + + public Task SetAsync(string name, bool isGranted, string providerName, string providerKey) + { + Logger.LogWarning($"Setting the grant value for {name} is not possible because current permission store is {nameof(NullPermissionStore)}"); + return Task.CompletedTask; + } + + public Task> GetListAsync(string providerName, string providerKey) + { + return Task.FromResult(new List()); + } + + public Task DeleteAsync(string name, string providerName, string providerKey) + { + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs new file mode 100644 index 0000000000..b4696132e9 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinition.cs @@ -0,0 +1,28 @@ +namespace Volo.Abp.Authorization.Permissions +{ + public class PermissionDefinition + { + /// + /// Unique name of the permission. + /// + public string Name { get; } + + /// + /// Parent of this permission if one exists. + /// If set, this permission can be granted only if parent is granted. + /// + public PermissionDefinition Parent { get; private set; } + + //TODO: Add Properties dictionary for custom stuff + + public PermissionDefinition(string name) + { + Name = name; + } + + public PermissionDefinition CreateChild(string name) + { + return new PermissionDefinition(name) {Parent = this}; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs new file mode 100644 index 0000000000..6328779e91 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionContext.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Volo.Abp.Authorization.Permissions +{ + public class PermissionDefinitionContext : IPermissionDefinitionContext + { + protected Dictionary Permissions { get; } + + public PermissionDefinitionContext(Dictionary permissions) + { + Permissions = permissions; + } + + public virtual PermissionDefinition GetOrNull(string name) + { + return Permissions.GetOrDefault(name); + } + + public virtual IReadOnlyList GetAll() + { + return Permissions.Values.ToImmutableList(); + } + + public virtual void Add(params PermissionDefinition[] definitions) + { + if (definitions.IsNullOrEmpty()) + { + return; + } + + foreach (var definition in definitions) + { + Permissions[definition.Name] = definition; + } + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs new file mode 100644 index 0000000000..ad580961d0 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionManager.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.Permissions +{ + public class PermissionDefinitionManager : IPermissionDefinitionManager, ISingletonDependency + { + protected Lazy> Providers { get; } + + protected Lazy> PermissionDefinitions { get; } + + protected PermissionOptions Options { get; } + + private readonly IServiceProvider _serviceProvider; + + public PermissionDefinitionManager( + IOptions options, + IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + Options = options.Value; + + Providers = new Lazy>(CreatePermissionProviders, true); + PermissionDefinitions = new Lazy>(CreatePermissionDefinitions, true); + } + + public virtual PermissionDefinition Get(string name) + { + Check.NotNull(name, nameof(name)); + + var permission = GetOrNull(name); + + if (permission == null) + { + throw new AbpException("Undefined permission: " + name); + } + + return permission; + } + + public virtual IReadOnlyList GetAll() + { + return PermissionDefinitions.Value.Values.ToImmutableList(); + } + + public virtual PermissionDefinition GetOrNull(string name) + { + return PermissionDefinitions.Value.GetOrDefault(name); + } + + protected virtual List CreatePermissionProviders() + { + return Options + .DefinitionProviders + .Select(p => _serviceProvider.GetRequiredService(p) as IPermissionDefinitionProvider) + .ToList(); + } + + protected virtual IDictionary CreatePermissionDefinitions() + { + var permissions = new Dictionary(); + + foreach (var provider in Providers.Value) + { + provider.Define(new PermissionDefinitionContext(permissions)); + } + + return permissions; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionProvider.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionProvider.cs new file mode 100644 index 0000000000..fb17c4369d --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionDefinitionProvider.cs @@ -0,0 +1,9 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.Permissions +{ + public abstract class PermissionDefinitionProvider : IPermissionDefinitionProvider, ISingletonDependency + { + public abstract void Define(IPermissionDefinitionContext context); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGrantInfo.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGrantInfo.cs new file mode 100644 index 0000000000..15517f624e --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionGrantInfo.cs @@ -0,0 +1,19 @@ +using JetBrains.Annotations; + +namespace Volo.Abp.Authorization.Permissions +{ + public class PermissionGrantInfo + { + public string Name { get; } + + public bool IsGranted { get; } + + public PermissionGrantInfo([NotNull] string name, bool isGranted) + { + Check.NotNull(name, nameof(name)); + + Name = name; + IsGranted = isGranted; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionManager.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionManager.cs new file mode 100644 index 0000000000..38df3bacac --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionManager.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.Permissions +{ + public class PermissionManager : IPermissionManager, ISingletonDependency + { + protected IPermissionDefinitionManager PermissionDefinitionManager { get; } + + protected Lazy> Providers { get; } + + protected PermissionOptions Options { get; } + + protected IPermissionStore PermissionStore { get; } + + public PermissionManager( + IOptions options, + IServiceProvider serviceProvider, + IPermissionDefinitionManager permissionDefinitionManager, + IPermissionStore permissionStore) + { + PermissionStore = permissionStore; + PermissionDefinitionManager = permissionDefinitionManager; + Options = options.Value; + + Providers = new Lazy>( + () => Options + .ValueProviders + .Select(c => serviceProvider.GetRequiredService(c) as IPermissionValueProvider) + .ToList(), + true + ); + } + + public virtual Task IsGrantedAsync(string name) + { + Check.NotNull(name, nameof(name)); + + return IsGrantedInternalAsync(name, null, null); + } + + public virtual Task IsGrantedAsync(string name, string providerName, string providerKey, bool fallback = true) + { + Check.NotNull(name, nameof(name)); + Check.NotNull(providerName, nameof(providerName)); + + return IsGrantedInternalAsync(name, providerName, providerKey, fallback); + } + + public virtual async Task IsGrantedInternalAsync(string name, string providerName, string providerKey, bool fallback = true) + { + var permission = PermissionDefinitionManager.Get(name); + var providers = Enumerable + .Reverse(Providers.Value); + + if (providerName != null) + { + providers = providers.SkipWhile(c => c.Name != providerName); + } + + if (!fallback) + { + providers = providers.TakeWhile(c => c.Name == providerName); + } + + foreach (var provider in providers) + { + var value = await provider.IsGrantedAsync(permission, providerKey); + if (value != null) + { + return value.Value; + } + } + + return false; + } + + public virtual async Task> GetAllAsync() + { + var permissionGrantInfos = new Dictionary(); + var permissionDefinitions = PermissionDefinitionManager.GetAll(); + + foreach (var provider in Providers.Value) + { + foreach (var permission in permissionDefinitions) + { + var value = await provider.IsGrantedAsync(permission, null); + if (value != null) + { + permissionGrantInfos[permission.Name] = new PermissionGrantInfo(permission.Name, value.Value); + } + } + } + + return permissionGrantInfos.Values.ToList(); + } + + public virtual async Task> GetAllAsync(string providerName, string providerKey, bool fallback = true) + { + Check.NotNull(providerName, nameof(providerName)); + + var permissionGrantInfos = new Dictionary(); + var permissionDefinitions = PermissionDefinitionManager.GetAll(); + var providers = Enumerable.Reverse(Providers.Value) + .SkipWhile(c => c.Name != providerName); + + if (!fallback) + { + providers = providers.TakeWhile(c => c.Name == providerName); + } + + var providerList = providers.Reverse().ToList(); + + if (providerList.Any()) + { + foreach (var permission in permissionDefinitions) + { + foreach (var provider in providerList) + { + var value = await provider.IsGrantedAsync(permission, providerKey); + if (value != null) + { + permissionGrantInfos[permission.Name] = new PermissionGrantInfo(permission.Name, value.Value); + } + } + } + } + + return permissionGrantInfos.Values.ToList(); + } + + public virtual async Task SetAsync(string name, bool? isGranted, string providerName, string providerKey, bool forceToSet = false) + { + Check.NotNull(name, nameof(name)); + Check.NotNull(providerName, nameof(providerName)); + + var permission = PermissionDefinitionManager.Get(name); + + var providers = Enumerable + .Reverse(Providers.Value) + .SkipWhile(p => p.Name != providerName) + .ToList(); + + if (!providers.Any()) + { + return; + } + + if (providers.Count > 1 && !forceToSet) + { + //Clear the value if it's same as it's fallback value + var fallbackValue = await IsGrantedInternalAsync(name, providers[1].Name, providerKey); + if (fallbackValue == isGranted) + { + isGranted = null; + } + } + + providers = providers + .TakeWhile(p => p.Name == providerName) + .ToList(); //Getting list for case of there are more than one provider with same EntityType + + if (isGranted == null) + { + foreach (var provider in providers) + { + await provider.ClearAsync(permission, providerKey); + } + } + else + { + foreach (var provider in providers) + { + await provider.SetAsync(permission, isGranted.Value, providerKey); + } + } + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionManagerSyncExtensions.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionManagerSyncExtensions.cs new file mode 100644 index 0000000000..eac6e9be37 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionManagerSyncExtensions.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.Authorization.Permissions +{ + public static class PermissionManagerSyncExtensions + { + //TODO: Add sync extension methods for all permission manager methods. + //TODO: Also add sync extension methods for all value provider extensions. + } +} diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionOptions.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionOptions.cs new file mode 100644 index 0000000000..30c1170e49 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionOptions.cs @@ -0,0 +1,17 @@ +using Volo.Abp.Collections; + +namespace Volo.Abp.Authorization.Permissions +{ + public class PermissionOptions + { + public ITypeList DefinitionProviders { get; } + + public ITypeList ValueProviders { get; } + + public PermissionOptions() + { + DefinitionProviders = new TypeList(); + ValueProviders = new TypeList(); + } + } +} diff --git a/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs new file mode 100644 index 0000000000..d04086db01 --- /dev/null +++ b/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/PermissionValueProvider.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Authorization.Permissions +{ + public abstract class PermissionValueProvider : IPermissionValueProvider, ISingletonDependency + { + public abstract string Name { get; } + + protected IPermissionStore PermissionStore { get; } + + protected PermissionValueProvider(IPermissionStore permissionStore) + { + PermissionStore = permissionStore; + } + + public abstract Task IsGrantedAsync(PermissionDefinition permission, string providerKey); + + public abstract Task SetAsync(PermissionDefinition permission, bool isGranted, string providerKey); + + public abstract Task ClearAsync(PermissionDefinition permission, string providerKey); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs index ade721431d..705f428792 100644 --- a/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs +++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/NullSettingStore.cs @@ -1,11 +1,20 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Settings { public class NullSettingStore : ISettingStore, ISingletonDependency { + public ILogger Logger { get; set; } + + public NullSettingStore() + { + Logger = NullLogger.Instance; + } + public Task GetOrNullAsync(string name, string providerName, string providerKey) { return Task.FromResult((string) null); @@ -13,6 +22,7 @@ namespace Volo.Abp.Settings public Task SetAsync(string name, string value, string providerName, string providerKey) { + Logger.LogWarning($"Setting the value for {name} is not possible because current setting store is {nameof(NullSettingStore)}"); return Task.CompletedTask; } diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs index 2de5a690a7..74a4a48f6c 100644 --- a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs +++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs @@ -30,6 +30,8 @@ /// public object CustomData { get; set; } + //TODO: Add Properties dictionary for custom stuff (and remove CustomData) + public SettingDefinition( string name, string defaultValue = null, diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs index 4615d1c147..7241d3654d 100644 --- a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs +++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinitionManager.cs @@ -33,17 +33,17 @@ namespace Volo.Abp.Settings { Check.NotNull(name, nameof(name)); - var settingDefinition = GetOrNull(name); + var setting = GetOrNull(name); - if (settingDefinition == null) + if (setting == null) { throw new AbpException("Undefined setting: " + name); } - return settingDefinition; + return setting; } - public IReadOnlyList GetAll() + public virtual IReadOnlyList GetAll() { return SettingDefinitions.Value.Values.ToImmutableList(); } @@ -53,7 +53,7 @@ namespace Volo.Abp.Settings return SettingDefinitions.Value.GetOrDefault(name); } - private List CreateSettingProviders() + protected virtual List CreateSettingProviders() { return Options .DefinitionProviders @@ -61,7 +61,7 @@ namespace Volo.Abp.Settings .ToList(); } - private IDictionary CreateSettingDefinitions() + protected virtual IDictionary CreateSettingDefinitions() { var settings = new Dictionary(); diff --git a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs index fb3f6cca0f..d75eb6ecee 100644 --- a/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs +++ b/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingManager.cs @@ -16,15 +16,11 @@ namespace Volo.Abp.Settings protected SettingOptions Options { get; } - protected ISettingStore SettingStore { get; } - public SettingManager( IOptions options, IServiceProvider serviceProvider, - ISettingDefinitionManager settingDefinitionManager, - ISettingStore settingStore) + ISettingDefinitionManager settingDefinitionManager) { - SettingStore = settingStore; SettingDefinitionManager = settingDefinitionManager; Options = options.Value;