- 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.
127 lines
4.4 KiB
Go
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)
|
|
}
|
|
}
|