ultisuite-backend/internal/migration/claim_email_match_test.go
R3D347HR4Y 1ffd0817d8
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run
feat(migration): enhance migration API with roster and audit export features
- Added endpoints for listing and importing migration rosters.
- Introduced audit export functionality for migration jobs in CSV and NDJSON formats.
- Implemented tenant mismatch validation for Microsoft migration claims.
- Enhanced error handling for email claiming and migration processes.
- Added integration tests for roster import and claim workflows.
2026-06-13 13:11:30 +02:00

127 lines
4.4 KiB
Go

package migration
import "testing"
func TestInviteEmailMatchesIdentityExact(t *testing.T) {
id := ClaimIdentity{Email: "Alice@Acme.com"}
if !InviteEmailMatchesIdentity("alice@acme.com", nil, "", id) {
t.Fatal("expected case-insensitive exact match")
}
}
func TestInviteEmailMatchesIdentityPreferredUsername(t *testing.T) {
id := ClaimIdentity{
Email: "alice.smith@acme.com",
PreferredUsername: "alice@acme.com",
}
if !InviteEmailMatchesIdentity("alice@acme.com", nil, "", id) {
t.Fatal("expected preferred_username match")
}
}
func TestInviteEmailMatchesIdentityUPN(t *testing.T) {
id := ClaimIdentity{
Email: "alice.smith@acme.com",
UPN: "alice@acme.com",
}
if !InviteEmailMatchesIdentity("alice@acme.com", nil, "", id) {
t.Fatal("expected upn match")
}
}
func TestInviteEmailMatchesIdentityAlternateEmail(t *testing.T) {
id := ClaimIdentity{Email: "alice.smith@acme.com"}
if !InviteEmailMatchesIdentity("alice@acme.com", []string{"alice.smith@acme.com"}, "", id) {
t.Fatal("expected alternate email match")
}
}
func TestInviteEmailMatchesIdentityGmailDotAlias(t *testing.T) {
id := ClaimIdentity{Email: "alice.smith@acme.com"}
if !InviteEmailMatchesIdentity("alice.smith@acme.com", nil, "", id) {
t.Fatal("expected exact match baseline")
}
id = ClaimIdentity{Email: "a.l.i.c.e.smith@gmail.com"}
if !InviteEmailMatchesIdentity("alice.smith@gmail.com", nil, "", id) {
t.Fatal("expected dot-insensitive local-part match on gmail.com")
}
id = ClaimIdentity{Email: "a.l.i.c.e.smith@acme.com"}
if InviteEmailMatchesIdentity("alice.smith@acme.com", nil, "", id) {
t.Fatal("expected reject dot-alias on non-gmail domain")
}
}
func TestInviteEmailMatchesIdentityPlusTag(t *testing.T) {
id := ClaimIdentity{Email: "alice+tag@gmail.com"}
if !InviteEmailMatchesIdentity("alice@gmail.com", nil, "", id) {
t.Fatal("expected plus-tag stripped match on gmail.com")
}
id = ClaimIdentity{Email: "alice+tag@acme.com"}
if InviteEmailMatchesIdentity("alice@acme.com", nil, "", id) {
t.Fatal("expected reject plus-tag alias on non-gmail domain")
}
}
func TestInviteEmailMatchesIdentityProjectDomainUPN(t *testing.T) {
id := ClaimIdentity{
Email: "alice.smith@acme.com",
PreferredUsername: "alice@contoso.onmicrosoft.com",
}
if !InviteEmailMatchesIdentity("alice@acme.com", nil, "acme.com", id) {
t.Fatal("expected project-domain UPN local-part match")
}
}
func TestInviteEmailMatchesIdentityRejectsDifferentUserSameDomain(t *testing.T) {
id := ClaimIdentity{Email: "bob@acme.com"}
if InviteEmailMatchesIdentity("alice@acme.com", nil, "acme.com", id) {
t.Fatal("expected reject for different local-part on same domain")
}
}
func TestInviteEmailMatchesIdentityRejectsUnrelatedDomain(t *testing.T) {
id := ClaimIdentity{Email: "alice@evil.com"}
if InviteEmailMatchesIdentity("alice@acme.com", nil, "", id) {
t.Fatal("expected reject for different domain without alias")
}
}
func TestInviteEmailMatchesIdentityEmptyIdentity(t *testing.T) {
if InviteEmailMatchesIdentity("alice@acme.com", nil, "", ClaimIdentity{}) {
t.Fatal("expected reject for empty identity")
}
}
func TestInviteEmailMatchesIdentityIgnoresNonEmailPreferredUsername(t *testing.T) {
id := ClaimIdentity{PreferredUsername: "alice"}
if InviteEmailMatchesIdentity("alice@acme.com", nil, "", id) {
t.Fatal("expected reject when preferred_username is not an email")
}
}
func TestValidateMicrosoftTenantClaim(t *testing.T) {
msProj := Project{SourceProvider: "microsoft", MicrosoftTenantID: "tenant-abc"}
if err := validateMicrosoftTenantClaim(msProj, "tenant-abc"); err != nil {
t.Fatalf("expected match: %v", err)
}
if err := validateMicrosoftTenantClaim(msProj, "TENANT-ABC"); err != nil {
t.Fatalf("expected case-insensitive match: %v", err)
}
if err := validateMicrosoftTenantClaim(msProj, "other-tenant"); err != ErrTenantMismatch {
t.Fatalf("expected tenant mismatch, got %v", err)
}
if err := validateMicrosoftTenantClaim(msProj, ""); err != ErrTenantMismatch {
t.Fatalf("expected reject empty tid when tenant pinned: %v", err)
}
googleProj := Project{SourceProvider: "google", MicrosoftTenantID: "tenant-abc"}
if err := validateMicrosoftTenantClaim(googleProj, "wrong"); err != nil {
t.Fatalf("google project should ignore tenant: %v", err)
}
noTenant := Project{SourceProvider: "microsoft"}
if err := validateMicrosoftTenantClaim(noTenant, "any"); err != nil {
t.Fatalf("expected skip when project tenant unset: %v", err)
}
}