fix: handle UserLoginMustBeDomain changes correctly (#4765)

* fix: handle UserLoginMustBeDomain changes correctly

* fix: remove verified domains (and not only primary) as suffix

* fix: ensure testability by changing map to slice

* cleanup

* reduce complexity of DomainPolicyUsernamesWriteModel.Reduce()

* add test for removed org policy
This commit is contained in:
Livio Spring
2022-12-06 09:01:31 +01:00
committed by GitHub
parent 97fe041a86
commit 3539418a4a
12 changed files with 1042 additions and 332 deletions

View File

@@ -5,14 +5,16 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/domain"
caos_errs "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/repository"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
"github.com/zitadel/zitadel/internal/repository/instance"
"github.com/zitadel/zitadel/internal/repository/org"
"github.com/zitadel/zitadel/internal/repository/policy"
"github.com/zitadel/zitadel/internal/repository/user"
)
func TestCommandSide_AddDomainPolicy(t *testing.T) {
@@ -20,12 +22,14 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
eventstore *eventstore.Eventstore
}
type args struct {
ctx context.Context
orgID string
policy *domain.DomainPolicy
ctx context.Context
orgID string
userLoginMustBeDomain bool
validateOrgDomains bool
smtpSenderAddressMatchesInstanceDomain bool
}
type res struct {
want *domain.DomainPolicy
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
@@ -42,18 +46,17 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
),
},
args: args{
ctx: context.Background(),
policy: &domain.DomainPolicy{
UserLoginMustBeDomain: true,
ValidateOrgDomains: true,
},
ctx: context.Background(),
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "mail template already existing, already exists error",
name: "policy already existing, already exists error",
fields: fields{
eventstore: eventstoreExpect(
t,
@@ -70,24 +73,32 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
policy: &domain.DomainPolicy{
UserLoginMustBeDomain: true,
ValidateOrgDomains: true,
SMTPSenderAddressMatchesInstanceDomain: true,
},
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
err: caos_errs.IsErrorAlreadyExists,
},
},
{
name: "add policy,ok",
name: "add policy, no userLoginMustBeDomain change, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
true,
false,
false,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
@@ -103,23 +114,139 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
policy: &domain.DomainPolicy{
UserLoginMustBeDomain: true,
ValidateOrgDomains: true,
SMTPSenderAddressMatchesInstanceDomain: true,
},
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
want: &domain.DomainPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: "org1",
ResourceOwner: "org1",
},
UserLoginMustBeDomain: true,
ValidateOrgDomains: true,
SMTPSenderAddressMatchesInstanceDomain: true,
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "add policy, userLoginMustBeDomain changed, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
false,
false,
false,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainVerifiedEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"org.com",
),
),
eventFromEventPusher(
org.NewDomainVerifiedEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"test.com",
),
),
eventFromEventPusher(
org.NewDomainRemovedEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"test.com",
true,
),
),
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"org.com",
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1@org.com",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"user1@org.com",
false,
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user2", "org1").Aggregate,
"user@test.com",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"user@test.com",
false,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
true,
true,
true,
),
),
eventFromEventPusher(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1@org.com",
"user1",
true,
user.UsernameChangedEventWithPolicyChange(),
),
),
eventFromEventPusher(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user2", "org1").Aggregate,
"user@test.com",
"user@test.com",
true,
user.UsernameChangedEventWithPolicyChange(),
),
),
},
uniqueConstraintsFromEventConstraint(user.NewRemoveUsernameUniqueConstraint("user1@org.com", "org1", false)),
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("user1", "org1", true)),
uniqueConstraintsFromEventConstraint(user.NewRemoveUsernameUniqueConstraint("user@test.com", "org1", false)),
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("user@test.com", "org1", true)),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
@@ -129,7 +256,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
}
got, err := r.AddOrgDomainPolicy(tt.args.ctx, tt.args.orgID, tt.args.policy)
got, err := r.AddOrgDomainPolicy(tt.args.ctx, tt.args.orgID, tt.args.userLoginMustBeDomain, tt.args.validateOrgDomains, tt.args.smtpSenderAddressMatchesInstanceDomain)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -148,12 +275,14 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
eventstore *eventstore.Eventstore
}
type args struct {
ctx context.Context
orgID string
policy *domain.DomainPolicy
ctx context.Context
orgID string
userLoginMustBeDomain bool
validateOrgDomains bool
smtpSenderAddressMatchesInstanceDomain bool
}
type res struct {
want *domain.DomainPolicy
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
@@ -170,11 +299,10 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
),
},
args: args{
ctx: context.Background(),
policy: &domain.DomainPolicy{
UserLoginMustBeDomain: true,
ValidateOrgDomains: true,
},
ctx: context.Background(),
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
@@ -189,12 +317,11 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
policy: &domain.DomainPolicy{
UserLoginMustBeDomain: true,
ValidateOrgDomains: true,
},
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
err: caos_errs.IsNotFound,
@@ -218,20 +345,58 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
policy: &domain.DomainPolicy{
UserLoginMustBeDomain: true,
ValidateOrgDomains: true,
SMTPSenderAddressMatchesInstanceDomain: true,
},
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
err: caos_errs.IsPreconditionFailed,
},
},
{
name: "change, ok",
name: "change, no userLoginMustBeDomain change, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
false,
true,
true,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
newDomainPolicyChangedEvent(context.Background(), "org1",
policy.ChangeValidateOrgDomains(false),
policy.ChangeSMTPSenderAddressMatchesInstanceDomain(false),
),
),
},
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: false,
validateOrgDomains: false,
smtpSenderAddressMatchesInstanceDomain: false,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "change, userLoginMustBeDomain changed, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
@@ -245,33 +410,69 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"org.com",
),
),
eventFromEventPusher(
org.NewDomainPrimarySetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"org.com",
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"user1@org.com",
false,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
newDomainPolicyChangedEvent(context.Background(), "org1", false, false, false),
newDomainPolicyChangedEvent(context.Background(), "org1",
policy.ChangeUserLoginMustBeDomain(false),
policy.ChangeValidateOrgDomains(false),
policy.ChangeSMTPSenderAddressMatchesInstanceDomain(false),
),
),
eventFromEventPusher(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"user1@org.com",
false,
user.UsernameChangedEventWithPolicyChange(),
),
),
},
uniqueConstraintsFromEventConstraint(user.NewRemoveUsernameUniqueConstraint("user1", "org1", true)),
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("user1@org.com", "org1", false)),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
policy: &domain.DomainPolicy{
UserLoginMustBeDomain: false,
ValidateOrgDomains: false,
SMTPSenderAddressMatchesInstanceDomain: false,
},
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: false,
validateOrgDomains: false,
smtpSenderAddressMatchesInstanceDomain: false,
},
res: res{
want: &domain.DomainPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: "org1",
ResourceOwner: "org1",
},
UserLoginMustBeDomain: false,
ValidateOrgDomains: false,
SMTPSenderAddressMatchesInstanceDomain: false,
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
@@ -281,7 +482,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
}
got, err := r.ChangeOrgDomainPolicy(tt.args.ctx, tt.args.orgID, tt.args.policy)
got, err := r.ChangeOrgDomainPolicy(tt.args.ctx, tt.args.orgID, tt.args.userLoginMustBeDomain, tt.args.validateOrgDomains, tt.args.smtpSenderAddressMatchesInstanceDomain)
if tt.res.err == nil {
assert.NoError(t, err)
}
@@ -344,7 +545,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
},
},
{
name: "remove, ok",
name: "remove, no userLoginMustBeDomain change, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
@@ -358,6 +559,16 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
),
),
),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
true,
true,
true,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
@@ -378,6 +589,91 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
},
},
},
{
name: "remove, userLoginMustBeDomain changed, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
true,
true,
true,
),
),
),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
false,
true,
true,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"org.com",
),
),
eventFromEventPusher(
org.NewDomainPrimarySetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"org.com",
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"user1@org.com",
false,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
org.NewDomainPolicyRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate),
),
eventFromEventPusher(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"user1@org.com",
false,
user.UsernameChangedEventWithPolicyChange(),
),
),
},
uniqueConstraintsFromEventConstraint(user.NewRemoveUsernameUniqueConstraint("user1", "org1", true)),
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("user1@org.com", "org1", false)),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -398,14 +694,10 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
}
}
func newDomainPolicyChangedEvent(ctx context.Context, orgID string, userLoginMustBeDomain, validateOrgDomains, smtpSenderAddressMatchesInstanceDomain bool) *org.DomainPolicyChangedEvent {
func newDomainPolicyChangedEvent(ctx context.Context, orgID string, changes ...policy.DomainPolicyChanges) *org.DomainPolicyChangedEvent {
event, _ := org.NewDomainPolicyChangedEvent(ctx,
&org.NewAggregate(orgID).Aggregate,
[]policy.DomainPolicyChanges{
policy.ChangeUserLoginMustBeDomain(userLoginMustBeDomain),
policy.ChangeValidateOrgDomains(validateOrgDomains),
policy.ChangeSMTPSenderAddressMatchesInstanceDomain(smtpSenderAddressMatchesInstanceDomain),
},
changes,
)
return event
}