chore: 提交现有修改
This commit is contained in:
@@ -3,40 +3,34 @@ namespace TakeoutSaaS.Module.Storage.Models;
|
||||
/// <summary>
|
||||
/// 直传(预签名上传)请求参数。
|
||||
/// </summary>
|
||||
public sealed class StorageDirectUploadRequest
|
||||
/// <remarks>
|
||||
/// 初始化请求。
|
||||
/// </remarks>
|
||||
/// <param name="objectKey">对象键。</param>
|
||||
/// <param name="contentType">内容类型。</param>
|
||||
/// <param name="contentLength">内容长度。</param>
|
||||
/// <param name="expires">签名有效期。</param>
|
||||
public sealed class StorageDirectUploadRequest(string objectKey, string contentType, long contentLength, TimeSpan expires)
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化请求。
|
||||
/// </summary>
|
||||
/// <param name="objectKey">对象键。</param>
|
||||
/// <param name="contentType">内容类型。</param>
|
||||
/// <param name="contentLength">内容长度。</param>
|
||||
/// <param name="expires">签名有效期。</param>
|
||||
public StorageDirectUploadRequest(string objectKey, string contentType, long contentLength, TimeSpan expires)
|
||||
{
|
||||
ObjectKey = objectKey;
|
||||
ContentType = contentType;
|
||||
ContentLength = contentLength;
|
||||
Expires = expires;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 目标对象键。
|
||||
/// </summary>
|
||||
public string ObjectKey { get; }
|
||||
public string ObjectKey { get; } = objectKey;
|
||||
|
||||
/// <summary>
|
||||
/// 内容类型。
|
||||
/// </summary>
|
||||
public string ContentType { get; }
|
||||
public string ContentType { get; } = contentType;
|
||||
|
||||
/// <summary>
|
||||
/// 内容长度。
|
||||
/// </summary>
|
||||
public long ContentLength { get; }
|
||||
public long ContentLength { get; } = contentLength;
|
||||
|
||||
/// <summary>
|
||||
/// 签名有效期。
|
||||
/// </summary>
|
||||
public TimeSpan Expires { get; }
|
||||
public TimeSpan Expires { get; } = expires;
|
||||
}
|
||||
|
||||
@@ -6,70 +6,60 @@ namespace TakeoutSaaS.Module.Storage.Models;
|
||||
/// <summary>
|
||||
/// 对象存储上传请求参数。
|
||||
/// </summary>
|
||||
public sealed class StorageUploadRequest
|
||||
/// <remarks>
|
||||
/// 初始化上传请求。
|
||||
/// </remarks>
|
||||
/// <param name="objectKey">对象键(含路径)。</param>
|
||||
/// <param name="content">文件流。</param>
|
||||
/// <param name="contentType">内容类型。</param>
|
||||
/// <param name="contentLength">内容长度。</param>
|
||||
/// <param name="generateSignedUrl">是否返回签名访问链接。</param>
|
||||
/// <param name="signedUrlExpires">签名有效期。</param>
|
||||
/// <param name="metadata">附加元数据。</param>
|
||||
public sealed class StorageUploadRequest(
|
||||
string objectKey,
|
||||
Stream content,
|
||||
string contentType,
|
||||
long contentLength,
|
||||
bool generateSignedUrl,
|
||||
TimeSpan signedUrlExpires,
|
||||
IDictionary<string, string>? metadata = null)
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化上传请求。
|
||||
/// </summary>
|
||||
/// <param name="objectKey">对象键(含路径)。</param>
|
||||
/// <param name="content">文件流。</param>
|
||||
/// <param name="contentType">内容类型。</param>
|
||||
/// <param name="contentLength">内容长度。</param>
|
||||
/// <param name="generateSignedUrl">是否返回签名访问链接。</param>
|
||||
/// <param name="signedUrlExpires">签名有效期。</param>
|
||||
/// <param name="metadata">附加元数据。</param>
|
||||
public StorageUploadRequest(
|
||||
string objectKey,
|
||||
Stream content,
|
||||
string contentType,
|
||||
long contentLength,
|
||||
bool generateSignedUrl,
|
||||
TimeSpan signedUrlExpires,
|
||||
IDictionary<string, string>? metadata = null)
|
||||
{
|
||||
ObjectKey = objectKey;
|
||||
Content = content;
|
||||
ContentType = contentType;
|
||||
ContentLength = contentLength;
|
||||
GenerateSignedUrl = generateSignedUrl;
|
||||
SignedUrlExpires = signedUrlExpires;
|
||||
Metadata = metadata == null
|
||||
? new Dictionary<string, string>()
|
||||
: new Dictionary<string, string>(metadata);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对象键。
|
||||
/// </summary>
|
||||
public string ObjectKey { get; }
|
||||
public string ObjectKey { get; } = objectKey;
|
||||
|
||||
/// <summary>
|
||||
/// 文件流。
|
||||
/// </summary>
|
||||
public Stream Content { get; }
|
||||
public Stream Content { get; } = content;
|
||||
|
||||
/// <summary>
|
||||
/// 内容类型。
|
||||
/// </summary>
|
||||
public string ContentType { get; }
|
||||
public string ContentType { get; } = contentType;
|
||||
|
||||
/// <summary>
|
||||
/// 内容长度。
|
||||
/// </summary>
|
||||
public long ContentLength { get; }
|
||||
public long ContentLength { get; } = contentLength;
|
||||
|
||||
/// <summary>
|
||||
/// 是否需要签名访问链接。
|
||||
/// </summary>
|
||||
public bool GenerateSignedUrl { get; }
|
||||
public bool GenerateSignedUrl { get; } = generateSignedUrl;
|
||||
|
||||
/// <summary>
|
||||
/// 签名有效期。
|
||||
/// </summary>
|
||||
public TimeSpan SignedUrlExpires { get; }
|
||||
public TimeSpan SignedUrlExpires { get; } = signedUrlExpires;
|
||||
|
||||
/// <summary>
|
||||
/// 元数据集合。
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, string> Metadata { get; }
|
||||
public IReadOnlyDictionary<string, string> Metadata { get; } = metadata == null
|
||||
? new Dictionary<string, string>()
|
||||
: new Dictionary<string, string>(metadata);
|
||||
}
|
||||
|
||||
@@ -5,20 +5,15 @@ namespace TakeoutSaaS.Module.Tenancy;
|
||||
/// <summary>
|
||||
/// 默认租户提供者:基于租户上下文访问器暴露当前租户 ID。
|
||||
/// </summary>
|
||||
public sealed class TenantProvider : ITenantProvider
|
||||
/// <remarks>
|
||||
/// 初始化租户提供者。
|
||||
/// </remarks>
|
||||
/// <param name="tenantContextAccessor">租户上下文访问器</param>
|
||||
public sealed class TenantProvider(ITenantContextAccessor tenantContextAccessor) : ITenantProvider
|
||||
{
|
||||
private readonly ITenantContextAccessor _tenantContextAccessor;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化租户提供者。
|
||||
/// </summary>
|
||||
/// <param name="tenantContextAccessor">租户上下文访问器</param>
|
||||
public TenantProvider(ITenantContextAccessor tenantContextAccessor)
|
||||
{
|
||||
_tenantContextAccessor = tenantContextAccessor;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public long GetCurrentTenantId()
|
||||
=> _tenantContextAccessor.Current?.TenantId ?? 0;
|
||||
=> tenantContextAccessor.Current?.TenantId ?? 0;
|
||||
}
|
||||
|
||||
@@ -11,54 +11,43 @@ namespace TakeoutSaaS.Module.Tenancy;
|
||||
/// <summary>
|
||||
/// 多租户解析中间件:支持 Header、域名与 Token Claim 的优先级解析。
|
||||
/// </summary>
|
||||
public sealed class TenantResolutionMiddleware
|
||||
/// <remarks>
|
||||
/// 初始化中间件。
|
||||
/// </remarks>
|
||||
public sealed class TenantResolutionMiddleware(
|
||||
RequestDelegate next,
|
||||
ILogger<TenantResolutionMiddleware> logger,
|
||||
ITenantContextAccessor tenantContextAccessor,
|
||||
IOptionsMonitor<TenantResolutionOptions> optionsMonitor)
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly ILogger<TenantResolutionMiddleware> _logger;
|
||||
private readonly ITenantContextAccessor _tenantContextAccessor;
|
||||
private readonly IOptionsMonitor<TenantResolutionOptions> _optionsMonitor;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化中间件。
|
||||
/// </summary>
|
||||
public TenantResolutionMiddleware(
|
||||
RequestDelegate next,
|
||||
ILogger<TenantResolutionMiddleware> logger,
|
||||
ITenantContextAccessor tenantContextAccessor,
|
||||
IOptionsMonitor<TenantResolutionOptions> optionsMonitor)
|
||||
{
|
||||
_next = next;
|
||||
_logger = logger;
|
||||
_tenantContextAccessor = tenantContextAccessor;
|
||||
_optionsMonitor = optionsMonitor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析租户并将上下文注入请求。
|
||||
/// </summary>
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
var options = _optionsMonitor.CurrentValue ?? new TenantResolutionOptions();
|
||||
var options = optionsMonitor.CurrentValue ?? new TenantResolutionOptions();
|
||||
if (ShouldSkip(context.Request.Path, options))
|
||||
{
|
||||
await _next(context);
|
||||
await next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
var tenantContext = ResolveTenant(context, options);
|
||||
_tenantContextAccessor.Current = tenantContext;
|
||||
tenantContextAccessor.Current = tenantContext;
|
||||
context.Items[TenantConstants.HttpContextItemKey] = tenantContext;
|
||||
|
||||
if (!tenantContext.IsResolved)
|
||||
{
|
||||
_logger.LogDebug("未能解析租户:{Path}", context.Request.Path);
|
||||
logger.LogDebug("未能解析租户:{Path}", context.Request.Path);
|
||||
|
||||
if (options.ThrowIfUnresolved)
|
||||
{
|
||||
var response = ApiResponse.Error(ErrorCodes.BadRequest, "缺少租户标识");
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
await context.Response.WriteAsJsonAsync(response, cancellationToken: context.RequestAborted);
|
||||
_tenantContextAccessor.Current = null;
|
||||
tenantContextAccessor.Current = null;
|
||||
context.Items.Remove(TenantConstants.HttpContextItemKey);
|
||||
return;
|
||||
}
|
||||
@@ -66,11 +55,11 @@ public sealed class TenantResolutionMiddleware
|
||||
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
await next(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_tenantContextAccessor.Current = null;
|
||||
tenantContextAccessor.Current = null;
|
||||
context.Items.Remove(TenantConstants.HttpContextItemKey);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user