feat: modularize external providers

This commit is contained in:
2026-07-27 17:47:21 +08:00
parent db4c7b4496
commit 70b99e6063
47 changed files with 1219 additions and 667 deletions

View File

@@ -4,15 +4,18 @@ using Tiku.Application.Assets;
using Tiku.Application.Catalog;
using Tiku.Application.Content;
using Tiku.Application.Storage;
using Tiku.Application.Tenancy;
using Tiku.Domain.Common;
using Tiku.Domain.Content;
using Tiku.Domain.Tenancy;
using Tiku.Infrastructure.Persistence;
namespace Tiku.Infrastructure.Assets;
public sealed class AssetManagementService(
TikuDbContext dbContext,
IObjectStorageService objectStorageService) : IAssetManagementService
IObjectStorageService objectStorageService,
ITenantExternalProviderConfigService providerConfigService) : IAssetManagementService
{
private const int DefaultLimit = 100;
private const int MaxLimit = 500;
@@ -140,10 +143,9 @@ public sealed class AssetManagementService(
ArgumentException.ThrowIfNullOrWhiteSpace(command.FileName);
ArgumentException.ThrowIfNullOrWhiteSpace(command.MimeType);
var provider = objectStorageService.NormalizeProvider(command.Provider, objectStorageService.ConfiguredDefaultProvider());
var bucket = string.IsNullOrWhiteSpace(command.Bucket)
? objectStorageService.ConfiguredDefaultBucket()
: command.Bucket.Trim();
var storageConfig = await ResolveObjectStorageConfigAsync(actor.TenantId, cancellationToken);
var provider = storageConfig.Provider;
var bucket = storageConfig.Bucket;
var mimeType = objectStorageService.ValidateMimeType(command.MimeType.Trim());
var fileSizeBytes = objectStorageService.ValidateFileSize(command.FileSizeBytes);
var asset = await ResolveUploadAssetAsync(actor, command, provider, bucket, mimeType, fileSizeBytes, cancellationToken);
@@ -782,7 +784,6 @@ public sealed class AssetManagementService(
return provider switch
{
ObjectStorageProviders.ExternalUrl => AssetStorageProvider.ExternalUrl,
ObjectStorageProviders.SupabaseStorage => AssetStorageProvider.SupabaseStorage,
ObjectStorageProviders.AliyunOss => AssetStorageProvider.AliyunOss,
ObjectStorageProviders.TencentCos => AssetStorageProvider.TencentCos,
ObjectStorageProviders.QiniuKodo => AssetStorageProvider.QiniuKodo,
@@ -796,7 +797,6 @@ public sealed class AssetManagementService(
return provider switch
{
AssetStorageProvider.ExternalUrl => ObjectStorageProviders.ExternalUrl,
AssetStorageProvider.SupabaseStorage => ObjectStorageProviders.SupabaseStorage,
AssetStorageProvider.AliyunOss => ObjectStorageProviders.AliyunOss,
AssetStorageProvider.TencentCos => ObjectStorageProviders.TencentCos,
AssetStorageProvider.QiniuKodo => ObjectStorageProviders.QiniuKodo,
@@ -804,4 +804,50 @@ public sealed class AssetManagementService(
_ => ObjectStorageProviders.ExternalUrl
};
}
private async Task<(string Provider, string Bucket)> ResolveObjectStorageConfigAsync(
Guid tenantId,
CancellationToken cancellationToken)
{
try
{
var account = await providerConfigService.GetActiveProviderAsync(
tenantId,
TenantExternalProviderCapability.ObjectStorage,
cancellationToken: cancellationToken);
var bucket = GetJsonString(account.ConfigPublic, "bucket", "defaultBucket", "default_bucket");
if (string.IsNullOrWhiteSpace(bucket))
{
throw new ObjectStorageException(
"Object storage provider bucket is not configured.",
"STORAGE_BUCKET_NOT_CONFIGURED");
}
return (objectStorageService.NormalizeProvider(account.Provider), bucket.Trim());
}
catch (TenantExternalProviderException)
{
return (
objectStorageService.ConfiguredDefaultProvider(),
objectStorageService.ConfiguredDefaultBucket());
}
}
private static string? GetJsonString(JsonElement element, params string[] keys)
{
if (element.ValueKind != JsonValueKind.Object)
{
return null;
}
foreach (var key in keys)
{
if (element.TryGetProperty(key, out var value) && value.ValueKind == JsonValueKind.String)
{
return value.GetString();
}
}
return null;
}
}