1
0
forked from baron/baron-sso
Files
baron-sso/backend/internal/service/worksmobile_live_flow_test.go

146 lines
5.1 KiB
Go

package service
import (
"baron-sso-backend/internal/domain"
"baron-sso-backend/internal/repository"
"context"
"fmt"
"os"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func TestWorksmobileLiveSamanUsersDirectoryProvisioning(t *testing.T) {
if os.Getenv("WORKSMOBILE_LIVE_SAMAN_PROVISIONING") != "1" {
t.Skip("live Worksmobile Saman provisioning is disabled")
}
ctx := context.Background()
db, err := gorm.Open(postgres.Open(worksmobileLiveDSN()), &gorm.Config{})
require.NoError(t, err)
tenantRepo := repository.NewTenantRepository(db)
userRepo := repository.NewUserRepository(db)
userGroupRepo := repository.NewUserGroupRepository(db)
outboxRepo := repository.NewWorksmobileOutboxRepository(db)
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
})
syncService := NewWorksmobileSyncService(tenantService, userRepo, outboxRepo, client)
worker := NewWorksmobileRelayWorker(outboxRepo, client)
root, err := tenantService.GetTenantBySlug(ctx, HanmacFamilyTenantSlug)
require.NoError(t, err)
samanTenant, err := tenantService.GetTenantBySlug(ctx, "saman")
require.NoError(t, err)
createWorksmobileLiveOrgUnitIfMissing(t, ctx, client, *samanTenant)
targetEmails := []string{"tester@samaneng.com", "orgadmin@samaneng.com"}
for _, email := range targetEmails {
user, err := userRepo.FindByEmail(ctx, email)
require.NoError(t, err)
dedupeKey := "user:" + strings.ToLower(WorksmobileUserStatusAction(user.Status)) + ":" + user.ID
job := findWorksmobileLiveOutboxByDedupe(t, db, dedupeKey)
if job.Status != domain.WorksmobileOutboxStatusProcessed {
remote, err := client.FindUser(ctx, user.Email)
require.NoError(t, err)
if remote != nil {
require.NoError(t, outboxRepo.MarkProcessed(ctx, job.ID))
continue
}
item, err := syncService.EnqueueUserSync(ctx, root.ID, user.ID)
require.NoError(t, err)
require.NotEmpty(t, item)
require.NoError(t, outboxRepo.MarkRetry(ctx, job.ID))
job = findWorksmobileLiveOutboxByDedupe(t, db, dedupeKey)
err = worker.processJob(ctx, job)
require.NoError(t, err)
}
processed, err := outboxRepo.FindByID(ctx, job.ID)
require.NoError(t, err)
require.Equal(t, domain.WorksmobileOutboxStatusProcessed, processed.Status)
}
credentials, err := syncService.ListInitialPasswordCredentials(ctx, root.ID)
require.NoError(t, err)
seen := map[string]bool{}
for _, credential := range credentials {
if credential.Email == "tester@samaneng.com" || credential.Email == "orgadmin@samaneng.com" {
require.Equal(t, domain.WorksmobileOutboxStatusProcessed, credential.Status)
require.Len(t, credential.InitialPassword, 16)
seen[credential.Email] = true
}
}
require.True(t, seen["tester@samaneng.com"])
require.True(t, seen["orgadmin@samaneng.com"])
remoteUsers, err := client.ListUsers(ctx)
require.NoError(t, err)
remoteByEmail := map[string]WorksmobileRemoteUser{}
for _, user := range remoteUsers {
remoteByEmail[user.Email] = user
}
require.NotEmpty(t, remoteByEmail["tester@samaneng.com"].ID)
require.NotEmpty(t, remoteByEmail["orgadmin@samaneng.com"].ID)
remoteGroups, err := client.ListGroups(ctx)
require.NoError(t, err)
foundSamanOrgUnit := false
for _, group := range remoteGroups {
if group.ExternalID == samanTenant.ID {
foundSamanOrgUnit = true
require.Equal(t, "삼안", group.DisplayName)
}
}
require.True(t, foundSamanOrgUnit)
}
func createWorksmobileLiveOrgUnitIfMissing(t *testing.T, ctx context.Context, client *WorksmobileHTTPClient, tenant domain.Tenant) {
t.Helper()
payload, err := BuildWorksmobileOrgUnitPayload(tenant, nil, 1)
require.NoError(t, err)
if tenant.ParentID != nil {
payload.ParentOrgUnitID = ""
}
err = client.CreateOrgUnit(ctx, payload)
if apiErr, ok := err.(WorksmobileHTTPError); ok && apiErr.StatusCode == 409 {
return
}
require.NoError(t, err)
}
func worksmobileLiveDSN() string {
host := getenvDefault("DB_HOST", "localhost")
port := getenvDefault("DB_PORT", "5432")
user := getenvDefault("DB_USER", "baron")
password := os.Getenv("DB_PASSWORD")
name := getenvDefault("DB_NAME", "baron_sso")
return fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Seoul", host, user, password, name, port)
}
func findWorksmobileLiveOutboxByDedupe(t *testing.T, db *gorm.DB, dedupeKey string) domain.WorksmobileOutbox {
t.Helper()
var job domain.WorksmobileOutbox
deadline := time.Now().Add(3 * time.Second)
for {
err := db.Where("dedupe_key = ?", dedupeKey).First(&job).Error
if err == nil {
return job
}
if time.Now().After(deadline) {
require.NoError(t, err)
}
time.Sleep(100 * time.Millisecond)
}
}