mirror of https://github.com/abpframework/abp.git
committed by
GitHub
244 changed files with 4597 additions and 990 deletions
@ -0,0 +1,13 @@ |
|||
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Client |
|||
{ |
|||
public static class CachedApplicationConfigurationClientExtensions |
|||
{ |
|||
public static ApplicationConfigurationDto Get(this ICachedApplicationConfigurationClient client) |
|||
{ |
|||
return AsyncHelper.RunSync(client.GetAsync); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Client |
|||
{ |
|||
public class RemoteLocalizationContributor : ILocalizationResourceContributor |
|||
{ |
|||
private LocalizationResource _resource; |
|||
private ICachedApplicationConfigurationClient _applicationConfigurationClient; |
|||
private ILogger<RemoteLocalizationContributor> _logger; |
|||
|
|||
public void Initialize(LocalizationResourceInitializationContext context) |
|||
{ |
|||
_resource = context.Resource; |
|||
_applicationConfigurationClient = context.ServiceProvider.GetRequiredService<ICachedApplicationConfigurationClient>(); |
|||
_logger = context.ServiceProvider.GetService<ILogger<RemoteLocalizationContributor>>() |
|||
?? NullLogger<RemoteLocalizationContributor>.Instance; |
|||
} |
|||
|
|||
public LocalizedString GetOrNull(string cultureName, string name) |
|||
{ |
|||
var resource = GetResourceOrNull(); |
|||
if (resource == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var value = resource.GetOrDefault(name); |
|||
if (value == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return new LocalizedString(name, value); |
|||
} |
|||
|
|||
public void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary) |
|||
{ |
|||
var resource = GetResourceOrNull(); |
|||
if (resource == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
foreach (var keyValue in resource) |
|||
{ |
|||
dictionary[keyValue.Key] = new LocalizedString(keyValue.Key, keyValue.Value); |
|||
} |
|||
} |
|||
|
|||
private Dictionary<string, string> GetResourceOrNull() |
|||
{ |
|||
var resource = _applicationConfigurationClient |
|||
.Get() |
|||
.Localization.Values |
|||
.GetOrDefault(_resource.ResourceName); |
|||
|
|||
if (resource == null) |
|||
{ |
|||
_logger.LogWarning($"Could not find the localization resource {_resource.ResourceName} on the remote server!"); |
|||
} |
|||
|
|||
return resource; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Client |
|||
{ |
|||
public class RemoteSettingProvider : ISettingProvider, ITransientDependency |
|||
{ |
|||
protected ICachedApplicationConfigurationClient ConfigurationClient { get; } |
|||
|
|||
public RemoteSettingProvider(ICachedApplicationConfigurationClient configurationClient) |
|||
{ |
|||
ConfigurationClient = configurationClient; |
|||
} |
|||
|
|||
public async Task<string> GetOrNullAsync(string name) |
|||
{ |
|||
var configuration = await ConfigurationClient.GetAsync(); |
|||
return configuration.Setting.Values.GetOrDefault(name); |
|||
} |
|||
|
|||
public async Task<List<SettingValue>> GetAllAsync() |
|||
{ |
|||
var configuration = await ConfigurationClient.GetAsync(); |
|||
return configuration |
|||
.Setting.Values |
|||
.Select(s => new SettingValue(s.Key, s.Value)) |
|||
.ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations |
|||
{ |
|||
[Serializable] |
|||
public class ApplicationSettingConfigurationDto |
|||
{ |
|||
public Dictionary<string, string> Values { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions |
|||
{ |
|||
public static class ModelExplorerExtensions |
|||
{ |
|||
public static T GetAttribute<T>(this ModelExplorer property) where T : Attribute |
|||
{ |
|||
return property?.Metadata?.ContainerType?.GetTypeInfo()?.GetProperty(property.Metadata.PropertyName)?.GetCustomAttribute<T>(); |
|||
} |
|||
|
|||
public static int GetDisplayOrder(this ModelExplorer explorer) |
|||
{ |
|||
return GetAttribute<DisplayOrder>(explorer)?.Number ?? DisplayOrder.Default; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Microsoft.AspNetCore.Razor.TagHelpers; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions |
|||
{ |
|||
public static class TagHelperContextExtensions |
|||
{ |
|||
public static T GetValue<T>(this TagHelperContext context, string key) |
|||
{ |
|||
if (!context.Items.ContainsKey(key)) |
|||
{ |
|||
return default(T); |
|||
} |
|||
|
|||
return (T)context.Items[key]; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Razor.TagHelpers; |
|||
using System.Text.Encodings.Web; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions |
|||
{ |
|||
public static class TagHelperExtensions |
|||
{ |
|||
public static TagHelperOutput ProcessAndGetOutput(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, string tagName = "div", TagMode tagMode = TagMode.SelfClosing, bool runAsync = false) |
|||
{ |
|||
var innerOutput = new TagHelperOutput(tagName, attributeList, (useCachedResult, encoder) => Task.Run<TagHelperContent>(() => new DefaultTagHelperContent())) |
|||
{ |
|||
TagMode = tagMode |
|||
}; |
|||
|
|||
var innerContext = new TagHelperContext(attributeList, context.Items, Guid.NewGuid().ToString()); |
|||
|
|||
tagHelper.Init(context); |
|||
|
|||
if (runAsync) |
|||
{ |
|||
AsyncHelper.RunSync(() => tagHelper.ProcessAsync(innerContext, innerOutput)); |
|||
} |
|||
else |
|||
{ |
|||
tagHelper.Process(innerContext, innerOutput); |
|||
} |
|||
|
|||
return innerOutput; |
|||
} |
|||
|
|||
public static string Render(this TagHelper tagHelper, TagHelperAttributeList attributeList, TagHelperContext context, HtmlEncoder htmlEncoder, string tagName = "div", TagMode tagMode = TagMode.SelfClosing, bool runAsync = false) |
|||
{ |
|||
var innerOutput = tagHelper.ProcessAndGetOutput(attributeList, context, tagName, tagMode, runAsync); |
|||
|
|||
return innerOutput.Render(htmlEncoder); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using Microsoft.AspNetCore.Razor.TagHelpers; |
|||
using System.IO; |
|||
using System.Text.Encodings.Web; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions |
|||
{ |
|||
public static class TagHelperOutputExtensions |
|||
{ |
|||
public static string Render(this TagHelperOutput output, HtmlEncoder htmlEncoder) |
|||
{ |
|||
using (var writer = new StringWriter()) |
|||
{ |
|||
output.WriteTo(writer, htmlEncoder); |
|||
return writer.ToString(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,11 +0,0 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Label |
|||
{ |
|||
public class AbpLabelTagHelper : AbpTagHelper<AbpLabelTagHelper, AbpLabelTagHelperService> |
|||
{ |
|||
public AbpLabelTagHelper(AbpLabelTagHelperService tagHelperService) |
|||
: base(tagHelperService) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -1,12 +0,0 @@ |
|||
using Microsoft.AspNetCore.Razor.TagHelpers; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Label |
|||
{ |
|||
public class AbpLabelTagHelperService : AbpTagHelperService<AbpLabelTagHelper> |
|||
{ |
|||
public override void Process(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
//TODO: fill
|
|||
} |
|||
} |
|||
} |
|||
@ -1,43 +0,0 @@ |
|||
using System; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.Auditing; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Auditing |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
public class AspNetCoreCorrelationIdProvider : ICorrelationIdProvider, ITransientDependency |
|||
{ |
|||
public const string CorrelationIdKey = "_CorrelationId"; |
|||
|
|||
protected IHttpContextAccessor HttpContextAccessor { get; } |
|||
|
|||
public AspNetCoreCorrelationIdProvider(IHttpContextAccessor httpContextAccessor) |
|||
{ |
|||
HttpContextAccessor = httpContextAccessor; |
|||
} |
|||
|
|||
public virtual string Get() |
|||
{ |
|||
if (HttpContextAccessor.HttpContext?.Request?.Headers == null) |
|||
{ |
|||
return CreateNewCorrelationId(); |
|||
} |
|||
|
|||
string correlationId = HttpContextAccessor.HttpContext.Request.Headers[CorrelationIdKey]; |
|||
|
|||
if (correlationId.IsNullOrEmpty()) |
|||
{ |
|||
correlationId = CreateNewCorrelationId(); |
|||
HttpContextAccessor.HttpContext.Request.Headers[CorrelationIdKey] = correlationId; |
|||
} |
|||
|
|||
return correlationId; |
|||
} |
|||
|
|||
protected virtual string CreateNewCorrelationId() |
|||
{ |
|||
return Guid.NewGuid().ToString("N"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.Options; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Tracing; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Tracing |
|||
{ |
|||
public class AbpCorrelationIdMiddleware |
|||
{ |
|||
private readonly RequestDelegate _next; |
|||
|
|||
public AbpCorrelationIdMiddleware(RequestDelegate next) |
|||
{ |
|||
_next = next; |
|||
} |
|||
|
|||
public async Task Invoke( |
|||
HttpContext httpContext, |
|||
IOptions<CorrelationIdOptions> options, |
|||
ICorrelationIdProvider correlationIdProvider) |
|||
{ |
|||
var correlationId = correlationIdProvider.Get(); |
|||
var optionsValue = options.Value; |
|||
|
|||
try |
|||
{ |
|||
await _next(httpContext); |
|||
} |
|||
finally |
|||
{ |
|||
CheckAndSetCorrelationIdOnResponse(httpContext, optionsValue, correlationId); |
|||
} |
|||
} |
|||
|
|||
protected virtual void CheckAndSetCorrelationIdOnResponse( |
|||
HttpContext httpContext, |
|||
CorrelationIdOptions options, |
|||
string correlationId) |
|||
{ |
|||
if (httpContext.Response.HasStarted) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (!options.SetResponseHeader) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (httpContext.Response.Headers.ContainsKey(options.HttpHeaderName)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
httpContext.Response.Headers[options.HttpHeaderName] = correlationId; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
using System; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Tracing; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Tracing |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
public class AspNetCoreCorrelationIdProvider : ICorrelationIdProvider, ITransientDependency |
|||
{ |
|||
protected IHttpContextAccessor HttpContextAccessor { get; } |
|||
protected CorrelationIdOptions Options { get; } |
|||
|
|||
public AspNetCoreCorrelationIdProvider( |
|||
IHttpContextAccessor httpContextAccessor, |
|||
IOptions<CorrelationIdOptions> options) |
|||
{ |
|||
HttpContextAccessor = httpContextAccessor; |
|||
Options = options.Value; |
|||
} |
|||
|
|||
public virtual string Get() |
|||
{ |
|||
if (HttpContextAccessor.HttpContext?.Request?.Headers == null) |
|||
{ |
|||
return CreateNewCorrelationId(); |
|||
} |
|||
|
|||
lock (HttpContextAccessor.HttpContext.Request.Headers) |
|||
{ |
|||
string correlationId = HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName]; |
|||
|
|||
if (correlationId.IsNullOrEmpty()) |
|||
{ |
|||
correlationId = CreateNewCorrelationId(); |
|||
HttpContextAccessor.HttpContext.Request.Headers[Options.HttpHeaderName] = correlationId; |
|||
} |
|||
|
|||
return correlationId; |
|||
} |
|||
} |
|||
|
|||
protected virtual string CreateNewCorrelationId() |
|||
{ |
|||
return Guid.NewGuid().ToString("N"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,12 +0,0 @@ |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Auditing |
|||
{ |
|||
public class NullCorrelationIdProvider : ICorrelationIdProvider, ISingletonDependency |
|||
{ |
|||
public string Get() |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
namespace Volo.Abp.Tracing |
|||
{ |
|||
public class CorrelationIdOptions |
|||
{ |
|||
public string HttpHeaderName { get; set; } = "X-Correlation-Id"; |
|||
|
|||
public bool SetResponseHeader { get; set; } = true; |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Tracing |
|||
{ |
|||
public class DefaultCorrelationIdProvider : ICorrelationIdProvider, ISingletonDependency |
|||
{ |
|||
public string Get() |
|||
{ |
|||
return CreateNewCorrelationId(); |
|||
} |
|||
|
|||
protected virtual string CreateNewCorrelationId() |
|||
{ |
|||
return Guid.NewGuid().ToString("N"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,7 +1,10 @@ |
|||
namespace Volo.Abp.Auditing |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Tracing |
|||
{ |
|||
public interface ICorrelationIdProvider |
|||
{ |
|||
[NotNull] |
|||
string Get(); |
|||
} |
|||
} |
|||
@ -1,98 +1,61 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.Domain.Values |
|||
{ |
|||
//Inspired from https://blogs.msdn.microsoft.com/cesardelatorre/2011/06/06/implementing-a-value-object-base-class-supertype-patternddd-patterns-related/
|
|||
|
|||
/// <summary>
|
|||
/// Base class for value objects.
|
|||
/// </summary>
|
|||
/// <typeparam name="TValueObject">The type of the value object.</typeparam>
|
|||
public abstract class ValueObject<TValueObject> : IEquatable<TValueObject> |
|||
where TValueObject : ValueObject<TValueObject> |
|||
//Inspired from https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects
|
|||
|
|||
public abstract class ValueObject |
|||
{ |
|||
public bool Equals(TValueObject other) |
|||
protected static bool EqualOperator(ValueObject left, ValueObject right) |
|||
{ |
|||
if ((object)other == null) |
|||
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null)) |
|||
{ |
|||
return false; |
|||
} |
|||
return ReferenceEquals(left, null) || left.Equals(right); |
|||
} |
|||
|
|||
var publicProperties = GetType().GetTypeInfo().GetProperties(); |
|||
if (!publicProperties.Any()) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return publicProperties.All(property => Equals(property.GetValue(this, null), property.GetValue(other, null))); |
|||
protected static bool NotEqualOperator(ValueObject left, ValueObject right) |
|||
{ |
|||
return !(EqualOperator(left, right)); |
|||
} |
|||
|
|||
protected abstract IEnumerable<object> GetAtomicValues(); |
|||
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj == null) |
|||
if (obj == null || obj.GetType() != GetType()) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
var item = obj as ValueObject<TValueObject>; |
|||
return (object)item != null && Equals((TValueObject)item); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
//TODO: Can we cache the hash value assuming value objects are always immutable? We can make a Reset-like method to reset it's mutated.
|
|||
|
|||
const int index = 1; |
|||
const int initialHasCode = 31; |
|||
|
|||
var publicProperties = GetType().GetTypeInfo().GetProperties(); |
|||
|
|||
if (!publicProperties.Any()) |
|||
ValueObject other = (ValueObject)obj; |
|||
IEnumerator<object> thisValues = GetAtomicValues().GetEnumerator(); |
|||
IEnumerator<object> otherValues = other.GetAtomicValues().GetEnumerator(); |
|||
while (thisValues.MoveNext() && otherValues.MoveNext()) |
|||
{ |
|||
return initialHasCode; |
|||
} |
|||
|
|||
var hashCode = initialHasCode; |
|||
var changeMultiplier = false; |
|||
|
|||
foreach (var property in publicProperties) |
|||
{ |
|||
var value = property.GetValue(this, null); |
|||
|
|||
if (value == null) |
|||
if (ReferenceEquals(thisValues.Current, null) ^ |
|||
ReferenceEquals(otherValues.Current, null)) |
|||
{ |
|||
//support {"a",null,null,"a"} != {null,"a","a",null}
|
|||
hashCode = hashCode ^ (index * 13); |
|||
continue; |
|||
return false; |
|||
} |
|||
|
|||
hashCode = hashCode * (changeMultiplier ? 59 : 114) + value.GetHashCode(); |
|||
changeMultiplier = !changeMultiplier; |
|||
} |
|||
|
|||
return hashCode; |
|||
} |
|||
|
|||
public static bool operator ==(ValueObject<TValueObject> x, ValueObject<TValueObject> y) |
|||
{ |
|||
if (ReferenceEquals(x, y)) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
if (((object)x == null) || ((object)y == null)) |
|||
{ |
|||
return false; |
|||
if (thisValues.Current != null && |
|||
!thisValues.Current.Equals(otherValues.Current)) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return x.Equals(y); |
|||
return !thisValues.MoveNext() && !otherValues.MoveNext(); |
|||
} |
|||
|
|||
public static bool operator !=(ValueObject<TValueObject> x, ValueObject<TValueObject> y) |
|||
public override int GetHashCode() |
|||
{ |
|||
return !(x == y); |
|||
return GetAtomicValues() |
|||
.Select(x => x != null ? x.GetHashCode() : 0) |
|||
.Aggregate((x, y) => x ^ y); |
|||
} |
|||
// Other utilility methods
|
|||
} |
|||
} |
|||
|
|||
@ -1,20 +1,13 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Data; |
|||
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 //TODO: Rename to AbpMultiTenancyModule
|
|||
[DependsOn( |
|||
typeof(AbpDataModule) |
|||
)] |
|||
public class AbpMultiTenancyAbstractionsModule : AbpModule //TODO: Rename to AbpMultiTenancyModule?
|
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<SettingOptions>(options => |
|||
{ |
|||
options.ValueProviders.Add<TenantSettingValueProvider>(); |
|||
}); |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
@ -1,45 +0,0 @@ |
|||
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) |
|||
{ |
|||
return await SettingStore.GetOrNullAsync(setting.Name, Name, NormalizeProviderKey(providerKey)); |
|||
} |
|||
|
|||
public override Task SetAsync(SettingDefinition setting, string value, string providerKey) |
|||
{ |
|||
return SettingStore.SetAsync(setting.Name, value, Name, NormalizeProviderKey(providerKey)); |
|||
} |
|||
|
|||
public override Task ClearAsync(SettingDefinition setting, string providerKey) |
|||
{ |
|||
return SettingStore.DeleteAsync(setting.Name, Name, NormalizeProviderKey(providerKey)); |
|||
} |
|||
|
|||
private string NormalizeProviderKey(string providerKey) |
|||
{ |
|||
if (providerKey == null && CurrentTenant.Id.HasValue) |
|||
{ |
|||
return CurrentTenant.Id.Value.ToString(); |
|||
} |
|||
|
|||
return providerKey; |
|||
} |
|||
} |
|||
} |
|||
@ -1,15 +1,27 @@ |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Security; |
|||
using Volo.Abp.Users; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpLocalizationAbstractionsModule), |
|||
typeof(AbpSecurityModule) |
|||
typeof(AbpSecurityModule), |
|||
typeof(AbpMultiTenancyAbstractionsModule) |
|||
)] |
|||
public class AbpSettingsModule : AbpModule |
|||
{ |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<SettingOptions>(options => |
|||
{ |
|||
options.ValueProviders.Add<DefaultValueSettingValueProvider>(); |
|||
options.ValueProviders.Add<GlobalSettingValueProvider>(); |
|||
options.ValueProviders.Add<TenantSettingValueProvider>(); |
|||
options.ValueProviders.Add<UserSettingValueProvider>(); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,13 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
public interface ISettingProvider |
|||
{ |
|||
Task<string> GetOrNullAsync([NotNull]string name); |
|||
|
|||
Task<List<SettingValue>> GetAllAsync(); |
|||
} |
|||
} |
|||
@ -1,17 +1,14 @@ |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
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); |
|||
Task<string> GetOrNullAsync( |
|||
[NotNull] string name, |
|||
[CanBeNull] string providerName, |
|||
[CanBeNull] string providerKey |
|||
); |
|||
} |
|||
} |
|||
|
|||
@ -1,31 +0,0 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
public static class SettingManagerExtensions |
|||
{ |
|||
public static async Task<bool> IsTrueAsync([NotNull] this ISettingManager settingManager, [NotNull] string name) |
|||
{ |
|||
Check.NotNull(settingManager, nameof(settingManager)); |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
return string.Equals( |
|||
await settingManager.GetOrNullAsync(name), |
|||
"true", |
|||
StringComparison.OrdinalIgnoreCase |
|||
); |
|||
} |
|||
|
|||
public static async Task<T> GetAsync<T>([NotNull] this ISettingManager settingManager, [NotNull] string name, T defaultValue = default) |
|||
where T : struct |
|||
{ |
|||
Check.NotNull(settingManager, nameof(settingManager)); |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
var value = await settingManager.GetOrNullAsync(name); |
|||
return value?.To<T>() ?? defaultValue; |
|||
} |
|||
} |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
public static class SettingManagerSyncExtensions |
|||
{ |
|||
public static string GetOrNull([NotNull] this ISettingManager settingManager, [NotNull] string name) |
|||
{ |
|||
Check.NotNull(settingManager, nameof(settingManager)); |
|||
|
|||
return AsyncHelper.RunSync(() => settingManager.GetOrNullAsync(name)); |
|||
} |
|||
|
|||
public static List<SettingValue> GetAll([NotNull] this ISettingManager settingManager) |
|||
{ |
|||
Check.NotNull(settingManager, nameof(settingManager)); |
|||
|
|||
return AsyncHelper.RunSync(settingManager.GetAllAsync); |
|||
} |
|||
|
|||
public static T Get<T>([NotNull] this ISettingManager settingManager, [NotNull] string name, T defaultValue = default) |
|||
where T : struct |
|||
{ |
|||
return AsyncHelper.RunSync(() => settingManager.GetAsync(name, defaultValue)); |
|||
} |
|||
|
|||
public static bool IsTrue([NotNull] this ISettingManager settingManager, [NotNull] string name) |
|||
{ |
|||
return AsyncHelper.RunSync(() => settingManager.IsTrueAsync(name)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,101 @@ |
|||
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 SettingProvider : ISettingProvider, ITransientDependency |
|||
{ |
|||
protected ISettingDefinitionManager SettingDefinitionManager { get; } |
|||
protected Lazy<List<ISettingValueProvider>> Providers { get; } |
|||
protected ISettingEncryptionService SettingEncryptionService { get; } |
|||
protected SettingOptions Options { get; } |
|||
|
|||
public SettingProvider( |
|||
IOptions<SettingOptions> options, |
|||
IServiceProvider serviceProvider, |
|||
ISettingDefinitionManager settingDefinitionManager, |
|||
ISettingEncryptionService settingEncryptionService) |
|||
{ |
|||
SettingDefinitionManager = settingDefinitionManager; |
|||
SettingEncryptionService = settingEncryptionService; |
|||
|
|||
Options = options.Value; |
|||
|
|||
Providers = new Lazy<List<ISettingValueProvider>>( |
|||
() => Options |
|||
.ValueProviders |
|||
.Select(c => serviceProvider.GetRequiredService(c) as ISettingValueProvider) |
|||
.ToList(), |
|||
true |
|||
); |
|||
} |
|||
|
|||
public virtual async Task<string> GetOrNullAsync(string name) |
|||
{ |
|||
var setting = SettingDefinitionManager.Get(name); |
|||
var providers = Enumerable |
|||
.Reverse(Providers.Value); |
|||
|
|||
if (setting.Providers.Any()) |
|||
{ |
|||
providers = providers.Where(p => setting.Providers.Contains(p.Name)); |
|||
} |
|||
|
|||
//TODO: How to implement setting.IsInherited?
|
|||
|
|||
var value = await GetOrNullValueFromProvidersAsync(providers, setting); |
|||
if (setting.IsEncrypted) |
|||
{ |
|||
value = SettingEncryptionService.Decrypt(setting, value); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
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); |
|||
if (value != null) |
|||
{ |
|||
if (setting.IsEncrypted) |
|||
{ |
|||
value = SettingEncryptionService.Decrypt(setting, value); |
|||
} |
|||
|
|||
settingValues[setting.Name] = new SettingValue(setting.Name, value); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return settingValues.Values.ToList(); |
|||
} |
|||
|
|||
protected virtual async Task<string> GetOrNullValueFromProvidersAsync( |
|||
IEnumerable<ISettingValueProvider> providers, |
|||
SettingDefinition setting) |
|||
{ |
|||
foreach (var provider in providers) |
|||
{ |
|||
var value = await provider.GetOrNullAsync(setting); |
|||
if (value != null) |
|||
{ |
|||
return value; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
public static class SettingProviderExtensions |
|||
{ |
|||
public static async Task<bool> IsTrueAsync([NotNull] this ISettingProvider settingProvider, [NotNull] string name) |
|||
{ |
|||
Check.NotNull(settingProvider, nameof(settingProvider)); |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
return string.Equals( |
|||
await settingProvider.GetOrNullAsync(name), |
|||
"true", |
|||
StringComparison.OrdinalIgnoreCase |
|||
); |
|||
} |
|||
|
|||
public static async Task<T> GetAsync<T>([NotNull] this ISettingProvider settingProvider, [NotNull] string name, T defaultValue = default) |
|||
where T : struct |
|||
{ |
|||
Check.NotNull(settingProvider, nameof(settingProvider)); |
|||
Check.NotNull(name, nameof(name)); |
|||
|
|||
var value = await settingProvider.GetOrNullAsync(name); |
|||
return value?.To<T>() ?? defaultValue; |
|||
} |
|||
|
|||
public static string GetOrNull([NotNull] this ISettingProvider settingProvider, [NotNull] string name) |
|||
{ |
|||
Check.NotNull(settingProvider, nameof(settingProvider)); |
|||
return AsyncHelper.RunSync(() => settingProvider.GetOrNullAsync(name)); |
|||
} |
|||
|
|||
public static List<SettingValue> GetAll([NotNull] this ISettingProvider settingProvider) |
|||
{ |
|||
Check.NotNull(settingProvider, nameof(settingProvider)); |
|||
return AsyncHelper.RunSync(settingProvider.GetAllAsync); |
|||
} |
|||
|
|||
public static T Get<T>([NotNull] this ISettingProvider settingProvider, [NotNull] string name, T defaultValue = default) |
|||
where T : struct |
|||
{ |
|||
return AsyncHelper.RunSync(() => settingProvider.GetAsync(name, defaultValue)); |
|||
} |
|||
|
|||
public static bool IsTrue([NotNull] this ISettingProvider settingProvider, [NotNull] string name) |
|||
{ |
|||
return AsyncHelper.RunSync(() => settingProvider.IsTrueAsync(name)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
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) |
|||
{ |
|||
return await SettingStore.GetOrNullAsync(setting.Name, Name, CurrentTenant.Id?.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Users; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
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) |
|||
{ |
|||
if (CurrentUser.Id == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return await SettingStore.GetOrNullAsync(setting.Name, Name, CurrentUser.Id.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,53 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
public class SettingManager_Tests : AbpIntegratedTest<AbpSettingsTestModule> |
|||
{ |
|||
private readonly ISettingManager _settingManager; |
|||
|
|||
public SettingManager_Tests() |
|||
{ |
|||
_settingManager = GetRequiredService<ISettingManager>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Get_Null_If_No_Value_Provided_And_No_Default_Value() |
|||
{ |
|||
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingWithoutDefaultValue)) |
|||
.ShouldBeNull(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Get_Default_Value_If_No_Value_Provided_And_There_Is_A_Default_Value() |
|||
{ |
|||
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingWithDefaultValue)) |
|||
.ShouldBe("default-value"); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(null)] |
|||
[InlineData("")] |
|||
[InlineData("abc")] |
|||
[InlineData("This is a relatively long text... This is a relatively long text... This is a relatively long text... ")] |
|||
public async Task Should_Set_And_Get_Encrypted_Values(string plainValue) |
|||
{ |
|||
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingEncrypted)) |
|||
.ShouldBeNull(); |
|||
|
|||
await _settingManager.SetAsync( |
|||
TestSettingNames.TestSettingEncrypted, |
|||
plainValue, |
|||
TestSettingValueProvider.ProviderName, |
|||
null |
|||
); |
|||
|
|||
(await _settingManager.GetOrNullAsync(TestSettingNames.TestSettingEncrypted)) |
|||
.ShouldBe(plainValue); |
|||
} |
|||
|
|||
//TODO: Needs more tests with more advanced scenarios.
|
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
using System.Threading.Tasks; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Settings |
|||
{ |
|||
public class SettingProvider_Tests : AbpIntegratedTest<AbpSettingsTestModule> |
|||
{ |
|||
private readonly ISettingProvider _settingProvider; |
|||
|
|||
public SettingProvider_Tests() |
|||
{ |
|||
_settingProvider = GetRequiredService<ISettingProvider>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Get_Null_If_No_Value_Provided_And_No_Default_Value() |
|||
{ |
|||
(await _settingProvider.GetOrNullAsync(TestSettingNames.TestSettingWithoutDefaultValue)) |
|||
.ShouldBeNull(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Get_Default_Value_If_No_Value_Provided_And_There_Is_A_Default_Value() |
|||
{ |
|||
(await _settingProvider.GetOrNullAsync(TestSettingNames.TestSettingWithDefaultValue)) |
|||
.ShouldBe("default-value"); |
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +1,21 @@ |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.PermissionManagement.Localization; |
|||
|
|||
namespace Volo.Abp.PermissionManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpLocalizationModule) |
|||
)] |
|||
public class AbpPermissionManagementDomainSharedModule : AbpModule |
|||
{ |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<AbpPermissionManagementResource>("en"); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,10 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace Volo.Abp.PermissionManagement.Localization |
|||
{ |
|||
[LocalizationResourceName("AbpPermissionManagement")] |
|||
public class AbpPermissionManagementResource |
|||
{ |
|||
|
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue