accounts/internal/store/xworkmate_test.go
2026-04-11 20:25:40 +08:00

205 lines
6.6 KiB
Go

package store
import (
"context"
"strings"
"testing"
)
func TestNormalizeHostname(t *testing.T) {
t.Parallel()
got := NormalizeHostname("https://XW-ABCD.svc.plus:443/path?q=1")
if got != "xw-abcd.svc.plus" {
t.Fatalf("expected normalized host, got %q", got)
}
}
func TestGenerateRandomTenantDomain(t *testing.T) {
t.Parallel()
got, err := GenerateRandomTenantDomain()
if err != nil {
t.Fatalf("expected domain generation to succeed: %v", err)
}
if !strings.HasPrefix(got, "xw-") || !strings.HasSuffix(got, ".svc.plus") {
t.Fatalf("expected generated svc.plus tenant domain, got %q", got)
}
}
func TestMemoryStoreResolveTenantAndProfile(t *testing.T) {
ctx := context.Background()
st := NewMemoryStore()
if err := st.EnsureTenant(ctx, &Tenant{
ID: SharedXWorkmateTenantID,
Name: SharedXWorkmateTenantName,
Edition: SharedPublicTenantEdition,
}); err != nil {
t.Fatalf("ensure shared tenant: %v", err)
}
if err := st.EnsureTenantDomain(ctx, &TenantDomain{
TenantID: SharedXWorkmateTenantID,
Domain: SharedXWorkmateDomain,
Kind: TenantDomainKindGenerated,
IsPrimary: true,
Status: TenantDomainStatusVerified,
}); err != nil {
t.Fatalf("ensure shared domain: %v", err)
}
tenant, domain, err := st.ResolveTenantByHost(ctx, "console.svc.plus")
if err != nil {
t.Fatalf("resolve shared tenant: %v", err)
}
if tenant.ID != SharedXWorkmateTenantID {
t.Fatalf("expected shared tenant id, got %q", tenant.ID)
}
if domain == nil || domain.Domain != SharedXWorkmateDomain {
t.Fatalf("expected shared primary domain, got %#v", domain)
}
privateTenant := &Tenant{
ID: "tenant-private-1",
Name: "Tenant One",
Edition: TenantPrivateEdition,
}
if err := st.EnsureTenant(ctx, privateTenant); err != nil {
t.Fatalf("ensure private tenant: %v", err)
}
if err := st.EnsureTenantDomain(ctx, &TenantDomain{
TenantID: privateTenant.ID,
Domain: "xw-tenant-one.svc.plus",
Kind: TenantDomainKindGenerated,
IsPrimary: true,
Status: TenantDomainStatusVerified,
}); err != nil {
t.Fatalf("ensure private domain: %v", err)
}
if err := st.UpsertTenantMembership(ctx, &TenantMembership{
TenantID: privateTenant.ID,
UserID: "user-1",
Role: TenantMembershipRoleAdmin,
}); err != nil {
t.Fatalf("ensure private membership: %v", err)
}
if err := st.UpsertXWorkmateProfile(ctx, &XWorkmateProfile{
TenantID: privateTenant.ID,
UserID: "user-1",
Scope: XWorkmateProfileScopeUserPrivate,
BridgeServerURL: "wss://openclaw.tenant-one.svc.plus",
VaultSecretPath: "kv/openclaw",
VaultSecretKey: "token",
}); err != nil {
t.Fatalf("upsert private profile: %v", err)
}
tenant, domain, err = st.ResolveTenantByHost(ctx, "https://xw-tenant-one.svc.plus")
if err != nil {
t.Fatalf("resolve private tenant: %v", err)
}
if tenant.ID != privateTenant.ID {
t.Fatalf("expected tenant %q, got %q", privateTenant.ID, tenant.ID)
}
if domain == nil || domain.Domain != "xw-tenant-one.svc.plus" {
t.Fatalf("expected tenant domain, got %#v", domain)
}
profile, err := st.GetXWorkmateProfile(ctx, privateTenant.ID, "user-1", XWorkmateProfileScopeUserPrivate)
if err != nil {
t.Fatalf("get private profile: %v", err)
}
if profile.BridgeServerURL != "wss://openclaw.tenant-one.svc.plus" {
t.Fatalf("expected persisted bridge server url, got %q", profile.BridgeServerURL)
}
if profile.VaultSecretPath != "kv/openclaw" || profile.VaultSecretKey != "token" {
t.Fatalf("expected legacy secret fields to round-trip, got %#v", profile)
}
if len(profile.SecretLocators) != 1 {
t.Fatalf("expected synthesized secret locator, got %#v", profile.SecretLocators)
}
if profile.SecretLocators[0].Provider != XWorkmateSecretLocatorProviderVault {
t.Fatalf("expected vault provider, got %#v", profile.SecretLocators[0])
}
if profile.SecretLocators[0].Target != XWorkmateSecretLocatorTargetBridgeAuthToken {
t.Fatalf("expected bridge auth token target, got %#v", profile.SecretLocators[0])
}
if profile.SecretLocators[0].SecretPath != "kv/openclaw" || profile.SecretLocators[0].SecretKey != "token" {
t.Fatalf("expected synthesized secret locator path/key, got %#v", profile.SecretLocators[0])
}
memberships, err := st.ListTenantMembershipsByUser(ctx, "user-1")
if err != nil {
t.Fatalf("list memberships: %v", err)
}
if len(memberships) != 1 {
t.Fatalf("expected 1 tenant membership, got %d", len(memberships))
}
if memberships[0].TenantName != "Tenant One" {
t.Fatalf("expected tenant name to be populated, got %q", memberships[0].TenantName)
}
}
func TestMemoryStorePersistsExplicitSecretLocators(t *testing.T) {
ctx := context.Background()
st := NewMemoryStore()
if err := st.EnsureTenant(ctx, &Tenant{
ID: "tenant-locator-1",
Name: "Tenant Locator",
Edition: TenantPrivateEdition,
}); err != nil {
t.Fatalf("ensure tenant: %v", err)
}
locators := []XWorkmateSecretLocator{
{
ID: "locator-openclaw",
Provider: "vault",
SecretPath: "kv/openclaw",
SecretKey: "gateway-token",
Target: XWorkmateSecretLocatorTargetBridgeAuthToken,
Required: true,
},
{
ID: "locator-ai-gateway",
Provider: "vault",
SecretPath: "kv/ai",
SecretKey: "access-token",
Target: XWorkmateSecretLocatorTargetAIGatewayAccessToken,
},
}
if err := st.UpsertXWorkmateProfile(ctx, &XWorkmateProfile{
TenantID: "tenant-locator-1",
UserID: "user-2",
Scope: XWorkmateProfileScopeUserPrivate,
VaultURL: "https://vault.example.com",
VaultNamespace: "team-locators",
SecretLocators: locators,
}); err != nil {
t.Fatalf("upsert profile: %v", err)
}
profile, err := st.GetXWorkmateProfile(ctx, "tenant-locator-1", "user-2", XWorkmateProfileScopeUserPrivate)
if err != nil {
t.Fatalf("get profile: %v", err)
}
if len(profile.SecretLocators) != len(locators) {
t.Fatalf("expected %d locators, got %#v", len(locators), profile.SecretLocators)
}
for i := range locators {
if profile.SecretLocators[i].ID != locators[i].ID ||
profile.SecretLocators[i].Provider != locators[i].Provider ||
profile.SecretLocators[i].SecretPath != locators[i].SecretPath ||
profile.SecretLocators[i].SecretKey != locators[i].SecretKey ||
profile.SecretLocators[i].Target != locators[i].Target ||
profile.SecretLocators[i].Required != locators[i].Required {
t.Fatalf("locator %d mismatch: got %#v want %#v", i, profile.SecretLocators[i], locators[i])
}
}
if profile.VaultSecretPath != "kv/openclaw" || profile.VaultSecretKey != "gateway-token" {
t.Fatalf("expected openclaw locator to back legacy fields, got %#v", profile)
}
}