chore: 提交当前变更
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 多租户实体约定:所有持久化实体须包含租户标识字段。
|
||||
/// </summary>
|
||||
public interface IMultiTenantEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 所属租户 ID。
|
||||
/// </summary>
|
||||
Guid TenantId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
/// <summary>
|
||||
/// 租户上下文访问器:用于在请求生命周期内读写当前租户上下文。
|
||||
/// </summary>
|
||||
public interface ITenantContextAccessor
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置当前租户上下文。
|
||||
/// </summary>
|
||||
TenantContext? Current { get; set; }
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
/// <summary>
|
||||
/// 租户提供者接口:用于获取当前请求的租户标识。
|
||||
/// 租户提供者:用于在各层读取当前请求绑定的租户 ID。
|
||||
/// </summary>
|
||||
public interface ITenantProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前请求的租户 ID。
|
||||
/// 获取当前租户 ID,未解析时返回 Guid.Empty。
|
||||
/// </summary>
|
||||
/// <returns>租户 ID,如果未设置则返回 Guid.Empty</returns>
|
||||
Guid GetCurrentTenantId();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
/// <summary>
|
||||
/// 多租户相关通用常量。
|
||||
/// </summary>
|
||||
public static class TenantConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// HttpContext.Items 中租户上下文的键名。
|
||||
/// </summary>
|
||||
public const string HttpContextItemKey = "__tenant_context";
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
/// <summary>
|
||||
/// 租户上下文:封装当前请求解析得到的租户标识、编号及解析来源。
|
||||
/// </summary>
|
||||
public sealed class TenantContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 未解析到租户时的默认上下文。
|
||||
/// </summary>
|
||||
public static TenantContext Empty { get; } = new(Guid.Empty, null, "unresolved");
|
||||
|
||||
/// <summary>
|
||||
/// 初始化租户上下文。
|
||||
/// </summary>
|
||||
/// <param name="tenantId">租户 ID</param>
|
||||
/// <param name="tenantCode">租户编码(可选)</param>
|
||||
/// <param name="source">解析来源</param>
|
||||
public TenantContext(Guid tenantId, string? tenantCode, string source)
|
||||
{
|
||||
TenantId = tenantId;
|
||||
TenantCode = tenantCode;
|
||||
Source = source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前租户 ID,未解析时为 Guid.Empty。
|
||||
/// </summary>
|
||||
public Guid TenantId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前租户编码(例如子域名或业务编码),可为空。
|
||||
/// </summary>
|
||||
public string? TenantCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 租户解析来源(Header、Host、Token 等)。
|
||||
/// </summary>
|
||||
public string Source { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已成功解析到租户。
|
||||
/// </summary>
|
||||
public bool IsResolved => TenantId != Guid.Empty;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Web.Security;
|
||||
|
||||
/// <summary>
|
||||
/// HttpContext 租户扩展方法。
|
||||
/// </summary>
|
||||
public static class TenantHttpContextExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取 HttpContext.Items 中缓存的租户上下文。
|
||||
/// </summary>
|
||||
/// <param name="context">当前 HttpContext</param>
|
||||
/// <returns>租户上下文,若不存在则返回 null</returns>
|
||||
public static TenantContext? GetTenantContext(this HttpContext? context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (context.Items.TryGetValue(TenantConstants.HttpContextItemKey, out var value) &&
|
||||
value is TenantContext tenantContext)
|
||||
{
|
||||
return tenantContext;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user