forked from baron/baron-sso
146 lines
5.1 KiB
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)
|
|
}
|
|
}
|