diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs index 917870aa9d..945c930175 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobContainerConfigurationExtensions.cs @@ -12,11 +12,11 @@ namespace Volo.Abp.BlobStoring.Azure public static BlobContainerConfiguration UseAzure( this BlobContainerConfiguration containerConfiguration, - Action fileSystemConfigureAction) + Action azureConfigureAction) { containerConfiguration.ProviderType = typeof(AzureBlobProvider); - fileSystemConfigureAction(new AzureBlobProviderConfiguration(containerConfiguration)); + azureConfigureAction(new AzureBlobProviderConfiguration(containerConfiguration)); return containerConfiguration; } diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index eb69bb802a..e0b70dc66c 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -1,15 +1,24 @@ using System.IO; using System.Threading.Tasks; using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Specialized; using Volo.Abp.DependencyInjection; namespace Volo.Abp.BlobStoring.Azure { public class AzureBlobProvider : BlobProviderBase, ITransientDependency { + protected IAzureBlobNameCalculator AzureBlobNameCalculator { get; } + + public AzureBlobProvider(IAzureBlobNameCalculator azureBlobNameCalculator) + { + AzureBlobNameCalculator = azureBlobNameCalculator; + } + public override async Task SaveAsync(BlobProviderSaveArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); if (!args.OverrideExisting && await BlobExistsAsync(blobClient)) { @@ -21,24 +30,22 @@ namespace Volo.Abp.BlobStoring.Azure public override async Task DeleteAsync(BlobProviderDeleteArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); - if (await BlobExistsAsync(blobClient)) - { - return (await blobClient.DeleteAsync()).Status == 200; - } - - return false; + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); + return await blobClient.DeleteIfExistsAsync(); } public override async Task ExistsAsync(BlobProviderExistsArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); return await BlobExistsAsync(blobClient); } public override async Task GetOrNullAsync(BlobProviderGetArgs args) { - var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName); + var blobName = AzureBlobNameCalculator.Calculate(args); + var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), blobName); if (!await BlobExistsAsync(blobClient)) { return null; @@ -62,7 +69,7 @@ namespace Volo.Abp.BlobStoring.Azure return blobServiceClient.GetBlobContainerClient(configuration.ContainerName); } - private static async Task BlobExistsAsync(BlobClient blobClient) + private static async Task BlobExistsAsync(BlobBaseClient blobClient) { return (await blobClient.ExistsAsync()).Value; } diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/DefaultAzureBlobNameCalculator.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/DefaultAzureBlobNameCalculator.cs new file mode 100644 index 0000000000..0c6cd481c9 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/DefaultAzureBlobNameCalculator.cs @@ -0,0 +1,22 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.BlobStoring.Azure +{ + public class DefaultAzureBlobNameCalculator : IAzureBlobNameCalculator, ITransientDependency + { + protected ICurrentTenant CurrentTenant { get; } + + public DefaultAzureBlobNameCalculator(ICurrentTenant currentTenant) + { + CurrentTenant = currentTenant; + } + + public virtual string Calculate(BlobProviderArgs args) + { + return CurrentTenant.Id == null + ? $"host/{args.BlobName}" + : $"tenants/{CurrentTenant.Id.Value.ToString("D")}/{args.BlobName}"; + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/IAzureBlobNameCalculator.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/IAzureBlobNameCalculator.cs new file mode 100644 index 0000000000..5985a9278d --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/IAzureBlobNameCalculator.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.BlobStoring.Azure +{ + public interface IAzureBlobNameCalculator + { + string Calculate(BlobProviderArgs args); + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs index 7213c8eb78..8941234cbf 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs @@ -2,6 +2,14 @@ namespace Volo.Abp.BlobStoring.Azure { + public class AbpBlobStoringAzureTestCommonBase : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + } + public class AbpBlobStoringAzureTestBase : AbpIntegratedTest { protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs index 4711699726..a45d209b32 100644 --- a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs @@ -6,10 +6,22 @@ using Volo.Abp.Modularity; namespace Volo.Abp.BlobStoring.Azure { + + /// + /// This module will not try to connect to azure. + /// [DependsOn( typeof(AbpBlobStoringAzureModule), typeof(AbpBlobStoringTestModule) )] + public class AbpBlobStoringAzureTestCommonModule : AbpModule + { + + } + + [DependsOn( + typeof(AbpBlobStoringAzureTestCommonModule) + )] public class AbpBlobStoringAzureTestModule : AbpModule { private const string UserSecretsId = "9f0d2c00-80c1-435b-bfab-2c39c8249091"; @@ -47,9 +59,9 @@ namespace Volo.Abp.BlobStoring.Azure public override void OnApplicationShutdown(ApplicationShutdownContext context) { - var configuration = context.ServiceProvider.GetRequiredService(); var blobServiceClient = new BlobServiceClient(_connectionString); blobServiceClient.DeleteBlobContainer(_randomContainerName); } } + } diff --git a/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobNameCalculator_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobNameCalculator_Tests.cs new file mode 100644 index 0000000000..4540d208ae --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobNameCalculator_Tests.cs @@ -0,0 +1,57 @@ +using System; +using Shouldly; +using Volo.Abp.MultiTenancy; +using Xunit; + +namespace Volo.Abp.BlobStoring.Azure +{ + public class AzureBlobNameCalculator_Tests : AbpBlobStoringAzureTestCommonBase + { + private readonly IAzureBlobNameCalculator _calculator; + private readonly ICurrentTenant _currentTenant; + + private const string AzureContainerName = "/"; + private const string AzureSeparator = "/"; + + public AzureBlobNameCalculator_Tests() + { + _calculator = GetRequiredService(); + _currentTenant = GetRequiredService(); + } + + [Fact] + public void Default_Settings() + { + _calculator.Calculate( + GetArgs("my-container", "my-blob") + ).ShouldBe($"host{AzureSeparator}my-blob"); + } + + [Fact] + public void Default_Settings_With_TenantId() + { + var tenantId = Guid.NewGuid(); + + using (_currentTenant.Change(tenantId)) + { + _calculator.Calculate( + GetArgs("my-container", "my-blob") + ).ShouldBe($"tenants{AzureSeparator}{tenantId:D}{AzureSeparator}my-blob"); + } + } + + private static BlobProviderArgs GetArgs( + string containerName, + string blobName) + { + return new BlobProviderGetArgs( + containerName, + new BlobContainerConfiguration().UseAzure(x => + { + x.ContainerName = containerName; + }), + blobName + ); + } + } +}