Browse Source

Add IMultiTenantUrlProvider

pull/18592/head
liangshiwei 2 years ago
parent
commit
38aba327cc
  1. 7
      framework/Volo.Abp.sln
  2. 9
      framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IMultiTenantUrlProvider.cs
  3. 78
      framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantUrlProvider.cs
  4. 1
      framework/src/Volo.Abp.RemoteServices/Volo.Abp.RemoteServices.csproj
  5. 8
      framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfiguration.cs
  6. 33
      framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationProvider.cs
  7. 2
      framework/src/Volo.Abp.RemoteServices/Volo/Abp/RemoteServices/AbpRemoteServicesModule.cs
  8. 63
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs
  9. 57
      framework/test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/MultiTenancy/MultiTenantUrlProivder_Tests.cs
  10. 17
      framework/test/Volo.Abp.RemoteServices.Tests/Volo.Abp.RemoteServices.Tests.csproj
  11. 8
      framework/test/Volo.Abp.RemoteServices.Tests/Volo/Abp/Http/Client/AbpRemoteServicesTestBase.cs
  12. 13
      framework/test/Volo.Abp.RemoteServices.Tests/Volo/Abp/Http/Client/AbpRemoteServicesTestModule.cs
  13. 74
      framework/test/Volo.Abp.RemoteServices.Tests/Volo/Abp/Http/Client/RemoteServiceConfigurationProvider_Tests.cs

7
framework/Volo.Abp.sln

@ -463,6 +463,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.SkiaSharp"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.SkiaSharp.Tests", "test\Volo.Abp.Imaging.SkiaSharp.Tests\Volo.Abp.Imaging.SkiaSharp.Tests.csproj", "{DFAF8763-D1D6-4EB4-B459-20E31007FE2F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RemoteServices.Tests", "test\Volo.Abp.RemoteServices.Tests\Volo.Abp.RemoteServices.Tests.csproj", "{DACD4485-61BE-4DE5-ACAE-4FFABC122500}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1381,6 +1383,10 @@ Global
{DFAF8763-D1D6-4EB4-B459-20E31007FE2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DFAF8763-D1D6-4EB4-B459-20E31007FE2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DFAF8763-D1D6-4EB4-B459-20E31007FE2F}.Release|Any CPU.Build.0 = Release|Any CPU
{DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1614,6 +1620,7 @@ Global
{F19A6E0C-F719-4ED9-A024-14E4B8D40883} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{198683D0-7DC6-40F2-B81B-8E446E70A9DE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DFAF8763-D1D6-4EB4-B459-20E31007FE2F} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{DACD4485-61BE-4DE5-ACAE-4FFABC122500} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

9
framework/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IMultiTenantUrlProvider.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.MultiTenancy;
public interface IMultiTenantUrlProvider
{
Task<string> GetUrlAsync(string templateUrl);
}

78
framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenantUrlProvider.cs

@ -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
framework/src/Volo.Abp.RemoteServices/Volo.Abp.RemoteServices.csproj

@ -18,6 +18,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
</ItemGroup>
</Project>

8
framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfiguration.cs

@ -30,4 +30,12 @@ public class RemoteServiceConfiguration : Dictionary<string, string?>
this[nameof(BaseUrl)] = baseUrl;
this[nameof(Version)] = version;
}
public RemoteServiceConfiguration(RemoteServiceConfiguration configuration)
{
foreach (var keyValuePair in configuration)
{
this.Add(keyValuePair.Key, keyValuePair.Value);
}
}
}

33
framework/src/Volo.Abp.RemoteServices/Volo/Abp/Http/Client/RemoteServiceConfigurationProvider.cs

@ -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;
}
}

2
framework/src/Volo.Abp.RemoteServices/Volo/Abp/RemoteServices/AbpRemoteServicesModule.cs

@ -1,9 +1,11 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.RemoteServices;
[DependsOn(typeof(AbpMultiTenancyAbstractionsModule))]
public class AbpRemoteServicesModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

63
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Urls/AppUrlProvider.cs

@ -13,29 +13,23 @@ namespace Volo.Abp.UI.Navigation.Urls;
public class AppUrlProvider : IAppUrlProvider, ITransientDependency
{
public const string TenantIdPlaceHolder = "{{tenantId}}";
public const string TenantNamePlaceHolder = "{{tenantName}}";
protected AppUrlOptions Options { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ITenantStore TenantStore { get; }
protected IMultiTenantUrlProvider MultiTenantUrlProvider { get; }
public ILogger<AppUrlProvider> Logger { get; set; }
public AppUrlProvider(
IOptions<AppUrlOptions> options,
ICurrentTenant currentTenant,
ITenantStore tenantStore)
IMultiTenantUrlProvider multiTenantUrlProvider)
{
CurrentTenant = currentTenant;
TenantStore = tenantStore;
MultiTenantUrlProvider = multiTenantUrlProvider;
Options = options.Value;
Logger = NullLogger<AppUrlProvider>.Instance;
}
public virtual async Task<string> GetUrlAsync(string appName, string? urlName = null)
{
return await ReplacePlaceHoldersAsync(
return await MultiTenantUrlProvider.GetUrlAsync(
await GetConfiguredUrl(
appName,
urlName
@ -59,8 +53,8 @@ public class AppUrlProvider : IAppUrlProvider, ITransientDependency
{
return url;
}
return await ReplacePlaceHoldersAsync(url!);
return await MultiTenantUrlProvider.GetUrlAsync(url!);
}
protected virtual async Task<string> GetConfiguredUrl(string appName, string? urlName)
@ -83,51 +77,6 @@ public class AppUrlProvider : IAppUrlProvider, ITransientDependency
);
}
protected virtual async Task<string> ReplacePlaceHoldersAsync(string url)
{
url = url.Replace(
TenantIdPlaceHolder,
CurrentTenant.Id.HasValue ? CurrentTenant.Id.Value.ToString() : ""
);
if (!url.Contains(TenantNamePlaceHolder))
{
return url;
}
var tenantNamePlaceHolder = TenantNamePlaceHolder;
if (url.Contains(TenantNamePlaceHolder + '.'))
{
tenantNamePlaceHolder = TenantNamePlaceHolder + '.';
}
if (url.Contains(tenantNamePlaceHolder))
{
if (CurrentTenant.Id.HasValue)
{
url = url.Replace(tenantNamePlaceHolder, await GetCurrentTenantNameAsync() + ".");
}
else
{
url = url.Replace(tenantNamePlaceHolder, "");
}
}
return url;
}
private 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!;
}
public Task<string?> GetUrlOrNullAsync([NotNull] string appName, string? urlName = null)
{
var app = Options.Applications[appName];

57
framework/test/Volo.Abp.MultiTenancy.Tests/Volo/Abp/MultiTenancy/MultiTenantUrlProivder_Tests.cs

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

17
framework/test/Volo.Abp.RemoteServices.Tests/Volo.Abp.RemoteServices.Tests.csproj

@ -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>

8
framework/test/Volo.Abp.RemoteServices.Tests/Volo/Abp/Http/Client/AbpRemoteServicesTestBase.cs

@ -0,0 +1,8 @@
using Volo.Abp.Testing;
namespace Volo.Abp.Http.Client;
public abstract class AbpRemoteServicesTestBase : AbpIntegratedTest<AbpRemoteServicesTestModule>
{
}

13
framework/test/Volo.Abp.RemoteServices.Tests/Volo/Abp/Http/Client/AbpRemoteServicesTestModule.cs

@ -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
{
}

74
framework/test/Volo.Abp.RemoteServices.Tests/Volo/Abp/Http/Client/RemoteServiceConfigurationProvider_Tests.cs

@ -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…
Cancel
Save