From 6be80447b4da0d7507490965bcf1649a6ed0255f Mon Sep 17 00:00:00 2001
From: cKey <35512826+colinin@users.noreply.github.com>
Date: Fri, 19 Jun 2020 11:59:46 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=98=BF=E9=87=8C=E4=BA=91?=
=?UTF-8?q?=E5=85=AC=E5=85=B1=E8=AE=BF=E9=97=AE=E6=A8=A1=E5=9D=97;?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=98=BF=E9=87=8C=E4=BA=91Oss=E5=AF=B9?=
=?UTF-8?q?=E8=B1=A1=E5=AD=98=E5=82=A8Abp=E6=89=A9=E5=B1=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../LINGYUN.Abp.Aliyun.Authorization.csproj | 12 ++
.../AbpAliyunAuthorizationModule.cs | 15 ++
.../Aliyun/Authorization/AbpAliyunOptions.cs | 14 ++
.../LINGYUN.Abp.BlobStoring.Aliyun.csproj | 25 +++
.../Aliyun/AbpBlobStoringAliyunModule.cs | 35 +++++
...yunBlobContainerConfigurationExtensions.cs | 25 +++
.../BlobStoring/Aliyun/AliyunBlobProvider.cs | 148 ++++++++++++++++++
.../Aliyun/AliyunBlobProviderConfiguration.cs | 62 ++++++++
.../AliyunBlobProviderConfigurationNames.cs | 22 +++
.../Aliyun/DefaultAliyunBlobNameCalculator.cs | 24 +++
.../Aliyun/IAliyunBlobNameCalculator.cs | 9 ++
.../LINGYUN.Abp.Sms.Aliyun.csproj | 4 +
.../Abp/Sms/Aliyun/AbpAliyunSmsModule.cs | 6 +-
.../LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs | 8 -
.../LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs | 9 +-
...INGYUN.Abp.BlobStoring.Aliyun.Tests.csproj | 18 +++
.../Aliyun/AbpBlobStoringAliyunTestBase.cs | 9 ++
.../Aliyun/AbpBlobStoringAliyunTestModule.cs | 56 +++++++
.../BlobStoring/Aliyun/BlobContainer_Tests.cs | 99 ++++++++++++
.../BlobStoring/TestObjects/TestContainer1.cs | 6 +
.../LINGYUN.Abp.TestsBase.csproj | 21 +++
.../LINGYUN/Abp/Tests/AbpTestsBase.cs | 59 +++++++
.../LINGYUN/Abp/Tests/AbpTestsBaseModule.cs | 21 +++
23 files changed, 695 insertions(+), 12 deletions(-)
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN.Abp.Aliyun.Authorization.csproj
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunAuthorizationModule.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunOptions.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobContainerConfigurationExtensions.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfigurationNames.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/DefaultAliyunBlobNameCalculator.cs
create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IAliyunBlobNameCalculator.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj
create mode 100644 aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestBase.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/BlobContainer_Tests.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN.Abp.TestsBase.csproj
create mode 100644 aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBase.cs
create mode 100644 aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBaseModule.cs
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN.Abp.Aliyun.Authorization.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN.Abp.Aliyun.Authorization.csproj
new file mode 100644
index 000000000..8be61f7bf
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN.Abp.Aliyun.Authorization.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunAuthorizationModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunAuthorizationModule.cs
new file mode 100644
index 000000000..1dc254e80
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunAuthorizationModule.cs
@@ -0,0 +1,15 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Aliyun.Authorization
+{
+ public class AbpAliyunAuthorizationModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+
+ Configure(configuration.GetSection("Aliyun:Auth"));
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunOptions.cs
new file mode 100644
index 000000000..7d90f6da9
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Aliyun.Authorization/LINGYUN/Abp/Aliyun/Authorization/AbpAliyunOptions.cs
@@ -0,0 +1,14 @@
+namespace LINGYUN.Abp.Aliyun.Authorization
+{
+ public class AbpAliyunOptions
+ {
+ ///
+ /// 访问标识
+ ///
+ public string AccessKeyId { get; set; }
+ ///
+ /// 访问密钥
+ ///
+ public string AccessKeySecret { get; set; }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj
new file mode 100644
index 000000000..92d56b011
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN.Abp.BlobStoring.Aliyun.csproj
@@ -0,0 +1,25 @@
+
+
+
+ netstandard2.0
+
+ true
+ 2.9.0
+ LINGYUN
+ 阿里云Oss对象存储Abp集成
+
+
+
+ D:\LocalNuget
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs
new file mode 100644
index 000000000..4e77d7030
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunModule.cs
@@ -0,0 +1,35 @@
+using LINGYUN.Abp.Aliyun.Authorization;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using System.Collections.Generic;
+using Volo.Abp.BlobStoring;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ [DependsOn(
+ typeof(AbpBlobStoringModule),
+ typeof(AbpAliyunAuthorizationModule))]
+ public class AbpBlobStoringAliyunModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+
+ Configure(options =>
+ {
+ context.Services.ExecutePreConfiguredActions(options);
+ options.Containers.ConfigureAll((containerName, containerConfiguration) =>
+ {
+ containerConfiguration.UseAliyun(aliyun =>
+ {
+ aliyun.BucketName = configuration[AliyunBlobProviderConfigurationNames.BucketName];
+ aliyun.CreateBucketIfNotExists = configuration.GetSection(AliyunBlobProviderConfigurationNames.CreateBucketIfNotExists).Get();
+ aliyun.CreateBucketReferer = configuration.GetSection(AliyunBlobProviderConfigurationNames.CreateBucketReferer).Get>();
+ aliyun.Endpoint = configuration[AliyunBlobProviderConfigurationNames.Endpoint];
+ });
+ });
+ });
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobContainerConfigurationExtensions.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobContainerConfigurationExtensions.cs
new file mode 100644
index 000000000..6a73a482a
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobContainerConfigurationExtensions.cs
@@ -0,0 +1,25 @@
+using System;
+using Volo.Abp.BlobStoring;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public static class AliyunBlobContainerConfigurationExtensions
+ {
+ public static AliyunBlobProviderConfiguration GetAliyunConfiguration(
+ this BlobContainerConfiguration containerConfiguration)
+ {
+ return new AliyunBlobProviderConfiguration(containerConfiguration);
+ }
+
+ public static BlobContainerConfiguration UseAliyun(
+ this BlobContainerConfiguration containerConfiguration,
+ Action aliyunConfigureAction)
+ {
+ containerConfiguration.ProviderType = typeof(AliyunBlobProvider);
+
+ aliyunConfigureAction(new AliyunBlobProviderConfiguration(containerConfiguration));
+
+ return containerConfiguration;
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs
new file mode 100644
index 000000000..c076c3843
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs
@@ -0,0 +1,148 @@
+using Aliyun.OSS;
+using LINGYUN.Abp.Aliyun.Authorization;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using Volo.Abp.BlobStoring;
+using Volo.Abp.DependencyInjection;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public class AliyunBlobProvider : BlobProviderBase, ITransientDependency
+ {
+ protected AbpAliyunOptions Options { get; }
+ protected IAliyunBlobNameCalculator AliyunBlobNameCalculator { get; }
+
+ public AliyunBlobProvider(
+ IOptions options,
+ IAliyunBlobNameCalculator aliyunBlobNameCalculator)
+ {
+ Options = options.Value;
+ AliyunBlobNameCalculator = aliyunBlobNameCalculator;
+ }
+
+ public override async Task DeleteAsync(BlobProviderDeleteArgs args)
+ {
+ var blobName = AliyunBlobNameCalculator.Calculate(args);
+
+ if (await BlobExistsAsync(args, blobName))
+ {
+ var ossClient = GetOssClient(args);
+
+ return ossClient.DeleteObject(GetBucketName(args), blobName).DeleteMarker;
+ }
+
+ return false;
+ }
+
+ public override async Task ExistsAsync(BlobProviderExistsArgs args)
+ {
+ var blobName = AliyunBlobNameCalculator.Calculate(args);
+
+ return await BlobExistsAsync(args, blobName);
+ }
+
+ public override async Task GetOrNullAsync(BlobProviderGetArgs args)
+ {
+ var blobName = AliyunBlobNameCalculator.Calculate(args);
+
+ if (!await BlobExistsAsync(args, blobName))
+ {
+ return null;
+ }
+
+ var ossClient = GetOssClient(args);
+ var ossObject = ossClient.GetObject(GetBucketName(args), blobName);
+ // 返回原始结果才会调用 Stream.ReadAsync();
+ return ossObject.Content;
+ }
+
+ public override async Task SaveAsync(BlobProviderSaveArgs args)
+ {
+ var blobName = AliyunBlobNameCalculator.Calculate(args);
+ var configuration = args.Configuration.GetAliyunConfiguration();
+ if (!args.OverrideExisting && await BlobExistsAsync(args, blobName))
+ {
+ throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the bucketName '{GetBucketName(args)}'! Set {nameof(args.OverrideExisting)} if it should be overwritten.");
+ }
+
+ if (configuration.CreateBucketIfNotExists)
+ {
+ await CreateBucketIfNotExists(args, configuration.CreateBucketReferer);
+ }
+
+ var bucketName = GetBucketName(args);
+ var ossClient = GetOssClient(args);
+
+ if (args.OverrideExisting && await BlobExistsAsync(args, blobName))
+ {
+ ossClient.DeleteObject(bucketName, blobName);
+ }
+
+ ossClient.PutObject(bucketName, blobName, args.BlobStream);
+ }
+
+ protected virtual OssClient GetOssClient(BlobProviderArgs args)
+ {
+ var configuration = args.Configuration.GetAliyunConfiguration();
+ var ossClient = new OssClient(configuration.Endpoint, Options.AccessKeyId, Options.AccessKeySecret);
+ return ossClient;
+ }
+
+ protected virtual async Task CreateBucketIfNotExists(BlobProviderArgs args, IList refererList = null)
+ {
+ if (! await BucketExistsAsync(args))
+ {
+ var ossClient = GetOssClient(args);
+ var bucketName = GetBucketName(args);
+
+ var request = new CreateBucketRequest(bucketName)
+ {
+ //设置存储空间访问权限ACL。
+ ACL = CannedAccessControlList.PublicReadWrite,
+ //设置数据容灾类型。
+ DataRedundancyType = DataRedundancyType.ZRS
+ };
+
+ ossClient.CreateBucket(request);
+
+ if (refererList != null && refererList.Count > 0)
+ {
+ var srq = new SetBucketRefererRequest(bucketName, refererList);
+ ossClient.SetBucketReferer(srq);
+ }
+ }
+ }
+
+ private async Task BlobExistsAsync(BlobProviderArgs args, string blobName)
+ {
+ var ossClient = GetOssClient(args);
+ var bucketExists = await BucketExistsAsync(args);
+ if (bucketExists)
+ {
+ var objectExists = ossClient.DoesObjectExist(GetBucketName(args), blobName);
+
+ return objectExists;
+ }
+ return false;
+ }
+
+ private Task BucketExistsAsync(BlobProviderArgs args)
+ {
+ var ossClient = GetOssClient(args);
+ var bucketExists = ossClient.DoesBucketExist(GetBucketName(args));
+
+ return Task.FromResult(bucketExists);
+ }
+
+ private static string GetBucketName(BlobProviderArgs args)
+ {
+ var configuration = args.Configuration.GetAliyunConfiguration();
+ return configuration.BucketName.IsNullOrWhiteSpace()
+ ? args.ContainerName
+ : configuration.BucketName;
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs
new file mode 100644
index 000000000..b6f2637ab
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfiguration.cs
@@ -0,0 +1,62 @@
+using System.Collections.Generic;
+using Volo.Abp;
+using Volo.Abp.BlobStoring;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public class AliyunBlobProviderConfiguration
+ {
+ ///
+ /// 数据中心
+ ///
+ ///
+ /// 详见 https://help.aliyun.com/document_detail/31837.html?spm=a2c4g.11186623.2.14.417cd47eLc9LHc#concept-zt4-cvy-5db
+ ///
+ public string Endpoint
+ {
+ get => _containerConfiguration.GetConfiguration(AliyunBlobProviderConfigurationNames.Endpoint);
+ set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.Endpoint, Check.NotNullOrWhiteSpace(value, nameof(value)));
+ }
+ ///
+ /// 命名空间
+ ///
+ public string BucketName
+ {
+ get => _containerConfiguration.GetConfiguration(AliyunBlobProviderConfigurationNames.BucketName);
+ set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.BucketName, Check.NotNullOrWhiteSpace(value, nameof(value)));
+ }
+ ///
+ /// 命名空间不存在是否创建
+ ///
+ public bool CreateBucketIfNotExists
+ {
+ get => _containerConfiguration.GetConfigurationOrDefault(AliyunBlobProviderConfigurationNames.CreateBucketIfNotExists, false);
+ set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.CreateBucketIfNotExists, value);
+ }
+ ///
+ /// 创建命名空间时防盗链列表
+ ///
+ public List CreateBucketReferer
+ {
+ get => _containerConfiguration.GetConfiguration>(AliyunBlobProviderConfigurationNames.CreateBucketReferer);
+ set
+ {
+ if (value == null)
+ {
+ _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.CreateBucketReferer, new List());
+ }
+ else
+ {
+ _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.CreateBucketReferer, value);
+ }
+ }
+ }
+
+ private readonly BlobContainerConfiguration _containerConfiguration;
+
+ public AliyunBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration)
+ {
+ _containerConfiguration = containerConfiguration;
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfigurationNames.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfigurationNames.cs
new file mode 100644
index 000000000..66b0c17ef
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/AliyunBlobProviderConfigurationNames.cs
@@ -0,0 +1,22 @@
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public static class AliyunBlobProviderConfigurationNames
+ {
+ ///
+ /// 数据中心
+ ///
+ public const string Endpoint = "Aliyun:OSS:Endpoint";
+ ///
+ /// 命名空间
+ ///
+ public const string BucketName = "Aliyun:OSS:BucketName";
+ ///
+ /// 命名空间不存在是否创建
+ ///
+ public const string CreateBucketIfNotExists = "Aliyun:OSS:CreateBucketIfNotExists";
+ ///
+ /// 创建命名空间时防盗链列表
+ ///
+ public const string CreateBucketReferer = "Aliyun:OSS:CreateBucketReferer";
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/DefaultAliyunBlobNameCalculator.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/DefaultAliyunBlobNameCalculator.cs
new file mode 100644
index 000000000..220a13c56
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/DefaultAliyunBlobNameCalculator.cs
@@ -0,0 +1,24 @@
+using Volo.Abp.BlobStoring;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public class DefaultAliyunBlobNameCalculator : IAliyunBlobNameCalculator, ITransientDependency
+ {
+ protected ICurrentTenant CurrentTenant { get; }
+
+ public DefaultAliyunBlobNameCalculator(
+ ICurrentTenant currentTenant)
+ {
+ CurrentTenant = currentTenant;
+ }
+
+ public string Calculate(BlobProviderArgs args)
+ {
+ return CurrentTenant.Id == null
+ ? $"host/{args.BlobName}"
+ : $"tenants/{CurrentTenant.Id.Value:D}/{args.BlobName}";
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IAliyunBlobNameCalculator.cs b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IAliyunBlobNameCalculator.cs
new file mode 100644
index 000000000..b8dbe6a60
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BlobStoring.Aliyun/LINGYUN/Abp/BlobStoring/Aliyun/IAliyunBlobNameCalculator.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.BlobStoring;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public interface IAliyunBlobNameCalculator
+ {
+ string Calculate(BlobProviderArgs args);
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj
index 8c6bc0335..1b84eb70e 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINGYUN.Abp.Sms.Aliyun.csproj
@@ -30,4 +30,8 @@
+
+
+
+
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs
index e36a96c42..cad4c903a 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AbpAliyunSmsModule.cs
@@ -1,4 +1,5 @@
-using LINYUN.Abp.Sms.Aliyun.Localization;
+using LINGYUN.Abp.Aliyun.Authorization;
+using LINYUN.Abp.Sms.Aliyun.Localization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Json;
using Volo.Abp.Localization;
@@ -11,7 +12,8 @@ namespace LINYUN.Abp.Sms.Aliyun
[DependsOn(
typeof(AbpSmsModule),
typeof(AbpJsonModule),
- typeof(AbpLocalizationModule))]
+ typeof(AbpLocalizationModule),
+ typeof(AbpAliyunAuthorizationModule))]
public class AbpAliyunSmsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs
index 3384f9982..19f3e04a4 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsOptions.cs
@@ -15,14 +15,6 @@
///
public string ActionName { get; set; } = "SendSms";
///
- /// ApiKey
- ///
- public string AccessKeyId { get; set; }
- ///
- /// Api密钥
- ///
- public string AccessKeySecret { get; set; }
- ///
/// 默认版本号
///
public string Version { get; set; } = "2017-05-25";
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs
index 36690094b..7f87d2a2f 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs
+++ b/aspnet-core/modules/common/LINGYUN.Abp.Sms.Aliyun/LINYUN/Abp/Sms/Aliyun/AliyunSmsSender.cs
@@ -2,6 +2,7 @@
using Aliyun.Acs.Core.Exceptions;
using Aliyun.Acs.Core.Http;
using Aliyun.Acs.Core.Profile;
+using LINGYUN.Abp.Aliyun.Authorization;
using LINYUN.Abp.Sms.Aliyun.Localization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -21,6 +22,7 @@ namespace LINYUN.Abp.Sms.Aliyun
[ExposeServices(typeof(ISmsSender), typeof(AliyunSmsSender))]
public class AliyunSmsSender : ISmsSender
{
+ protected AbpAliyunOptions AuthOptions { get; }
protected AliyunSmsOptions Options { get; }
protected IJsonSerializer JsonSerializer { get; }
protected IHostEnvironment Environment { get; }
@@ -29,9 +31,12 @@ namespace LINYUN.Abp.Sms.Aliyun
IHostEnvironment environment,
IJsonSerializer jsonSerializer,
IServiceProvider serviceProvider,
- IOptions options)
+ IOptions options,
+ IOptions authOptions)
{
Options = options.Value;
+ AuthOptions = authOptions.Value;
+
Environment = environment;
JsonSerializer = jsonSerializer;
ServiceProvider = serviceProvider;
@@ -53,7 +58,7 @@ namespace LINYUN.Abp.Sms.Aliyun
try
{
- IClientProfile profile = DefaultProfile.GetProfile(Options.RegionId, Options.AccessKeyId, Options.AccessKeySecret);
+ IClientProfile profile = DefaultProfile.GetProfile(Options.RegionId, AuthOptions.AccessKeyId, AuthOptions.AccessKeySecret);
IAcsClient client = new DefaultAcsClient(profile);
CommonResponse response = client.GetCommonResponse(request);
var responseContent = Encoding.Default.GetString(response.HttpResponse.Content);
diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj
new file mode 100644
index 000000000..acf12d3c1
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestBase.cs
new file mode 100644
index 000000000..2a75696bd
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestBase.cs
@@ -0,0 +1,9 @@
+using LINGYUN.Abp.Tests;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public class AbpBlobStoringAliyunTestBase : AbpTestsBase
+ {
+
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs
new file mode 100644
index 000000000..4333b987f
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs
@@ -0,0 +1,56 @@
+using Aliyun.OSS;
+using LINGYUN.Abp.Tests;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using Volo.Abp;
+using Volo.Abp.Autofac;
+using Volo.Abp.BlobStoring;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ [DependsOn(
+ typeof(AbpBlobStoringModule),
+ typeof(AbpBlobStoringAliyunModule),
+ typeof(AbpTestsBaseModule),
+ typeof(AbpAutofacModule)
+ )]
+ public class AbpBlobStoringAliyunTestModule : AbpModule
+ {
+ private string _bucketName;
+ private string _accessKeyId;
+ private string _accessKeySecret;
+ private string _endPoint;
+
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ var configurationOptions = new AbpConfigurationBuilderOptions
+ {
+ BasePath = @"D:\Projects\Development\Abp\BlobStoring\Aliyun",
+ EnvironmentName = "Development"
+ };
+
+ context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(configurationOptions));
+ }
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var configuration = context.Services.GetConfiguration();
+
+ _endPoint = configuration[AliyunBlobProviderConfigurationNames.Endpoint];
+ _bucketName = configuration[AliyunBlobProviderConfigurationNames.BucketName];
+ _accessKeyId = configuration["Aliyun:Auth:AccessKeyId"];
+ _accessKeySecret = configuration["Aliyun:Auth:AccessKeySecret"];
+ }
+
+ public override void OnApplicationShutdown(ApplicationShutdownContext context)
+ {
+ var ossClient = new OssClient(_endPoint, _accessKeyId, _accessKeySecret);
+ if (ossClient.DoesBucketExist(_bucketName))
+ {
+ ossClient.DeleteBucket(_bucketName);
+ }
+ }
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/BlobContainer_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/BlobContainer_Tests.cs
new file mode 100644
index 000000000..b28628fc2
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/BlobContainer_Tests.cs
@@ -0,0 +1,99 @@
+using LINGYUN.Abp.BlobStoring.TestObjects;
+using Shouldly;
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.BlobStoring;
+using Xunit;
+
+namespace LINGYUN.Abp.BlobStoring.Aliyun
+{
+ public class BlobContainer_Tests : AbpBlobStoringAliyunTestBase
+ {
+ protected IBlobContainer Container { get; }
+ public BlobContainer_Tests()
+ {
+ Container = GetRequiredService>();
+ }
+
+ [Theory]
+ [InlineData("test-blob-1")]
+ [InlineData("test-blob-1.txt")]
+ [InlineData("test-folder/test-blob-1")]
+ public async Task Should_Save_And_Get_Blobs(string blobName)
+ {
+ var testContent = "test content".GetBytes();
+ await Container.SaveAsync(blobName, testContent);
+ try
+ {
+ var resultBytes = await Container.GetAllBytesAsync(blobName);
+ resultBytes.SequenceEqual(testContent).ShouldBeTrue();
+ }
+ finally
+ {
+ await Container.DeleteAsync(blobName);
+ }
+ }
+
+ [Fact]
+ public async Task Should_Overwrite_Pre_Saved_Blob_If_Requested()
+ {
+ var blobName = "test-blob-1";
+
+ var testContent = "test content".GetBytes();
+ await Container.SaveAsync(blobName, testContent);
+
+ var testContentOverwritten = "test content overwritten".GetBytes();
+ await Container.SaveAsync(blobName, testContentOverwritten, true);
+
+ var result = await Container.GetAllBytesAsync(blobName);
+ result.SequenceEqual(testContentOverwritten).ShouldBeTrue();
+
+ await Container.DeleteAsync(blobName);
+ }
+
+
+ [Fact]
+ public async Task Should_Not_Allow_To_Overwrite_Pre_Saved_Blob_By_Default()
+ {
+ var blobName = "test-blob-1";
+
+ var testContent = "test content".GetBytes();
+ await Container.SaveAsync(blobName, testContent);
+
+ var testContentOverwritten = "test content overwritten".GetBytes();
+ await Assert.ThrowsAsync(() =>
+ Container.SaveAsync(blobName, testContentOverwritten)
+ );
+
+ await Container.DeleteAsync(blobName);
+ }
+
+ [Theory]
+ [InlineData("test-blob-1")]
+ [InlineData("test-blob-1.txt")]
+ [InlineData("test-folder/test-blob-1")]
+ public async Task Should_Delete_Saved_Blobs(string blobName)
+ {
+ await Container.SaveAsync(blobName, "test content".GetBytes());
+ (await Container.GetAllBytesAsync(blobName)).ShouldNotBeNull();
+
+ await Container.DeleteAsync(blobName);
+ (await Container.GetAllBytesOrNullAsync(blobName)).ShouldBeNull();
+ }
+
+ [Theory]
+ [InlineData("test-blob-1")]
+ [InlineData("test-blob-1.txt")]
+ [InlineData("test-folder/test-blob-1")]
+ public virtual async Task Saved_Blobs_Should_Exists(string blobName)
+ {
+ await Container.SaveAsync(blobName, "test content".GetBytes());
+ (await Container.ExistsAsync(blobName)).ShouldBeTrue();
+
+ await Container.DeleteAsync(blobName);
+ (await Container.ExistsAsync(blobName)).ShouldBeFalse();
+ }
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs
new file mode 100644
index 000000000..47562c6a3
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/TestObjects/TestContainer1.cs
@@ -0,0 +1,6 @@
+namespace LINGYUN.Abp.BlobStoring.TestObjects
+{
+ public class TestContainer1
+ {
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN.Abp.TestsBase.csproj b/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN.Abp.TestsBase.csproj
new file mode 100644
index 000000000..d1b8b5acc
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN.Abp.TestsBase.csproj
@@ -0,0 +1,21 @@
+
+
+
+ netcoreapp3.1
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBase.cs b/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBase.cs
new file mode 100644
index 000000000..fb8afac33
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBase.cs
@@ -0,0 +1,59 @@
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp;
+using Volo.Abp.Modularity;
+using Volo.Abp.Testing;
+using Volo.Abp.Uow;
+
+namespace LINGYUN.Abp.Tests
+{
+ public abstract class AbpTestsBase : AbpIntegratedTest
+ where TStartupModule : IAbpModule
+ {
+ protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
+ {
+ options.UseAutofac();
+ }
+
+ protected virtual Task WithUnitOfWorkAsync(Func func)
+ {
+ return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
+ }
+
+ protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func action)
+ {
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ var uowManager = scope.ServiceProvider.GetRequiredService();
+
+ using (var uow = uowManager.Begin(options))
+ {
+ await action();
+
+ await uow.CompleteAsync();
+ }
+ }
+ }
+
+ protected virtual Task WithUnitOfWorkAsync(Func> func)
+ {
+ return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
+ }
+
+ protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func> func)
+ {
+ using (var scope = ServiceProvider.CreateScope())
+ {
+ var uowManager = scope.ServiceProvider.GetRequiredService();
+
+ using (var uow = uowManager.Begin(options))
+ {
+ var result = await func();
+ await uow.CompleteAsync();
+ return result;
+ }
+ }
+ }
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBaseModule.cs b/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBaseModule.cs
new file mode 100644
index 000000000..f7b0d6cff
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBaseModule.cs
@@ -0,0 +1,21 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp;
+using Volo.Abp.Authorization;
+using Volo.Abp.Autofac;
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.Tests
+{
+ [DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(AbpTestBaseModule),
+ typeof(AbpAuthorizationModule)
+ )]
+ public class AbpTestsBaseModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAlwaysAllowAuthorization();
+ }
+ }
+}