Merge pull request #204 from aspnetzero/setting-system

Setting system
pull/206/head
Halil İbrahim Kalkan 7 years ago committed by GitHub
commit 3488bab759
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -244,7 +244,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy.Appli
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy.Web", "src\Volo.Abp.MultiTenancy.Web\Volo.Abp.MultiTenancy.Web.csproj", "{0808036D-065B-4525-BF30-CBCEA062F8E9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MultiTenancy.HttpApi", "src\Volo.Abp.MultiTenancy.HttpApi\Volo.Abp.MultiTenancy.HttpApi.csproj", "{06423FAC-67E2-4B7C-B29F-39578F460C4F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy.HttpApi", "src\Volo.Abp.MultiTenancy.HttpApi\Volo.Abp.MultiTenancy.HttpApi.csproj", "{06423FAC-67E2-4B7C-B29F-39578F460C4F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Settings", "src\Volo.Abp.Settings\Volo.Abp.Settings.csproj", "{CB6FD800-B6C5-4C2A-8920-B8A29C74AEF6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Settings.EntityFrameworkCore", "src\Volo.Abp.Settings.EntityFrameworkCore\Volo.Abp.Settings.EntityFrameworkCore.csproj", "{1DCD9600-215A-4A94-AEFD-577568D62633}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Settings.Domain", "src\Volo.Abp.Settings.Domain\Volo.Abp.Settings.Domain.csproj", "{837BC537-3AEC-4F6D-9D64-9704F64D0E1E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Settings.Tests", "test\Volo.Abp.Settings.Tests\Volo.Abp.Settings.Tests.csproj", "{61422EC8-8FFB-48EA-B4B5-527E29077930}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Settings.Domain.Shared", "src\Volo.Abp.Settings.Domain.Shared\Volo.Abp.Settings.Domain.Shared.csproj", "{27F990E2-6820-4159-B54A-59C8ADED8D28}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -640,6 +650,26 @@ Global
{06423FAC-67E2-4B7C-B29F-39578F460C4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06423FAC-67E2-4B7C-B29F-39578F460C4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06423FAC-67E2-4B7C-B29F-39578F460C4F}.Release|Any CPU.Build.0 = Release|Any CPU
{CB6FD800-B6C5-4C2A-8920-B8A29C74AEF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB6FD800-B6C5-4C2A-8920-B8A29C74AEF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB6FD800-B6C5-4C2A-8920-B8A29C74AEF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB6FD800-B6C5-4C2A-8920-B8A29C74AEF6}.Release|Any CPU.Build.0 = Release|Any CPU
{1DCD9600-215A-4A94-AEFD-577568D62633}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1DCD9600-215A-4A94-AEFD-577568D62633}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1DCD9600-215A-4A94-AEFD-577568D62633}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1DCD9600-215A-4A94-AEFD-577568D62633}.Release|Any CPU.Build.0 = Release|Any CPU
{837BC537-3AEC-4F6D-9D64-9704F64D0E1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{837BC537-3AEC-4F6D-9D64-9704F64D0E1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{837BC537-3AEC-4F6D-9D64-9704F64D0E1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{837BC537-3AEC-4F6D-9D64-9704F64D0E1E}.Release|Any CPU.Build.0 = Release|Any CPU
{61422EC8-8FFB-48EA-B4B5-527E29077930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61422EC8-8FFB-48EA-B4B5-527E29077930}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61422EC8-8FFB-48EA-B4B5-527E29077930}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61422EC8-8FFB-48EA-B4B5-527E29077930}.Release|Any CPU.Build.0 = Release|Any CPU
{27F990E2-6820-4159-B54A-59C8ADED8D28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27F990E2-6820-4159-B54A-59C8ADED8D28}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27F990E2-6820-4159-B54A-59C8ADED8D28}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27F990E2-6820-4159-B54A-59C8ADED8D28}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -759,6 +789,11 @@ Global
{B65973F1-9EE0-4914-B6F2-D88F753E1D21} = {3CE22CAC-4B27-4EEC-A35E-C01219ED6E99}
{0808036D-065B-4525-BF30-CBCEA062F8E9} = {CA154803-3589-47B3-B7CB-B18F94FE1EB6}
{06423FAC-67E2-4B7C-B29F-39578F460C4F} = {CA154803-3589-47B3-B7CB-B18F94FE1EB6}
{CB6FD800-B6C5-4C2A-8920-B8A29C74AEF6} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
{1DCD9600-215A-4A94-AEFD-577568D62633} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
{837BC537-3AEC-4F6D-9D64-9704F64D0E1E} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
{61422EC8-8FFB-48EA-B4B5-527E29077930} = {37087D1B-3693-4E96-983D-A69F210BDE53}
{27F990E2-6820-4159-B54A-59C8ADED8D28} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

@ -26,7 +26,7 @@ namespace AbpDesk.EntityFrameworkCore
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureMultiTenancy(MultiTenancyDbContext.TablePrefix, MultiTenancyDbContext.Schema);
modelBuilder.ConfigureMultiTenancy();
//Use different classes to map each entity type, as a better practice?
modelBuilder.Entity<Ticket>(b =>

@ -2,6 +2,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Uow;
@ -17,6 +18,8 @@ namespace Volo.Abp
public ILoggerFactory LoggerFactory { get; set; }
public ICurrentTenant CurrentTenant { get; set; }
protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current;
protected ILogger Logger => _lazyLogger.Value;

@ -59,12 +59,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
}
/// <summary>
/// Configures the schema needed for the identity framework.
/// </summary>
/// <param name="builder">
/// The builder being used to construct the model for this context.
/// </param>
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

@ -1,6 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Grants;
using Volo.Abp.IdentityServer.IdentityResources;
using Volo.Abp.Modularity;
namespace Volo.Abp.IdentityServer.EntityFrameworkCore
@ -14,7 +17,11 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore
services.AddAbpDbContext<IdentityServerDbContext>(options =>
{
options.AddDefaultRepositories<IIdentityServerDbContext>();
options.AddRepository<Client, ClientRepository>();
options.AddRepository<ApiResource, ApiResourceRepository>();
options.AddRepository<IdentityResource, IdentityResourceRepository>();
options.AddRepository<PersistedGrant, PersistentGrantRepository>();
});
services.AddAssemblyOf<AbpIdentityServerEntityFrameworkCoreModule>();

@ -6,6 +6,6 @@ namespace Volo.Abp.Localization
public interface IInheritedResourceTypesProvider
{
[NotNull]
Type[] GetInheritedModuleTypes();
Type[] GetInheritedResourceTypes();
}
}

@ -12,7 +12,7 @@ namespace Volo.Abp.Localization
ResourceTypes = resourceTypes ?? new Type[0];
}
public Type[] GetInheritedModuleTypes()
public virtual Type[] GetInheritedResourceTypes()
{
return ResourceTypes;
}

@ -82,7 +82,7 @@ namespace Volo.Abp.Localization
foreach (var descriptor in descriptors)
{
foreach (var baseResourceType in descriptor.GetInheritedModuleTypes())
foreach (var baseResourceType in descriptor.GetInheritedResourceTypes())
{
BaseResourceTypes.AddIfNotContains(baseResourceType);
}

@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
</ItemGroup>
</Project>

@ -1,14 +1,21 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
namespace Volo.Abp.MultiTenancy
{
[DependsOn(typeof(AbpDataModule))]
[DependsOn(typeof(AbpSettingsModule))]
public class AbpMultiTenancyAbstractionsModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<SettingOptions>(options =>
{
options.ValueProviders.Add<TenantSettingValueProvider>();
});
services.AddAssemblyOf<AbpMultiTenancyAbstractionsModule>();
}
}

@ -21,7 +21,7 @@ namespace Volo.Abp.MultiTenancy
return SetCurrent(id);
}
public IDisposable Clear()
public IDisposable Clear() //TODO: Remove
{
return Change(null);
}

@ -0,0 +1,45 @@
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace Volo.Abp.MultiTenancy
{
public class TenantSettingValueProvider : SettingValueProvider
{
public const string ProviderName = "Tenant";
public override string Name => ProviderName;
protected ICurrentTenant CurrentTenant { get; }
public TenantSettingValueProvider(ISettingStore settingStore, ICurrentTenant currentTenant)
: base(settingStore)
{
CurrentTenant = currentTenant;
}
public override async Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
{
if (providerKey == null)
{
if (CurrentTenant.Id == null)
{
return null;
}
providerKey = CurrentTenant.Id.ToString();
}
return await SettingStore.GetOrNullAsync(setting.Name, Name, providerKey);
}
public override Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
return SettingStore.SetAsync(setting.Name, value, Name, providerKey);
}
public override Task ClearAsync(SettingDefinition setting, string providerKey)
{
return SettingStore.DeleteAsync(setting.Name, Name, providerKey);
}
}
}

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Settings
{
public static class TenantSettingManagerExtensions
{
public static Task<string> GetOrNullForTenantAsync(this ISettingManager settingManager, [NotNull] string name, Guid tenantId, bool fallback = true)
{
return settingManager.GetOrNullAsync(name, TenantSettingValueProvider.ProviderName, tenantId.ToString(), fallback);
}
public static Task<string> GetOrNullForCurrentTenantAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true)
{
return settingManager.GetOrNullAsync(name, TenantSettingValueProvider.ProviderName, null, fallback);
}
public static Task<List<SettingValue>> GetAllForTenantAsync(this ISettingManager settingManager, Guid tenantId, bool fallback = true)
{
return settingManager.GetAllAsync(TenantSettingValueProvider.ProviderName, tenantId.ToString(), fallback);
}
public static Task<List<SettingValue>> GetAllForCurrentTenantAsync(this ISettingManager settingManager, bool fallback = true)
{
return settingManager.GetAllAsync(TenantSettingValueProvider.ProviderName, null, fallback);
}
public static Task SetForTenantAsync(this ISettingManager settingManager, Guid tenantId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false)
{
return settingManager.SetAsync(name, value, TenantSettingValueProvider.ProviderName, tenantId.ToString(), forceToSet);
}
public static Task SetForCurrentTenantAsync(this ISettingManager settingManager, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false)
{
return settingManager.SetAsync(name, value, TenantSettingValueProvider.ProviderName, null, forceToSet);
}
}
}

@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
</ItemGroup>
</Project>

@ -1,14 +1,21 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.Security;
using Volo.Abp.Settings;
namespace Volo.Abp.Session
{
[DependsOn(typeof(AbpSecurityModule))]
[DependsOn(typeof(AbpSettingsModule))]
public class AbpSessionModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.Configure<SettingOptions>(options =>
{
options.ValueProviders.Add<UserSettingValueProvider>();
});
services.AddAssemblyOf<AbpSessionModule>();
}
}

@ -0,0 +1,47 @@
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace Volo.Abp.Session
{
//TODO: Optimization: Get all settings and cache it!
public class UserSettingValueProvider : SettingValueProvider
{
public const string ProviderName = "User";
public override string Name => ProviderName;
protected ICurrentUser CurrentUser { get; }
public UserSettingValueProvider(ISettingStore settingStore, ICurrentUser currentUser)
: base(settingStore)
{
CurrentUser = currentUser;
}
public override async Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
{
if (providerKey == null)
{
if (CurrentUser.Id == null)
{
return null;
}
providerKey = CurrentUser.Id.ToString();
}
return await SettingStore.GetOrNullAsync(setting.Name, Name, providerKey);
}
public override Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
return SettingStore.SetAsync(setting.Name, value, Name, providerKey);
}
public override Task ClearAsync(SettingDefinition setting, string providerKey)
{
return SettingStore.DeleteAsync(setting.Name, Name, providerKey);
}
}
}

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Session;
namespace Volo.Abp.Settings
{
public static class UserSettingManagerExtensions
{
public static Task<string> GetOrNullForUserAsync(this ISettingManager settingManager, [NotNull] string name, Guid userId, bool fallback = true)
{
return settingManager.GetOrNullAsync(name, UserSettingValueProvider.ProviderName, userId.ToString(), fallback);
}
public static Task<string> GetOrNullForCurrentUserAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true)
{
return settingManager.GetOrNullAsync(name, UserSettingValueProvider.ProviderName, null, fallback);
}
public static Task<List<SettingValue>> GetAllForUserAsync(this ISettingManager settingManager, Guid userId, bool fallback = true)
{
return settingManager.GetAllAsync(UserSettingValueProvider.ProviderName, userId.ToString(), fallback);
}
public static Task<List<SettingValue>> GetAllForCurrentUserAsync(this ISettingManager settingManager, bool fallback = true)
{
return settingManager.GetAllAsync(UserSettingValueProvider.ProviderName, null, fallback);
}
public static Task SetForUserAsync(this ISettingManager settingManager, Guid userId, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false)
{
return settingManager.SetAsync(name, value, UserSettingValueProvider.ProviderName, userId.ToString(), forceToSet);
}
public static Task SetForCurrentUserAsync(this ISettingManager settingManager, [NotNull] string name, [CanBeNull] string value, bool forceToSet = false)
{
return settingManager.SetAsync(name, value, UserSettingValueProvider.ProviderName, null, forceToSet);
}
}
}

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Settings.Domain.Shared</AssemblyName>
<PackageId>Volo.Abp.Settings.Domain.Shared</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Settings
{
public class AbpSettingsDomainSharedModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAssemblyOf<AbpSettingsDomainSharedModule>();
}
}
}

@ -0,0 +1,10 @@
namespace Volo.Abp.Settings
{
public static class SettingsConsts
{
public const int MaxNameLength = 128;
public const int MaxValueLength = 2048;
public const int MaxProviderNameLength = 64;
public const int MaxProviderKeyLength = 64;
}
}

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Settings.Domain</AssemblyName>
<PackageId>Volo.Abp.Settings.Domain</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Ddd\Volo.Abp.Ddd.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings.Domain.Shared\Volo.Abp.Settings.Domain.Shared.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,9 @@
namespace Volo.Abp.Settings
{
public static class AbpSettingsConsts
{
public const string DefaultDbTablePrefix = "Abp";
public const string DefaultDbSchema = null;
}
}

@ -0,0 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Settings
{
[DependsOn(typeof(AbpSettingsModule))]
[DependsOn(typeof(AbpDddModule))]
[DependsOn(typeof(AbpSettingsDomainSharedModule))]
public class AbpSettingsDomainModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAssemblyOf<AbpSettingsDomainModule>();
}
}
}

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Settings
{
public interface ISettingRepository : IBasicRepository<Setting, Guid>
{
Task<Setting> FindAsync(string name, string providerName, string providerKey);
Task<List<Setting>> GetListAsync(string providerName, string providerKey);
}
}

@ -0,0 +1,43 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Settings
{
public class Setting : Entity<Guid>
{
[NotNull]
public virtual string Name { get; protected set; }
[NotNull]
public virtual string Value { get; internal set; }
[CanBeNull]
public virtual string ProviderName { get; protected set; }
[CanBeNull]
public virtual string ProviderKey { get; protected set; }
protected Setting()
{
}
public Setting(
Guid id,
[NotNull] string name,
[NotNull] string value,
[CanBeNull] string providerName = null,
[CanBeNull] string providerKey = null)
{
Check.NotNull(name, nameof(name));
Check.NotNull(value, nameof(value));
Id = id;
Name = name;
Value = value;
ProviderName = providerName;
ProviderKey = providerKey;
}
}
}

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Settings
{
public class SettingStore : AbpServiceBase, ISettingStore, ITransientDependency
{
private readonly ISettingRepository _settingRepository;
public SettingStore(ISettingRepository settingRepository)
{
_settingRepository = settingRepository;
}
public async Task<string> GetOrNullAsync(string name, string providerName, string providerKey)
{
var setting = await _settingRepository.FindAsync(name, providerName, providerKey);
return setting?.Value;
}
public async Task SetAsync(string name, string value, string providerName, string providerKey)
{
var setting = await _settingRepository.FindAsync(name, providerName, providerKey);
if (setting == null)
{
setting = new Setting(GuidGenerator.Create(), name, value, providerName, providerKey);
await _settingRepository.InsertAsync(setting);
}
setting.Value = value;
await _settingRepository.UpdateAsync(setting);
}
public async Task<List<SettingValue>> GetListAsync(string providerName, string providerKey)
{
var setting = await _settingRepository.GetListAsync(providerName, providerKey);
return setting.Select(s => new SettingValue(s.Name, s.Value)).ToList();
}
public async Task DeleteAsync(string name, string providerName, string providerKey)
{
var setting = await _settingRepository.FindAsync(name, providerName, providerKey);
if (setting != null)
{
await _settingRepository.DeleteAsync(setting);
}
}
}
}

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Settings.EntityFrameworkCore</AssemblyName>
<PackageId>Volo.Abp.Settings.EntityFrameworkCore</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.EntityFrameworkCore\Volo.Abp.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings.Domain\Volo.Abp.Settings.Domain.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.Settings.EntityFrameworkCore
{
[ConnectionStringName("AbpSettings")]
public class AbpSettingsDbContext : AbpDbContext<AbpSettingsDbContext>, IAbpSettingsDbContext
{
public static string TablePrefix { get; set; } = AbpSettingsConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = AbpSettingsConsts.DefaultDbSchema;
public DbSet<Setting> Settings { get; set; }
public AbpSettingsDbContext(DbContextOptions<AbpSettingsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureAbpSettings(TablePrefix, Schema);
}
}
}

@ -0,0 +1,33 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
namespace Volo.Abp.Settings.EntityFrameworkCore
{
public static class AbpSettingsDbContextModelBuilderExtensions
{
public static void ConfigureAbpSettings(
[NotNull] this ModelBuilder builder,
[CanBeNull] string tablePrefix = AbpSettingsConsts.DefaultDbTablePrefix,
[CanBeNull] string schema = AbpSettingsConsts.DefaultDbSchema)
{
Check.NotNull(builder, nameof(builder));
if (tablePrefix == null)
{
tablePrefix = "";
}
builder.Entity<Setting>(b =>
{
b.ToTable(tablePrefix + "Settings", schema);
b.Property(x => x.Name).HasMaxLength(SettingsConsts.MaxNameLength).IsRequired();
b.Property(x => x.Value).HasMaxLength(SettingsConsts.MaxValueLength).IsRequired();
b.Property(x => x.ProviderName).HasMaxLength(SettingsConsts.MaxProviderNameLength);
b.Property(x => x.ProviderKey).HasMaxLength(SettingsConsts.MaxProviderKeyLength);
b.HasIndex(x => new {x.Name, x.ProviderName, x.ProviderKey});
});
}
}
}

@ -0,0 +1,23 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace Volo.Abp.Settings.EntityFrameworkCore
{
[DependsOn(typeof(AbpSettingsDomainModule))]
[DependsOn(typeof(AbpEntityFrameworkCoreModule))]
public class AbpSettingsEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAbpDbContext<AbpSettingsDbContext>(options =>
{
options.AddDefaultRepositories<IAbpSettingsDbContext>();
options.AddRepository<Setting, EfCoreSettingRepository>();
});
services.AddAssemblyOf<AbpSettingsEntityFrameworkCoreModule>();
}
}
}

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.Settings.EntityFrameworkCore
{
public class EfCoreSettingRepository : EfCoreRepository<IAbpSettingsDbContext, Setting, Guid>, ISettingRepository
{
public EfCoreSettingRepository(IDbContextProvider<IAbpSettingsDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<Setting> FindAsync(string name, string providerName, string providerKey)
{
return await DbSet.FirstOrDefaultAsync(s => s.Name == name && s.ProviderName == providerName && s.ProviderKey == providerKey);
}
public async Task<List<Setting>> GetListAsync(string providerName, string providerKey)
{
return await DbSet.Where(s => s.ProviderName == providerName && s.ProviderKey == providerKey).ToListAsync();
}
}
}

@ -0,0 +1,10 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.Settings.EntityFrameworkCore
{
public interface IAbpSettingsDbContext : IEfCoreDbContext
{
DbSet<Setting> Settings { get; set; }
}
}

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Settings</AssemblyName>
<PackageId>Volo.Abp.Settings</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.Settings
{
public class AbpSettingsModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAssemblyOf<AbpSettingsModule>();
}
}
}

@ -0,0 +1,34 @@
using System.Threading.Tasks;
namespace Volo.Abp.Settings
{
public class DefaultValueSettingValueProvider : SettingValueProvider
{
public const string ProviderName = null;
public override string Name => ProviderName;
public DefaultValueSettingValueProvider(ISettingStore settingStore)
: base(settingStore)
{
}
public override Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
{
return Task.FromResult(setting.DefaultValue);
}
public override Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
setting.DefaultValue = value;
return Task.CompletedTask;
}
public override Task ClearAsync(SettingDefinition setting, string providerKey)
{
setting.DefaultValue = null;
return Task.CompletedTask;
}
}
}

@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public static class GlobalSettingManagerExtensions
{
public static Task<string> GetOrNullGlobalAsync(this ISettingManager settingManager, [NotNull] string name, bool fallback = true)
{
return settingManager.GetOrNullAsync(name, GlobalSettingValueProvider.ProviderName, null, fallback);
}
public static Task<List<SettingValue>> GetAllGlobalAsync(this ISettingManager settingManager, bool fallback = true)
{
return settingManager.GetAllAsync(GlobalSettingValueProvider.ProviderName, null, fallback);
}
public static Task SetGlobalAsync(this ISettingManager settingManager, [NotNull] string name, [CanBeNull] string value)
{
return settingManager.SetAsync(name, value, GlobalSettingValueProvider.ProviderName, null);
}
}
}

@ -0,0 +1,31 @@
using System.Threading.Tasks;
namespace Volo.Abp.Settings
{
public class GlobalSettingValueProvider : SettingValueProvider
{
public const string ProviderName = "Global";
public override string Name => ProviderName;
public GlobalSettingValueProvider(ISettingStore settingStore)
: base(settingStore)
{
}
public override Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey)
{
return SettingStore.GetOrNullAsync(setting.Name, Name, null);
}
public override Task SetAsync(SettingDefinition setting, string value, string providerKey)
{
return SettingStore.SetAsync(setting.Name, value, Name, null);
}
public override Task ClearAsync(SettingDefinition setting, string providerKey)
{
return SettingStore.DeleteAsync(setting.Name, Name, null);
}
}
}

@ -0,0 +1,9 @@
namespace Volo.Abp.Settings
{
public interface ISettingDefinitionContext
{
SettingDefinition GetOrNull(string name);
void Add(params SettingDefinition[] definitions);
}
}

@ -0,0 +1,13 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public interface ISettingDefinitionManager
{
[NotNull]
SettingDefinition Get([NotNull] string name);
IReadOnlyList<SettingDefinition> GetAll();
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Settings
{
public interface ISettingDefinitionProvider
{
void Define(ISettingDefinitionContext context);
}
}

@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public interface ISettingManager
{
Task<string> GetOrNullAsync([NotNull]string name);
Task<string> GetOrNullAsync([NotNull]string name, [NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true);
Task<List<SettingValue>> GetAllAsync();
Task<List<SettingValue>> GetAllAsync([NotNull] string providerName, [CanBeNull] string providerKey, bool fallback = true);
Task SetAsync([NotNull] string name, [CanBeNull] string value, [NotNull] string providerName, [CanBeNull] string providerKey, bool forceToSet = false);
}
}

@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public interface ISettingStore
{
Task<string> GetOrNullAsync([NotNull] string name, [CanBeNull] string providerName, [CanBeNull] string providerKey);
Task SetAsync([NotNull] string name, [NotNull] string value, [CanBeNull] string providerName, [CanBeNull] string providerKey);
Task<List<SettingValue>> GetListAsync([CanBeNull] string providerName, [CanBeNull] string providerKey);
Task DeleteAsync([NotNull] string name, [CanBeNull]string providerName, [CanBeNull]string providerKey);
}
}

@ -0,0 +1,16 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Settings
{
public interface ISettingValueProvider
{
string Name { get; }
Task<string> GetOrNullAsync([NotNull] SettingDefinition setting, [CanBeNull] string providerKey);
Task SetAsync([NotNull] SettingDefinition setting, [NotNull] string value, [CanBeNull] string providerKey);
Task ClearAsync([NotNull] SettingDefinition setting, [CanBeNull] string providerKey);
}
}

@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Settings
{
public class NullSettingStore : ISettingStore, ISingletonDependency
{
public Task<string> GetOrNullAsync(string name, string providerName, string providerKey)
{
return Task.FromResult((string) null);
}
public Task SetAsync(string name, string value, string providerName, string providerKey)
{
return Task.CompletedTask;
}
public Task<List<SettingValue>> GetListAsync(string providerName, string providerKey)
{
return Task.FromResult(new List<SettingValue>());
}
public Task DeleteAsync(string name, string providerName, string providerKey)
{
return Task.CompletedTask;
}
}
}

@ -0,0 +1,47 @@
namespace Volo.Abp.Settings
{
public class SettingDefinition
{
/// <summary>
/// Unique name of the setting.
/// </summary>
public string Name { get; }
/// <summary>
/// Default value of the setting.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Can clients see this setting and it's value.
/// It maybe dangerous for some settings to be visible to clients (such as an email server password).
/// Default: false.
/// </summary>
public bool IsVisibleToClients { get; set; }
/// <summary>
/// Is this setting inherited from parent scopes.
/// Default: True.
/// </summary>
public bool IsInherited { get; set; }
/// <summary>
/// Can be used to store a custom object related to this setting.
/// </summary>
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;
}
}
}

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Collections.Immutable;
namespace Volo.Abp.Settings
{
public class SettingDefinitionContext : ISettingDefinitionContext
{
protected Dictionary<string, SettingDefinition> Settings { get; }
public SettingDefinitionContext(Dictionary<string, SettingDefinition> settings)
{
Settings = settings;
}
public virtual SettingDefinition GetOrNull(string name)
{
return Settings.GetOrDefault(name);
}
public virtual IReadOnlyList<SettingDefinition> GetAll()
{
return Settings.Values.ToImmutableList();
}
public virtual void Add(params SettingDefinition[] definitions)
{
if (definitions.IsNullOrEmpty())
{
return;
}
foreach (var definition in definitions)
{
Settings[definition.Name] = definition;
}
}
}
}

@ -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.Settings
{
public class SettingDefinitionManager : ISettingDefinitionManager, ISingletonDependency
{
protected Lazy<List<ISettingDefinitionProvider>> Providers { get; }
protected Lazy<IDictionary<string, SettingDefinition>> SettingDefinitions { get; }
protected SettingOptions Options { get; }
private readonly IServiceProvider _serviceProvider;
public SettingDefinitionManager(
IOptions<SettingOptions> options,
IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
Options = options.Value;
Providers = new Lazy<List<ISettingDefinitionProvider>>(CreateSettingProviders, true);
SettingDefinitions = new Lazy<IDictionary<string, SettingDefinition>>(CreateSettingDefinitions, true);
}
public virtual SettingDefinition Get(string name)
{
Check.NotNull(name, nameof(name));
var settingDefinition = GetOrNull(name);
if (settingDefinition == null)
{
throw new AbpException("Undefined setting: " + name);
}
return settingDefinition;
}
public IReadOnlyList<SettingDefinition> GetAll()
{
return SettingDefinitions.Value.Values.ToImmutableList();
}
public virtual SettingDefinition GetOrNull(string name)
{
return SettingDefinitions.Value.GetOrDefault(name);
}
private List<ISettingDefinitionProvider> CreateSettingProviders()
{
return Options
.DefinitionProviders
.Select(p => _serviceProvider.GetRequiredService(p) as ISettingDefinitionProvider)
.ToList();
}
private IDictionary<string, SettingDefinition> CreateSettingDefinitions()
{
var settings = new Dictionary<string, SettingDefinition>();
foreach (var provider in Providers.Value)
{
provider.Define(new SettingDefinitionContext(settings));
}
return settings;
}
}
}

@ -0,0 +1,9 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Settings
{
public abstract class SettingDefinitionProvider : ISettingDefinitionProvider, ISingletonDependency
{
public abstract void Define(ISettingDefinitionContext context);
}
}

@ -0,0 +1,194 @@
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.Settings
{
public class SettingManager : ISettingManager, ISingletonDependency
{
protected ISettingDefinitionManager SettingDefinitionManager { get; }
protected Lazy<List<ISettingValueProvider>> Providers { get; }
protected SettingOptions Options { get; }
protected ISettingStore SettingStore { get; }
public SettingManager(
IOptions<SettingOptions> options,
IServiceProvider serviceProvider,
ISettingDefinitionManager settingDefinitionManager,
ISettingStore settingStore)
{
SettingStore = settingStore;
SettingDefinitionManager = settingDefinitionManager;
Options = options.Value;
Providers = new Lazy<List<ISettingValueProvider>>(
() => Options
.ValueProviders
.Select(c => serviceProvider.GetRequiredService(c) as ISettingValueProvider)
.ToList(),
true
);
}
public virtual Task<string> GetOrNullAsync(string name)
{
Check.NotNull(name, nameof(name));
return GetOrNullInternalAsync(name, null, null);
}
public virtual Task<string> GetOrNullAsync(string name, string providerName, string providerKey, bool fallback = true)
{
Check.NotNull(name, nameof(name));
Check.NotNull(providerName, nameof(providerName));
return GetOrNullInternalAsync(name, providerName, providerKey, fallback);
}
public virtual async Task<string> GetOrNullInternalAsync(string name, string providerName, string providerKey, bool fallback = true)
{
var setting = SettingDefinitionManager.Get(name);
var providers = Enumerable
.Reverse(Providers.Value);
if (providerName != null)
{
providers = providers.SkipWhile(c => c.Name != providerName);
}
if (!fallback || !setting.IsInherited)
{
providers = providers.TakeWhile(c => c.Name == providerName);
}
foreach (var provider in providers)
{
var value = await provider.GetOrNullAsync(setting, providerKey);
if (value != null)
{
return value;
}
}
return null;
}
public virtual async Task<List<SettingValue>> GetAllAsync()
{
var settingValues = new Dictionary<string, SettingValue>();
var settingDefinitions = SettingDefinitionManager.GetAll();
foreach (var provider in Providers.Value)
{
foreach (var setting in settingDefinitions)
{
var value = await provider.GetOrNullAsync(setting, null);
if (value != null)
{
settingValues[setting.Name] = new SettingValue(setting.Name, value);
}
}
}
return settingValues.Values.ToList();
}
public virtual async Task<List<SettingValue>> GetAllAsync(string providerName, string providerKey, bool fallback = true)
{
Check.NotNull(providerName, nameof(providerName));
var settingValues = new Dictionary<string, SettingValue>();
var settingDefinitions = SettingDefinitionManager.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 setting in settingDefinitions)
{
if (setting.IsInherited)
{
foreach (var provider in providerList)
{
var value = await provider.GetOrNullAsync(setting, providerKey);
if (value != null)
{
settingValues[setting.Name] = new SettingValue(setting.Name, value);
}
}
}
else
{
settingValues[setting.Name] = new SettingValue(
setting.Name,
await providerList[0].GetOrNullAsync(setting, providerKey)
);
}
}
}
return settingValues.Values.ToList();
}
public virtual async Task SetAsync(string name, string value, string providerName, string providerKey, bool forceToSet = false)
{
Check.NotNull(name, nameof(name));
Check.NotNull(providerName, nameof(providerName));
var setting = SettingDefinitionManager.Get(name);
var providers = Enumerable
.Reverse(Providers.Value)
.SkipWhile(p => p.Name != providerName)
.ToList();
if (!providers.Any())
{
return;
}
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].Name, providerKey);
if (fallbackValue == value)
{
value = null;
}
}
providers = providers
.TakeWhile(p => p.Name == providerName)
.ToList(); //Getting list for case of there are more than one provider with same EntityType
if (value == null)
{
foreach (var provider in providers)
{
await provider.ClearAsync(setting, providerKey);
}
}
else
{
foreach (var provider in providers)
{
await provider.SetAsync(setting, value, providerKey);
}
}
}
}
}

@ -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).
}
}

@ -0,0 +1,21 @@
using Volo.Abp.Collections;
namespace Volo.Abp.Settings
{
public class SettingOptions
{
public ITypeList<ISettingDefinitionProvider> DefinitionProviders { get; }
public ITypeList<ISettingValueProvider> ValueProviders { get; }
public SettingOptions()
{
DefinitionProviders = new TypeList<ISettingDefinitionProvider>();
ValueProviders = new TypeList<ISettingValueProvider>
{
typeof(DefaultValueSettingValueProvider),
typeof(GlobalSettingValueProvider)
};
}
}
}

@ -0,0 +1,22 @@
namespace Volo.Abp.Settings
{
public class SettingValue : NameValue
{
/// <summary>
/// Creates a new <see cref="NameValue"/>.
/// </summary>
public SettingValue()
{
}
/// <summary>
/// Creates a new <see cref="NameValue"/>.
/// </summary>
public SettingValue(string name, string value)
{
Name = name;
Value = value;
}
}
}

@ -0,0 +1,23 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Settings
{
public abstract class SettingValueProvider : ISettingValueProvider, ISingletonDependency
{
public abstract string Name { get; }
protected ISettingStore SettingStore { get; }
protected SettingValueProvider(ISettingStore settingStore)
{
SettingStore = settingStore;
}
public abstract Task<string> GetOrNullAsync(SettingDefinition setting, string providerKey);
public abstract Task SetAsync(SettingDefinition setting, string value, string providerKey);
public abstract Task ClearAsync(SettingDefinition setting, string providerKey);
}
}

@ -24,6 +24,7 @@
<ProjectReference Include="..\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Session\Volo.Abp.Session.csproj" />
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
<ProjectReference Include="..\Volo.Abp.Validation\Volo.Abp.Validation.csproj" />
<ProjectReference Include="..\Volo.Abp.VirtualFileSystem\Volo.Abp.VirtualFileSystem.csproj" />
</ItemGroup>

@ -9,6 +9,7 @@ using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
using Volo.Abp.Security;
using Volo.Abp.Session;
using Volo.Abp.Settings;
using Volo.Abp.Validation;
using Volo.Abp.VirtualFileSystem;
@ -20,6 +21,7 @@ namespace Volo.Abp
[DependsOn(typeof(AbpObjectMappingModule))]
[DependsOn(typeof(AbpSecurityModule))]
[DependsOn(typeof(AbpSessionModule))]
[DependsOn(typeof(AbpSettingsModule))]
[DependsOn(typeof(AbpDataModule))]
[DependsOn(typeof(AbpJsonModule))]
[DependsOn(typeof(AbpVirtualFileSystemModule))]

@ -19,9 +19,5 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>Volo.Abp.MultiTenancy.Tests</AssemblyName>
<PackageId>Volo.Abp.MultiTenancy.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Settings.EntityFrameworkCore\Volo.Abp.Settings.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
</ItemGroup>
</Project>

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Session;
using Volo.Abp.Settings.EntityFrameworkCore;
using Volo.Abp.TestBase;
namespace Volo.Abp.Settings
{
public class AbpSettingsTestBase : AbpIntegratedTest<AbpSettingsTestModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
protected virtual void UsingDbContext(Action<IAbpSettingsDbContext> action)
{
using (var dbContext = GetRequiredService<IAbpSettingsDbContext>())
{
action.Invoke(dbContext);
}
}
protected virtual T UsingDbContext<T>(Func<IAbpSettingsDbContext, T> action)
{
using (var dbContext = GetRequiredService<IAbpSettingsDbContext>())
{
return action.Invoke(dbContext);
}
}
protected List<Setting> GetSettingsFromDbContext(string entityType, string entityId, string name)
{
return UsingDbContext(context =>
context.Settings.Where(
s =>
s.ProviderName == UserSettingValueProvider.ProviderName &&
s.ProviderKey == AbpIdentityTestDataBuilder.User1Id.ToString() &&
s.Name == "MySetting2"
).ToList()
);
}
}
}

@ -0,0 +1,61 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Autofac;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
using Volo.Abp.Session;
using Volo.Abp.Settings.EntityFrameworkCore;
using Volo.Abp.Uow;
namespace Volo.Abp.Settings
{
[DependsOn(
typeof(AbpSettingsEntityFrameworkCoreModule),
typeof(AbpSessionModule),
typeof(AbpAutofacModule))]
public class AbpSettingsTestModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAssemblyOf<AbpSettingsTestModule>();
services.AddEntityFrameworkInMemoryDatabase();
var databaseName = Guid.NewGuid().ToString();
services.Configure<AbpDbContextOptions>(options =>
{
options.Configure(context =>
{
context.DbContextOptions.UseInMemoryDatabase(databaseName);
});
});
services.Configure<UnitOfWorkDefaultOptions>(options =>
{
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
});
services.Configure<SettingOptions>(options =>
{
options.DefinitionProviders.Add<TestSettingDefinitionProvider>();
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
SeedTestData(context);
}
private static void SeedTestData(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())
{
scope.ServiceProvider
.GetRequiredService<AbpIdentityTestDataBuilder>()
.Build();
}
}
}
}

@ -0,0 +1,34 @@
using System;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Session;
namespace Volo.Abp.Settings
{
public class AbpIdentityTestDataBuilder : ITransientDependency
{
public static Guid User1Id = Guid.NewGuid();
public static Guid User2Id = Guid.NewGuid();
private readonly ISettingRepository _settingRepository;
private readonly IGuidGenerator _guidGenerator;
public AbpIdentityTestDataBuilder(ISettingRepository settingRepository, IGuidGenerator guidGenerator)
{
_settingRepository = settingRepository;
_guidGenerator = guidGenerator;
}
public void Build()
{
_settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySetting1", "42", GlobalSettingValueProvider.ProviderName));
_settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySetting2", "default-store-value", GlobalSettingValueProvider.ProviderName));
_settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySetting2", "user1-store-value", UserSettingValueProvider.ProviderName, User1Id.ToString()));
_settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySetting2", "user2-store-value", UserSettingValueProvider.ProviderName, User2Id.ToString()));
_settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySettingWithoutInherit", "default-store-value", GlobalSettingValueProvider.ProviderName));
_settingRepository.InsertAsync(new Setting(_guidGenerator.Create(), "MySettingWithoutInherit", "user1-store-value", UserSettingValueProvider.ProviderName, User1Id.ToString()));
}
}
}

@ -0,0 +1,55 @@
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.Settings
{
public class SettingManager_Basic_Tests : AbpSettingsTestBase
{
private readonly ISettingManager _settingManager;
public SettingManager_Basic_Tests()
{
_settingManager = GetRequiredService<ISettingManager>();
}
[Fact]
public async Task Should_Throw_Exception_When_Try_To_Get_An_Undefined_Setting()
{
await Assert.ThrowsAsync<AbpException>(
async () => await _settingManager.GetOrNullAsync("UndefinedSetting")
);
}
[Fact]
public async Task Should_Get_Default_Value_If_Not_Set_In_Store()
{
var value = await _settingManager.GetOrNullAsync("SettingNotSetInStore");
value.ShouldBe("default-value");
}
[Fact]
public async Task Should_Get_Base_Store_Value()
{
(await _settingManager.GetOrNullAsync("MySetting1")).ShouldBe("42");
}
[Fact]
public async Task Should_Get_All_Base_Store_Values()
{
var settingValues = await _settingManager.GetAllAsync();
settingValues.ShouldContain(sv => sv.Name == "MySetting1" && sv.Value == "42");
settingValues.ShouldContain(sv => sv.Name == "MySetting2" && sv.Value == "default-store-value");
settingValues.ShouldContain(sv => sv.Name == "SettingNotSetInStore" && sv.Value == "default-value");
}
[Fact]
public async Task Should_Set_Global_Value()
{
await _settingManager.SetGlobalAsync("MySetting1", "43");
(await _settingManager.GetOrNullGlobalAsync("MySetting1")).ShouldBe("43");
(await _settingManager.GetOrNullAsync("MySetting1")).ShouldBe("43");
}
}
}

@ -0,0 +1,185 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using Shouldly;
using Volo.Abp.Session;
using Xunit;
namespace Volo.Abp.Settings
{
public class SettingManager_User_Tests: AbpSettingsTestBase
{
private Guid _currentUserId;
private readonly ISettingManager _settingManager;
public SettingManager_User_Tests()
{
_settingManager = GetRequiredService<ISettingManager>();
}
protected override void AfterAddApplication(IServiceCollection services)
{
var currentUser = Substitute.For<ICurrentUser>();
currentUser.Id.Returns(ci => _currentUserId);
services.AddSingleton(currentUser);
}
[Fact]
public async Task Should_Get_From_Store_For_Given_User()
{
(await _settingManager.GetOrNullForUserAsync("MySetting2", AbpIdentityTestDataBuilder.User1Id)).ShouldBe("user1-store-value");
(await _settingManager.GetOrNullForUserAsync("MySetting2", AbpIdentityTestDataBuilder.User2Id)).ShouldBe("user2-store-value");
}
[Fact]
public async Task Should_Fallback_To_Default_Store_Value_When_No_Value_For_Given_User()
{
(await _settingManager.GetOrNullForUserAsync("MySetting2", Guid.NewGuid())).ShouldBe("default-store-value");
}
[Fact]
public async Task Should_Not_Fallback_To_Default_Store_Value_When_No_Value_For_Given_User_But_Specified_Fallback_As_False()
{
(await _settingManager.GetOrNullForUserAsync("MySetting2", Guid.NewGuid(), fallback: false)).ShouldBeNull();
}
[Fact]
public async Task Should_Get_From_Store_For_Current_User()
{
_currentUserId = AbpIdentityTestDataBuilder.User1Id;
(await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("user1-store-value");
_currentUserId = AbpIdentityTestDataBuilder.User2Id;
(await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("user2-store-value");
}
[Fact]
public async Task Should_Fallback_To_Default_Store_Value_When_No_Value_For_Current_User()
{
_currentUserId = Guid.NewGuid();
(await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("default-store-value");
}
[Fact]
public async Task Should_Get_From_Store_For_Current_User_With_GetOrNullForCurrentUserAsync()
{
_currentUserId = AbpIdentityTestDataBuilder.User1Id;
(await _settingManager.GetOrNullForCurrentUserAsync("MySetting2")).ShouldBe("user1-store-value");
_currentUserId = AbpIdentityTestDataBuilder.User2Id;
(await _settingManager.GetOrNullForCurrentUserAsync("MySetting2")).ShouldBe("user2-store-value");
}
[Fact]
public async Task Should_Fallback_To_Default_Store_Value_When_No_Value_For_Current_User_With_GetOrNullForCurrentUserAsync()
{
_currentUserId = Guid.NewGuid();
(await _settingManager.GetOrNullAsync("MySetting2")).ShouldBe("default-store-value");
}
[Fact]
public async Task Should_Not_Fallback_To_Default_Store_Value_When_No_Value_For_Current_User_But_Specified_Fallback_As_False()
{
_currentUserId = Guid.NewGuid();
(await _settingManager.GetOrNullForCurrentUserAsync("MySetting2", fallback: false)).ShouldBeNull();
}
[Fact]
public async Task Should_Get_All_From_Store_For_Given_User()
{
var settingValues = await _settingManager.GetAllForUserAsync(AbpIdentityTestDataBuilder.User1Id);
settingValues.ShouldContain(sv => sv.Name == "MySetting1" && sv.Value == "42");
settingValues.ShouldContain(sv => sv.Name == "MySetting2" && sv.Value == "user1-store-value");
settingValues.ShouldContain(sv => sv.Name == "SettingNotSetInStore" && sv.Value == "default-value");
}
[Fact]
public async Task Should_Get_All_From_Store_For_Given_User_Without_Fallback()
{
var settingValues = await _settingManager.GetAllForUserAsync(AbpIdentityTestDataBuilder.User1Id, fallback: false);
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]
public async Task Should_Delete_Setting_Record_When_Set_To_Null()
{
await _settingManager.SetForUserAsync(AbpIdentityTestDataBuilder.User1Id, "MySetting2", null);
GetSettingsFromDbContext(
UserSettingValueProvider.ProviderName,
AbpIdentityTestDataBuilder.User1Id.ToString(),
"MySetting2"
).Count.ShouldBe(0);
}
[Fact]
public async Task Should_Change_User_Setting()
{
(await _settingManager.GetOrNullForUserAsync("MySetting2", AbpIdentityTestDataBuilder.User1Id))
.ShouldBe("user1-store-value");
await _settingManager.SetForUserAsync(AbpIdentityTestDataBuilder.User1Id, "MySetting2", "user1-new-store-value");
(await _settingManager.GetOrNullForUserAsync("MySetting2", AbpIdentityTestDataBuilder.User1Id))
.ShouldBe("user1-new-store-value");
GetSettingsFromDbContext(
UserSettingValueProvider.ProviderName,
AbpIdentityTestDataBuilder.User1Id.ToString(),
"MySetting2"
).Single().Value.ShouldBe("user1-new-store-value");
}
[Fact]
public async Task Should_Delete_Setting_Record_When_Set_To_Fallback_Value()
{
await _settingManager.SetForUserAsync(
AbpIdentityTestDataBuilder.User1Id,
"MySetting2",
"default-store-value"
);
GetSettingsFromDbContext(
UserSettingValueProvider.ProviderName,
AbpIdentityTestDataBuilder.User1Id.ToString(),
"MySetting2"
).Count.ShouldBe(0);
(await _settingManager.GetOrNullForUserAsync("MySetting2", AbpIdentityTestDataBuilder.User1Id))
.ShouldBe("default-store-value");
}
[Fact]
public async Task Should_Not_Delete_Setting_Record_When_Set_To_Fallback_Value_If_Forced()
{
await _settingManager.SetForUserAsync(
AbpIdentityTestDataBuilder.User1Id,
"MySetting2",
"default-store-value",
forceToSet: true
);
GetSettingsFromDbContext(
UserSettingValueProvider.ProviderName,
AbpIdentityTestDataBuilder.User1Id.ToString(),
"MySetting2"
).Single().Value.ShouldBe("default-store-value");
(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");
}
}
}

@ -0,0 +1,13 @@
namespace Volo.Abp.Settings
{
public class TestSettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
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"));
}
}
}
Loading…
Cancel
Save