feat: complete tenant site provisioning flow

This commit is contained in:
2026-08-01 17:27:51 +08:00
parent d58bcd97e9
commit ecf506df8a
39 changed files with 22760 additions and 271 deletions

View File

@@ -41,7 +41,8 @@ public sealed record PlatformTenantDetail(
IReadOnlyCollection<PlatformTenantDomainItem> Domains,
IReadOnlyCollection<PlatformTenantSubscriptionItem> Subscriptions,
TenantBillingProfileItem? BillingProfile,
TenantBillingPolicyItem? BillingPolicy);
TenantBillingPolicyItem? BillingPolicy,
PlatformOwnerActivationStatus OwnerActivation);
public sealed record PlatformTenantDomainItem(
Guid Id,
@@ -54,7 +55,29 @@ public sealed record PlatformTenantDomainItem(
DateTimeOffset? DnsVerifiedAt,
DateTimeOffset? TlsReadyAt,
DateTimeOffset? LastCheckedAt,
string? LastFailureReason);
string? LastFailureReason,
string? VerificationRecordName,
string? VerificationToken,
string? CnameTarget);
public sealed record PlatformOwnerActivationStatus(
string Status,
Guid? ActivationId,
DateTimeOffset? ExpiresAt);
public sealed record PlatformOwnerActivationLinkResult(
Guid ActivationId,
string? ActivationUrl,
DateTimeOffset ExpiresAt,
bool IsReplay);
public sealed record IssuePlatformOwnerActivationLinkCommand(
Guid TenantId,
string IdempotencyKey,
string Reason,
bool ReplaceExisting);
public sealed record ReplacePlatformPrimaryDomainCommand(Guid TenantId, string Host, string Reason);
public sealed record PlatformTenantSubscriptionItem(
Guid Id,
@@ -88,29 +111,36 @@ public sealed record CreatePlatformTenantCommand(
TenantStatus Status,
BillingStatus BillingStatus,
JsonElement Metadata,
string PrimaryDomainHost,
string? OwnerEmail,
string? OwnerPhone,
string OwnerName,
string? TemporaryPassword,
Guid? InitialOfferingVersionId,
int TrialDays,
int? TrialDays,
TenantBillingCollectionMode CollectionMode,
string DefaultPaymentProvider,
bool AutoGenerateRenewal,
int RenewalLeadDays,
string IdempotencyKey,
bool AllowTemporaryPassword);
string IdempotencyKey);
public sealed record PlatformTenantProvisioningResult(
PlatformTenantItem Tenant,
Guid OwnerUserId,
string OwnerIdentifier,
bool MustChangePassword,
Guid? ActivationId,
string? ActivationToken,
DateTimeOffset? ActivationExpiresAt,
PlatformTenantDomainItem PrimaryDomain,
PlatformOwnerActivationStatus OwnerActivation,
bool IsReplay);
public sealed class TenantProvisioningOptions
{
public const string SectionName = "TenantProvisioning";
public string DefaultBaseOfferingCode { get; set; } = "starter";
public int DefaultTrialDays { get; set; } = 14;
public int OwnerActivationMinutes { get; set; } = 30;
public string OwnerActivationUrlTemplate { get; set; } = "https://{host}";
}
public sealed record TenantBillingPolicyItem(
Guid TenantId,
TenantBillingCollectionMode CollectionMode,
@@ -264,6 +294,8 @@ public interface IPlatformAdminService
Task<PlatformTenantList> GetTenantsAsync(PlatformAdminActor actor, PlatformAdminQuery query, CancellationToken cancellationToken = default);
Task<PlatformTenantDetail> GetTenantDetailAsync(PlatformAdminActor actor, Guid tenantId, CancellationToken cancellationToken = default);
Task<PlatformTenantProvisioningResult> CreateTenantAsync(PlatformAdminActor actor, CreatePlatformTenantCommand command, CancellationToken cancellationToken = default);
Task<PlatformTenantDomainItem> ReplacePrimaryDomainAsync(PlatformAdminActor actor, ReplacePlatformPrimaryDomainCommand command, CancellationToken cancellationToken = default);
Task<PlatformOwnerActivationLinkResult> IssueOwnerActivationLinkAsync(PlatformAdminActor actor, IssuePlatformOwnerActivationLinkCommand command, CancellationToken cancellationToken = default);
Task<PlatformTenantItem> UpdateTenantStatusAsync(PlatformAdminActor actor, UpdatePlatformTenantStatusCommand command, CancellationToken cancellationToken = default);
Task<TenantBillingProfileItem> UpsertTenantBillingProfileAsync(PlatformAdminActor actor, UpsertPlatformTenantBillingProfileCommand command, CancellationToken cancellationToken = default);
Task<TenantBillingPolicyItem> GetTenantBillingPolicyAsync(PlatformAdminActor actor, Guid tenantId, CancellationToken cancellationToken = default);