mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 06:37:31 +00:00
356 lines
10 KiB
Go
356 lines
10 KiB
Go
![]() |
package projection
|
||
|
|
||
|
import (
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
|
||
|
"github.com/zitadel/zitadel/internal/domain"
|
||
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||
|
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||
|
"github.com/zitadel/zitadel/internal/repository/instance"
|
||
|
"github.com/zitadel/zitadel/internal/repository/org"
|
||
|
)
|
||
|
|
||
|
func TestDomainsProjection_reduceOrgDomainAdded(t *testing.T) {
|
||
|
projection := &domainsProjection{}
|
||
|
|
||
|
event := &org.DomainAddedEvent{
|
||
|
BaseEvent: &eventstore.BaseEvent{
|
||
|
Agg: &eventstore.Aggregate{
|
||
|
ID: "org-id",
|
||
|
InstanceID: "instance-id",
|
||
|
Type: org.AggregateType,
|
||
|
ResourceOwner: "instance-id",
|
||
|
},
|
||
|
CreationDate: time.Now(),
|
||
|
},
|
||
|
Domain: "test.example.com",
|
||
|
}
|
||
|
|
||
|
stmt, err := projection.reduceOrgDomainAdded(event)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
assert.NotNil(t, stmt)
|
||
|
|
||
|
createStmt, ok := stmt.(*handler.CreateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// Verify the columns being set
|
||
|
expectedColumns := map[string]interface{}{
|
||
|
DomainsInstanceIDCol: "instance-id",
|
||
|
DomainsOrgIDCol: "org-id",
|
||
|
DomainsDomainCol: "test.example.com",
|
||
|
DomainsIsVerifiedCol: false,
|
||
|
DomainsIsPrimaryCol: false,
|
||
|
DomainsValidationTypeCol: domain.OrgDomainValidationTypeUnspecified,
|
||
|
DomainsCreatedAtCol: event.CreationDate(),
|
||
|
DomainsUpdatedAtCol: event.CreationDate(),
|
||
|
}
|
||
|
|
||
|
assert.Len(t, createStmt.Cols, len(expectedColumns))
|
||
|
|
||
|
for i, col := range createStmt.Cols {
|
||
|
switch col.Name {
|
||
|
case DomainsInstanceIDCol:
|
||
|
assert.Equal(t, "instance-id", col.Value)
|
||
|
case DomainsOrgIDCol:
|
||
|
assert.Equal(t, "org-id", col.Value)
|
||
|
case DomainsDomainCol:
|
||
|
assert.Equal(t, "test.example.com", col.Value)
|
||
|
case DomainsIsVerifiedCol:
|
||
|
assert.Equal(t, false, col.Value)
|
||
|
case DomainsIsPrimaryCol:
|
||
|
assert.Equal(t, false, col.Value)
|
||
|
case DomainsValidationTypeCol:
|
||
|
assert.Equal(t, domain.OrgDomainValidationTypeUnspecified, col.Value)
|
||
|
case DomainsCreatedAtCol, DomainsUpdatedAtCol:
|
||
|
assert.Equal(t, event.CreationDate(), col.Value)
|
||
|
default:
|
||
|
t.Errorf("Unexpected column: %s at index %d", col.Name, i)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDomainsProjection_reduceOrgDomainVerified(t *testing.T) {
|
||
|
projection := &domainsProjection{}
|
||
|
|
||
|
event := &org.DomainVerifiedEvent{
|
||
|
BaseEvent: &eventstore.BaseEvent{
|
||
|
Agg: &eventstore.Aggregate{
|
||
|
ID: "org-id",
|
||
|
InstanceID: "instance-id",
|
||
|
Type: org.AggregateType,
|
||
|
ResourceOwner: "instance-id",
|
||
|
},
|
||
|
CreationDate: time.Now(),
|
||
|
},
|
||
|
Domain: "test.example.com",
|
||
|
}
|
||
|
|
||
|
stmt, err := projection.reduceOrgDomainVerified(event)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
assert.NotNil(t, stmt)
|
||
|
|
||
|
updateStmt, ok := stmt.(*handler.UpdateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// Verify update columns
|
||
|
assert.Len(t, updateStmt.Cols, 2)
|
||
|
assert.Equal(t, DomainsUpdatedAtCol, updateStmt.Cols[0].Name)
|
||
|
assert.Equal(t, event.CreationDate(), updateStmt.Cols[0].Value)
|
||
|
assert.Equal(t, DomainsIsVerifiedCol, updateStmt.Cols[1].Name)
|
||
|
assert.Equal(t, true, updateStmt.Cols[1].Value)
|
||
|
|
||
|
// Verify conditions
|
||
|
assert.Len(t, updateStmt.Conditions, 4)
|
||
|
|
||
|
conditionMap := make(map[string]interface{})
|
||
|
for _, cond := range updateStmt.Conditions {
|
||
|
conditionMap[cond.Name] = cond.Value
|
||
|
}
|
||
|
|
||
|
assert.Equal(t, "instance-id", conditionMap[DomainsInstanceIDCol])
|
||
|
assert.Equal(t, "org-id", conditionMap[DomainsOrgIDCol])
|
||
|
assert.Equal(t, "test.example.com", conditionMap[DomainsDomainCol])
|
||
|
assert.Nil(t, conditionMap[DomainsDeletedAtCol])
|
||
|
}
|
||
|
|
||
|
func TestDomainsProjection_reduceOrgPrimaryDomainSet(t *testing.T) {
|
||
|
projection := &domainsProjection{}
|
||
|
|
||
|
event := &org.DomainPrimarySetEvent{
|
||
|
BaseEvent: &eventstore.BaseEvent{
|
||
|
Agg: &eventstore.Aggregate{
|
||
|
ID: "org-id",
|
||
|
InstanceID: "instance-id",
|
||
|
Type: org.AggregateType,
|
||
|
ResourceOwner: "instance-id",
|
||
|
},
|
||
|
CreationDate: time.Now(),
|
||
|
},
|
||
|
Domain: "test.example.com",
|
||
|
}
|
||
|
|
||
|
stmt, err := projection.reduceOrgPrimaryDomainSet(event)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
assert.NotNil(t, stmt)
|
||
|
|
||
|
multiStmt, ok := stmt.(*handler.MultiStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// Should have 2 update statements: unset old primary, set new primary
|
||
|
assert.Len(t, multiStmt.Statements, 2)
|
||
|
|
||
|
// First statement: unset existing primary
|
||
|
unsetStmt, ok := multiStmt.Statements[0].(*handler.UpdateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
assert.Len(t, unsetStmt.Cols, 2)
|
||
|
assert.Equal(t, DomainsUpdatedAtCol, unsetStmt.Cols[0].Name)
|
||
|
assert.Equal(t, DomainsIsPrimaryCol, unsetStmt.Cols[1].Name)
|
||
|
assert.Equal(t, false, unsetStmt.Cols[1].Value)
|
||
|
|
||
|
// Second statement: set new primary
|
||
|
setStmt, ok := multiStmt.Statements[1].(*handler.UpdateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
assert.Len(t, setStmt.Cols, 2)
|
||
|
assert.Equal(t, DomainsUpdatedAtCol, setStmt.Cols[0].Name)
|
||
|
assert.Equal(t, DomainsIsPrimaryCol, setStmt.Cols[1].Name)
|
||
|
assert.Equal(t, true, setStmt.Cols[1].Value)
|
||
|
}
|
||
|
|
||
|
func TestDomainsProjection_reduceInstanceDomainAdded(t *testing.T) {
|
||
|
projection := &domainsProjection{}
|
||
|
|
||
|
event := &instance.DomainAddedEvent{
|
||
|
BaseEvent: &eventstore.BaseEvent{
|
||
|
Agg: &eventstore.Aggregate{
|
||
|
ID: "instance-id",
|
||
|
InstanceID: "instance-id",
|
||
|
Type: instance.AggregateType,
|
||
|
ResourceOwner: "instance-id",
|
||
|
},
|
||
|
CreationDate: time.Now(),
|
||
|
},
|
||
|
Domain: "instance.example.com",
|
||
|
Generated: false,
|
||
|
}
|
||
|
|
||
|
stmt, err := projection.reduceInstanceDomainAdded(event)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
assert.NotNil(t, stmt)
|
||
|
|
||
|
createStmt, ok := stmt.(*handler.CreateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// Verify the columns being set for instance domain
|
||
|
expectedColumns := map[string]interface{}{
|
||
|
DomainsInstanceIDCol: "instance-id",
|
||
|
DomainsOrgIDCol: nil, // Instance domains have no org_id
|
||
|
DomainsDomainCol: "instance.example.com",
|
||
|
DomainsIsVerifiedCol: true, // Instance domains are always verified
|
||
|
DomainsIsPrimaryCol: false,
|
||
|
DomainsValidationTypeCol: nil, // Instance domains have no validation type
|
||
|
DomainsCreatedAtCol: event.CreationDate(),
|
||
|
DomainsUpdatedAtCol: event.CreationDate(),
|
||
|
}
|
||
|
|
||
|
assert.Len(t, createStmt.Cols, len(expectedColumns))
|
||
|
|
||
|
for _, col := range createStmt.Cols {
|
||
|
switch col.Name {
|
||
|
case DomainsInstanceIDCol:
|
||
|
assert.Equal(t, "instance-id", col.Value)
|
||
|
case DomainsOrgIDCol:
|
||
|
assert.Nil(t, col.Value)
|
||
|
case DomainsDomainCol:
|
||
|
assert.Equal(t, "instance.example.com", col.Value)
|
||
|
case DomainsIsVerifiedCol:
|
||
|
assert.Equal(t, true, col.Value)
|
||
|
case DomainsIsPrimaryCol:
|
||
|
assert.Equal(t, false, col.Value)
|
||
|
case DomainsValidationTypeCol:
|
||
|
assert.Nil(t, col.Value)
|
||
|
case DomainsCreatedAtCol, DomainsUpdatedAtCol:
|
||
|
assert.Equal(t, event.CreationDate(), col.Value)
|
||
|
default:
|
||
|
t.Errorf("Unexpected column: %s", col.Name)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestDomainsProjection_reduceOrgDomainRemoved(t *testing.T) {
|
||
|
projection := &domainsProjection{}
|
||
|
|
||
|
event := &org.DomainRemovedEvent{
|
||
|
BaseEvent: &eventstore.BaseEvent{
|
||
|
Agg: &eventstore.Aggregate{
|
||
|
ID: "org-id",
|
||
|
InstanceID: "instance-id",
|
||
|
Type: org.AggregateType,
|
||
|
ResourceOwner: "instance-id",
|
||
|
},
|
||
|
CreationDate: time.Now(),
|
||
|
},
|
||
|
Domain: "test.example.com",
|
||
|
}
|
||
|
|
||
|
stmt, err := projection.reduceOrgDomainRemoved(event)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
assert.NotNil(t, stmt)
|
||
|
|
||
|
updateStmt, ok := stmt.(*handler.UpdateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// Should update updated_at and deleted_at
|
||
|
assert.Len(t, updateStmt.Cols, 2)
|
||
|
assert.Equal(t, DomainsUpdatedAtCol, updateStmt.Cols[0].Name)
|
||
|
assert.Equal(t, event.CreationDate(), updateStmt.Cols[0].Value)
|
||
|
assert.Equal(t, DomainsDeletedAtCol, updateStmt.Cols[1].Name)
|
||
|
assert.Equal(t, event.CreationDate(), updateStmt.Cols[1].Value)
|
||
|
|
||
|
// Verify conditions include instance, org, and domain
|
||
|
assert.Len(t, updateStmt.Conditions, 3)
|
||
|
|
||
|
conditionMap := make(map[string]interface{})
|
||
|
for _, cond := range updateStmt.Conditions {
|
||
|
conditionMap[cond.Name] = cond.Value
|
||
|
}
|
||
|
|
||
|
assert.Equal(t, "instance-id", conditionMap[DomainsInstanceIDCol])
|
||
|
assert.Equal(t, "org-id", conditionMap[DomainsOrgIDCol])
|
||
|
assert.Equal(t, "test.example.com", conditionMap[DomainsDomainCol])
|
||
|
}
|
||
|
|
||
|
func TestDomainsProjection_reduceOrgRemoved(t *testing.T) {
|
||
|
projection := &domainsProjection{}
|
||
|
|
||
|
event := &org.OrgRemovedEvent{
|
||
|
BaseEvent: &eventstore.BaseEvent{
|
||
|
Agg: &eventstore.Aggregate{
|
||
|
ID: "org-id",
|
||
|
InstanceID: "instance-id",
|
||
|
Type: org.AggregateType,
|
||
|
ResourceOwner: "instance-id",
|
||
|
},
|
||
|
CreationDate: time.Now(),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
stmt, err := projection.reduceOrgRemoved(event)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
assert.NotNil(t, stmt)
|
||
|
|
||
|
updateStmt, ok := stmt.(*handler.UpdateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// Should update updated_at and deleted_at
|
||
|
assert.Len(t, updateStmt.Cols, 2)
|
||
|
assert.Equal(t, DomainsUpdatedAtCol, updateStmt.Cols[0].Name)
|
||
|
assert.Equal(t, event.CreationDate(), updateStmt.Cols[0].Value)
|
||
|
assert.Equal(t, DomainsDeletedAtCol, updateStmt.Cols[1].Name)
|
||
|
assert.Equal(t, event.CreationDate(), updateStmt.Cols[1].Value)
|
||
|
|
||
|
// Should soft delete all domains for the org
|
||
|
assert.Len(t, updateStmt.Conditions, 3)
|
||
|
|
||
|
conditionMap := make(map[string]interface{})
|
||
|
for _, cond := range updateStmt.Conditions {
|
||
|
conditionMap[cond.Name] = cond.Value
|
||
|
}
|
||
|
|
||
|
assert.Equal(t, "instance-id", conditionMap[DomainsInstanceIDCol])
|
||
|
assert.Equal(t, "org-id", conditionMap[DomainsOrgIDCol])
|
||
|
assert.Nil(t, conditionMap[DomainsDeletedAtCol]) // Only affect non-deleted domains
|
||
|
}
|
||
|
|
||
|
func TestDomainsProjection_reduceInstanceRemoved(t *testing.T) {
|
||
|
projection := &domainsProjection{}
|
||
|
|
||
|
event := &instance.InstanceRemovedEvent{
|
||
|
BaseEvent: &eventstore.BaseEvent{
|
||
|
Agg: &eventstore.Aggregate{
|
||
|
ID: "instance-id",
|
||
|
InstanceID: "instance-id",
|
||
|
Type: instance.AggregateType,
|
||
|
ResourceOwner: "instance-id",
|
||
|
},
|
||
|
CreationDate: time.Now(),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
stmt, err := projection.reduceInstanceRemoved(event)
|
||
|
|
||
|
require.NoError(t, err)
|
||
|
assert.NotNil(t, stmt)
|
||
|
|
||
|
updateStmt, ok := stmt.(*handler.UpdateStatement)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// Should update updated_at and deleted_at
|
||
|
assert.Len(t, updateStmt.Cols, 2)
|
||
|
assert.Equal(t, DomainsUpdatedAtCol, updateStmt.Cols[0].Name)
|
||
|
assert.Equal(t, event.CreationDate(), updateStmt.Cols[0].Value)
|
||
|
assert.Equal(t, DomainsDeletedAtCol, updateStmt.Cols[1].Name)
|
||
|
assert.Equal(t, event.CreationDate(), updateStmt.Cols[1].Value)
|
||
|
|
||
|
// Should soft delete all domains for the instance
|
||
|
assert.Len(t, updateStmt.Conditions, 2)
|
||
|
|
||
|
conditionMap := make(map[string]interface{})
|
||
|
for _, cond := range updateStmt.Conditions {
|
||
|
conditionMap[cond.Name] = cond.Value
|
||
|
}
|
||
|
|
||
|
assert.Equal(t, "instance-id", conditionMap[DomainsInstanceIDCol])
|
||
|
assert.Nil(t, conditionMap[DomainsDeletedAtCol]) // Only affect non-deleted domains
|
||
|
}
|