forked from xiongyuxing/tiku-backend.net
feat: add aliyun oss storage foundation
This commit is contained in:
134
Tiku.UnitTests/Storage/AliyunOssObjectStorageServiceTests.cs
Normal file
134
Tiku.UnitTests/Storage/AliyunOssObjectStorageServiceTests.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Tiku.Application.Storage;
|
||||
using Tiku.Infrastructure.Storage;
|
||||
|
||||
namespace Tiku.UnitTests.Storage;
|
||||
|
||||
public sealed class AliyunOssObjectStorageServiceTests
|
||||
{
|
||||
private static readonly Guid TenantId = Guid.Parse("11111111-1111-1111-1111-111111111111");
|
||||
|
||||
[Fact]
|
||||
public void Validate_object_key_requires_tenant_prefix_like_original_storage_service()
|
||||
{
|
||||
using var service = CreateConfiguredService();
|
||||
|
||||
var exception = Assert.Throws<ObjectStorageException>(() =>
|
||||
service.ValidateObjectKey(TenantId, "other-tenant/file.pdf"));
|
||||
|
||||
Assert.Equal("OBJECT_KEY_TENANT_PREFIX_REQUIRED", exception.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_mime_type_and_size_use_configured_allow_list()
|
||||
{
|
||||
using var service = CreateConfiguredService(new ObjectStorageOptions
|
||||
{
|
||||
MaxUploadBytes = 100,
|
||||
AllowedMimePrefixes = ["image/"],
|
||||
AllowedMimeTypes = ["application/pdf"]
|
||||
});
|
||||
|
||||
Assert.Equal("image/png", service.ValidateMimeType(" Image/PNG "));
|
||||
Assert.Equal(99, service.ValidateFileSize(99));
|
||||
Assert.Equal("MIME_TYPE_NOT_ALLOWED", Assert.Throws<ObjectStorageException>(() => service.ValidateMimeType("text/html")).Code);
|
||||
Assert.Equal("FILE_TOO_LARGE", Assert.Throws<ObjectStorageException>(() => service.ValidateFileSize(101)).Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sign_download_requires_complete_aliyun_oss_options()
|
||||
{
|
||||
using var service = CreateUnconfiguredService();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<ObjectStorageNotConfiguredException>(() =>
|
||||
service.SignDownloadAsync(new ObjectStorageDownloadSignRequest(
|
||||
TenantId,
|
||||
ObjectStorageProviders.AliyunOss,
|
||||
"bucket",
|
||||
$"{TenantId:N}/path/file.pdf",
|
||||
TimeSpan.FromMinutes(15))));
|
||||
|
||||
Assert.Contains("ALIYUN_OSS_ACCESS_KEY_ID", exception.Message, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sign_download_generates_aliyun_oss_presigned_get_url()
|
||||
{
|
||||
using var service = CreateConfiguredService();
|
||||
|
||||
var signedUrl = await service.SignDownloadAsync(new ObjectStorageDownloadSignRequest(
|
||||
TenantId,
|
||||
ObjectStorageProviders.AliyunOss,
|
||||
"tiku-assets",
|
||||
$"{TenantId:N}/handbook.pdf",
|
||||
TimeSpan.FromMinutes(15),
|
||||
FileName: "handbook.pdf",
|
||||
Disposition: "attachment"));
|
||||
|
||||
Assert.Equal(ObjectStorageProviders.AliyunOss, signedUrl.Provider);
|
||||
Assert.Equal("GET", signedUrl.Method);
|
||||
Assert.Equal("aliyun-oss-signature-url-v4", signedUrl.SignatureMode);
|
||||
Assert.Contains("tiku-assets", signedUrl.Url.Host, StringComparison.Ordinal);
|
||||
Assert.Contains($"{TenantId:N}/handbook.pdf", signedUrl.Url.AbsoluteUri, StringComparison.Ordinal);
|
||||
Assert.Contains("x-oss-", signedUrl.Url.Query, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sign_upload_generates_aliyun_oss_presigned_put_url_with_content_type_header()
|
||||
{
|
||||
using var service = CreateConfiguredService();
|
||||
|
||||
var signedUrl = await service.SignUploadAsync(new ObjectStorageUploadSignRequest(
|
||||
TenantId,
|
||||
ObjectStorageProviders.AliyunOss,
|
||||
"tiku-assets",
|
||||
$"{TenantId:N}/upload.pdf",
|
||||
"upload.pdf",
|
||||
"application/pdf",
|
||||
1024,
|
||||
TimeSpan.FromMinutes(10)));
|
||||
|
||||
Assert.Equal("PUT", signedUrl.Method);
|
||||
Assert.Contains("x-oss-", signedUrl.Url.Query, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cdn_url_download_returns_public_or_provider_managed_url_without_oss_signing()
|
||||
{
|
||||
using var service = CreateUnconfiguredService();
|
||||
|
||||
var signedUrl = await service.SignDownloadAsync(new ObjectStorageDownloadSignRequest(
|
||||
TenantId,
|
||||
ObjectStorageProviders.ExternalUrl,
|
||||
null,
|
||||
null,
|
||||
TimeSpan.FromMinutes(5),
|
||||
"https://cdn.example.com/file.pdf"));
|
||||
|
||||
Assert.Equal("public-or-provider-managed", signedUrl.SignatureMode);
|
||||
Assert.Equal("https://cdn.example.com/file.pdf", signedUrl.Url.AbsoluteUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Aliyun_oss_options_allow_empty_optional_configuration()
|
||||
{
|
||||
Assert.True(AliyunOssOptions.BeValid(new AliyunOssOptions()));
|
||||
Assert.False(AliyunOssOptions.BeValid(new AliyunOssOptions
|
||||
{
|
||||
PresignDefaultMinutes = 0
|
||||
}));
|
||||
}
|
||||
|
||||
private static AliyunOssObjectStorageService CreateConfiguredService(ObjectStorageOptions? storageOptions = null) =>
|
||||
new(
|
||||
Options.Create(storageOptions ?? new ObjectStorageOptions()),
|
||||
Options.Create(new AliyunOssOptions
|
||||
{
|
||||
Region = "cn-hangzhou",
|
||||
AccessKeyId = "test-access-key-id",
|
||||
AccessKeySecret = "test-access-key-secret"
|
||||
}));
|
||||
|
||||
private static AliyunOssObjectStorageService CreateUnconfiguredService() =>
|
||||
new(Options.Create(new ObjectStorageOptions()), Options.Create(new AliyunOssOptions()));
|
||||
}
|
||||
Reference in New Issue
Block a user