mirror of https://github.com/abpframework/abp.git
13 changed files with 308 additions and 62 deletions
@ -0,0 +1,9 @@ |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.MultiTenancy; |
|||
|
|||
public interface IMultiTenantUrlProvider |
|||
{ |
|||
Task<string> GetUrlAsync(string templateUrl); |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.MultiTenancy; |
|||
|
|||
public class MultiTenantUrlProvider : IMultiTenantUrlProvider , ITransientDependency |
|||
{ |
|||
public const string TenantPlaceHolder = "{0}"; |
|||
public const string TenantIdPlaceHolder = "{{tenantId}}"; |
|||
public const string TenantNamePlaceHolder = "{{tenantName}}"; |
|||
|
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
protected ITenantStore TenantStore { get; } |
|||
|
|||
public MultiTenantUrlProvider( |
|||
ICurrentTenant currentTenant, |
|||
ITenantStore tenantStore) |
|||
{ |
|||
CurrentTenant = currentTenant; |
|||
TenantStore = tenantStore; |
|||
} |
|||
|
|||
public virtual async Task<string> GetUrlAsync(string templateUrl) |
|||
{ |
|||
return await ReplacePlaceHoldersAsync(templateUrl); |
|||
} |
|||
|
|||
protected virtual async Task<string> ReplacePlaceHoldersAsync(string templateUrl) |
|||
{ |
|||
templateUrl = await ReplacePlaceHolderAsync(templateUrl, TenantIdPlaceHolder); |
|||
|
|||
templateUrl = await ReplacePlaceHolderAsync(templateUrl, TenantNamePlaceHolder); |
|||
|
|||
templateUrl = await ReplacePlaceHolderAsync(templateUrl, TenantPlaceHolder); |
|||
|
|||
return templateUrl; |
|||
} |
|||
|
|||
protected virtual async Task<string> ReplacePlaceHolderAsync(string templateUrl, string placeHolder) |
|||
{ |
|||
if (!templateUrl.Contains(placeHolder)) |
|||
{ |
|||
return templateUrl; |
|||
} |
|||
|
|||
var placeHolderValue = string.Empty; |
|||
if (CurrentTenant.IsAvailable) |
|||
{ |
|||
placeHolderValue = (placeHolder == TenantIdPlaceHolder ? CurrentTenant.Id!.Value.ToString() : await GetCurrentTenantNameAsync()) + "."; |
|||
} |
|||
|
|||
if (templateUrl.Contains(placeHolder + '.')) |
|||
{ |
|||
placeHolder += '.'; |
|||
} |
|||
|
|||
templateUrl = templateUrl.Replace( |
|||
placeHolder, |
|||
placeHolderValue |
|||
); |
|||
|
|||
return templateUrl; |
|||
} |
|||
|
|||
protected virtual async Task<string> GetCurrentTenantNameAsync() |
|||
{ |
|||
if (CurrentTenant.Id.HasValue && CurrentTenant.Name.IsNullOrEmpty()) |
|||
{ |
|||
var tenantConfiguration = await TenantStore.FindAsync(CurrentTenant.Id.Value); |
|||
return tenantConfiguration!.Name; |
|||
} |
|||
|
|||
return CurrentTenant.Name!; |
|||
} |
|||
} |
|||
@ -1,25 +1,48 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.Http.Client; |
|||
|
|||
public class RemoteServiceConfigurationProvider : IRemoteServiceConfigurationProvider, IScopedDependency |
|||
{ |
|||
protected AbpRemoteServiceOptions Options { get; } |
|||
protected IMultiTenantUrlProvider MultiTenantUrlProvider { get; } |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
|
|||
public RemoteServiceConfigurationProvider(IOptionsMonitor<AbpRemoteServiceOptions> options) |
|||
public RemoteServiceConfigurationProvider( |
|||
IOptionsMonitor<AbpRemoteServiceOptions> options, |
|||
IMultiTenantUrlProvider multiTenantUrlProvider, |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
MultiTenantUrlProvider = multiTenantUrlProvider; |
|||
CurrentTenant = currentTenant; |
|||
Options = options.CurrentValue; |
|||
} |
|||
|
|||
public Task<RemoteServiceConfiguration> GetConfigurationOrDefaultAsync(string name) |
|||
public virtual async Task<RemoteServiceConfiguration> GetConfigurationOrDefaultAsync(string name) |
|||
{ |
|||
return Task.FromResult(Options.RemoteServices.GetConfigurationOrDefault(name)); |
|||
return (await GetMultiTenantConfigurationAsync(Options.RemoteServices.GetConfigurationOrDefault(name)))!; |
|||
} |
|||
|
|||
public Task<RemoteServiceConfiguration?> GetConfigurationOrDefaultOrNullAsync(string name) |
|||
public virtual async Task<RemoteServiceConfiguration?> GetConfigurationOrDefaultOrNullAsync(string name) |
|||
{ |
|||
return Task.FromResult(Options.RemoteServices.GetConfigurationOrDefaultOrNull(name)); |
|||
return await GetMultiTenantConfigurationAsync(Options.RemoteServices.GetConfigurationOrDefaultOrNull(name)); |
|||
} |
|||
|
|||
protected virtual async Task<RemoteServiceConfiguration?> GetMultiTenantConfigurationAsync(RemoteServiceConfiguration? configuration) |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
return configuration; |
|||
} |
|||
|
|||
var multiTenantConfiguration = new RemoteServiceConfiguration(configuration) |
|||
{ |
|||
BaseUrl = await MultiTenantUrlProvider.GetUrlAsync(configuration.BaseUrl) |
|||
}; |
|||
|
|||
return multiTenantConfiguration; |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,57 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.MultiTenancy.ConfigurationStore; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.MultiTenancy; |
|||
|
|||
public class MultiTenantUrlProivder_Tests : MultiTenancyTestBase |
|||
{ |
|||
private readonly ICurrentTenant _currentTenant; |
|||
private readonly IMultiTenantUrlProvider _multiTenantUrlProvider; |
|||
|
|||
private readonly Guid _tenantAId = Guid.NewGuid(); |
|||
|
|||
public MultiTenantUrlProivder_Tests() |
|||
{ |
|||
_currentTenant = ServiceProvider.GetRequiredService<ICurrentTenant>(); |
|||
_multiTenantUrlProvider = ServiceProvider.GetRequiredService<IMultiTenantUrlProvider>(); |
|||
} |
|||
protected override void BeforeAddApplication(IServiceCollection services) |
|||
{ |
|||
services.Configure<AbpDefaultTenantStoreOptions>(options => |
|||
{ |
|||
options.Tenants = |
|||
[ |
|||
new TenantConfiguration(_tenantAId, "TenantA") |
|||
]; |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetUrlAsync() |
|||
{ |
|||
var tenantNameHolderUrl = "https://{{tenantName}}.abp.io"; |
|||
var tenantIdHolderUrl = "https://{{tenantId}}.abp.io"; |
|||
var tenantHolderUrl = "https://{0}.abp.io"; |
|||
var hostUrl = "https://abp.io"; |
|||
|
|||
_currentTenant.Id.ShouldBeNull(); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantNameHolderUrl)).ShouldBe(hostUrl); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantIdHolderUrl)).ShouldBe(hostUrl); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantHolderUrl)).ShouldBe(hostUrl); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(hostUrl)).ShouldBe(hostUrl); |
|||
|
|||
using (_currentTenant.Change(_tenantAId)) |
|||
{ |
|||
_currentTenant.Id.ShouldBe(_tenantAId); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantNameHolderUrl)).ShouldBe("https://TenantA.abp.io"); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantIdHolderUrl)).ShouldBe("https://"+_tenantAId+".abp.io"); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(tenantHolderUrl)).ShouldBe("https://TenantA.abp.io"); |
|||
(await _multiTenantUrlProvider.GetUrlAsync(hostUrl)).ShouldBe(hostUrl); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\common.test.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net8.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.RemoteServices\Volo.Abp.RemoteServices.csproj" /> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" /> |
|||
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,8 @@ |
|||
using Volo.Abp.Testing; |
|||
|
|||
namespace Volo.Abp.Http.Client; |
|||
|
|||
public abstract class AbpRemoteServicesTestBase : AbpIntegratedTest<AbpRemoteServicesTestModule> |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.RemoteServices; |
|||
|
|||
namespace Volo.Abp.Http.Client; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpMultiTenancyModule), |
|||
typeof(AbpRemoteServicesModule) |
|||
)] |
|||
public class AbpRemoteServicesTestModule: AbpModule |
|||
{ |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.MultiTenancy.ConfigurationStore; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Http.Client; |
|||
|
|||
public class RemoteServiceConfigurationProvider_Tests : AbpRemoteServicesTestBase |
|||
{ |
|||
private readonly ICurrentTenant _currentTenant; |
|||
private readonly IRemoteServiceConfigurationProvider _remoteServiceConfigurationProvider; |
|||
private readonly Guid _tenantAId = Guid.NewGuid(); |
|||
|
|||
public RemoteServiceConfigurationProvider_Tests() |
|||
{ |
|||
_currentTenant = GetRequiredService<ICurrentTenant>(); |
|||
_remoteServiceConfigurationProvider = GetRequiredService<IRemoteServiceConfigurationProvider>(); |
|||
} |
|||
|
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
services.Configure<AbpRemoteServiceOptions>(options => |
|||
{ |
|||
options.RemoteServices[RemoteServiceConfigurationDictionary.DefaultName] = new RemoteServiceConfiguration("https://abp.io"); |
|||
options.RemoteServices["Identity"] = new RemoteServiceConfiguration("https://{{tenantName}}.abp.io"); |
|||
options.RemoteServices["Permission"] = new RemoteServiceConfiguration("https://{{tenantId}}.abp.io"); |
|||
options.RemoteServices["Setting"] = new RemoteServiceConfiguration("https://{0}.abp.io"); |
|||
}); |
|||
|
|||
services.Configure<AbpDefaultTenantStoreOptions>(options => |
|||
{ |
|||
options.Tenants = |
|||
[ |
|||
new TenantConfiguration(_tenantAId, "TenantA") |
|||
]; |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task GetConfigurationOrDefaultAsync() |
|||
{ |
|||
_currentTenant.Id.ShouldBeNull(); |
|||
|
|||
var defaultConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(RemoteServiceConfigurationDictionary.DefaultName); |
|||
defaultConfiguration.BaseUrl.ShouldBe("https://abp.io"); |
|||
|
|||
var identityConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Identity"); |
|||
identityConfiguration.BaseUrl.ShouldBe("https://abp.io"); |
|||
|
|||
var permissionConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Permission"); |
|||
permissionConfiguration.BaseUrl.ShouldBe("https://abp.io"); |
|||
|
|||
var settingConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Setting"); |
|||
settingConfiguration.BaseUrl.ShouldBe("https://abp.io"); |
|||
|
|||
using (_currentTenant.Change(_tenantAId, "TenantA")) |
|||
{ |
|||
defaultConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(RemoteServiceConfigurationDictionary.DefaultName); |
|||
defaultConfiguration.BaseUrl.ShouldBe("https://abp.io"); |
|||
|
|||
identityConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Identity"); |
|||
identityConfiguration.BaseUrl.ShouldBe($"https://{_currentTenant.Name}.abp.io"); |
|||
|
|||
permissionConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Permission"); |
|||
permissionConfiguration.BaseUrl.ShouldBe($"https://{_currentTenant.Id}.abp.io"); |
|||
|
|||
settingConfiguration = await _remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync("Setting"); |
|||
settingConfiguration.BaseUrl.ShouldBe($"https://{_currentTenant.Name}.abp.io"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue