feat(saas): implement marketplace and tenant onboarding

This commit is contained in:
2026-07-29 13:58:59 +08:00
parent 76606029e2
commit 6db200a2fc
145 changed files with 16862 additions and 94529 deletions

View File

@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using Tiku.Application.Auth;
using Tiku.Application.Security;
using Tiku.Application.Tenancy;
using Tiku.Domain.Identity;
using Tiku.Domain.Tenancy;
@@ -19,7 +20,8 @@ public sealed class AuthService(
ISmsVerificationService smsVerificationService,
IAuthSessionStore sessionStore,
IWechatOAuthClient wechatOAuthClient,
ITenantExternalProviderConfigService providerConfigService) : IAuthService
ITenantExternalProviderConfigService providerConfigService,
IFeatureAccessService featureAccessService) : IAuthService
{
private const string PasswordProvider = "password";
private const string SmsProvider = "sms";
@@ -393,6 +395,9 @@ public sealed class AuthService(
throw;
}
await using var transaction = dbContext.Database.CurrentTransaction is null
? await dbContext.Database.BeginTransactionAsync(cancellationToken)
: null;
var providerSubject = $"{config.AppId}:{identity.OpenId}";
var user = await UpsertWechatUserAsync(
provider,
@@ -408,6 +413,10 @@ public sealed class AuthService(
// tenant policy and existing membership state have accepted the login.
// A denied first login must not leave a user or provider identity behind.
await dbContext.SaveChangesAsync(cancellationToken);
if (transaction is not null)
{
await transaction.CommitAsync(cancellationToken);
}
return await CompleteSuccessfulLoginAsync(
request.Realm,
@@ -568,6 +577,11 @@ public sealed class AuthService(
throw new TenantAccessDeniedException();
}
await featureAccessService.ConsumeQuotaIfConfiguredAsync(
tenantId,
SaasQuotaMetricCatalog.StudentCount,
cancellationToken: cancellationToken);
dbContext.TenantMemberships.Add(new TenantMembership
{
TenantId = tenantId,