From a547c6b0384e6f4fd44bc8d37ccb4608fa26182c Mon Sep 17 00:00:00 2001 From: "nuck.tang" Date: Wed, 15 Jul 2020 10:10:57 +0800 Subject: [PATCH] Add MinioBlobNamingNormalizer --- .gitignore | 8 --- .../Minio/MinioBlobNamingNormalizer.cs | 52 +++++++++++++++++ .../BlobStoring/Minio/MinioBlobProvider.cs | 17 ++---- .../Minio/AbpBlobStoringMinioTestModule.cs | 18 +++--- ...MinioBlobNamingNormalizerProvider_Tests.cs | 57 +++++++++++++++++++ .../Minio/MinioBlobContainer_Tests.cs | 5 +- 6 files changed, 127 insertions(+), 30 deletions(-) create mode 100644 framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobNamingNormalizer.cs create mode 100644 framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/DefaultMinioBlobNamingNormalizerProvider_Tests.cs diff --git a/.gitignore b/.gitignore index 2058b364a5..1f14485237 100644 --- a/.gitignore +++ b/.gitignore @@ -304,11 +304,3 @@ modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/Logs/ /templates/app/angular/package-lock.json /modules/client-simulation/demo/Volo.ClientSimulation.Demo/package-lock.json -/framework/src/Volo.Abp.AspNetCore/Properties/launchSettings.json -/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Properties/launchSettings.json -/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Properties/launchSettings.json -/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Properties/launchSettings.json -/framework/src/Volo.Abp.AspNetCore.Serilog/Properties/launchSettings.json -/framework/src/Volo.Abp.AspNetCore.SignalR/Properties/launchSettings.json -/framework/src/Volo.Abp.AspNetCore.TestBase/Properties/launchSettings.json -/framework/src/Volo.Abp.Http.Client.IdentityModel.Web/Properties/launchSettings.json diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobNamingNormalizer.cs b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobNamingNormalizer.cs new file mode 100644 index 0000000000..d350910105 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobNamingNormalizer.cs @@ -0,0 +1,52 @@ +using System.Text.RegularExpressions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.BlobStoring.Minio +{ + public class MinioBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency + { + /// + ///https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html + /// + public virtual string NormalizeContainerName(string containerName) + { + // All letters in a container name must be lowercase. + containerName = containerName.ToLower(); + + // Container names can contain only letters, numbers, and the dash (-) character. + containerName = Regex.Replace(containerName, "[^a-z0-9-]", string.Empty); + + // Every dash (-) character must be immediately preceded and followed by a letter or number; + // consecutive dashes are not permitted in container names. + // Container names must start or end with a letter or number + containerName = Regex.Replace(containerName, "-{2,}", "-"); + containerName = Regex.Replace(containerName, "^-", string.Empty); + containerName = Regex.Replace(containerName, "-$", string.Empty); + + // Container names must be from 3 through 63 characters long. + if (containerName.Length < 3) + { + var length = containerName.Length; + for (var i = 0; i < 3 - length; i++) + { + containerName += "0"; + } + } + + if (containerName.Length > 63) + { + containerName = containerName.Substring(0, 63); + } + + return containerName; + } + + /// + /// https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html + /// + public virtual string NormalizeBlobName(string blobName) + { + return blobName; + } + } +} diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs index 54824b4ac4..2d1585542c 100644 --- a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs @@ -115,10 +115,6 @@ namespace Volo.Abp.BlobStoring.Minio { try { - // Check whether the object exists using statObject(). - // If the object is not found, statObject() throws an exception, - // else it means that the object exists. - // Execution is successful. await client.StatObjectAsync(containerName, blobName); } catch (Exception e) @@ -126,11 +122,9 @@ namespace Volo.Abp.BlobStoring.Minio if (e is ObjectNotFoundException) { return false; - } - else - { - throw e; - } + } + + throw; } return true; @@ -143,10 +137,9 @@ namespace Volo.Abp.BlobStoring.Minio { var configuration = args.Configuration.GetMinioConfiguration(); - //Minio bucket name must be lowercase return configuration.BucketName.IsNullOrWhiteSpace() - ? args.ContainerName.ToLower() - : configuration.BucketName.ToLower(); + ? args.ContainerName + : configuration.BucketName; } } } diff --git a/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioTestModule.cs b/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioTestModule.cs index a65222c8c9..71d780e880 100644 --- a/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioTestModule.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reactive.Linq; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Minio; @@ -59,18 +60,19 @@ namespace Volo.Abp.BlobStoring.Minio }); } - public async override void OnApplicationShutdown(ApplicationShutdownContext context) + public override async void OnApplicationShutdown(ApplicationShutdownContext context) { var minioClient = new MinioClient(_endPoint, _accessKey, _secretKey); if (await minioClient.BucketExistsAsync(_randomContainerName)) { - var observables =minioClient.ListObjectsAsync(_randomContainerName,null,true); - var objectNames = new List(); - IDisposable subscription = observables.Subscribe( - async item => await minioClient.RemoveObjectAsync(_randomContainerName, item.Key), - async () => await minioClient.RemoveBucketAsync(_randomContainerName) - ); - + var objects = await minioClient.ListObjectsAsync(_randomContainerName, null, true).ToList(); + + foreach (var item in objects) + { + await minioClient.RemoveObjectAsync(_randomContainerName, item.Key); + } + + await minioClient.RemoveBucketAsync(_randomContainerName); } } diff --git a/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/DefaultMinioBlobNamingNormalizerProvider_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/DefaultMinioBlobNamingNormalizerProvider_Tests.cs new file mode 100644 index 0000000000..ae7c4fab75 --- /dev/null +++ b/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/DefaultMinioBlobNamingNormalizerProvider_Tests.cs @@ -0,0 +1,57 @@ +using Shouldly; +using Xunit; + +namespace Volo.Abp.BlobStoring.Minio +{ + public class DefaultMinioBlobNamingNormalizerProvider_Tests : AbpBlobStoringMinioTestCommonBase + { + private readonly IBlobNamingNormalizer _blobNamingNormalizer; + + public DefaultMinioBlobNamingNormalizerProvider_Tests() + { + _blobNamingNormalizer = GetRequiredService(); + } + + [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); + } + } +} diff --git a/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/MinioBlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/MinioBlobContainer_Tests.cs index a9c2776714..8ee92274ad 100644 --- a/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/MinioBlobContainer_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Minio.Tests/Volo/Abp/BlobStoring/Minio/MinioBlobContainer_Tests.cs @@ -2,7 +2,7 @@ namespace Volo.Abp.BlobStoring.Minio { - /* + //Please set the correct connection string in secrets.json and continue the test. public class MinioBlobContainer_Tests : BlobContainer_Tests @@ -10,7 +10,8 @@ namespace Volo.Abp.BlobStoring.Minio public MinioBlobContainer_Tests() { + } } - */ + }