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

@@ -2,11 +2,13 @@ using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Tiku.Application.Auth;
using Tiku.Api.Contracts;
using Tiku.Domain.Identity;
using Tiku.Domain.Tenancy;
using Tiku.Infrastructure.Auth;
using Tiku.Infrastructure.Commerce;
using Tiku.Infrastructure.Persistence;
namespace Tiku.IntegrationTests.Api;
@@ -166,6 +168,11 @@ public sealed class AuthEndpointTests
{
await using var factory = new ApiTestFactory(new FakeWechatOAuthClient());
var tenantId = Guid.NewGuid();
var secretRef = "tenant_secrets:identity:wechat_miniapp:default";
var protectedSecret = ProtectTenantSecret(
tenantId,
secretRef,
JsonSerializer.SerializeToElement(new { appSecret = "wx-app-secret" }));
await factory.SeedAsync(
new Tenant
{
@@ -173,16 +180,30 @@ public sealed class AuthEndpointTests
Slug = tenantId.ToString("N"),
Name = "Wechat Tenant"
},
new TenantAuthProvider
new TenantExternalProvider
{
TenantId = tenantId,
Provider = "wechat-miniapp",
Status = TenantAuthProviderStatus.Testing,
Provider = "wechat_miniapp",
Capability = TenantExternalProviderCapability.Identity,
Status = TenantExternalProviderStatus.Active,
SecretRef = secretRef,
ConfigPublic = JsonSerializer.SerializeToElement(new
{
appId = "wx-app-id",
appSecret = "wx-app-secret"
appId = "wx-app-id"
})
},
new TenantSecret
{
TenantId = tenantId,
Purpose = "identity",
Provider = "wechat_miniapp",
SecretKey = "default",
SecretRef = secretRef,
Status = TenantSecretStatus.Active,
EncryptionKeyId = protectedSecret.KeyId,
EncryptedPayload = protectedSecret.Ciphertext,
EncryptionNonce = protectedSecret.Nonce,
EncryptionTag = protectedSecret.Tag
});
using var client = factory.CreateClient();
@@ -207,7 +228,7 @@ public sealed class AuthEndpointTests
Assert.Equal(HttpStatusCode.OK, loginResponse.StatusCode);
Assert.Equal(HttpStatusCode.OK, meResponse.StatusCode);
Assert.Contains(dbContext.UserIdentities, identity =>
identity.Provider == "wechat-miniapp" &&
identity.Provider == "wechat_miniapp" &&
identity.OpenId == "mini-open-id" &&
identity.UnionId == "union-id");
}
@@ -285,6 +306,16 @@ public sealed class AuthEndpointTests
return document.RootElement.Clone();
}
private static ProtectedTenantSecret ProtectTenantSecret(Guid tenantId, string secretRef, JsonElement payload)
{
var protector = new TenantSecretProtector(Options.Create(new TenantSecretEncryptionOptions
{
KeyId = "development-v1",
MasterKey = TenantSecretEncryptionOptions.DevelopmentMasterKey
}));
return protector.Protect(tenantId, secretRef, payload);
}
private sealed class FakeWechatOAuthClient : IWechatOAuthClient
{
public Task<WechatIdentity> ExchangeWebCodeAsync(