mirror of https://github.com/abpframework/abp.git
15 changed files with 362 additions and 45 deletions
@ -0,0 +1,12 @@ |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aws |
|||
{ |
|||
[DependsOn(typeof(AbpBlobStoringModule), |
|||
typeof(AbpCachingModule))] |
|||
public class AbpBlobStoringAwsModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -1,10 +0,0 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Azure |
|||
{ |
|||
[DependsOn(typeof(AbpBlobStoringModule))] |
|||
public class AbpBlobStoringAzureModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aws |
|||
{ |
|||
public class DefaultAwsBlobNameCalculator : IAwsBlobNameCalculator, ITransientDependency |
|||
{ |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
|
|||
public DefaultAwsBlobNameCalculator(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}"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\common.test.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<UserSecretsId>9f0d2c00-80c1-435b-bfab-2c39c8249091</UserSecretsId> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.BlobStoring.Aws\Volo.Abp.BlobStoring.Aws.csproj" /> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
|||
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" /> |
|||
<ProjectReference Include="..\Volo.Abp.BlobStoring.Tests\Volo.Abp.BlobStoring.Tests.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,20 @@ |
|||
using Volo.Abp.Testing; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aws |
|||
{ |
|||
public class AbpBlobStoringAwsTestCommonBase : AbpIntegratedTest<AbpBlobStoringAwsTestCommonModule> |
|||
{ |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
options.UseAutofac(); |
|||
} |
|||
} |
|||
|
|||
public class AbpBlobStoringAwsTestBase : AbpIntegratedTest<AbpBlobStoringAwsTestModule> |
|||
{ |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
options.UseAutofac(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Amazon.S3.Model; |
|||
using Amazon.S3.Util; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Threading; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aws |
|||
{ |
|||
/// <summary>
|
|||
/// This module will not try to connect to aws.
|
|||
/// </summary>
|
|||
[DependsOn( |
|||
typeof(AbpBlobStoringAwsModule), |
|||
typeof(AbpBlobStoringTestModule) |
|||
)] |
|||
public class AbpBlobStoringAwsTestCommonModule : AbpModule |
|||
{ |
|||
} |
|||
|
|||
[DependsOn( |
|||
typeof(AbpBlobStoringAwsTestCommonModule) |
|||
)] |
|||
public class AbpBlobStoringAwsTestModule : AbpModule |
|||
{ |
|||
private const string UserSecretsId = "9f0d2c00-80c1-435b-bfab-2c39c8249091"; |
|||
|
|||
private readonly string _randomContainerName = "abp-aws-test-container-" + Guid.NewGuid().ToString("N"); |
|||
|
|||
private AwsBlobProviderConfiguration _configuration; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder => |
|||
{ |
|||
builder.AddUserSecrets(UserSecretsId); |
|||
})); |
|||
|
|||
var configuration = context.Services.GetConfiguration(); |
|||
var accessKeyId = configuration["Aws:AccessKeyId"]; |
|||
var secretAccessKey = configuration["Aws:SecretAccessKey"]; |
|||
var region = configuration["Aws:Region"]; |
|||
|
|||
Configure<AbpBlobStoringOptions>(options => |
|||
{ |
|||
options.Containers.ConfigureAll((containerName, containerConfiguration) => |
|||
{ |
|||
containerConfiguration.UseAws(aws => |
|||
{ |
|||
aws.AccessKeyId = accessKeyId; |
|||
aws.SecretAccessKey = secretAccessKey; |
|||
aws.Region = region; |
|||
aws.CreateContainerIfNotExists = true; |
|||
|
|||
_configuration = aws; |
|||
}); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
public override void OnApplicationShutdown(ApplicationShutdownContext context) |
|||
{ |
|||
AsyncHelper.RunSync(() => DeleteBucketAsync(context)); |
|||
} |
|||
|
|||
private async Task DeleteBucketAsync(ApplicationShutdownContext context) |
|||
{ |
|||
var amazonS3Client = await context.ServiceProvider.GetService<IAmazonS3ClientFactory>() |
|||
.GetAmazonS3Client(_configuration); |
|||
|
|||
if (await AmazonS3Util.DoesS3BucketExistV2Async(amazonS3Client, _randomContainerName)) |
|||
{ |
|||
var blobs = await amazonS3Client.ListObjectsAsync(_randomContainerName); |
|||
|
|||
if (blobs.S3Objects.Any()) |
|||
{ |
|||
await amazonS3Client.DeleteObjectsAsync(new DeleteObjectsRequest |
|||
{ |
|||
BucketName = _randomContainerName, |
|||
Objects = blobs.S3Objects.Select(o => new KeyVersion {Key = o.Key}).ToList() |
|||
}); |
|||
} |
|||
|
|||
await amazonS3Client.DeleteBucketAsync(_randomContainerName); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aws |
|||
{ |
|||
/* |
|||
//Please set the correct connection string in secrets.json and continue the test.
|
|||
|
|||
public class AwsBlobContainer_Tests : BlobContainer_Tests<AbpBlobStoringAwsTestModule> |
|||
{ |
|||
public AwsBlobContainer_Tests() |
|||
{ |
|||
|
|||
} |
|||
} |
|||
*/ |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
using System; |
|||
using Shouldly; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aws |
|||
{ |
|||
public class AwsBlobNameCalculatorTests : AbpBlobStoringAwsTestCommonBase |
|||
{ |
|||
private readonly IAwsBlobNameCalculator _calculator; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
private const string AwsContainerName = "/"; |
|||
private const string AwsSeparator = "/"; |
|||
|
|||
public AwsBlobNameCalculatorTests() |
|||
{ |
|||
_calculator = GetRequiredService<IAwsBlobNameCalculator>(); |
|||
_currentTenant = GetRequiredService<ICurrentTenant>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Default_Settings() |
|||
{ |
|||
_calculator.Calculate( |
|||
GetArgs("my-container", "my-blob") |
|||
).ShouldBe($"host{AwsSeparator}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{AwsSeparator}{tenantId:D}{AwsSeparator}my-blob"); |
|||
} |
|||
} |
|||
|
|||
private static BlobProviderArgs GetArgs( |
|||
string containerName, |
|||
string blobName) |
|||
{ |
|||
return new BlobProviderGetArgs( |
|||
containerName, |
|||
new BlobContainerConfiguration().UseAws(x => |
|||
{ |
|||
x.ContainerName = containerName; |
|||
}), |
|||
blobName |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aws |
|||
{ |
|||
public class DefaultAwsBlobNamingNormalizerProviderTests : AbpBlobStoringAwsTestCommonBase |
|||
{ |
|||
private readonly IBlobNamingNormalizer _blobNamingNormalizer; |
|||
|
|||
public DefaultAwsBlobNamingNormalizerProviderTests() |
|||
{ |
|||
_blobNamingNormalizer = GetRequiredService<IBlobNamingNormalizer>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Lowercase() |
|||
{ |
|||
var filename = "ThisIsMyContainerName"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.ShouldBe("thisismycontainername"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Only_Letters_Numbers_Dash() |
|||
{ |
|||
var filename = ",./this-i,./s-my-c,./ont,./ai+*/.=!@#$n^&*er-name.+/"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.ShouldBe("this-is-my-container-name"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Dash() |
|||
{ |
|||
var filename = "-this--is----my-container----name-"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.ShouldBe("this-is-my-container-name"); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Min_Length() |
|||
{ |
|||
var filename = "a"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.Length.ShouldBeGreaterThanOrEqualTo(3); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Max_Length() |
|||
{ |
|||
var filename = "abpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabp"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.Length.ShouldBeLessThanOrEqualTo(63); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue