mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 17:47:51 +00:00

# 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. <marco@zitadel.com>
543 lines
14 KiB
Go
543 lines
14 KiB
Go
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@test.ch",
|
|
userMustBeDomain,
|
|
),
|
|
)
|
|
}
|
|
return expectFilter(
|
|
events...,
|
|
)
|
|
}
|