feat: organization settings for user uniqueness (#10246)

# Which Problems Are Solved

Currently the username uniqueness is on instance level, we want to
achieve a way to set it at organization level.

# How the Problems Are Solved

Addition of endpoints and a resource on organization level, where this
setting can be managed. If nothing it set, the uniqueness is expected to
be at instance level, where only users with instance permissions should
be able to change this setting.

# Additional Changes

None

# Additional Context

Includes #10086
Closes #9964 

---------

Co-authored-by: Marco A. <[email protected]>
This commit is contained in:
Stefan Benz
2025-07-29 15:56:21 +02:00
committed by GitHub
co-authored by Marco A.
parent b206a8ed87
commit 6d98b33c56
55 changed files with 4785 additions and 352 deletions
+10 -1
View File
@@ -130,11 +130,20 @@ func prepareChangeDefaultDomainPolicy(
// loop over all found organisations to get their usernames
// and to compute the username changed events
for _, orgID := range orgsWriteModel.OrgIDs {
organizationScopedUsernames, err := checkOrganizationScopedUsernames(ctx, filter, a.ID, nil)
if err != nil {
return nil, err
}
usersWriteModel, err := domainPolicyUsernames(ctx, filter, orgID)
if err != nil {
return nil, err
}
cmds = append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx, userLoginMustBeDomain)...)
cmds = append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx,
userLoginMustBeDomain,
organizationScopedUsernames,
writeModel.UserLoginMustBeDomain,
)...)
}
return cmds, nil
}, nil
+319 -16
View File
@@ -19,7 +19,7 @@ import (
func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -40,8 +40,7 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) {
{
name: "domain policy already existing, already exists error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
@@ -67,8 +66,7 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) {
{
name: "add policy,ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
expectPush(
instance.NewDomainPolicyAddedEvent(context.Background(),
@@ -96,7 +94,7 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.AddDefaultDomainPolicy(tt.args.ctx, tt.args.userLoginMustBeDomain, tt.args.validateOrgDomains, tt.args.smtpSenderAddressMatchesInstanceDomain)
if tt.res.err == nil {
@@ -114,7 +112,7 @@ func TestCommandSide_AddDefaultDomainPolicy(t *testing.T) {
func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -135,8 +133,7 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
{
name: "domain policy not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -153,8 +150,7 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
{
name: "no changes, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
@@ -180,8 +176,7 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
{
name: "change, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
@@ -236,6 +231,7 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
),
// domainPolicyUsernames for each org
// org1
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
@@ -266,6 +262,7 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
),
),
// org3
expectFilterOrganizationSettings("org3", false, false),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
@@ -302,14 +299,16 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
"user1",
"[email protected]",
false,
user.UsernameChangedEventWithPolicyChange(),
false,
user.UsernameChangedEventWithPolicyChange(true),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org3").Aggregate,
"user1",
"[email protected]",
false,
user.UsernameChangedEventWithPolicyChange(),
false,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
@@ -326,11 +325,315 @@ func TestCommandSide_ChangeDefaultDomainPolicy(t *testing.T) {
},
},
},
{
name: "change, organization scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
true,
true,
true,
),
),
),
// domainPolicyOrgs
expectFilter(
eventFromEventPusher(
org.NewOrgAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"org1",
),
),
eventFromEventPusher(
org.NewOrgAddedEvent(context.Background(),
&org.NewAggregate("org2").Aggregate,
"org2",
),
),
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org2").Aggregate,
false,
false,
false,
),
),
eventFromEventPusher(
org.NewOrgAddedEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
"org3",
),
),
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
false,
false,
false,
),
),
eventFromEventPusher(
org.NewDomainPolicyRemovedEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
),
),
),
// domainPolicyUsernames for each org
// org1
expectFilterOrganizationSettings("org1", true, true),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"org1.com",
),
),
eventFromEventPusher(
org.NewDomainPrimarySetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"org1.com",
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
false,
),
),
),
// org3
expectFilterOrganizationSettings("org3", true, true),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
context.Background(),
&org.NewAggregate("org3").Aggregate,
"org3.com",
),
),
eventFromEventPusher(
org.NewDomainPrimarySetEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
"org3.com",
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org3").Aggregate,
"user1",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
false,
),
),
),
expectPush(
newDefaultDomainPolicyChangedEvent(context.Background(), false, false, false),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"[email protected]",
false,
true,
user.UsernameChangedEventWithPolicyChange(true),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org3").Aggregate,
"user1",
"[email protected]",
false,
true,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
userLoginMustBeDomain: false,
validateOrgDomains: false,
smtpSenderAddressMatchesInstanceDomain: false,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
{
name: "change, organization scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
false,
true,
true,
),
),
),
// domainPolicyOrgs
expectFilter(
eventFromEventPusher(
org.NewOrgAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"org1",
),
),
eventFromEventPusher(
org.NewOrgAddedEvent(context.Background(),
&org.NewAggregate("org2").Aggregate,
"org2",
),
),
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org2").Aggregate,
true,
false,
false,
),
),
eventFromEventPusher(
org.NewOrgAddedEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
"org3",
),
),
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
true,
false,
false,
),
),
eventFromEventPusher(
org.NewDomainPolicyRemovedEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
),
),
),
// domainPolicyUsernames for each org
// org1
expectFilterOrganizationSettings("org1", true, true),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
context.Background(),
&org.NewAggregate("org1").Aggregate,
"org1.com",
),
),
eventFromEventPusher(
org.NewDomainPrimarySetEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"org1.com",
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"[email protected]",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
false,
),
),
),
// org3
expectFilterOrganizationSettings("org3", true, true),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
context.Background(),
&org.NewAggregate("org3").Aggregate,
"org3.com",
),
),
eventFromEventPusher(
org.NewDomainPrimarySetEvent(context.Background(),
&org.NewAggregate("org3").Aggregate,
"org3.com",
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org3").Aggregate,
"[email protected]",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
true,
),
),
),
expectPush(
newDefaultDomainPolicyChangedEvent(context.Background(), true, false, false),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"[email protected]",
"[email protected]",
true,
true,
user.UsernameChangedEventWithPolicyChange(false),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org3").Aggregate,
"[email protected]",
"[email protected]",
true,
true,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
userLoginMustBeDomain: true,
validateOrgDomains: false,
smtpSenderAddressMatchesInstanceDomain: false,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.ChangeDefaultDomainPolicy(tt.args.ctx, tt.args.userLoginMustBeDomain, tt.args.validateOrgDomains, tt.args.smtpSenderAddressMatchesInstanceDomain)
if tt.res.err == nil {
+3
View File
@@ -478,6 +478,7 @@ func humanFilters(orgID string) []expect {
true,
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
org.NewPasswordComplexityPolicyAddedEvent(
context.Background(),
@@ -519,6 +520,7 @@ func machineFilters(orgID string, pat bool) []expect {
true,
),
),
expectFilterOrganizationSettings("org1", false, false),
}
if pat {
filters = append(filters,
@@ -562,6 +564,7 @@ func loginClientFilters(orgID string, pat bool) []expect {
true,
),
),
expectFilterOrganizationSettings("org1", false, false),
}
if pat {
filters = append(filters,
+8 -2
View File
@@ -522,10 +522,16 @@ func (c *Commands) prepareRemoveOrg(a *org.Aggregate) preparation.Validation {
return nil, zerrors.ThrowNotFound(nil, "COMMA-aps2n", "Errors.Org.NotFound")
}
domainPolicy, err := c.domainPolicyWriteModel(ctx, a.ID)
domainPolicy, err := domainPolicyWriteModel(ctx, filter, a.ID)
if err != nil {
return nil, err
}
organizationScopedUsername, err := checkOrganizationScopedUsernames(ctx, filter, a.ID, nil)
if err != nil {
return nil, err
}
usernames, err := OrgUsers(ctx, filter, a.ID)
if err != nil {
return nil, err
@@ -542,7 +548,7 @@ func (c *Commands) prepareRemoveOrg(a *org.Aggregate) preparation.Validation {
if err != nil {
return nil, err
}
return []eventstore.Command{org.NewOrgRemovedEvent(ctx, &a.Aggregate, writeModel.Name, usernames, domainPolicy.UserLoginMustBeDomain, domains, links, entityIds)}, nil
return []eventstore.Command{org.NewOrgRemovedEvent(ctx, &a.Aggregate, writeModel.Name, usernames, domainPolicy.UserLoginMustBeDomain || organizationScopedUsername, domains, links, entityIds)}, nil
}, nil
}
}
+88
View File
@@ -1050,6 +1050,7 @@ func TestCommandSide_ValidateOrgDomain(t *testing.T) {
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org2").Aggregate,
false, false, false))),
expectFilterOrganizationSettings("org2", false, false),
expectPush(
org.NewDomainVerifiedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
@@ -1084,6 +1085,93 @@ func TestCommandSide_ValidateOrgDomain(t *testing.T) {
},
},
},
{
name: "domain verification, claimed users, orgScopedUsername, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewOrgAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"name",
),
),
eventFromEventPusher(
org.NewDomainAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"domain.ch",
),
),
eventFromEventPusher(
org.NewDomainVerificationAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"domain.ch",
domain.OrgDomainValidationTypeDNS,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
),
),
),
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org2").Aggregate,
"[email protected]",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"email",
true,
),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org2").Aggregate,
false, false, false))),
expectFilterOrganizationSettings("org2", true, true),
expectPush(
org.NewDomainVerifiedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
"domain.ch",
),
user.NewDomainClaimedEvent(http.WithRequestedHost(context.Background(), "zitadel.ch"),
&user.NewAggregate("user1", "org2").Aggregate,
"[email protected]",
"[email protected]",
true,
),
),
),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
domainValidationFunc: validDomainVerification,
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "tempid"),
},
args: args{
ctx: context.Background(),
domain: &domain.OrgDomain{
ObjectRoot: models.ObjectRoot{
AggregateID: "org1",
},
Domain: "domain.ch",
ValidationType: domain.OrgDomainValidationTypeDNS,
},
claimedUserIDs: []string{"user1"},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+35 -5
View File
@@ -124,13 +124,23 @@ func prepareAddOrgDomainPolicy(
if instancePolicy.UserLoginMustBeDomain == userLoginMustBeDomain {
return cmds, nil
}
organizationScopedUsernames, err := checkOrganizationScopedUsernames(ctx, filter, a.ID, nil)
if err != nil {
return nil, err
}
// the UserLoginMustBeDomain setting will be different from the instance
// therefore get all usernames and the current primary domain
usersWriteModel, err := domainPolicyUsernames(ctx, filter, a.ID)
if err != nil {
return nil, err
}
return append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx, userLoginMustBeDomain)...), nil
return append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx,
userLoginMustBeDomain,
organizationScopedUsernames,
instancePolicy.UserLoginMustBeDomain,
)...), nil
}, nil
}
}
@@ -163,13 +173,22 @@ func prepareChangeOrgDomainPolicy(
if !usernameChange {
return cmds, err
}
organizationScopedUsernames, err := checkOrganizationScopedUsernames(ctx, filter, a.ID, nil)
if err != nil {
return nil, err
}
// get all usernames and the primary domain
usersWriteModel, err := domainPolicyUsernames(ctx, filter, a.ID)
if err != nil {
return nil, err
}
// to compute the username changed events
return append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx, userLoginMustBeDomain)...), nil
return append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx,
userLoginMustBeDomain,
organizationScopedUsernames,
writeModel.UserLoginMustBeDomain,
)...), nil
}, nil
}
}
@@ -190,13 +209,20 @@ func prepareRemoveOrgDomainPolicy(
if err != nil {
return nil, err
}
policyChange := org.NewDomainPolicyRemovedEvent(ctx, &a.Aggregate)
cmds := []eventstore.Command{
org.NewDomainPolicyRemovedEvent(ctx, &a.Aggregate),
policyChange,
}
organizationScopedUsernames, err := checkOrganizationScopedUsernames(ctx, filter, a.ID, nil)
if err != nil {
return nil, err
}
// regardless if the UserLoginMustBeDomain setting is true or false,
// if it will be the same value as currently on the instance,
// then there no further changes are needed
if instancePolicy.UserLoginMustBeDomain == writeModel.UserLoginMustBeDomain {
if writeModel.UserLoginMustBeDomain == instancePolicy.UserLoginMustBeDomain {
return cmds, nil
}
// get all usernames and the primary domain
@@ -205,7 +231,11 @@ func prepareRemoveOrgDomainPolicy(
return nil, err
}
// to compute the username changed events
return append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx, instancePolicy.UserLoginMustBeDomain)...), nil
return append(cmds, usersWriteModel.NewUsernameChangedEvents(ctx,
instancePolicy.UserLoginMustBeDomain,
organizationScopedUsernames,
writeModel.UserLoginMustBeDomain,
)...), nil
}, nil
}
}
+567 -41
View File
@@ -18,7 +18,7 @@ import (
func TestCommandSide_AddDomainPolicy(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -40,9 +40,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
{
name: "org id missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -57,8 +55,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
{
name: "policy already existing, already exists error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
@@ -85,8 +82,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
{
name: "add policy, no userLoginMustBeDomain change, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
@@ -124,8 +120,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
{
name: "add policy, userLoginMustBeDomain changed, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
@@ -137,6 +132,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewDomainVerifiedEvent(
@@ -170,7 +166,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1@org.com",
"user1",
"firstname",
"lastname",
"nickname",
@@ -205,17 +201,19 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1@org.com",
"user1",
"user1",
true,
user.UsernameChangedEventWithPolicyChange(),
false,
user.UsernameChangedEventWithPolicyChange(false),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user2", "org1").Aggregate,
"[email protected]",
"[email protected]",
true,
user.UsernameChangedEventWithPolicyChange(),
false,
user.UsernameChangedEventWithPolicyChange(false),
),
),
),
@@ -233,11 +231,239 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
},
},
},
{
name: "add policy, userLoginMustBeDomain changed, org scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
false,
false,
false,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
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",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
false,
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user2", "org1").Aggregate,
"[email protected]",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
false,
),
),
),
expectPush(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
true,
true,
true,
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"user1",
true,
true,
user.UsernameChangedEventWithPolicyChange(false),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user2", "org1").Aggregate,
"[email protected]",
"[email protected]",
true,
true,
user.UsernameChangedEventWithPolicyChange(false),
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: true,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "add policy, userLoginMustBeDomain removed, org scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
true,
false,
false,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
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",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
true,
),
),
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user2", "org1").Aggregate,
"[email protected]",
"firstname",
"lastname",
"nickname",
"displayname",
language.English,
domain.GenderUnspecified,
"[email protected]",
true,
),
),
),
expectPush(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
false,
true,
true,
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"[email protected]",
false,
true,
user.UsernameChangedEventWithPolicyChange(true),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user2", "org1").Aggregate,
"[email protected]",
"[email protected]@org.com",
false,
true,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: false,
validateOrgDomains: true,
smtpSenderAddressMatchesInstanceDomain: true,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.AddOrgDomainPolicy(tt.args.ctx, tt.args.orgID, tt.args.userLoginMustBeDomain, tt.args.validateOrgDomains, tt.args.smtpSenderAddressMatchesInstanceDomain)
if tt.res.err == nil {
@@ -255,7 +481,7 @@ func TestCommandSide_AddDomainPolicy(t *testing.T) {
func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -277,9 +503,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
{
name: "org id missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -294,8 +518,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
{
name: "policy not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -313,8 +536,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
{
name: "no changes, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
@@ -341,8 +563,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
{
name: "change, no userLoginMustBeDomain change, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
@@ -377,8 +598,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
{
name: "change, userLoginMustBeDomain changed, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
@@ -389,6 +609,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
@@ -429,7 +650,156 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
"user1",
"[email protected]",
false,
user.UsernameChangedEventWithPolicyChange(),
false,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: false,
validateOrgDomains: false,
smtpSenderAddressMatchesInstanceDomain: false,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "change, userLoginMustBeDomain changed, org scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", 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,
"[email protected]",
false,
),
),
),
expectPush(
newDomainPolicyChangedEvent(context.Background(), "org1",
policy.ChangeUserLoginMustBeDomain(true),
policy.ChangeValidateOrgDomains(false),
policy.ChangeSMTPSenderAddressMatchesInstanceDomain(false),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"user1",
true,
true,
user.UsernameChangedEventWithPolicyChange(false),
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userLoginMustBeDomain: true,
validateOrgDomains: false,
smtpSenderAddressMatchesInstanceDomain: false,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "change, userLoginMustBeDomain removed, org scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", 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,
"[email protected]",
true,
),
),
),
expectPush(
newDomainPolicyChangedEvent(context.Background(), "org1",
policy.ChangeUserLoginMustBeDomain(false),
policy.ChangeValidateOrgDomains(false),
policy.ChangeSMTPSenderAddressMatchesInstanceDomain(false),
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"[email protected]",
false,
true,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
@@ -451,7 +821,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.ChangeOrgDomainPolicy(tt.args.ctx, tt.args.orgID, tt.args.userLoginMustBeDomain, tt.args.validateOrgDomains, tt.args.smtpSenderAddressMatchesInstanceDomain)
if tt.res.err == nil {
@@ -469,7 +839,7 @@ func TestCommandSide_ChangeDomainPolicy(t *testing.T) {
func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -488,9 +858,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
{
name: "org id missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -502,8 +870,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
{
name: "policy not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -518,8 +885,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
{
name: "remove, no userLoginMustBeDomain change, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
@@ -540,6 +906,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
org.NewDomainPolicyRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate),
@@ -559,8 +926,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
{
name: "remove, userLoginMustBeDomain changed, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
@@ -581,6 +947,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewDomainPrimarySetEvent(
@@ -619,7 +986,166 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
"user1",
"[email protected]",
false,
user.UsernameChangedEventWithPolicyChange(),
false,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "remove, userLoginMustBeDomain removed, org scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
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,
),
),
),
expectFilterOrganizationSettings("org1", 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,
"[email protected]",
false,
),
),
),
expectPush(
org.NewDomainPolicyRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"[email protected]",
false,
true,
user.UsernameChangedEventWithPolicyChange(true),
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "remove, userLoginMustBeDomain changed, org scoped usernames, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
false,
true,
true,
),
),
),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&instance.NewAggregate("instanceID").Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", 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,
"[email protected]",
true,
),
),
),
expectPush(
org.NewDomainPolicyRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
),
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"user1",
true,
true,
user.UsernameChangedEventWithPolicyChange(false),
),
),
),
@@ -638,7 +1164,7 @@ func TestCommandSide_RemoveDomainPolicy(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.RemoveOrgDomainPolicy(tt.args.ctx, tt.args.orgID)
if tt.res.err == nil {
+5
View File
@@ -1101,6 +1101,7 @@ func TestCommandSide_RemoveOrg(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(),
expectFilter(),
expectFilter(),
@@ -1143,6 +1144,7 @@ func TestCommandSide_RemoveOrg(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(),
expectFilter(),
expectFilter(),
@@ -1183,6 +1185,7 @@ func TestCommandSide_RemoveOrg(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1397,6 +1400,7 @@ func TestCommandSide_SetUpOrg(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(), // org member check
expectFilter(
eventFromEventPusher(
@@ -1706,6 +1710,7 @@ func TestCommandSide_SetUpOrg(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(),
expectFilter(),
expectFilter(), // org member check
+140
View File
@@ -0,0 +1,140 @@
package command
import (
"context"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
"github.com/zitadel/zitadel/internal/zerrors"
)
type SetOrganizationSettings struct {
OrganizationID string
OrganizationScopedUsernames *bool
}
func (e *SetOrganizationSettings) IsValid() error {
if e.OrganizationID == "" {
return zerrors.ThrowInvalidArgument(nil, "COMMAND-zI4z7cLLRJ", "Errors.Org.Settings.Invalid")
}
return nil
}
func (c *Commands) SetOrganizationSettings(ctx context.Context, set *SetOrganizationSettings) (_ *domain.ObjectDetails, err error) {
if err := set.IsValid(); err != nil {
return nil, err
}
wm, err := c.getOrganizationSettingsWriteModelByID(ctx, set.OrganizationID)
if err != nil {
return nil, err
}
if !wm.OrganizationState.Exists() {
return nil, zerrors.ThrowNotFound(nil, "COMMAND-oDzwP5kmdP", "Errors.NotFound")
}
domainPolicy, err := c.domainPolicyWriteModel(ctx, wm.AggregateID)
if err != nil {
return nil, err
}
events, err := wm.NewSet(ctx,
set.OrganizationScopedUsernames,
domainPolicy.UserLoginMustBeDomain,
c.getOrganizationScopedUsernames,
)
if err != nil {
return nil, err
}
return c.pushAppendAndReduceDetails(ctx, wm, events...)
}
func (c *Commands) DeleteOrganizationSettings(ctx context.Context, id string) (*domain.ObjectDetails, error) {
if id == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-eU5hkMy3Pf", "Errors.IDMissing")
}
wm, err := c.getOrganizationSettingsWriteModelByID(ctx, id)
if err != nil {
return nil, err
}
if !wm.State.Exists() {
return writeModelToObjectDetails(wm.GetWriteModel()), nil
}
domainPolicy, err := c.domainPolicyWriteModel(ctx, wm.AggregateID)
if err != nil {
return nil, err
}
events, err := wm.NewRemoved(ctx,
domainPolicy.UserLoginMustBeDomain,
c.getOrganizationScopedUsernames,
)
if err != nil {
return nil, err
}
return c.pushAppendAndReduceDetails(ctx, wm, events...)
}
func checkOrganizationScopedUsernames(ctx context.Context, filter preparation.FilterToQueryReducer, id string, checkPermission domain.PermissionCheck) (_ bool, err error) {
wm := NewOrganizationSettingsWriteModel(id, checkPermission)
events, err := filter(ctx, wm.Query())
if err != nil {
return false, err
}
if len(events) == 0 {
return false, nil
}
wm.AppendEvents(events...)
err = wm.Reduce()
if err != nil {
return false, err
}
return wm.State.Exists() && wm.OrganizationScopedUsernames, nil
}
func (c *Commands) getOrganizationSettingsWriteModelByID(ctx context.Context, id string) (*OrganizationSettingsWriteModel, error) {
wm := NewOrganizationSettingsWriteModel(id, c.checkPermission)
err := c.eventstore.FilterToQueryReducer(ctx, wm)
if err != nil {
return nil, err
}
return wm, nil
}
func (c *Commands) checkOrganizationScopedUsernames(ctx context.Context, orgID string) (_ bool, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
wm, err := c.getOrganizationSettingsWriteModelByID(ctx, orgID)
if err != nil {
return false, err
}
return wm.State.Exists() && wm.OrganizationScopedUsernames, nil
}
func (c *Commands) getOrganizationScopedUsernamesWriteModelByID(ctx context.Context, id string) (*OrganizationScopedUsernamesWriteModel, error) {
wm := NewOrganizationScopedUsernamesWriteModel(id)
err := c.eventstore.FilterToQueryReducer(ctx, wm)
if err != nil {
return nil, err
}
return wm, nil
}
func (c *Commands) getOrganizationScopedUsernames(ctx context.Context, id string) ([]string, error) {
wm, err := c.getOrganizationScopedUsernamesWriteModelByID(ctx, id)
if err != nil {
return nil, err
}
usernames := make([]string, len(wm.Users))
for i, user := range wm.Users {
usernames[i] = user.username
}
return usernames, nil
}
@@ -0,0 +1,245 @@
package command
import (
"context"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/org"
settings "github.com/zitadel/zitadel/internal/repository/organization_settings"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/zerrors"
)
type OrganizationSettingsWriteModel struct {
eventstore.WriteModel
OrganizationScopedUsernames bool
OrganizationState domain.OrgState
State domain.OrganizationSettingsState
checkPermission domain.PermissionCheck
}
func (wm *OrganizationSettingsWriteModel) GetWriteModel() *eventstore.WriteModel {
return &wm.WriteModel
}
func (wm *OrganizationSettingsWriteModel) checkPermissionWrite(
ctx context.Context,
resourceOwner string,
aggregateID string,
) error {
if wm.checkPermission == nil {
return zerrors.ThrowPermissionDenied(nil, "COMMAND-8Dttuyj0B4", "Permission check not defined")
}
return wm.checkPermission(ctx, domain.PermissionIAMPolicyWrite, resourceOwner, aggregateID)
}
func (wm *OrganizationSettingsWriteModel) checkPermissionDelete(
ctx context.Context,
resourceOwner string,
aggregateID string,
) error {
if wm.checkPermission == nil {
return zerrors.ThrowPermissionDenied(nil, "COMMAND-6R54f4vWqv", "Permission check not defined")
}
return wm.checkPermission(ctx, domain.PermissionIAMPolicyDelete, resourceOwner, aggregateID)
}
func NewOrganizationSettingsWriteModel(id string, checkPermission domain.PermissionCheck) *OrganizationSettingsWriteModel {
return &OrganizationSettingsWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: id,
ResourceOwner: id,
},
checkPermission: checkPermission,
}
}
func (wm *OrganizationSettingsWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *settings.OrganizationSettingsSetEvent:
wm.OrganizationScopedUsernames = e.OrganizationScopedUsernames
wm.State = domain.OrganizationSettingsStateActive
case *settings.OrganizationSettingsRemovedEvent:
wm.OrganizationScopedUsernames = false
wm.State = domain.OrganizationSettingsStateRemoved
case *org.OrgAddedEvent:
wm.OrganizationState = domain.OrgStateActive
wm.OrganizationScopedUsernames = false
case *org.OrgRemovedEvent:
wm.OrganizationState = domain.OrgStateRemoved
wm.OrganizationScopedUsernames = false
}
}
return wm.WriteModel.Reduce()
}
func (wm *OrganizationSettingsWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
ResourceOwner(wm.ResourceOwner).
AddQuery().
AggregateTypes(settings.AggregateType).
AggregateIDs(wm.AggregateID).
EventTypes(settings.OrganizationSettingsSetEventType,
settings.OrganizationSettingsRemovedEventType).
Or().
AggregateTypes(org.AggregateType).
AggregateIDs(wm.AggregateID).
EventTypes(org.OrgAddedEventType,
org.OrgRemovedEventType).
Builder()
}
func (wm *OrganizationSettingsWriteModel) NewSet(
ctx context.Context,
organizationScopedUsernames *bool,
userLoginMustBeDomain bool,
usernamesF func(ctx context.Context, orgID string) ([]string, error),
) (_ []eventstore.Command, err error) {
if err := wm.checkPermissionWrite(ctx, wm.ResourceOwner, wm.AggregateID); err != nil {
return nil, err
}
// no changes
if organizationScopedUsernames == nil || *organizationScopedUsernames == wm.OrganizationScopedUsernames {
return nil, nil
}
var usernames []string
if (wm.OrganizationScopedUsernames || userLoginMustBeDomain) != (*organizationScopedUsernames || userLoginMustBeDomain) {
usernames, err = usernamesF(ctx, wm.AggregateID)
if err != nil {
return nil, err
}
}
events := []eventstore.Command{
settings.NewOrganizationSettingsAddedEvent(ctx,
SettingsAggregateFromWriteModel(&wm.WriteModel),
usernames,
*organizationScopedUsernames || userLoginMustBeDomain,
wm.OrganizationScopedUsernames || userLoginMustBeDomain,
),
}
return events, nil
}
func (wm *OrganizationSettingsWriteModel) NewRemoved(
ctx context.Context,
userLoginMustBeDomain bool,
usernamesF func(ctx context.Context, orgID string) ([]string, error),
) (_ []eventstore.Command, err error) {
if err := wm.checkPermissionDelete(ctx, wm.ResourceOwner, wm.AggregateID); err != nil {
return nil, err
}
var usernames []string
if userLoginMustBeDomain != wm.OrganizationScopedUsernames {
usernames, err = usernamesF(ctx, wm.AggregateID)
if err != nil {
return nil, err
}
}
events := []eventstore.Command{
settings.NewOrganizationSettingsRemovedEvent(ctx,
SettingsAggregateFromWriteModel(&wm.WriteModel),
usernames,
userLoginMustBeDomain,
wm.OrganizationScopedUsernames || userLoginMustBeDomain,
),
}
return events, nil
}
func SettingsAggregateFromWriteModel(wm *eventstore.WriteModel) *eventstore.Aggregate {
return &eventstore.Aggregate{
ID: wm.AggregateID,
Type: settings.AggregateType,
ResourceOwner: wm.ResourceOwner,
InstanceID: wm.InstanceID,
Version: settings.AggregateVersion,
}
}
type OrganizationScopedUsernamesWriteModel struct {
eventstore.WriteModel
Users []*organizationScopedUser
}
type organizationScopedUser struct {
id string
username string
}
func NewOrganizationScopedUsernamesWriteModel(orgID string) *OrganizationScopedUsernamesWriteModel {
return &OrganizationScopedUsernamesWriteModel{
WriteModel: eventstore.WriteModel{
ResourceOwner: orgID,
},
Users: make([]*organizationScopedUser, 0),
}
}
func (wm *OrganizationScopedUsernamesWriteModel) AppendEvents(events ...eventstore.Event) {
wm.WriteModel.AppendEvents(events...)
}
func (wm *OrganizationScopedUsernamesWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *user.HumanAddedEvent:
wm.Users = append(wm.Users, &organizationScopedUser{id: e.Aggregate().ID, username: e.UserName})
case *user.HumanRegisteredEvent:
wm.Users = append(wm.Users, &organizationScopedUser{id: e.Aggregate().ID, username: e.UserName})
case *user.MachineAddedEvent:
wm.Users = append(wm.Users, &organizationScopedUser{id: e.Aggregate().ID, username: e.UserName})
case *user.UsernameChangedEvent:
for _, user := range wm.Users {
if user.id == e.Aggregate().ID {
user.username = e.UserName
break
}
}
case *user.DomainClaimedEvent:
for _, user := range wm.Users {
if user.id == e.Aggregate().ID {
user.username = e.UserName
break
}
}
case *user.UserRemovedEvent:
wm.removeUser(e.Aggregate().ID)
}
}
return wm.WriteModel.Reduce()
}
func (wm *OrganizationScopedUsernamesWriteModel) removeUser(userID string) {
for i, user := range wm.Users {
if user.id == userID {
wm.Users[i] = wm.Users[len(wm.Users)-1]
wm.Users[len(wm.Users)-1] = nil
wm.Users = wm.Users[:len(wm.Users)-1]
return
}
}
}
func (wm *OrganizationScopedUsernamesWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
ResourceOwner(wm.ResourceOwner).
AddQuery().
AggregateTypes(user.AggregateType).
EventTypes(
user.HumanAddedType,
user.HumanRegisteredType,
user.MachineAddedEventType,
user.UserUserNameChangedType,
user.UserDomainClaimedType,
user.UserRemovedType,
).
Builder()
}
@@ -0,0 +1,542 @@
package command
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/org"
settings "github.com/zitadel/zitadel/internal/repository/organization_settings"
"github.com/zitadel/zitadel/internal/repository/user"
"github.com/zitadel/zitadel/internal/zerrors"
)
func TestCommandSide_SetSettingsOrganization(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
}
type args struct {
ctx context.Context
settings *SetOrganizationSettings
}
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "org id missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "",
OrganizationScopedUsernames: boolPtr(true),
},
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "org not found, not found error",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "org1",
OrganizationScopedUsernames: boolPtr(true),
},
},
res: res{
err: zerrors.IsNotFound,
},
},
{
name: "settings already existing, no changes",
fields: fields{
eventstore: expectEventstore(
expectFilterPreOrganizationSettings("org1", true, true, true),
expectFilterOrgDomainPolicy(false),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "org1",
OrganizationScopedUsernames: boolPtr(true),
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings set, new",
fields: fields{
eventstore: expectEventstore(
expectFilterPreOrganizationSettings("org1", true, false, false),
expectFilterOrgDomainPolicy(false),
expectFilterOrganizationScopedUsernames(false, "username1", "username2", "username3"),
expectPush(
settings.NewOrganizationSettingsAddedEvent(context.Background(),
&settings.NewAggregate("org1", "org1").Aggregate,
[]string{"username1", "username2", "username3"},
true,
false,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "org1",
OrganizationScopedUsernames: boolPtr(true),
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings set, no permission",
fields: fields{
eventstore: expectEventstore(
expectFilterPreOrganizationSettings("org1", true, false, true),
expectFilterOrgDomainPolicy(false),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "org1",
OrganizationScopedUsernames: boolPtr(true),
},
},
res: res{
err: zerrors.IsPermissionDenied,
},
},
{
name: "settings set, changed",
fields: fields{
eventstore: expectEventstore(
expectFilterPreOrganizationSettings("org1", true, true, false),
expectFilterOrgDomainPolicy(false),
expectFilterOrganizationScopedUsernames(false, "username1", "username2", "username3"),
expectPush(
settings.NewOrganizationSettingsAddedEvent(context.Background(),
&settings.NewAggregate("org1", "org1").Aggregate,
[]string{"username1", "username2", "username3"},
true,
false,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "org1",
OrganizationScopedUsernames: boolPtr(true),
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings not set, not existing",
fields: fields{
eventstore: expectEventstore(
expectFilterPreOrganizationSettings("org1", true, false, false),
expectFilterOrgDomainPolicy(false),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "org1",
OrganizationScopedUsernames: boolPtr(false),
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings set, changed, usernameMustBeDomain set",
fields: fields{
eventstore: expectEventstore(
expectFilterPreOrganizationSettings("org1", true, true, false),
expectFilterOrgDomainPolicy(true),
expectPush(
settings.NewOrganizationSettingsAddedEvent(context.Background(),
&settings.NewAggregate("org1", "org1").Aggregate,
[]string{"username1", "username2", "username3"},
true,
true,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
settings: &SetOrganizationSettings{
OrganizationID: "org1",
OrganizationScopedUsernames: boolPtr(true),
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
checkPermission: tt.fields.checkPermission,
}
got, err := r.SetOrganizationSettings(tt.args.ctx, tt.args.settings)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assert.Equal(t, tt.res.want, got)
}
})
}
}
func TestCommandSide_DeleteSettingsOrganization(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
}
type args struct {
ctx context.Context
orgID string
}
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "org id missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "",
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "settings delete, no change",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings delete, ok",
fields: fields{
eventstore: expectEventstore(
expectFilterOrganizationSettings("org1", true, true),
expectFilterOrgDomainPolicy(false),
expectFilterOrganizationScopedUsernames(false, "username1", "username2", "username3"),
expectPush(
settings.NewOrganizationSettingsRemovedEvent(context.Background(),
&settings.NewAggregate("org1", "org1").Aggregate,
[]string{"username1", "username2", "username3"},
false,
true,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings delete, unset, ok",
fields: fields{
eventstore: expectEventstore(
expectFilterOrganizationSettings("org1", true, false),
expectFilterOrgDomainPolicy(false),
expectPush(
settings.NewOrganizationSettingsRemovedEvent(context.Background(),
&settings.NewAggregate("org1", "org1").Aggregate,
[]string{"username1", "username2", "username3"},
false,
false,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings delete, unset, usernameMustBeDomain set",
fields: fields{
eventstore: expectEventstore(
expectFilterOrganizationSettings("org1", true, false),
expectFilterOrgDomainPolicy(true),
expectFilterOrganizationScopedUsernames(true, "username1", "username2", "username3"),
expectPush(
settings.NewOrganizationSettingsRemovedEvent(context.Background(),
&settings.NewAggregate("org1", "org1").Aggregate,
[]string{"username1", "username2", "username3"},
true,
true,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings delete, set, usernameMustBeDomain set",
fields: fields{
eventstore: expectEventstore(
expectFilterOrganizationSettings("org1", true, true),
expectFilterOrgDomainPolicy(true),
expectPush(
settings.NewOrganizationSettingsRemovedEvent(context.Background(),
&settings.NewAggregate("org1", "org1").Aggregate,
[]string{"username1", "username2", "username3"},
true,
true,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
ID: "org1",
},
},
},
{
name: "settings delete, no permission",
fields: fields{
eventstore: expectEventstore(
expectFilterOrganizationSettings("org1", true, true),
expectFilterOrgDomainPolicy(true),
),
checkPermission: newMockPermissionCheckNotAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
},
res: res{
err: zerrors.IsPermissionDenied,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
checkPermission: tt.fields.checkPermission,
}
got, err := r.DeleteOrganizationSettings(tt.args.ctx, tt.args.orgID)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
if tt.res.err == nil {
assert.Equal(t, tt.res.want, got)
}
})
}
}
func expectFilterPreOrganizationSettings(orgID string, orgExisting, settingExisting, orgScopedUsernames bool) expect {
var events []eventstore.Event
events = append(events,
expectFilterPreOrganizationSettingsEvents(context.Background(), orgID, orgExisting)...,
)
events = append(events,
expectFilterOrganizationSettingsEvents(context.Background(), orgID, settingExisting, orgScopedUsernames)...,
)
return expectFilter(
events...,
)
}
func expectFilterPreOrganizationSettingsEvents(ctx context.Context, orgID string, orgExisting bool) []eventstore.Event {
var events []eventstore.Event
if orgExisting {
events = append(events,
eventFromEventPusher(
org.NewOrgAddedEvent(ctx,
&org.NewAggregate(orgID).Aggregate,
"org",
),
),
)
}
return events
}
func expectFilterOrganizationSettings(orgID string, settingExisting, orgScopedUsernames bool) expect {
return expectFilter(
expectFilterOrganizationSettingsEvents(context.Background(), orgID, settingExisting, orgScopedUsernames)...,
)
}
func expectFilterOrganizationSettingsEvents(ctx context.Context, orgID string, settingExisting, orgScopedUsernames bool) []eventstore.Event {
var events []eventstore.Event
if settingExisting {
events = append(events,
eventFromEventPusher(
settings.NewOrganizationSettingsAddedEvent(ctx,
&settings.NewAggregate(orgID, orgID).Aggregate,
[]string{},
orgScopedUsernames,
!orgScopedUsernames,
),
),
)
}
return events
}
func expectFilterOrgDomainPolicy(userLoginMustBeDomain bool) expect {
return expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
userLoginMustBeDomain, false, false,
),
),
)
}
func expectFilterOrganizationScopedUsernames(userMustBeDomain bool, usernames ...string) expect {
events := make([]eventstore.Event, len(usernames))
for i, username := range usernames {
events[i] = eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate(username, "org1").Aggregate,
username,
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"[email protected]",
userMustBeDomain,
),
)
}
return expectFilter(
events...,
)
}
+12 -3
View File
@@ -148,7 +148,7 @@ func (wm *DomainPolicyUsernamesWriteModel) Query() *eventstore.SearchQueryBuilde
Builder()
}
func (wm *DomainPolicyUsernamesWriteModel) NewUsernameChangedEvents(ctx context.Context, userLoginMustBeDomain bool) []eventstore.Command {
func (wm *DomainPolicyUsernamesWriteModel) NewUsernameChangedEvents(ctx context.Context, userLoginMustBeDomain, organizationScopedUsernames, oldUserLoginMustBeDomain bool) []eventstore.Command {
events := make([]eventstore.Command, 0, len(wm.Users))
for _, changeUser := range wm.Users {
events = append(events, user.NewUsernameChangedEvent(ctx,
@@ -156,12 +156,21 @@ func (wm *DomainPolicyUsernamesWriteModel) NewUsernameChangedEvents(ctx context.
changeUser.username,
wm.newUsername(changeUser.username, userLoginMustBeDomain),
userLoginMustBeDomain,
user.UsernameChangedEventWithPolicyChange()),
)
organizationScopedUsernames,
user.UsernameChangedEventWithPolicyChange(oldUserLoginMustBeDomain),
))
}
return events
}
func (wm *DomainPolicyUsernamesWriteModel) Usernames() []string {
usernames := make([]string, 0, len(wm.Users))
for i, user := range wm.Users {
usernames[i] = user.username
}
return usernames
}
func (wm *DomainPolicyUsernamesWriteModel) newUsername(username string, userLoginMustBeDomain bool) string {
if !userLoginMustBeDomain {
// if the UserLoginMustBeDomain will be false, then it's currently true
+26 -4
View File
@@ -43,10 +43,15 @@ func (c *Commands) ChangeUsername(ctx context.Context, orgID, userID, userName s
if err = c.userValidateDomain(ctx, orgID, userName, domainPolicy.UserLoginMustBeDomain); err != nil {
return nil, err
}
orgScopedUsernames, err := c.checkOrganizationScopedUsernames(ctx, orgID)
if err != nil {
return nil, err
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
pushedEvents, err := c.eventstore.Push(ctx,
user.NewUsernameChangedEvent(ctx, userAgg, existingUser.UserName, userName, domainPolicy.UserLoginMustBeDomain))
user.NewUsernameChangedEvent(ctx, userAgg, existingUser.UserName, userName, domainPolicy.UserLoginMustBeDomain, orgScopedUsernames))
if err != nil {
return nil, err
}
@@ -189,9 +194,13 @@ func (c *Commands) RemoveUser(ctx context.Context, userID, resourceOwner string,
if err != nil {
return nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-3M9fs", "Errors.Org.DomainPolicy.NotExisting")
}
orgScopedUsername, err := c.checkOrganizationScopedUsernames(ctx, existingUser.ResourceOwner)
if err != nil {
return nil, err
}
var events []eventstore.Command
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
events = append(events, user.NewUserRemovedEvent(ctx, userAgg, existingUser.UserName, existingUser.IDPLinks, domainPolicy.UserLoginMustBeDomain))
events = append(events, user.NewUserRemovedEvent(ctx, userAgg, existingUser.UserName, existingUser.IDPLinks, domainPolicy.UserLoginMustBeDomain || orgScopedUsername))
for _, grantID := range cascadingGrantIDs {
removeEvent, _, err := c.removeUserGrant(ctx, grantID, "", true, false, nil)
@@ -269,6 +278,11 @@ func (c *Commands) userDomainClaimed(ctx context.Context, userID string) (events
return nil, nil, err
}
organizationScopedUsername, err := c.checkOrganizationScopedUsernames(ctx, existingUser.ResourceOwner)
if err != nil {
return nil, nil, err
}
id, err := c.idGenerator.Next()
if err != nil {
return nil, nil, err
@@ -279,7 +293,8 @@ func (c *Commands) userDomainClaimed(ctx context.Context, userID string) (events
userAgg,
fmt.Sprintf("%s@temporary.%s", id, http_util.DomainContext(ctx).RequestedDomain()),
existingUser.UserName,
domainPolicy.UserLoginMustBeDomain),
domainPolicy.UserLoginMustBeDomain || organizationScopedUsername,
),
}, changedUserGrant, nil
}
@@ -295,6 +310,12 @@ func (c *Commands) prepareUserDomainClaimed(ctx context.Context, filter preparat
if err != nil {
return nil, err
}
organizationScopedUsername, err := checkOrganizationScopedUsernames(ctx, filter, userWriteModel.ResourceOwner, nil)
if err != nil {
return nil, err
}
userAgg := UserAggregateFromWriteModel(&userWriteModel.WriteModel)
id, err := c.idGenerator.Next()
@@ -307,7 +328,8 @@ func (c *Commands) prepareUserDomainClaimed(ctx context.Context, filter preparat
userAgg,
fmt.Sprintf("%s@temporary.%s", id, http_util.DomainContext(ctx).RequestedDomain()),
userWriteModel.UserName,
domainPolicy.UserLoginMustBeDomain), nil
domainPolicy.UserLoginMustBeDomain || organizationScopedUsername,
), nil
}
func (c *Commands) UserDomainClaimedSent(ctx context.Context, orgID, userID string) (err error) {
+20 -9
View File
@@ -199,6 +199,11 @@ func (c *Commands) AddHumanCommand(human *AddHuman, orgID string, hasher *crypto
return nil, err
}
organizationScopedUsername, err := checkOrganizationScopedUsernames(ctx, filter, a.ResourceOwner, nil)
if err != nil {
return nil, err
}
var createCmd humanCreationCommand
if human.Register {
createCmd = user.NewHumanRegisteredEvent(
@@ -212,7 +217,7 @@ func (c *Commands) AddHumanCommand(human *AddHuman, orgID string, hasher *crypto
human.PreferredLanguage,
human.Gender,
human.Email.Address,
domainPolicy.UserLoginMustBeDomain,
domainPolicy.UserLoginMustBeDomain || organizationScopedUsername,
"", // no user agent id available
)
} else {
@@ -227,7 +232,7 @@ func (c *Commands) AddHumanCommand(human *AddHuman, orgID string, hasher *crypto
human.PreferredLanguage,
human.Gender,
human.Email.Address,
domainPolicy.UserLoginMustBeDomain,
domainPolicy.UserLoginMustBeDomain || organizationScopedUsername,
)
}
@@ -439,6 +444,12 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
if err != nil {
return nil, nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-2N9fs", "Errors.Org.DomainPolicy.NotFound")
}
organizationScopedUsername, err := c.checkOrganizationScopedUsernames(ctx, orgID)
if err != nil {
return nil, nil, err
}
pwPolicy, err := c.getOrgPasswordComplexityPolicy(ctx, orgID)
if err != nil {
return nil, nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-4N8gs", "Errors.Org.PasswordComplexityPolicy.NotFound")
@@ -455,7 +466,7 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
}
}
events, userAgg, addedHuman, addedCode, code, err := c.importHuman(ctx, orgID, human, passwordless, links, domainPolicy, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator)
events, userAgg, addedHuman, addedCode, code, err := c.importHuman(ctx, orgID, human, passwordless, links, domainPolicy, organizationScopedUsername, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator)
if err != nil {
return nil, nil, err
}
@@ -501,7 +512,7 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
return writeModelToHuman(addedHuman), passwordlessCode, nil
}
func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, links []*domain.UserIDPLink, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator crypto.Generator) (events []eventstore.Command, userAgg *eventstore.Aggregate, humanWriteModel *HumanWriteModel, passwordlessCodeWriteModel *HumanPasswordlessInitCodeWriteModel, code string, err error) {
func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, links []*domain.UserIDPLink, domainPolicy *domain.DomainPolicy, orgScopedUsername bool, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator crypto.Generator) (events []eventstore.Command, userAgg *eventstore.Aggregate, humanWriteModel *HumanWriteModel, passwordlessCodeWriteModel *HumanPasswordlessInitCodeWriteModel, code string, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
@@ -511,7 +522,7 @@ func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.
if err = human.Normalize(); err != nil {
return nil, nil, nil, nil, "", err
}
events, userAgg, humanWriteModel, err = c.createHuman(ctx, orgID, human, links, passwordless, domainPolicy, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
events, userAgg, humanWriteModel, err = c.createHuman(ctx, orgID, human, links, passwordless, domainPolicy, orgScopedUsername, pwPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator)
if err != nil {
return nil, nil, nil, nil, "", err
}
@@ -526,7 +537,7 @@ func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.
return events, userAgg, humanWriteModel, passwordlessCodeWriteModel, code, nil
}
func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.Human, links []*domain.UserIDPLink, passwordless bool, domainPolicy *domain.DomainPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator crypto.Generator) (events []eventstore.Command, userAgg *eventstore.Aggregate, addedHuman *HumanWriteModel, err error) {
func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.Human, links []*domain.UserIDPLink, passwordless bool, domainPolicy *domain.DomainPolicy, orgScopedUsername bool, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator, emailCodeGenerator, phoneCodeGenerator crypto.Generator) (events []eventstore.Command, userAgg *eventstore.Aggregate, addedHuman *HumanWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
@@ -559,7 +570,7 @@ func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.
// TODO: adlerhurst maybe we could simplify the code below
userAgg = UserAggregateFromWriteModelCtx(ctx, &addedHuman.WriteModel)
events = append(events, createAddHumanEvent(ctx, userAgg, human, domainPolicy.UserLoginMustBeDomain))
events = append(events, createAddHumanEvent(ctx, userAgg, human, domainPolicy.UserLoginMustBeDomain, orgScopedUsername))
for _, link := range links {
event, err := c.addUserIDPLink(ctx, userAgg, link, false)
@@ -619,7 +630,7 @@ func (c *Commands) HumanSkipMFAInit(ctx context.Context, userID, resourceowner s
}
// TODO: adlerhurst maybe we can simplify createAddHumanEvent and createRegisterHumanEvent
func createAddHumanEvent(ctx context.Context, aggregate *eventstore.Aggregate, human *domain.Human, userLoginMustBeDomain bool) *user.HumanAddedEvent {
func createAddHumanEvent(ctx context.Context, aggregate *eventstore.Aggregate, human *domain.Human, userLoginMustBeDomain, orgScopedUsername bool) *user.HumanAddedEvent {
addEvent := user.NewHumanAddedEvent(
ctx,
aggregate,
@@ -631,7 +642,7 @@ func createAddHumanEvent(ctx context.Context, aggregate *eventstore.Aggregate, h
human.PreferredLanguage,
human.Gender,
human.EmailAddress,
userLoginMustBeDomain,
userLoginMustBeDomain || orgScopedUsername,
)
if human.Phone != nil {
addEvent.AddPhoneData(human.PhoneNumber)
+286
View File
@@ -190,6 +190,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(),
expectFilter(),
),
@@ -231,6 +232,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanAddedEvent(context.Background(),
&userAgg.Aggregate,
@@ -299,6 +301,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanAddedEvent(context.Background(),
&userAgg.Aggregate,
@@ -368,6 +371,77 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanAddedEvent(context.Background(),
&userAgg.Aggregate,
"username",
"firstname",
"lastname",
"",
"firstname lastname",
AllowedLanguage,
domain.GenderUnspecified,
"[email protected]",
true,
),
user.NewHumanInitialCodeAddedEvent(context.Background(),
&userAgg.Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("userinit"),
},
time.Hour*1,
"",
),
),
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
orgID: "org1",
human: &AddHuman{
Username: "username",
FirstName: "firstname",
LastName: "lastname",
Email: Email{
Address: "[email protected]",
},
PreferredLanguage: AllowedLanguage,
},
secretGenerator: GetMockSecretGenerator(t),
allowInitMail: true,
},
res: res{
want: &domain.ObjectDetails{
Sequence: 0,
EventDate: time.Time{},
ResourceOwner: "org1",
},
wantID: "user1",
},
},
{
name: "add human (with initial code), orgScopedUsername, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectPush(
user.NewHumanAddedEvent(context.Background(),
&userAgg.Aggregate,
@@ -437,6 +511,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -507,6 +582,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -580,6 +656,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -654,6 +731,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -714,6 +792,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -777,6 +856,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -840,6 +920,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -963,6 +1044,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1042,6 +1124,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1151,6 +1234,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
newAddHumanEvent("", false, true, "+41711234567", AllowedLanguage),
user.NewHumanInitialCodeAddedEvent(
@@ -1216,6 +1300,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1326,6 +1411,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
newAddHumanEvent("", false, true, "", AllowedLanguage),
user.NewHumanInitialCodeAddedEvent(
@@ -1518,6 +1604,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(),
expectFilter(),
),
@@ -1557,6 +1644,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1602,6 +1690,94 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
1,
false,
false,
false,
false,
),
),
),
expectPush(
newAddHumanEvent("$plain$x$password", true, true, "", AllowedLanguage),
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
time.Hour*1,
"",
),
),
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
userPasswordHasher: mockPasswordHasher("x"),
},
args{
ctx: context.Background(),
orgID: "org1",
human: &domain.Human{
Username: "username",
Password: &domain.Password{
SecretString: "password",
ChangeRequired: true,
},
Profile: &domain.Profile{
FirstName: "firstname",
LastName: "lastname",
PreferredLanguage: AllowedLanguage,
},
Email: &domain.Email{
EmailAddress: "[email protected]",
},
},
secretGenerator: GetMockSecretGenerator(t),
}
},
res: res{
wantHuman: &domain.Human{
ObjectRoot: models.ObjectRoot{
AggregateID: "user1",
ResourceOwner: "org1",
},
Username: "username",
Profile: &domain.Profile{
FirstName: "firstname",
LastName: "lastname",
DisplayName: "firstname lastname",
PreferredLanguage: AllowedLanguage,
},
Email: &domain.Email{
EmailAddress: "[email protected]",
},
State: domain.UserStateInitial,
},
},
},
{
name: "add human (with password and initial code), orgScopedUsername, ok",
given: func(t *testing.T) (fields, args) {
return fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1688,6 +1864,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1768,6 +1945,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1867,6 +2045,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1970,6 +2149,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -2105,6 +2285,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -2200,6 +2381,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -2285,6 +2467,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -2371,6 +2554,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -2516,6 +2700,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -2659,6 +2844,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -2831,6 +3017,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -3003,6 +3190,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -3182,6 +3370,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -3829,6 +4018,10 @@ func TestAddHumanCommand(t *testing.T) {
),
}, nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return expectFilterOrganizationSettingsEvents(ctx, "org1", false, false), nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
@@ -3882,6 +4075,87 @@ func TestAddHumanCommand(t *testing.T) {
),
}, nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return expectFilterOrganizationSettingsEvents(ctx, "org1", false, false), nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
org.NewPasswordComplexityPolicyAddedEvent(
ctx,
&org.NewAggregate("id").Aggregate,
2,
false,
false,
false,
false,
),
}, nil
}).
Filter(),
},
want: Want{
Commands: []eventstore.Command{
func() *user.HumanAddedEvent {
event := user.NewHumanAddedEvent(
context.Background(),
&agg.Aggregate,
"username",
"gigi",
"giraffe",
"",
"gigi giraffe",
AllowedLanguage,
0,
"[email protected]",
true,
)
event.AddPasswordData("$plain$x$password", false)
return event
}(),
user.NewHumanEmailVerifiedEvent(context.Background(), &agg.Aggregate),
},
},
},
{
name: "correct, orgScopedUsername",
fields: fields{
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id"),
},
args: args{
human: &AddHuman{
Email: Email{Address: "[email protected]", Verified: true},
FirstName: "gigi",
LastName: "giraffe",
Password: "password",
Username: "username",
PreferredLanguage: AllowedLanguage,
},
orgID: "ro",
hasher: mockPasswordHasher("x"),
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
filter: NewMultiFilter().Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{}, nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
org.NewDomainPolicyAddedEvent(
ctx,
&org.NewAggregate("id").Aggregate,
true,
true,
true,
),
}, nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
// never set, as only used in creation of instance and org
return expectFilterOrganizationSettingsEvents(ctx, "org1", false, false), nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
@@ -3953,6 +4227,10 @@ func TestAddHumanCommand(t *testing.T) {
),
}, nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return expectFilterOrganizationSettingsEvents(ctx, "org1", false, false), nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
@@ -4025,6 +4303,10 @@ func TestAddHumanCommand(t *testing.T) {
),
}, nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return expectFilterOrganizationSettingsEvents(ctx, "org1", false, false), nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
@@ -4097,6 +4379,10 @@ func TestAddHumanCommand(t *testing.T) {
),
}, nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return expectFilterOrganizationSettingsEvents(ctx, "org1", false, false), nil
}).
Append(
func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
return []eventstore.Event{
+5 -1
View File
@@ -61,8 +61,12 @@ func AddMachineCommand(a *user.Aggregate, machine *Machine) preparation.Validati
if err != nil {
return nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-3M9fs", "Errors.Org.DomainPolicy.NotFound")
}
orgScopedUsername, err := checkOrganizationScopedUsernames(ctx, filter, a.ResourceOwner, nil)
if err != nil {
return nil, err
}
return []eventstore.Command{
user.NewMachineAddedEvent(ctx, &a.Aggregate, machine.Username, machine.Name, machine.Description, domainPolicy.UserLoginMustBeDomain, machine.AccessTokenType),
user.NewMachineAddedEvent(ctx, &a.Aggregate, machine.Username, machine.Name, machine.Description, domainPolicy.UserLoginMustBeDomain || orgScopedUsername, machine.AccessTokenType),
}, nil
}, nil
}
+55
View File
@@ -121,6 +121,54 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"name",
"description",
true,
domain.OIDCTokenTypeBearer,
),
),
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
},
args: args{
ctx: context.Background(),
machine: &Machine{
ObjectRoot: models.ObjectRoot{
ResourceOwner: "org1",
},
Description: "description",
Name: "name",
Username: "username",
},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "add machine, orgScopedUsername, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
@@ -167,6 +215,7 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("optionalID1", "org1").Aggregate,
@@ -214,6 +263,7 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("aggregateID", "org1").Aggregate,
@@ -264,6 +314,7 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("aggregateID", "org1").Aggregate,
@@ -312,6 +363,7 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("aggregateID", "org1").Aggregate,
@@ -361,6 +413,7 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
@@ -436,6 +489,7 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
@@ -489,6 +543,7 @@ func TestCommandSide_AddMachine(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
+161 -73
View File
@@ -295,12 +295,14 @@ func TestCommandSide_UsernameChange(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"[email protected]",
true,
false,
),
),
),
@@ -317,6 +319,61 @@ func TestCommandSide_UsernameChange(t *testing.T) {
},
},
},
{
name: "email as username, orgScopedUsername, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"[email protected]",
true,
),
),
),
expectFilter(),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"test",
false,
true,
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userID: "user1",
username: "test",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "email as username, verified domain, ok",
fields: fields{
@@ -348,6 +405,7 @@ func TestCommandSide_UsernameChange(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewDomainVerifiedEvent(context.Background(),
@@ -362,6 +420,7 @@ func TestCommandSide_UsernameChange(t *testing.T) {
"username",
"[email protected]",
false,
false,
),
),
),
@@ -409,12 +468,14 @@ func TestCommandSide_UsernameChange(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"username1",
true,
false,
),
),
),
@@ -462,11 +523,13 @@ func TestCommandSide_UsernameChange(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"username1",
false,
true,
),
),
@@ -506,7 +569,7 @@ func TestCommandSide_UsernameChange(t *testing.T) {
func TestCommandSide_DeactivateUser(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type (
args struct {
@@ -528,9 +591,7 @@ func TestCommandSide_DeactivateUser(t *testing.T) {
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -544,8 +605,7 @@ func TestCommandSide_DeactivateUser(t *testing.T) {
{
name: "user not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -561,8 +621,7 @@ func TestCommandSide_DeactivateUser(t *testing.T) {
{
name: "user already inactive, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -598,8 +657,7 @@ func TestCommandSide_DeactivateUser(t *testing.T) {
{
name: "deactivate user, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -638,7 +696,7 @@ func TestCommandSide_DeactivateUser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.DeactivateUser(tt.args.ctx, tt.args.userID, tt.args.orgID)
if tt.res.err == nil {
@@ -656,7 +714,7 @@ func TestCommandSide_DeactivateUser(t *testing.T) {
func TestCommandSide_ReactivateUser(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type (
args struct {
@@ -678,9 +736,7 @@ func TestCommandSide_ReactivateUser(t *testing.T) {
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -694,8 +750,7 @@ func TestCommandSide_ReactivateUser(t *testing.T) {
{
name: "user not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -711,8 +766,7 @@ func TestCommandSide_ReactivateUser(t *testing.T) {
{
name: "user already active, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -743,8 +797,7 @@ func TestCommandSide_ReactivateUser(t *testing.T) {
{
name: "reactivate user, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -787,7 +840,7 @@ func TestCommandSide_ReactivateUser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.ReactivateUser(tt.args.ctx, tt.args.userID, tt.args.orgID)
if tt.res.err == nil {
@@ -805,7 +858,7 @@ func TestCommandSide_ReactivateUser(t *testing.T) {
func TestCommandSide_LockUser(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type (
args struct {
@@ -827,9 +880,7 @@ func TestCommandSide_LockUser(t *testing.T) {
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -843,8 +894,7 @@ func TestCommandSide_LockUser(t *testing.T) {
{
name: "user not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -860,8 +910,7 @@ func TestCommandSide_LockUser(t *testing.T) {
{
name: "user already locked, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -897,8 +946,7 @@ func TestCommandSide_LockUser(t *testing.T) {
{
name: "lock user, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -937,7 +985,7 @@ func TestCommandSide_LockUser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.LockUser(tt.args.ctx, tt.args.userID, tt.args.orgID)
if tt.res.err == nil {
@@ -955,7 +1003,7 @@ func TestCommandSide_LockUser(t *testing.T) {
func TestCommandSide_UnlockUser(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type (
args struct {
@@ -977,9 +1025,7 @@ func TestCommandSide_UnlockUser(t *testing.T) {
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -993,8 +1039,7 @@ func TestCommandSide_UnlockUser(t *testing.T) {
{
name: "user not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -1010,8 +1055,7 @@ func TestCommandSide_UnlockUser(t *testing.T) {
{
name: "user already active, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1042,8 +1086,7 @@ func TestCommandSide_UnlockUser(t *testing.T) {
{
name: "unlock user, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1086,7 +1129,7 @@ func TestCommandSide_UnlockUser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.UnlockUser(tt.args.ctx, tt.args.userID, tt.args.orgID)
if tt.res.err == nil {
@@ -1104,7 +1147,7 @@ func TestCommandSide_UnlockUser(t *testing.T) {
func TestCommandSide_RemoveUser(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type (
args struct {
@@ -1129,9 +1172,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -1145,8 +1186,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
{
name: "user not existing, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -1162,8 +1202,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
{
name: "org iam policy not found, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1196,8 +1235,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
{
name: "remove user, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1225,6 +1263,60 @@ func TestCommandSide_RemoveUser(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
nil,
true,
),
),
),
},
args: args{
ctx: context.Background(),
orgID: "org1",
userID: "user1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "remove user, orgScopedUsername, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"username",
"firstname",
"lastname",
"nickname",
"displayname",
language.German,
domain.GenderUnspecified,
"[email protected]",
true,
),
),
),
expectFilter(),
expectFilter(
eventFromEventPusher(
instance.NewDomainPolicyAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectPush(
user.NewUserRemovedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
@@ -1249,8 +1341,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
{
name: "remove user with erxternal idp, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1286,6 +1377,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
@@ -1315,8 +1407,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
{
name: "remove user with user memberships, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1344,6 +1435,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
@@ -1418,7 +1510,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := r.RemoveUser(tt.args.ctx, tt.args.userID, tt.args.orgID, tt.args.cascadeUserMemberships, tt.args.cascadeUserGrants...)
if tt.res.err == nil {
@@ -1434,7 +1526,7 @@ func TestCommandSide_RemoveUser(t *testing.T) {
func TestCommands_RevokeAccessToken(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -1455,7 +1547,7 @@ func TestCommands_RevokeAccessToken(t *testing.T) {
{
"id missing error",
fields{
eventstoreExpect(t),
expectEventstore(),
},
args{
context.Background(),
@@ -1471,7 +1563,7 @@ func TestCommands_RevokeAccessToken(t *testing.T) {
{
"not active error",
fields{
eventstoreExpect(t,
expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewUserTokenAddedEvent(context.Background(),
@@ -1507,7 +1599,7 @@ func TestCommands_RevokeAccessToken(t *testing.T) {
{
"active ok",
fields{
eventstoreExpect(t,
expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewUserTokenAddedEvent(context.Background(),
@@ -1552,7 +1644,7 @@ func TestCommands_RevokeAccessToken(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
got, err := c.RevokeAccessToken(tt.args.ctx, tt.args.userID, tt.args.orgID, tt.args.tokenID)
if tt.res.err == nil {
@@ -1570,7 +1662,7 @@ func TestCommands_RevokeAccessToken(t *testing.T) {
func TestCommandSide_UserDomainClaimedSent(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
eventstore func(t *testing.T) *eventstore.Eventstore
}
type args struct {
ctx context.Context
@@ -1589,9 +1681,7 @@ func TestCommandSide_UserDomainClaimedSent(t *testing.T) {
{
name: "userid missing, invalid argument error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
eventstore: expectEventstore(),
},
args: args{
ctx: context.Background(),
@@ -1604,8 +1694,7 @@ func TestCommandSide_UserDomainClaimedSent(t *testing.T) {
{
name: "user not existing, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(),
),
},
@@ -1621,8 +1710,7 @@ func TestCommandSide_UserDomainClaimedSent(t *testing.T) {
{
name: "code sent, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
@@ -1657,7 +1745,7 @@ func TestCommandSide_UserDomainClaimedSent(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
eventstore: tt.fields.eventstore(t),
}
err := r.UserDomainClaimedSent(tt.args.ctx, tt.args.resourceOwner, tt.args.userID)
if tt.res.err == nil {
+7 -1
View File
@@ -2,6 +2,7 @@ package command
import (
"context"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/domain"
@@ -145,8 +146,13 @@ func (c *Commands) RemoveUserV2(ctx context.Context, userID, resourceOwner strin
if err != nil {
return nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-l40ykb3xh2", "Errors.Org.DomainPolicy.NotExisting")
}
organizationScopedUsername, err := c.checkOrganizationScopedUsernames(ctx, existingUser.ResourceOwner)
if err != nil {
return nil, err
}
var events []eventstore.Command
events = append(events, user.NewUserRemovedEvent(ctx, &existingUser.Aggregate().Aggregate, existingUser.UserName, existingUser.IDPLinks, domainPolicy.UserLoginMustBeDomain))
events = append(events, user.NewUserRemovedEvent(ctx, &existingUser.Aggregate().Aggregate, existingUser.UserName, existingUser.IDPLinks, domainPolicy.UserLoginMustBeDomain || organizationScopedUsername))
for _, grantID := range cascadingGrantIDs {
removeEvent, _, err := c.removeUserGrant(ctx, grantID, "", true, true, nil)
+7 -2
View File
@@ -165,6 +165,11 @@ func (c *Commands) AddUserHuman(ctx context.Context, resourceOwner string, human
return err
}
organizationScopedUsername, err := c.checkOrganizationScopedUsernames(ctx, resourceOwner)
if err != nil {
return err
}
var createCmd humanCreationCommand
if human.Register {
createCmd = user.NewHumanRegisteredEvent(
@@ -178,7 +183,7 @@ func (c *Commands) AddUserHuman(ctx context.Context, resourceOwner string, human
human.PreferredLanguage,
human.Gender,
human.Email.Address,
domainPolicy.UserLoginMustBeDomain,
domainPolicy.UserLoginMustBeDomain || organizationScopedUsername,
human.UserAgentID,
)
} else {
@@ -193,7 +198,7 @@ func (c *Commands) AddUserHuman(ctx context.Context, resourceOwner string, human
human.PreferredLanguage,
human.Gender,
human.Email.Address,
domainPolicy.UserLoginMustBeDomain,
domainPolicy.UserLoginMustBeDomain || organizationScopedUsername,
)
}
+179 -22
View File
@@ -60,6 +60,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
}
userAgg := user.NewAggregate("user1", "org1")
orgAgg := org.NewAggregate("org1")
cryptoAlg := crypto.CreateMockEncryptionAlg(gomock.NewController(t))
totpSecret := "TOTPSecret"
@@ -191,7 +192,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
@@ -199,6 +200,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
expectFilter(),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(),
),
checkPermission: newMockPermissionCheckAllowed(),
@@ -233,13 +235,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
@@ -335,13 +338,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanAddedEvent(context.Background(),
&userAgg.Aggregate,
@@ -412,6 +416,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -483,6 +488,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
newAddHumanEvent("", false, true, "", language.English),
user.NewHumanEmailCodeAddedEventV2(context.Background(),
@@ -542,6 +548,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -616,6 +623,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -684,13 +692,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -748,13 +757,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -812,13 +822,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -876,7 +887,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
false,
true,
true,
@@ -929,7 +940,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
false,
true,
true,
@@ -944,6 +955,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1017,13 +1029,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1127,13 +1140,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1232,13 +1246,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
newAddHumanEvent("", false, true, "+41711234567", language.English),
user.NewHumanInitialCodeAddedEvent(
@@ -1305,6 +1320,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
@@ -1409,13 +1425,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
newAddHumanEvent("", false, true, "", language.English),
user.NewHumanInitialCodeAddedEvent(
@@ -1479,13 +1496,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewGoogleIDPAddedEvent(context.Background(),
@@ -1566,13 +1584,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectFilter(
eventFromEventPusher(
org.NewGoogleIDPAddedEvent(context.Background(),
@@ -1646,13 +1665,98 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
"username",
"firstname",
"lastname",
"",
"firstname lastname",
language.English,
domain.GenderUnspecified,
"[email protected]",
true,
"userAgentID",
),
user.NewHumanInitialCodeAddedEvent(context.Background(),
&userAgg.Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("userinit"),
},
time.Hour*1,
"authRequestID",
),
user.NewHumanOTPAddedEvent(context.Background(),
&userAgg.Aggregate,
totpSecretEnc,
),
user.NewHumanOTPVerifiedEvent(context.Background(),
&userAgg.Aggregate,
"",
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
newCode: mockEncryptedCode("userinit", time.Hour),
},
args: args{
ctx: context.Background(),
orgID: "org1",
human: &AddHuman{
Username: "username",
FirstName: "firstname",
LastName: "lastname",
Email: Email{
Address: "[email protected]",
},
PreferredLanguage: language.English,
Register: true,
UserAgentID: "userAgentID",
AuthRequestID: "authRequestID",
TOTPSecret: totpSecret,
},
secretGenerator: GetMockSecretGenerator(t),
allowInitMail: true,
codeAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
res: res{
want: &domain.ObjectDetails{
Sequence: 0,
EventDate: time.Time{},
ResourceOwner: "org1",
},
wantID: "user1",
},
},
{
name: "register human with TOTPSecret, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
@@ -1729,7 +1833,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
false,
true,
true,
@@ -1775,14 +1879,14 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
},
},
{
name: "register human (validate domain), ok",
name: "register human (validate domain), orgScopedUsername, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
false,
true,
true,
@@ -1797,6 +1901,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
@@ -1808,7 +1913,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
language.English,
domain.GenderUnspecified,
"[email protected]",
false,
true,
"userAgentID",
),
user.NewHumanInitialCodeAddedEvent(context.Background(),
@@ -1864,7 +1969,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
false,
true,
true,
@@ -1886,6 +1991,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
@@ -1953,7 +2059,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
false,
true,
true,
@@ -1979,6 +2085,7 @@ func TestCommandSide_AddUserHuman(t *testing.T) {
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewHumanRegisteredEvent(context.Background(),
&userAgg.Aggregate,
@@ -2107,6 +2214,7 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
}
userAgg := user.NewAggregate("user1", "org1")
orgAgg := user.NewAggregate("org1", "org1")
tests := []struct {
name string
@@ -2199,19 +2307,68 @@ func TestCommandSide_ChangeUserHuman(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&userAgg.Aggregate,
"username",
"changed",
true,
false,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
human: &ChangeHuman{
Username: gu.Ptr("changed"),
},
},
res: res{
want: &domain.ObjectDetails{
Sequence: 0,
EventDate: time.Time{},
ResourceOwner: "org1",
},
},
},
{
name: "change human username, orgScopedUsername, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
newAddHumanEvent("$plain$x$password", true, false, "", language.English),
),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&orgAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&userAgg.Aggregate,
"username",
"changed",
false,
true,
),
),
),
+49 -1
View File
@@ -32,6 +32,8 @@ func TestCommandSide_ChangeUserMachine(t *testing.T) {
}
userAgg := user.NewAggregate("user1", "org1")
orgAgg := org.NewAggregate("org1")
userAddedEvent := user.NewMachineAddedEvent(context.Background(),
&userAgg.Aggregate,
"username",
@@ -101,19 +103,65 @@ func TestCommandSide_ChangeUserMachine(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&userAgg.Aggregate,
&orgAgg.Aggregate,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&userAgg.Aggregate,
"username",
"changed",
true,
false,
),
),
),
checkPermission: newMockPermissionCheckAllowed(),
},
args: args{
ctx: context.Background(),
orgID: "org1",
machine: &ChangeMachine{
Username: gu.Ptr("changed"),
},
},
res: res{
want: &domain.ObjectDetails{
Sequence: 0,
EventDate: time.Time{},
ResourceOwner: "org1",
},
},
}, {
name: "change machine username, orgScopedUsername, ok",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(userAddedEvent),
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(context.Background(),
&orgAgg.Aggregate,
false,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", true, true),
expectPush(
user.NewUsernameChangedEvent(context.Background(),
&userAgg.Aggregate,
"username",
"changed",
false,
true,
),
),
),
+1
View File
@@ -343,6 +343,7 @@ func TestCommandSide_userExistsWriteModel(t *testing.T) {
"username",
"changed",
true,
false,
),
),
),
+66 -57
View File
@@ -18,6 +18,7 @@ import (
)
func TestCommandSide_LockUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
@@ -79,7 +80,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -93,7 +94,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -117,7 +118,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -127,7 +128,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -151,7 +152,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -166,7 +167,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
),
expectPush(
user.NewUserLockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -189,7 +190,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -222,7 +223,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -233,7 +234,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
),
expectPush(
user.NewUserLockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -271,6 +272,7 @@ func TestCommandSide_LockUserV2(t *testing.T) {
}
func TestCommandSide_UnlockUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
@@ -332,7 +334,7 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -364,7 +366,7 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
eventstore: expectEventstore(
expectFilter(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -392,7 +394,7 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -406,12 +408,12 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate),
userAgg),
),
),
expectPush(
user.NewUserUnlockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -434,7 +436,7 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -448,7 +450,7 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate),
userAgg),
),
),
),
@@ -471,7 +473,7 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -481,12 +483,12 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserLockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate),
userAgg),
),
),
expectPush(
user.NewUserUnlockedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -524,6 +526,7 @@ func TestCommandSide_UnlockUserV2(t *testing.T) {
}
func TestCommandSide_DeactivateUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
@@ -585,7 +588,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -599,7 +602,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewHumanInitialCodeAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
nil, time.Hour*1,
"",
),
@@ -625,7 +628,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -639,7 +642,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -663,7 +666,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -677,13 +680,13 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewHumanInitializedCheckSucceededEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
expectPush(
user.NewUserDeactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -706,7 +709,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -720,7 +723,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewHumanInitializedCheckSucceededEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -744,7 +747,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -754,7 +757,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -778,7 +781,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -789,7 +792,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
),
expectPush(
user.NewUserDeactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -827,6 +830,7 @@ func TestCommandSide_DeactivateUserV2(t *testing.T) {
}
func TestCommandSide_ReactivateUserV2(t *testing.T) {
userAgg := &user.NewAggregate("user1", "org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
@@ -888,7 +892,7 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -921,7 +925,7 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -950,7 +954,7 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -964,12 +968,12 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate),
userAgg),
),
),
expectPush(
user.NewUserReactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -992,7 +996,7 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -1006,7 +1010,7 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate),
userAgg),
),
),
),
@@ -1029,7 +1033,7 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -1039,12 +1043,12 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserDeactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate),
userAgg),
),
),
expectPush(
user.NewUserReactivatedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -1084,6 +1088,8 @@ func TestCommandSide_ReactivateUserV2(t *testing.T) {
func TestCommandSide_RemoveUserV2(t *testing.T) {
ctxUserID := "ctxUserID"
ctx := authz.SetCtxData(context.Background(), authz.CtxData{UserID: ctxUserID})
userAgg := &user.NewAggregate("user1", "org1").Aggregate
orgAgg := &org.NewAggregate("org1").Aggregate
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
checkPermission domain.PermissionCheck
@@ -1144,7 +1150,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -1158,7 +1164,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserRemovedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
nil,
true,
@@ -1184,7 +1190,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -1199,17 +1205,18 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
org.NewDomainPolicyAddedEvent(context.Background(),
orgAgg,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
nil,
true,
@@ -1234,7 +1241,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewHumanAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"firstname",
"lastname",
@@ -1248,7 +1255,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewHumanInitializedCheckSucceededEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
),
),
),
@@ -1269,7 +1276,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -1279,7 +1286,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
),
eventFromEventPusher(
user.NewUserRemovedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
nil,
true,
@@ -1304,7 +1311,7 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
"name",
"description",
@@ -1315,17 +1322,18 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
),
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
org.NewDomainPolicyAddedEvent(context.Background(),
orgAgg,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
userAgg,
"username",
nil,
true,
@@ -1366,13 +1374,14 @@ func TestCommandSide_RemoveUserV2(t *testing.T) {
expectFilter(
eventFromEventPusher(
org.NewDomainPolicyAddedEvent(ctx,
&user.NewAggregate(ctxUserID, "org1").Aggregate,
orgAgg,
true,
true,
true,
),
),
),
expectFilterOrganizationSettings("org1", false, false),
expectPush(
user.NewUserRemovedEvent(ctx,
&user.NewAggregate(ctxUserID, "org1").Aggregate,
+12 -1
View File
@@ -18,10 +18,21 @@ func (c *Commands) changeUsername(ctx context.Context, cmds []eventstore.Command
if err != nil {
return cmds, zerrors.ThrowPreconditionFailed(err, "COMMAND-79pv6e1q62", "Errors.Org.DomainPolicy.NotExisting")
}
organizationScopedUsername, err := c.checkOrganizationScopedUsernames(ctx, orgID)
if err != nil {
return cmds, err
}
if err = c.userValidateDomain(ctx, orgID, userName, domainPolicy.UserLoginMustBeDomain); err != nil {
return cmds, err
}
return append(cmds,
user.NewUsernameChangedEvent(ctx, &wm.Aggregate().Aggregate, wm.UserName, userName, domainPolicy.UserLoginMustBeDomain),
user.NewUsernameChangedEvent(ctx, &wm.Aggregate().Aggregate,
wm.UserName,
userName,
domainPolicy.UserLoginMustBeDomain,
organizationScopedUsername,
),
), nil
}