mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 14:37:34 +00:00
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. <marco@zitadel.com>
This commit is contained in:
@@ -19,8 +19,9 @@ import (
|
||||
var _ settingsconnect.SettingsServiceHandler = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
command *command.Commands
|
||||
query *query.Queries
|
||||
command *command.Commands
|
||||
query *query.Queries
|
||||
|
||||
assetsAPIDomain func(context.Context) string
|
||||
}
|
||||
|
||||
|
281
internal/api/grpc/settings/v2beta/integration_test/query_test.go
Normal file
281
internal/api/grpc/settings/v2beta/integration_test/query_test.go
Normal file
@@ -0,0 +1,281 @@
|
||||
//go:build integration
|
||||
|
||||
package settings_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/brianvoe/gofakeit/v6"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/filter/v2beta"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/settings/v2beta"
|
||||
)
|
||||
|
||||
func TestServer_ListOrganizationSettings(t *testing.T) {
|
||||
instance := integration.NewInstance(CTX)
|
||||
iamOwnerCtx := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
dep func(*settings.ListOrganizationSettingsRequest, *settings.ListOrganizationSettingsResponse)
|
||||
req *settings.ListOrganizationSettingsRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *settings.ListOrganizationSettingsResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list by id, unauthenticated",
|
||||
args: args{
|
||||
ctx: CTX,
|
||||
dep: func(request *settings.ListOrganizationSettingsRequest, response *settings.ListOrganizationSettingsResponse) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp.GetOrganizationId(), true)
|
||||
|
||||
request.Filters[0].Filter = &settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter{
|
||||
InOrganizationIdsFilter: &filter.InIDsFilter{
|
||||
Ids: []string{orgResp.GetOrganizationId()},
|
||||
},
|
||||
}
|
||||
},
|
||||
req: &settings.ListOrganizationSettingsRequest{
|
||||
Filters: []*settings.OrganizationSettingsSearchFilter{{}},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "list by id, no permission",
|
||||
args: args{
|
||||
ctx: instance.WithAuthorizationToken(CTX, integration.UserTypeNoPermission),
|
||||
dep: func(request *settings.ListOrganizationSettingsRequest, response *settings.ListOrganizationSettingsResponse) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp.GetOrganizationId(), true)
|
||||
|
||||
request.Filters[0].Filter = &settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter{
|
||||
InOrganizationIdsFilter: &filter.InIDsFilter{
|
||||
Ids: []string{orgResp.GetOrganizationId()},
|
||||
},
|
||||
}
|
||||
},
|
||||
req: &settings.ListOrganizationSettingsRequest{
|
||||
Filters: []*settings.OrganizationSettingsSearchFilter{{}},
|
||||
},
|
||||
},
|
||||
want: &settings.ListOrganizationSettingsResponse{
|
||||
Pagination: &filter.PaginationResponse{
|
||||
TotalResult: 1,
|
||||
AppliedLimit: 100,
|
||||
},
|
||||
OrganizationSettings: []*settings.OrganizationSettings{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list by id, missing permission",
|
||||
args: args{
|
||||
ctx: instance.WithAuthorizationToken(CTX, integration.UserTypeOrgOwner),
|
||||
dep: func(request *settings.ListOrganizationSettingsRequest, response *settings.ListOrganizationSettingsResponse) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp.GetOrganizationId(), true)
|
||||
|
||||
request.Filters[0].Filter = &settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter{
|
||||
InOrganizationIdsFilter: &filter.InIDsFilter{
|
||||
Ids: []string{orgResp.GetOrganizationId()},
|
||||
},
|
||||
}
|
||||
},
|
||||
req: &settings.ListOrganizationSettingsRequest{
|
||||
Filters: []*settings.OrganizationSettingsSearchFilter{{}},
|
||||
},
|
||||
},
|
||||
want: &settings.ListOrganizationSettingsResponse{
|
||||
Pagination: &filter.PaginationResponse{
|
||||
TotalResult: 1,
|
||||
AppliedLimit: 100,
|
||||
},
|
||||
OrganizationSettings: []*settings.OrganizationSettings{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list, not found",
|
||||
args: args{
|
||||
ctx: iamOwnerCtx,
|
||||
|
||||
req: &settings.ListOrganizationSettingsRequest{
|
||||
Filters: []*settings.OrganizationSettingsSearchFilter{{
|
||||
Filter: &settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter{
|
||||
InOrganizationIdsFilter: &filter.InIDsFilter{
|
||||
Ids: []string{"notexisting"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
want: &settings.ListOrganizationSettingsResponse{
|
||||
Pagination: &filter.PaginationResponse{
|
||||
TotalResult: 0,
|
||||
AppliedLimit: 100,
|
||||
},
|
||||
OrganizationSettings: []*settings.OrganizationSettings{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list single id",
|
||||
args: args{
|
||||
ctx: iamOwnerCtx,
|
||||
dep: func(request *settings.ListOrganizationSettingsRequest, response *settings.ListOrganizationSettingsResponse) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
settingsResp := instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp.GetOrganizationId(), true)
|
||||
|
||||
request.Filters[0].Filter = &settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter{
|
||||
InOrganizationIdsFilter: &filter.InIDsFilter{
|
||||
Ids: []string{orgResp.GetOrganizationId()},
|
||||
},
|
||||
}
|
||||
response.OrganizationSettings[0] = &settings.OrganizationSettings{
|
||||
OrganizationId: orgResp.GetOrganizationId(),
|
||||
CreationDate: settingsResp.GetSetDate(),
|
||||
ChangeDate: settingsResp.GetSetDate(),
|
||||
OrganizationScopedUsernames: true,
|
||||
}
|
||||
},
|
||||
req: &settings.ListOrganizationSettingsRequest{
|
||||
Filters: []*settings.OrganizationSettingsSearchFilter{{}},
|
||||
},
|
||||
},
|
||||
want: &settings.ListOrganizationSettingsResponse{
|
||||
Pagination: &filter.PaginationResponse{
|
||||
TotalResult: 1,
|
||||
AppliedLimit: 100,
|
||||
},
|
||||
OrganizationSettings: []*settings.OrganizationSettings{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list multiple id",
|
||||
args: args{
|
||||
ctx: iamOwnerCtx,
|
||||
dep: func(request *settings.ListOrganizationSettingsRequest, response *settings.ListOrganizationSettingsResponse) {
|
||||
orgResp1 := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
settingsResp1 := instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp1.GetOrganizationId(), true)
|
||||
orgResp2 := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
settingsResp2 := instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp2.GetOrganizationId(), true)
|
||||
orgResp3 := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
settingsResp3 := instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp3.GetOrganizationId(), true)
|
||||
|
||||
request.Filters[0].Filter = &settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter{
|
||||
InOrganizationIdsFilter: &filter.InIDsFilter{
|
||||
Ids: []string{orgResp1.GetOrganizationId(), orgResp2.GetOrganizationId(), orgResp3.GetOrganizationId()},
|
||||
},
|
||||
}
|
||||
response.OrganizationSettings[2] = &settings.OrganizationSettings{
|
||||
OrganizationId: orgResp1.GetOrganizationId(),
|
||||
CreationDate: settingsResp1.GetSetDate(),
|
||||
ChangeDate: settingsResp1.GetSetDate(),
|
||||
OrganizationScopedUsernames: true,
|
||||
}
|
||||
response.OrganizationSettings[1] = &settings.OrganizationSettings{
|
||||
OrganizationId: orgResp2.GetOrganizationId(),
|
||||
CreationDate: settingsResp2.GetSetDate(),
|
||||
ChangeDate: settingsResp2.GetSetDate(),
|
||||
OrganizationScopedUsernames: true,
|
||||
}
|
||||
response.OrganizationSettings[0] = &settings.OrganizationSettings{
|
||||
OrganizationId: orgResp3.GetOrganizationId(),
|
||||
CreationDate: settingsResp3.GetSetDate(),
|
||||
ChangeDate: settingsResp3.GetSetDate(),
|
||||
OrganizationScopedUsernames: true,
|
||||
}
|
||||
},
|
||||
req: &settings.ListOrganizationSettingsRequest{
|
||||
Filters: []*settings.OrganizationSettingsSearchFilter{{}},
|
||||
},
|
||||
},
|
||||
want: &settings.ListOrganizationSettingsResponse{
|
||||
Pagination: &filter.PaginationResponse{
|
||||
TotalResult: 3,
|
||||
AppliedLimit: 100,
|
||||
},
|
||||
OrganizationSettings: []*settings.OrganizationSettings{{}, {}, {}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list multiple id, only org scoped usernames",
|
||||
args: args{
|
||||
ctx: iamOwnerCtx,
|
||||
dep: func(request *settings.ListOrganizationSettingsRequest, response *settings.ListOrganizationSettingsResponse) {
|
||||
orgResp1 := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp1.GetOrganizationId(), false)
|
||||
orgResp2 := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
settingsResp2 := instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp2.GetOrganizationId(), true)
|
||||
orgResp3 := instance.CreateOrganization(iamOwnerCtx, gofakeit.Company(), gofakeit.Email())
|
||||
instance.SetOrganizationSettings(iamOwnerCtx, t, orgResp3.GetOrganizationId(), false)
|
||||
|
||||
request.Filters[0].Filter = &settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter{
|
||||
InOrganizationIdsFilter: &filter.InIDsFilter{
|
||||
Ids: []string{orgResp1.GetOrganizationId(), orgResp2.GetOrganizationId(), orgResp3.GetOrganizationId()},
|
||||
},
|
||||
}
|
||||
request.Filters[1].Filter = &settings.OrganizationSettingsSearchFilter_OrganizationScopedUsernamesFilter{
|
||||
OrganizationScopedUsernamesFilter: &settings.OrganizationScopedUsernamesFilter{
|
||||
OrganizationScopedUsernames: true,
|
||||
},
|
||||
}
|
||||
response.OrganizationSettings[0] = &settings.OrganizationSettings{
|
||||
OrganizationId: orgResp2.GetOrganizationId(),
|
||||
CreationDate: settingsResp2.GetSetDate(),
|
||||
ChangeDate: settingsResp2.GetSetDate(),
|
||||
OrganizationScopedUsernames: true,
|
||||
}
|
||||
},
|
||||
req: &settings.ListOrganizationSettingsRequest{
|
||||
Filters: []*settings.OrganizationSettingsSearchFilter{{}, {}},
|
||||
},
|
||||
},
|
||||
want: &settings.ListOrganizationSettingsResponse{
|
||||
Pagination: &filter.PaginationResponse{
|
||||
TotalResult: 1,
|
||||
AppliedLimit: 100,
|
||||
},
|
||||
OrganizationSettings: []*settings.OrganizationSettings{{}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.args.dep != nil {
|
||||
tt.args.dep(tt.args.req, tt.want)
|
||||
}
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(iamOwnerCtx, time.Minute)
|
||||
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
got, listErr := instance.Client.SettingsV2beta.ListOrganizationSettings(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
require.Error(ttt, listErr)
|
||||
return
|
||||
}
|
||||
require.NoError(ttt, listErr)
|
||||
|
||||
// always first check length, otherwise its failed anyway
|
||||
if assert.Len(ttt, got.OrganizationSettings, len(tt.want.OrganizationSettings)) {
|
||||
for i := range tt.want.OrganizationSettings {
|
||||
assert.EqualExportedValues(ttt, tt.want.OrganizationSettings[i], got.OrganizationSettings[i])
|
||||
}
|
||||
}
|
||||
assertPaginationResponse(ttt, tt.want.Pagination, got.Pagination)
|
||||
}, retryDuration, tick, "timeout waiting for expected execution result")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func assertPaginationResponse(t *assert.CollectT, expected *filter.PaginationResponse, actual *filter.PaginationResponse) {
|
||||
assert.Equal(t, expected.AppliedLimit, actual.AppliedLimit)
|
||||
assert.Equal(t, expected.TotalResult, actual.TotalResult)
|
||||
}
|
@@ -7,6 +7,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/brianvoe/gofakeit/v6"
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
@@ -178,3 +180,279 @@ func TestServer_SetSecuritySettings(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_SetOrganizationSettings(t *testing.T) {
|
||||
instance := integration.NewInstance(CTX)
|
||||
iamOwnerCTX := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *settings.SetOrganizationSettingsRequest
|
||||
}
|
||||
type want struct {
|
||||
set bool
|
||||
setDate bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare func(req *settings.SetOrganizationSettingsRequest)
|
||||
args args
|
||||
want want
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "permission error",
|
||||
args: args{
|
||||
ctx: instance.WithAuthorizationToken(CTX, integration.UserTypeOrgOwner),
|
||||
req: &settings.SetOrganizationSettingsRequest{
|
||||
OrganizationId: Instance.DefaultOrg.GetId(),
|
||||
OrganizationScopedUsernames: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "org not provided",
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.SetOrganizationSettingsRequest{
|
||||
OrganizationId: "",
|
||||
OrganizationScopedUsernames: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "org not existing",
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.SetOrganizationSettingsRequest{
|
||||
OrganizationId: "notexisting",
|
||||
OrganizationScopedUsernames: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "success no changes",
|
||||
prepare: func(req *settings.SetOrganizationSettingsRequest) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCTX, gofakeit.Company(), gofakeit.Email())
|
||||
req.OrganizationId = orgResp.GetOrganizationId()
|
||||
},
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.SetOrganizationSettingsRequest{},
|
||||
},
|
||||
want: want{
|
||||
set: false,
|
||||
setDate: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success user uniqueness",
|
||||
prepare: func(req *settings.SetOrganizationSettingsRequest) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCTX, gofakeit.Company(), gofakeit.Email())
|
||||
req.OrganizationId = orgResp.GetOrganizationId()
|
||||
},
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.SetOrganizationSettingsRequest{
|
||||
OrganizationScopedUsernames: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
set: true,
|
||||
setDate: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success no change",
|
||||
prepare: func(req *settings.SetOrganizationSettingsRequest) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCTX, gofakeit.Company(), gofakeit.Email())
|
||||
req.OrganizationId = orgResp.GetOrganizationId()
|
||||
},
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.SetOrganizationSettingsRequest{
|
||||
OrganizationScopedUsernames: gu.Ptr(false),
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
set: false,
|
||||
setDate: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
creationDate := time.Now().UTC()
|
||||
if tt.prepare != nil {
|
||||
tt.prepare(tt.args.req)
|
||||
}
|
||||
|
||||
got, err := instance.Client.SettingsV2beta.SetOrganizationSettings(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
setDate := time.Time{}
|
||||
if tt.want.set {
|
||||
setDate = time.Now().UTC()
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assertOrganizationSettingsResponse(t, creationDate, setDate, tt.want.setDate, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func assertOrganizationSettingsResponse(t *testing.T, creationDate, setDate time.Time, expectedSetDate bool, actualResp *settings.SetOrganizationSettingsResponse) {
|
||||
if expectedSetDate {
|
||||
if !setDate.IsZero() {
|
||||
assert.WithinRange(t, actualResp.GetSetDate().AsTime(), creationDate, setDate)
|
||||
} else {
|
||||
assert.WithinRange(t, actualResp.GetSetDate().AsTime(), creationDate, time.Now().UTC())
|
||||
}
|
||||
} else {
|
||||
assert.Nil(t, actualResp.SetDate)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_DeleteOrganizationSettings(t *testing.T) {
|
||||
instance := integration.NewInstance(CTX)
|
||||
iamOwnerCTX := instance.WithAuthorizationToken(CTX, integration.UserTypeIAMOwner)
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *settings.DeleteOrganizationSettingsRequest
|
||||
}
|
||||
type want struct {
|
||||
deletion bool
|
||||
deletionDate bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare func(t *testing.T, req *settings.DeleteOrganizationSettingsRequest)
|
||||
args args
|
||||
want want
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "permission error",
|
||||
prepare: func(t *testing.T, req *settings.DeleteOrganizationSettingsRequest) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCTX, gofakeit.Company(), gofakeit.Email())
|
||||
req.OrganizationId = orgResp.GetOrganizationId()
|
||||
instance.SetOrganizationSettings(iamOwnerCTX, t, orgResp.GetOrganizationId(), true)
|
||||
},
|
||||
args: args{
|
||||
ctx: instance.WithAuthorizationToken(CTX, integration.UserTypeOrgOwner),
|
||||
req: &settings.DeleteOrganizationSettingsRequest{
|
||||
OrganizationId: Instance.DefaultOrg.GetId(),
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "org not provided",
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.DeleteOrganizationSettingsRequest{
|
||||
OrganizationId: "",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "org not existing",
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.DeleteOrganizationSettingsRequest{
|
||||
OrganizationId: "notexisting",
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
deletion: false,
|
||||
deletionDate: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success user uniqueness",
|
||||
prepare: func(t *testing.T, req *settings.DeleteOrganizationSettingsRequest) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCTX, gofakeit.Company(), gofakeit.Email())
|
||||
req.OrganizationId = orgResp.GetOrganizationId()
|
||||
instance.SetOrganizationSettings(iamOwnerCTX, t, orgResp.GetOrganizationId(), true)
|
||||
},
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.DeleteOrganizationSettingsRequest{},
|
||||
},
|
||||
want: want{
|
||||
deletion: true,
|
||||
deletionDate: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success no existing",
|
||||
prepare: func(t *testing.T, req *settings.DeleteOrganizationSettingsRequest) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCTX, gofakeit.Company(), gofakeit.Email())
|
||||
req.OrganizationId = orgResp.GetOrganizationId()
|
||||
},
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.DeleteOrganizationSettingsRequest{},
|
||||
},
|
||||
want: want{
|
||||
deletion: false,
|
||||
deletionDate: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success already deleted",
|
||||
prepare: func(t *testing.T, req *settings.DeleteOrganizationSettingsRequest) {
|
||||
orgResp := instance.CreateOrganization(iamOwnerCTX, gofakeit.Company(), gofakeit.Email())
|
||||
req.OrganizationId = orgResp.GetOrganizationId()
|
||||
instance.SetOrganizationSettings(iamOwnerCTX, t, orgResp.GetOrganizationId(), true)
|
||||
instance.DeleteOrganizationSettings(iamOwnerCTX, t, orgResp.GetOrganizationId())
|
||||
},
|
||||
args: args{
|
||||
ctx: iamOwnerCTX,
|
||||
req: &settings.DeleteOrganizationSettingsRequest{},
|
||||
},
|
||||
want: want{
|
||||
deletion: false,
|
||||
deletionDate: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
creationDate := time.Now().UTC()
|
||||
if tt.prepare != nil {
|
||||
tt.prepare(t, tt.args.req)
|
||||
}
|
||||
|
||||
got, err := instance.Client.SettingsV2beta.DeleteOrganizationSettings(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
deletionDate := time.Time{}
|
||||
if tt.want.deletion {
|
||||
deletionDate = time.Now().UTC()
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assertDeleteOrganizationSettingsResponse(t, creationDate, deletionDate, tt.want.deletionDate, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func assertDeleteOrganizationSettingsResponse(t *testing.T, creationDate, deletionDate time.Time, expectedDeletionDate bool, actualResp *settings.DeleteOrganizationSettingsResponse) {
|
||||
if expectedDeletionDate {
|
||||
if !deletionDate.IsZero() {
|
||||
assert.WithinRange(t, actualResp.GetDeletionDate().AsTime(), creationDate, deletionDate)
|
||||
} else {
|
||||
assert.WithinRange(t, actualResp.GetDeletionDate().AsTime(), creationDate, time.Now().UTC())
|
||||
}
|
||||
} else {
|
||||
assert.Nil(t, actualResp.DeletionDate)
|
||||
}
|
||||
}
|
||||
|
114
internal/api/grpc/settings/v2beta/query.go
Normal file
114
internal/api/grpc/settings/v2beta/query.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/filter/v2beta"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
filter_pb "github.com/zitadel/zitadel/pkg/grpc/filter/v2beta"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/settings/v2beta"
|
||||
)
|
||||
|
||||
func (s *Server) ListOrganizationSettings(ctx context.Context, req *connect.Request[settings.ListOrganizationSettingsRequest]) (*connect.Response[settings.ListOrganizationSettingsResponse], error) {
|
||||
queries, err := s.listOrganizationSettingsRequestToModel(req.Msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := s.query.SearchOrganizationSettings(ctx, queries, s.checkPermission)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connect.NewResponse(&settings.ListOrganizationSettingsResponse{
|
||||
OrganizationSettings: organizationSettingsListToPb(resp.OrganizationSettingsList),
|
||||
Pagination: filter.QueryToPaginationPb(queries.SearchRequest, resp.SearchResponse),
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) listOrganizationSettingsRequestToModel(req *settings.ListOrganizationSettingsRequest) (*query.OrganizationSettingsSearchQueries, error) {
|
||||
offset, limit, asc, err := filter.PaginationPbToQuery(s.systemDefaults, req.Pagination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queries, err := organizationSettingsFiltersToQuery(req.Filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &query.OrganizationSettingsSearchQueries{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
SortingColumn: organizationSettingsFieldNameToSortingColumn(req.SortingColumn),
|
||||
},
|
||||
Queries: queries,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func organizationSettingsFieldNameToSortingColumn(field *settings.OrganizationSettingsFieldName) query.Column {
|
||||
if field == nil {
|
||||
return query.OrganizationSettingsColumnCreationDate
|
||||
}
|
||||
switch *field {
|
||||
case settings.OrganizationSettingsFieldName_ORGANIZATION_SETTINGS_FIELD_NAME_CREATION_DATE:
|
||||
return query.OrganizationSettingsColumnCreationDate
|
||||
case settings.OrganizationSettingsFieldName_ORGANIZATION_SETTINGS_FIELD_NAME_ORGANIZATION_ID:
|
||||
return query.OrganizationSettingsColumnID
|
||||
case settings.OrganizationSettingsFieldName_ORGANIZATION_SETTINGS_FIELD_NAME_CHANGE_DATE:
|
||||
return query.OrganizationSettingsColumnChangeDate
|
||||
case settings.OrganizationSettingsFieldName_ORGANIZATION_SETTINGS_FIELD_NAME_UNSPECIFIED:
|
||||
return query.OrganizationSettingsColumnCreationDate
|
||||
default:
|
||||
return query.OrganizationSettingsColumnCreationDate
|
||||
}
|
||||
}
|
||||
|
||||
func organizationSettingsFiltersToQuery(queries []*settings.OrganizationSettingsSearchFilter) (_ []query.SearchQuery, err error) {
|
||||
q := make([]query.SearchQuery, len(queries))
|
||||
for i, qry := range queries {
|
||||
q[i], err = organizationSettingsToModel(qry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func organizationSettingsToModel(filter *settings.OrganizationSettingsSearchFilter) (query.SearchQuery, error) {
|
||||
switch q := filter.Filter.(type) {
|
||||
case *settings.OrganizationSettingsSearchFilter_InOrganizationIdsFilter:
|
||||
return organizationInIDsFilterToQuery(q.InOrganizationIdsFilter)
|
||||
case *settings.OrganizationSettingsSearchFilter_OrganizationScopedUsernamesFilter:
|
||||
return organizationScopedUsernamesFilterToQuery(q.OrganizationScopedUsernamesFilter)
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "SETTINGS-uvTDqZHlvS", "List.Query.Invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func organizationInIDsFilterToQuery(q *filter_pb.InIDsFilter) (query.SearchQuery, error) {
|
||||
return query.NewOrganizationSettingsOrganizationIDSearchQuery(q.Ids)
|
||||
}
|
||||
|
||||
func organizationScopedUsernamesFilterToQuery(q *settings.OrganizationScopedUsernamesFilter) (query.SearchQuery, error) {
|
||||
return query.NewOrganizationSettingsOrganizationScopedUsernamesSearchQuery(q.OrganizationScopedUsernames)
|
||||
}
|
||||
|
||||
func organizationSettingsListToPb(settingsList []*query.OrganizationSettings) []*settings.OrganizationSettings {
|
||||
o := make([]*settings.OrganizationSettings, len(settingsList))
|
||||
for i, organizationSettings := range settingsList {
|
||||
o[i] = organizationSettingsToPb(organizationSettings)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func organizationSettingsToPb(organizationSettings *query.OrganizationSettings) *settings.OrganizationSettings {
|
||||
return &settings.OrganizationSettings{
|
||||
OrganizationId: organizationSettings.ID,
|
||||
CreationDate: timestamppb.New(organizationSettings.CreationDate),
|
||||
ChangeDate: timestamppb.New(organizationSettings.ChangeDate),
|
||||
OrganizationScopedUsernames: organizationSettings.OrganizationScopedUsernames,
|
||||
}
|
||||
}
|
@@ -11,6 +11,8 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/server"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/config/systemdefaults"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
settings "github.com/zitadel/zitadel/pkg/grpc/settings/v2beta"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/settings/v2beta/settingsconnect"
|
||||
@@ -19,20 +21,27 @@ import (
|
||||
var _ settingsconnect.SettingsServiceHandler = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
command *command.Commands
|
||||
query *query.Queries
|
||||
systemDefaults systemdefaults.SystemDefaults
|
||||
command *command.Commands
|
||||
query *query.Queries
|
||||
|
||||
checkPermission domain.PermissionCheck
|
||||
assetsAPIDomain func(context.Context) string
|
||||
}
|
||||
|
||||
type Config struct{}
|
||||
|
||||
func CreateServer(
|
||||
systemDefaults systemdefaults.SystemDefaults,
|
||||
command *command.Commands,
|
||||
query *query.Queries,
|
||||
checkPermission domain.PermissionCheck,
|
||||
) *Server {
|
||||
return &Server{
|
||||
systemDefaults: systemDefaults,
|
||||
command: command,
|
||||
query: query,
|
||||
checkPermission: checkPermission,
|
||||
assetsAPIDomain: assets.AssetAPI(),
|
||||
}
|
||||
}
|
||||
|
@@ -167,3 +167,31 @@ func (s *Server) SetSecuritySettings(ctx context.Context, req *connect.Request[s
|
||||
Details: object.DomainToDetailsPb(details),
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) SetOrganizationSettings(ctx context.Context, req *connect.Request[settings.SetOrganizationSettingsRequest]) (*connect.Response[settings.SetOrganizationSettingsResponse], error) {
|
||||
details, err := s.command.SetOrganizationSettings(ctx, organizationSettingsToCommand(req.Msg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var setDate *timestamppb.Timestamp
|
||||
if !details.EventDate.IsZero() {
|
||||
setDate = timestamppb.New(details.EventDate)
|
||||
}
|
||||
return connect.NewResponse(&settings.SetOrganizationSettingsResponse{
|
||||
SetDate: setDate,
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Server) DeleteOrganizationSettings(ctx context.Context, req *connect.Request[settings.DeleteOrganizationSettingsRequest]) (*connect.Response[settings.DeleteOrganizationSettingsResponse], error) {
|
||||
details, err := s.command.DeleteOrganizationSettings(ctx, req.Msg.GetOrganizationId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var deletionDate *timestamppb.Timestamp
|
||||
if !details.EventDate.IsZero() {
|
||||
deletionDate = timestamppb.New(details.EventDate)
|
||||
}
|
||||
return connect.NewResponse(&settings.DeleteOrganizationSettingsResponse{
|
||||
DeletionDate: deletionDate,
|
||||
}), nil
|
||||
}
|
||||
|
@@ -243,3 +243,10 @@ func securitySettingsToCommand(req *settings.SetSecuritySettingsRequest) *comman
|
||||
EnableImpersonation: req.GetEnableImpersonation(),
|
||||
}
|
||||
}
|
||||
|
||||
func organizationSettingsToCommand(req *settings.SetOrganizationSettingsRequest) *command.SetOrganizationSettings {
|
||||
return &command.SetOrganizationSettings{
|
||||
OrganizationID: req.OrganizationId,
|
||||
OrganizationScopedUsernames: req.OrganizationScopedUsernames,
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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",
|
||||
"user1@org1.com",
|
||||
false,
|
||||
user.UsernameChangedEventWithPolicyChange(),
|
||||
false,
|
||||
user.UsernameChangedEventWithPolicyChange(true),
|
||||
),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org3").Aggregate,
|
||||
"user1",
|
||||
"user1@org3.com",
|
||||
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,
|
||||
"user1@org1.com",
|
||||
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,
|
||||
"user1@org3.com",
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
newDefaultDomainPolicyChangedEvent(context.Background(), false, false, false),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"user1",
|
||||
"user1@org1.com",
|
||||
false,
|
||||
true,
|
||||
user.UsernameChangedEventWithPolicyChange(true),
|
||||
),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org3").Aggregate,
|
||||
"user1",
|
||||
"user1@org3.com",
|
||||
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,
|
||||
"user1@org1.com",
|
||||
"firstname",
|
||||
"lastname",
|
||||
"nickname",
|
||||
"displayname",
|
||||
language.English,
|
||||
domain.GenderUnspecified,
|
||||
"user1@org1.com",
|
||||
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@org3.com",
|
||||
"firstname",
|
||||
"lastname",
|
||||
"nickname",
|
||||
"displayname",
|
||||
language.English,
|
||||
domain.GenderUnspecified,
|
||||
"user1@org3.com",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
newDefaultDomainPolicyChangedEvent(context.Background(), true, false, false),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"user1@org1.com",
|
||||
"user1@org1.com",
|
||||
true,
|
||||
true,
|
||||
user.UsernameChangedEventWithPolicyChange(false),
|
||||
),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org3").Aggregate,
|
||||
"user1@org3.com",
|
||||
"user1@org3.com",
|
||||
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 {
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
"username@domain.ch",
|
||||
"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,
|
||||
"tempid@temporary.zitadel.ch",
|
||||
"username@domain.ch",
|
||||
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) {
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
"user@test.com",
|
||||
"user@test.com",
|
||||
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,
|
||||
"user1@org.com",
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user2", "org1").Aggregate,
|
||||
"user@test.com",
|
||||
"firstname",
|
||||
"lastname",
|
||||
"nickname",
|
||||
"displayname",
|
||||
language.English,
|
||||
domain.GenderUnspecified,
|
||||
"user@test.com",
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
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,
|
||||
"user@test.com",
|
||||
"user@test.com",
|
||||
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,
|
||||
"user1@org.com",
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user2", "org1").Aggregate,
|
||||
"user@test.com",
|
||||
"firstname",
|
||||
"lastname",
|
||||
"nickname",
|
||||
"displayname",
|
||||
language.English,
|
||||
domain.GenderUnspecified,
|
||||
"user@test.com",
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"user1",
|
||||
"user1@org.com",
|
||||
false,
|
||||
true,
|
||||
user.UsernameChangedEventWithPolicyChange(true),
|
||||
),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user2", "org1").Aggregate,
|
||||
"user@test.com",
|
||||
"user@test.com@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",
|
||||
"user1@org.com",
|
||||
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,
|
||||
"user1@org.com",
|
||||
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,
|
||||
"user1@org.com",
|
||||
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",
|
||||
"user1@org.com",
|
||||
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",
|
||||
"user1@org.com",
|
||||
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,
|
||||
"user1@org.com",
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
org.NewDomainPolicyRemovedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
),
|
||||
user.NewUsernameChangedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"user1",
|
||||
"user1@org.com",
|
||||
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,
|
||||
"user1@org.com",
|
||||
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 {
|
||||
|
@@ -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
internal/command/organization_settings.go
Normal file
140
internal/command/organization_settings.go
Normal 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
|
||||
}
|
245
internal/command/organization_settings_model.go
Normal file
245
internal/command/organization_settings_model.go
Normal file
@@ -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()
|
||||
}
|
542
internal/command/organization_settings_test.go
Normal file
542
internal/command/organization_settings_test.go
Normal file
@@ -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@test.ch",
|
||||
userMustBeDomain,
|
||||
),
|
||||
)
|
||||
}
|
||||
return expectFilter(
|
||||
events...,
|
||||
)
|
||||
}
|
@@ -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
|
||||
|
@@ -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) {
|
||||
|
@@ -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)
|
||||
|
@@ -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@test.ch",
|
||||
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@test.ch",
|
||||
},
|
||||
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@test.ch",
|
||||
},
|
||||
},
|
||||
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@test.ch",
|
||||
},
|
||||
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,
|
||||
"support@zitadel.com",
|
||||
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: "support@zitadel.com", 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{
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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",
|
||||
"test@test.ch",
|
||||
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@test.ch",
|
||||
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",
|
||||
"test@test.ch",
|
||||
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@test.ch",
|
||||
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 {
|
||||
|
@@ -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)
|
||||
|
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -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@test.ch",
|
||||
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@test.ch",
|
||||
},
|
||||
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@example.com",
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@@ -343,6 +343,7 @@ func TestCommandSide_userExistsWriteModel(t *testing.T) {
|
||||
"username",
|
||||
"changed",
|
||||
true,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
}
|
||||
|
19
internal/domain/organization_settings.go
Normal file
19
internal/domain/organization_settings.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package domain
|
||||
|
||||
type OrganizationSettingsState int32
|
||||
|
||||
const (
|
||||
OrganizationSettingsStateUnspecified OrganizationSettingsState = iota
|
||||
OrganizationSettingsStateActive
|
||||
OrganizationSettingsStateRemoved
|
||||
|
||||
organizationSettingsStateCount
|
||||
)
|
||||
|
||||
func (c OrganizationSettingsState) Valid() bool {
|
||||
return c >= 0 && c < organizationSettingsStateCount
|
||||
}
|
||||
|
||||
func (s OrganizationSettingsState) Exists() bool {
|
||||
return s.Valid() && s != OrganizationSettingsStateUnspecified && s != OrganizationSettingsStateRemoved
|
||||
}
|
@@ -65,6 +65,9 @@ const (
|
||||
PermissionUserGrantWrite = "user.grant.write"
|
||||
PermissionUserGrantRead = "user.grant.read"
|
||||
PermissionUserGrantDelete = "user.grant.delete"
|
||||
PermissionIAMPolicyWrite = "iam.policy.write"
|
||||
PermissionIAMPolicyDelete = "iam.policy.delete"
|
||||
PermissionPolicyRead = "policy.read"
|
||||
)
|
||||
|
||||
// ProjectPermissionCheck is used as a check for preconditions dependent on application, project, user resourceowner and usergrants.
|
||||
|
@@ -405,6 +405,27 @@ func (i *Instance) CreateOrganizationWithUserID(ctx context.Context, name, userI
|
||||
return resp
|
||||
}
|
||||
|
||||
func (i *Instance) SetOrganizationSettings(ctx context.Context, t *testing.T, orgID string, organizationScopedUsernames bool) *settings_v2beta.SetOrganizationSettingsResponse {
|
||||
resp, err := i.Client.SettingsV2beta.SetOrganizationSettings(ctx,
|
||||
&settings_v2beta.SetOrganizationSettingsRequest{
|
||||
OrganizationId: orgID,
|
||||
OrganizationScopedUsernames: gu.Ptr(organizationScopedUsernames),
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
return resp
|
||||
}
|
||||
|
||||
func (i *Instance) DeleteOrganizationSettings(ctx context.Context, t *testing.T, orgID string) *settings_v2beta.DeleteOrganizationSettingsResponse {
|
||||
resp, err := i.Client.SettingsV2beta.DeleteOrganizationSettings(ctx,
|
||||
&settings_v2beta.DeleteOrganizationSettingsRequest{
|
||||
OrganizationId: orgID,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
return resp
|
||||
}
|
||||
|
||||
func (i *Instance) CreateHumanUserVerified(ctx context.Context, org, email, phone string) *user_v2.AddHumanUserResponse {
|
||||
resp, err := i.Client.UserV2.AddHumanUser(ctx, &user_v2.AddHumanUserRequest{
|
||||
Organization: &object.Organization{
|
||||
|
@@ -185,7 +185,7 @@ func (q *Queries) searchAdministrators(ctx context.Context, queries *MembershipS
|
||||
eq := sq.Eq{membershipInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||
stmt, args, err := queries.toQuery(query).Where(eq).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "QUERY-TODO", "Errors.Query.InvalidRequest")
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "QUERY-xhEnpLFNpJ", "Errors.Query.InvalidRequest")
|
||||
}
|
||||
latestState, err := q.latestState(ctx, orgMemberTable, instanceMemberTable, projectMemberTable, projectGrantMemberTable)
|
||||
if err != nil {
|
||||
@@ -335,7 +335,7 @@ func prepareAdministratorsQuery(ctx context.Context, queries *MembershipSearchQu
|
||||
}
|
||||
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-TODO", "Errors.Query.CloseRows")
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-ajYcn0eK7f", "Errors.Query.CloseRows")
|
||||
}
|
||||
|
||||
return &Administrators{
|
||||
|
196
internal/query/organization_settings.go
Normal file
196
internal/query/organization_settings.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/query/projection"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
var (
|
||||
organizationSettingsTable = table{
|
||||
name: projection.OrganizationSettingsTable,
|
||||
instanceIDCol: projection.OrganizationSettingsInstanceIDCol,
|
||||
}
|
||||
OrganizationSettingsColumnID = Column{
|
||||
name: projection.OrganizationSettingsIDCol,
|
||||
table: organizationSettingsTable,
|
||||
}
|
||||
OrganizationSettingsColumnCreationDate = Column{
|
||||
name: projection.OrganizationSettingsCreationDateCol,
|
||||
table: organizationSettingsTable,
|
||||
}
|
||||
OrganizationSettingsColumnChangeDate = Column{
|
||||
name: projection.OrganizationSettingsChangeDateCol,
|
||||
table: organizationSettingsTable,
|
||||
}
|
||||
OrganizationSettingsColumnResourceOwner = Column{
|
||||
name: projection.OrganizationSettingsResourceOwnerCol,
|
||||
table: organizationSettingsTable,
|
||||
}
|
||||
OrganizationSettingsColumnInstanceID = Column{
|
||||
name: projection.OrganizationSettingsInstanceIDCol,
|
||||
table: organizationSettingsTable,
|
||||
}
|
||||
OrganizationSettingsColumnSequence = Column{
|
||||
name: projection.OrganizationSettingsSequenceCol,
|
||||
table: organizationSettingsTable,
|
||||
}
|
||||
OrganizationSettingsColumnOrganizationScopedUsernames = Column{
|
||||
name: projection.OrganizationSettingsOrganizationScopedUsernamesCol,
|
||||
table: organizationSettingsTable,
|
||||
}
|
||||
)
|
||||
|
||||
type OrganizationSettingsList struct {
|
||||
SearchResponse
|
||||
OrganizationSettingsList []*OrganizationSettings
|
||||
}
|
||||
|
||||
func organizationSettingsListCheckPermission(ctx context.Context, organizationSettingsList *OrganizationSettingsList, permissionCheck domain.PermissionCheck) {
|
||||
organizationSettingsList.OrganizationSettingsList = slices.DeleteFunc(organizationSettingsList.OrganizationSettingsList,
|
||||
func(organizationSettings *OrganizationSettings) bool {
|
||||
return organizationSettingsCheckPermission(ctx, organizationSettings.ResourceOwner, organizationSettings.ID, permissionCheck) != nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func organizationSettingsCheckPermission(ctx context.Context, resourceOwner string, id string, permissionCheck domain.PermissionCheck) error {
|
||||
return permissionCheck(ctx, domain.PermissionPolicyRead, resourceOwner, id)
|
||||
}
|
||||
|
||||
type OrganizationSettings struct {
|
||||
ID string
|
||||
CreationDate time.Time
|
||||
ChangeDate time.Time
|
||||
ResourceOwner string
|
||||
Sequence uint64
|
||||
|
||||
OrganizationScopedUsernames bool
|
||||
}
|
||||
|
||||
type OrganizationSettingsSearchQueries struct {
|
||||
SearchRequest
|
||||
Queries []SearchQuery
|
||||
}
|
||||
|
||||
func (q *OrganizationSettingsSearchQueries) toQuery(query sq.SelectBuilder) sq.SelectBuilder {
|
||||
query = q.SearchRequest.toQuery(query)
|
||||
for _, q := range q.Queries {
|
||||
query = q.toQuery(query)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func organizationSettingsPermissionCheckV2(ctx context.Context, query sq.SelectBuilder, enabled bool, queries *OrganizationSettingsSearchQueries) sq.SelectBuilder {
|
||||
if !enabled {
|
||||
return query
|
||||
}
|
||||
join, args := PermissionClause(
|
||||
ctx,
|
||||
OrganizationSettingsColumnID,
|
||||
domain.PermissionPolicyRead,
|
||||
SingleOrgPermissionOption(queries.Queries),
|
||||
)
|
||||
return query.JoinClause(join, args...)
|
||||
}
|
||||
|
||||
func (q *Queries) SearchOrganizationSettings(ctx context.Context, queries *OrganizationSettingsSearchQueries, permissionCheck domain.PermissionCheck) (*OrganizationSettingsList, error) {
|
||||
permissionCheckV2 := PermissionV2(ctx, permissionCheck)
|
||||
settings, err := q.searchOrganizationSettings(ctx, queries, permissionCheckV2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if permissionCheck != nil && !authz.GetFeatures(ctx).PermissionCheckV2 {
|
||||
organizationSettingsListCheckPermission(ctx, settings, permissionCheck)
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
func (q *Queries) searchOrganizationSettings(ctx context.Context, queries *OrganizationSettingsSearchQueries, permissionCheckV2 bool) (settingsList *OrganizationSettingsList, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
query, scan := prepareOrganizationSettingsListQuery()
|
||||
query = organizationSettingsPermissionCheckV2(ctx, query, permissionCheckV2, queries)
|
||||
eq := sq.Eq{OrganizationSettingsColumnInstanceID.identifier(): authz.GetInstance(ctx).InstanceID()}
|
||||
stmt, args, err := queries.toQuery(query).Where(eq).ToSql()
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "QUERY-qNPeOXlMwj", "Errors.Query.InvalidRequest")
|
||||
}
|
||||
|
||||
err = q.client.QueryContext(ctx, func(rows *sql.Rows) error {
|
||||
settingsList, err = scan(rows)
|
||||
return err
|
||||
}, stmt, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return settingsList, nil
|
||||
}
|
||||
|
||||
func NewOrganizationSettingsOrganizationIDSearchQuery(ids []string) (SearchQuery, error) {
|
||||
list := make([]interface{}, len(ids))
|
||||
for i, value := range ids {
|
||||
list[i] = value
|
||||
}
|
||||
return NewListQuery(OrganizationSettingsColumnID, list, ListIn)
|
||||
}
|
||||
|
||||
func NewOrganizationSettingsOrganizationScopedUsernamesSearchQuery(organizationScopedUsernames bool) (SearchQuery, error) {
|
||||
return NewBoolQuery(OrganizationSettingsColumnOrganizationScopedUsernames, organizationScopedUsernames)
|
||||
}
|
||||
|
||||
func prepareOrganizationSettingsListQuery() (sq.SelectBuilder, func(*sql.Rows) (*OrganizationSettingsList, error)) {
|
||||
return sq.Select(
|
||||
OrganizationSettingsColumnID.identifier(),
|
||||
OrganizationSettingsColumnCreationDate.identifier(),
|
||||
OrganizationSettingsColumnChangeDate.identifier(),
|
||||
OrganizationSettingsColumnResourceOwner.identifier(),
|
||||
OrganizationSettingsColumnSequence.identifier(),
|
||||
OrganizationSettingsColumnOrganizationScopedUsernames.identifier(),
|
||||
countColumn.identifier(),
|
||||
).From(organizationSettingsTable.identifier()).
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(rows *sql.Rows) (*OrganizationSettingsList, error) {
|
||||
settingsList := make([]*OrganizationSettings, 0)
|
||||
var (
|
||||
count uint64
|
||||
)
|
||||
for rows.Next() {
|
||||
settings := new(OrganizationSettings)
|
||||
err := rows.Scan(
|
||||
&settings.ID,
|
||||
&settings.CreationDate,
|
||||
&settings.ChangeDate,
|
||||
&settings.ResourceOwner,
|
||||
&settings.Sequence,
|
||||
&settings.OrganizationScopedUsernames,
|
||||
&count,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
settingsList = append(settingsList, settings)
|
||||
}
|
||||
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, zerrors.ThrowInternal(err, "QUERY-mmC1K0t5Fq", "Errors.Query.CloseRows")
|
||||
}
|
||||
|
||||
return &OrganizationSettingsList{
|
||||
OrganizationSettingsList: settingsList,
|
||||
SearchResponse: SearchResponse{
|
||||
Count: count,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
180
internal/query/organization_settings_test.go
Normal file
180
internal/query/organization_settings_test.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
prepareOrganizationSettingsListStmt = `SELECT projections.organization_settings.id,` +
|
||||
` projections.organization_settings.creation_date,` +
|
||||
` projections.organization_settings.change_date,` +
|
||||
` projections.organization_settings.resource_owner,` +
|
||||
` projections.organization_settings.sequence,` +
|
||||
` projections.organization_settings.organization_scoped_usernames,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.organization_settings`
|
||||
prepareOrganizationSettingsListCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
"change_date",
|
||||
"resource_owner",
|
||||
"sequence",
|
||||
"organization_scoped_usernames",
|
||||
"count",
|
||||
}
|
||||
)
|
||||
|
||||
func Test_OrganizationSettingsListPrepares(t *testing.T) {
|
||||
type want struct {
|
||||
sqlExpectations sqlExpectation
|
||||
err checkErr
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
prepare interface{}
|
||||
want want
|
||||
object interface{}
|
||||
}{
|
||||
{
|
||||
name: "prepareOrganizationSettingsListQuery no result",
|
||||
prepare: prepareOrganizationSettingsListQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
regexp.QuoteMeta(prepareOrganizationSettingsListStmt),
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
},
|
||||
object: &OrganizationSettingsList{OrganizationSettingsList: []*OrganizationSettings{}},
|
||||
},
|
||||
{
|
||||
name: "prepareOrganizationSettingsListQuery one result",
|
||||
prepare: prepareOrganizationSettingsListQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
regexp.QuoteMeta(prepareOrganizationSettingsListStmt),
|
||||
prepareOrganizationSettingsListCols,
|
||||
[][]driver.Value{
|
||||
{
|
||||
"id",
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211108),
|
||||
true,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &OrganizationSettingsList{
|
||||
SearchResponse: SearchResponse{
|
||||
Count: 1,
|
||||
},
|
||||
OrganizationSettingsList: []*OrganizationSettings{
|
||||
{
|
||||
ID: "id",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
OrganizationScopedUsernames: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareOrganizationSettingsListQuery multiple result",
|
||||
prepare: prepareOrganizationSettingsListQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
regexp.QuoteMeta(prepareOrganizationSettingsListStmt),
|
||||
prepareOrganizationSettingsListCols,
|
||||
[][]driver.Value{
|
||||
{
|
||||
"id-1",
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211108),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"id-2",
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211108),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"id-3",
|
||||
testNow,
|
||||
testNow,
|
||||
"ro",
|
||||
uint64(20211108),
|
||||
true,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &OrganizationSettingsList{
|
||||
SearchResponse: SearchResponse{
|
||||
Count: 3,
|
||||
},
|
||||
OrganizationSettingsList: []*OrganizationSettings{
|
||||
{
|
||||
ID: "id-1",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
OrganizationScopedUsernames: true,
|
||||
},
|
||||
{
|
||||
ID: "id-2",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
OrganizationScopedUsernames: false,
|
||||
},
|
||||
{
|
||||
ID: "id-3",
|
||||
CreationDate: testNow,
|
||||
ChangeDate: testNow,
|
||||
ResourceOwner: "ro",
|
||||
Sequence: 20211108,
|
||||
OrganizationScopedUsernames: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prepareOrganizationSettingsListQuery sql err",
|
||||
prepare: prepareOrganizationSettingsListQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(prepareOrganizationSettingsListStmt),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
if !errors.Is(err, sql.ErrConnDone) {
|
||||
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
|
||||
}
|
||||
return nil, true
|
||||
},
|
||||
},
|
||||
object: (*OrganizationSettingsList)(nil),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assertPrepare(t, tt.prepare, tt.object, tt.want.sqlExpectations, tt.want.err)
|
||||
})
|
||||
}
|
||||
}
|
141
internal/query/projection/organization_settings.go
Normal file
141
internal/query/projection/organization_settings.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
old_handler "github.com/zitadel/zitadel/internal/eventstore/handler"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
settings "github.com/zitadel/zitadel/internal/repository/organization_settings"
|
||||
)
|
||||
|
||||
const (
|
||||
OrganizationSettingsTable = "projections.organization_settings"
|
||||
OrganizationSettingsIDCol = "id"
|
||||
OrganizationSettingsCreationDateCol = "creation_date"
|
||||
OrganizationSettingsChangeDateCol = "change_date"
|
||||
OrganizationSettingsResourceOwnerCol = "resource_owner"
|
||||
OrganizationSettingsInstanceIDCol = "instance_id"
|
||||
OrganizationSettingsSequenceCol = "sequence"
|
||||
OrganizationSettingsOrganizationScopedUsernamesCol = "organization_scoped_usernames"
|
||||
)
|
||||
|
||||
type organizationSettingsProjection struct{}
|
||||
|
||||
func newOrganizationSettingsProjection(ctx context.Context, config handler.Config) *handler.Handler {
|
||||
return handler.NewHandler(ctx, &config, new(organizationSettingsProjection))
|
||||
}
|
||||
|
||||
func (*organizationSettingsProjection) Name() string {
|
||||
return OrganizationSettingsTable
|
||||
}
|
||||
|
||||
func (*organizationSettingsProjection) Init() *old_handler.Check {
|
||||
return handler.NewTableCheck(
|
||||
handler.NewTable([]*handler.InitColumn{
|
||||
handler.NewColumn(OrganizationSettingsIDCol, handler.ColumnTypeText),
|
||||
handler.NewColumn(OrganizationSettingsCreationDateCol, handler.ColumnTypeTimestamp),
|
||||
handler.NewColumn(OrganizationSettingsChangeDateCol, handler.ColumnTypeTimestamp),
|
||||
handler.NewColumn(OrganizationSettingsResourceOwnerCol, handler.ColumnTypeText),
|
||||
handler.NewColumn(OrganizationSettingsInstanceIDCol, handler.ColumnTypeText),
|
||||
handler.NewColumn(OrganizationSettingsSequenceCol, handler.ColumnTypeInt64),
|
||||
handler.NewColumn(OrganizationSettingsOrganizationScopedUsernamesCol, handler.ColumnTypeBool),
|
||||
},
|
||||
handler.NewPrimaryKey(OrganizationSettingsInstanceIDCol, OrganizationSettingsResourceOwnerCol, OrganizationSettingsIDCol),
|
||||
handler.WithIndex(handler.NewIndex("resource_owner", []string{OrganizationSettingsResourceOwnerCol})),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (p *organizationSettingsProjection) Reducers() []handler.AggregateReducer {
|
||||
return []handler.AggregateReducer{
|
||||
{
|
||||
Aggregate: settings.AggregateType,
|
||||
EventReducers: []handler.EventReducer{
|
||||
{
|
||||
Event: settings.OrganizationSettingsSetEventType,
|
||||
Reduce: p.reduceOrganizationSettingsSet,
|
||||
},
|
||||
{
|
||||
Event: settings.OrganizationSettingsRemovedEventType,
|
||||
Reduce: p.reduceOrganizationSettingsRemoved,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Aggregate: org.AggregateType,
|
||||
EventReducers: []handler.EventReducer{
|
||||
{
|
||||
Event: org.OrgRemovedEventType,
|
||||
Reduce: p.reduceOrgRemoved,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Aggregate: instance.AggregateType,
|
||||
EventReducers: []handler.EventReducer{
|
||||
{
|
||||
Event: instance.InstanceRemovedEventType,
|
||||
Reduce: reduceInstanceRemovedHelper(OrganizationSettingsInstanceIDCol),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *organizationSettingsProjection) reduceOrganizationSettingsSet(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, err := assertEvent[*settings.OrganizationSettingsSetEvent](event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return handler.NewUpsertStatement(e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(OrganizationSettingsInstanceIDCol, e.Aggregate().InstanceID),
|
||||
handler.NewCol(OrganizationSettingsResourceOwnerCol, e.Aggregate().ResourceOwner),
|
||||
handler.NewCol(OrganizationSettingsIDCol, e.Aggregate().ID),
|
||||
},
|
||||
[]handler.Column{
|
||||
handler.NewCol(OrganizationSettingsInstanceIDCol, e.Aggregate().InstanceID),
|
||||
handler.NewCol(OrganizationSettingsResourceOwnerCol, e.Aggregate().ResourceOwner),
|
||||
handler.NewCol(OrganizationSettingsIDCol, e.Aggregate().ID),
|
||||
handler.NewCol(OrganizationSettingsCreationDateCol, handler.OnlySetValueOnInsert(OrganizationSettingsTable, e.CreationDate())),
|
||||
handler.NewCol(OrganizationSettingsChangeDateCol, e.CreationDate()),
|
||||
handler.NewCol(OrganizationSettingsSequenceCol, e.Sequence()),
|
||||
handler.NewCol(OrganizationSettingsOrganizationScopedUsernamesCol, e.OrganizationScopedUsernames),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *organizationSettingsProjection) reduceOrganizationSettingsRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, err := assertEvent[*settings.OrganizationSettingsRemovedEvent](event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return handler.NewDeleteStatement(e,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(OrganizationSettingsInstanceIDCol, e.Aggregate().InstanceID),
|
||||
handler.NewCond(OrganizationSettingsResourceOwnerCol, e.Aggregate().ResourceOwner),
|
||||
handler.NewCond(OrganizationSettingsIDCol, e.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *organizationSettingsProjection) reduceOrgRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, err := assertEvent[*org.OrgRemovedEvent](event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return handler.NewDeleteStatement(
|
||||
e,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(OrganizationSettingsInstanceIDCol, e.Aggregate().InstanceID),
|
||||
handler.NewCond(OrganizationSettingsResourceOwnerCol, e.Aggregate().ResourceOwner),
|
||||
handler.NewCond(OrganizationSettingsIDCol, e.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
}
|
154
internal/query/projection/organization_settings_test.go
Normal file
154
internal/query/projection/organization_settings_test.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
settings "github.com/zitadel/zitadel/internal/repository/organization_settings"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
func TestOrganizationSettingsProjection_reduces(t *testing.T) {
|
||||
type args struct {
|
||||
event func(t *testing.T) eventstore.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
reduce func(event eventstore.Event) (*handler.Statement, error)
|
||||
want wantReduce
|
||||
}{
|
||||
{
|
||||
name: "reduce organization settings set",
|
||||
args: args{
|
||||
event: getEvent(
|
||||
testEvent(
|
||||
settings.OrganizationSettingsSetEventType,
|
||||
settings.AggregateType,
|
||||
[]byte(`{"organizationScopedUsernames": true}`),
|
||||
), eventstore.GenericEventMapper[settings.OrganizationSettingsSetEvent],
|
||||
),
|
||||
},
|
||||
reduce: (&organizationSettingsProjection{}).reduceOrganizationSettingsSet,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("organization_settings"),
|
||||
sequence: 15,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.organization_settings (instance_id, resource_owner, id, creation_date, change_date, sequence, organization_scoped_usernames) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (instance_id, resource_owner, id) DO UPDATE SET (creation_date, change_date, sequence, organization_scoped_usernames) = (projections.organization_settings.creation_date, EXCLUDED.change_date, EXCLUDED.sequence, EXCLUDED.organization_scoped_usernames)",
|
||||
expectedArgs: []interface{}{
|
||||
"instance-id",
|
||||
"ro-id",
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduce organization settings removed",
|
||||
args: args{
|
||||
event: getEvent(
|
||||
testEvent(
|
||||
settings.OrganizationSettingsRemovedEventType,
|
||||
settings.AggregateType,
|
||||
[]byte(`{}`),
|
||||
), eventstore.GenericEventMapper[settings.OrganizationSettingsRemovedEvent],
|
||||
),
|
||||
},
|
||||
reduce: (&organizationSettingsProjection{}).reduceOrganizationSettingsRemoved,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("organization_settings"),
|
||||
sequence: 15,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.organization_settings WHERE (instance_id = $1) AND (resource_owner = $2) AND (id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"instance-id",
|
||||
"ro-id",
|
||||
"agg-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceOrgRemoved",
|
||||
args: args{
|
||||
event: getEvent(
|
||||
testEvent(
|
||||
org.OrgRemovedEventType,
|
||||
org.AggregateType,
|
||||
nil,
|
||||
), org.OrgRemovedEventMapper),
|
||||
},
|
||||
reduce: (&organizationSettingsProjection{}).reduceOrgRemoved,
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("org"),
|
||||
sequence: 15,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.organization_settings WHERE (instance_id = $1) AND (resource_owner = $2) AND (id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"instance-id",
|
||||
"ro-id",
|
||||
"agg-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "instance reduceInstanceRemoved",
|
||||
args: args{
|
||||
event: getEvent(
|
||||
testEvent(
|
||||
instance.InstanceRemovedEventType,
|
||||
instance.AggregateType,
|
||||
nil,
|
||||
), instance.InstanceRemovedEventMapper),
|
||||
},
|
||||
reduce: reduceInstanceRemovedHelper(OrganizationSettingsInstanceIDCol),
|
||||
want: wantReduce{
|
||||
aggregateType: eventstore.AggregateType("instance"),
|
||||
sequence: 15,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.organization_settings WHERE (instance_id = $1)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
event := baseEvent(t)
|
||||
got, err := tt.reduce(event)
|
||||
if ok := zerrors.IsErrorInvalidArgument(err); !ok {
|
||||
t.Errorf("no wrong event mapping: %v, got: %v", err, got)
|
||||
}
|
||||
|
||||
event = tt.args.event(t)
|
||||
got, err = tt.reduce(event)
|
||||
assertReduce(t, got, err, OrganizationSettingsTable, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
@@ -87,6 +87,7 @@ var (
|
||||
WebKeyProjection *handler.Handler
|
||||
DebugEventsProjection *handler.Handler
|
||||
HostedLoginTranslationProjection *handler.Handler
|
||||
OrganizationSettingsProjection *handler.Handler
|
||||
|
||||
ProjectGrantFields *handler.FieldHandler
|
||||
OrgDomainVerifiedFields *handler.FieldHandler
|
||||
@@ -181,6 +182,7 @@ func Create(ctx context.Context, sqlClient *database.DB, es handler.EventStore,
|
||||
WebKeyProjection = newWebKeyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["web_keys"]))
|
||||
DebugEventsProjection = newDebugEventsProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["debug_events"]))
|
||||
HostedLoginTranslationProjection = newHostedLoginTranslationProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["hosted_login_translation"]))
|
||||
OrganizationSettingsProjection = newOrganizationSettingsProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["organization_settings"]))
|
||||
|
||||
ProjectGrantFields = newFillProjectGrantFields(applyCustomConfig(projectionConfig, config.Customizations[fieldsProjectGrant]))
|
||||
OrgDomainVerifiedFields = newFillOrgDomainVerifiedFields(applyCustomConfig(projectionConfig, config.Customizations[fieldsOrgDomainVerified]))
|
||||
@@ -360,5 +362,6 @@ func newProjectionsList() {
|
||||
WebKeyProjection,
|
||||
DebugEventsProjection,
|
||||
HostedLoginTranslationProjection,
|
||||
OrganizationSettingsProjection,
|
||||
}
|
||||
}
|
||||
|
@@ -275,13 +275,13 @@ func OrgReactivatedEventMapper(event eventstore.Event) (eventstore.Event, error)
|
||||
}
|
||||
|
||||
type OrgRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
name string
|
||||
usernames []string
|
||||
loginMustBeDomain bool
|
||||
domains []string
|
||||
externalIDPs []*domain.UserIDPLink
|
||||
samlEntityIDs []string
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
name string
|
||||
usernames []string
|
||||
organizationScopedUsernames bool
|
||||
domains []string
|
||||
externalIDPs []*domain.UserIDPLink
|
||||
samlEntityIDs []string
|
||||
}
|
||||
|
||||
func (e *OrgRemovedEvent) Payload() interface{} {
|
||||
@@ -293,7 +293,7 @@ func (e *OrgRemovedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
NewRemoveOrgNameUniqueConstraint(e.name),
|
||||
}
|
||||
for _, name := range e.usernames {
|
||||
constraints = append(constraints, user.NewRemoveUsernameUniqueConstraint(name, e.Aggregate().ID, e.loginMustBeDomain))
|
||||
constraints = append(constraints, user.NewRemoveUsernameUniqueConstraint(name, e.Aggregate().ID, e.organizationScopedUsernames))
|
||||
}
|
||||
for _, domain := range e.domains {
|
||||
constraints = append(constraints, NewRemoveOrgDomainUniqueConstraint(domain))
|
||||
@@ -314,19 +314,19 @@ func (e *OrgRemovedEvent) Fields() []*eventstore.FieldOperation {
|
||||
}
|
||||
}
|
||||
|
||||
func NewOrgRemovedEvent(ctx context.Context, aggregate *eventstore.Aggregate, name string, usernames []string, loginMustBeDomain bool, domains []string, externalIDPs []*domain.UserIDPLink, samlEntityIDs []string) *OrgRemovedEvent {
|
||||
func NewOrgRemovedEvent(ctx context.Context, aggregate *eventstore.Aggregate, name string, usernames []string, organizationScopedUsernames bool, domains []string, externalIDPs []*domain.UserIDPLink, samlEntityIDs []string) *OrgRemovedEvent {
|
||||
return &OrgRemovedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
aggregate,
|
||||
OrgRemovedEventType,
|
||||
),
|
||||
name: name,
|
||||
usernames: usernames,
|
||||
domains: domains,
|
||||
externalIDPs: externalIDPs,
|
||||
samlEntityIDs: samlEntityIDs,
|
||||
loginMustBeDomain: loginMustBeDomain,
|
||||
name: name,
|
||||
usernames: usernames,
|
||||
domains: domains,
|
||||
externalIDPs: externalIDPs,
|
||||
samlEntityIDs: samlEntityIDs,
|
||||
organizationScopedUsernames: organizationScopedUsernames,
|
||||
}
|
||||
}
|
||||
|
||||
|
23
internal/repository/organization_settings/aggregate.go
Normal file
23
internal/repository/organization_settings/aggregate.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package organization_settings
|
||||
|
||||
import "github.com/zitadel/zitadel/internal/eventstore"
|
||||
|
||||
const (
|
||||
AggregateType = "organization_settings"
|
||||
AggregateVersion = "v1"
|
||||
)
|
||||
|
||||
type Aggregate struct {
|
||||
eventstore.Aggregate
|
||||
}
|
||||
|
||||
func NewAggregate(id, resourceOwner string) *Aggregate {
|
||||
return &Aggregate{
|
||||
Aggregate: eventstore.Aggregate{
|
||||
Type: AggregateType,
|
||||
Version: AggregateVersion,
|
||||
ID: id,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
8
internal/repository/organization_settings/eventstore.go
Normal file
8
internal/repository/organization_settings/eventstore.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package organization_settings
|
||||
|
||||
import "github.com/zitadel/zitadel/internal/eventstore"
|
||||
|
||||
func init() {
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, OrganizationSettingsSetEventType, eventstore.GenericEventMapper[OrganizationSettingsSetEvent])
|
||||
eventstore.RegisterFilterEventMapper(AggregateType, OrganizationSettingsRemovedEventType, eventstore.GenericEventMapper[OrganizationSettingsRemovedEvent])
|
||||
}
|
96
internal/repository/organization_settings/organization.go
Normal file
96
internal/repository/organization_settings/organization.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package organization_settings
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
)
|
||||
|
||||
const (
|
||||
organizationSettingsPrefix = "settings.organization."
|
||||
OrganizationSettingsSetEventType = organizationSettingsPrefix + "set"
|
||||
OrganizationSettingsRemovedEventType = organizationSettingsPrefix + "removed"
|
||||
)
|
||||
|
||||
type OrganizationSettingsSetEvent struct {
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
|
||||
OrganizationScopedUsernames bool `json:"organizationScopedUsernames,omitempty"`
|
||||
oldOrganizationScopedUsernames bool
|
||||
usernameChanges []string
|
||||
}
|
||||
|
||||
func (e *OrganizationSettingsSetEvent) SetBaseEvent(b *eventstore.BaseEvent) {
|
||||
e.BaseEvent = b
|
||||
}
|
||||
|
||||
func (e *OrganizationSettingsSetEvent) Payload() any {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *OrganizationSettingsSetEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
if len(e.usernameChanges) == 0 || e.oldOrganizationScopedUsernames == e.OrganizationScopedUsernames {
|
||||
return []*eventstore.UniqueConstraint{}
|
||||
}
|
||||
changes := make([]*eventstore.UniqueConstraint, len(e.usernameChanges)*2)
|
||||
for i, username := range e.usernameChanges {
|
||||
changes[i*2] = user.NewRemoveUsernameUniqueConstraint(username, e.Aggregate().ResourceOwner, e.oldOrganizationScopedUsernames)
|
||||
changes[i*2+1] = user.NewAddUsernameUniqueConstraint(username, e.Aggregate().ResourceOwner, e.OrganizationScopedUsernames)
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
func NewOrganizationSettingsAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
usernameChanges []string,
|
||||
organizationScopedUsernames bool,
|
||||
oldOrganizationScopedUsernames bool,
|
||||
) *OrganizationSettingsSetEvent {
|
||||
return &OrganizationSettingsSetEvent{
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx, aggregate, OrganizationSettingsSetEventType,
|
||||
),
|
||||
OrganizationScopedUsernames: organizationScopedUsernames,
|
||||
oldOrganizationScopedUsernames: oldOrganizationScopedUsernames,
|
||||
usernameChanges: usernameChanges,
|
||||
}
|
||||
}
|
||||
|
||||
type OrganizationSettingsRemovedEvent struct {
|
||||
*eventstore.BaseEvent `json:"-"`
|
||||
|
||||
organizationScopedUsernames bool
|
||||
oldOrganizationScopedUsernames bool
|
||||
usernameChanges []string
|
||||
}
|
||||
|
||||
func (e *OrganizationSettingsRemovedEvent) SetBaseEvent(b *eventstore.BaseEvent) {
|
||||
e.BaseEvent = b
|
||||
}
|
||||
|
||||
func (e *OrganizationSettingsRemovedEvent) Payload() any {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *OrganizationSettingsRemovedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return user.NewUsernameUniqueConstraints(e.usernameChanges, e.Aggregate().ResourceOwner, e.organizationScopedUsernames, e.oldOrganizationScopedUsernames)
|
||||
}
|
||||
|
||||
func NewOrganizationSettingsRemovedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
usernameChanges []string,
|
||||
organizationScopedUsernames bool,
|
||||
oldOrganizationScopedUsernames bool,
|
||||
) *OrganizationSettingsRemovedEvent {
|
||||
return &OrganizationSettingsRemovedEvent{
|
||||
BaseEvent: eventstore.NewBaseEventForPush(
|
||||
ctx, aggregate, OrganizationSettingsRemovedEventType,
|
||||
),
|
||||
organizationScopedUsernames: organizationScopedUsernames,
|
||||
oldOrganizationScopedUsernames: oldOrganizationScopedUsernames,
|
||||
usernameChanges: usernameChanges,
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ package policy
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@@ -122,6 +123,10 @@ func DomainPolicyChangedEventMapper(event eventstore.Event) (eventstore.Event, e
|
||||
|
||||
type DomainPolicyRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
usernameChanges []string
|
||||
userLoginMustBeDomain bool
|
||||
oldUserLoginMustBeDomain bool
|
||||
}
|
||||
|
||||
func (e *DomainPolicyRemovedEvent) Payload() interface{} {
|
||||
@@ -129,7 +134,7 @@ func (e *DomainPolicyRemovedEvent) Payload() interface{} {
|
||||
}
|
||||
|
||||
func (e *DomainPolicyRemovedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return nil
|
||||
return user.NewUsernameUniqueConstraints(e.usernameChanges, e.Aggregate().ResourceOwner, e.userLoginMustBeDomain, e.oldUserLoginMustBeDomain)
|
||||
}
|
||||
|
||||
func NewDomainPolicyRemovedEvent(base *eventstore.BaseEvent) *DomainPolicyRemovedEvent {
|
||||
@@ -143,3 +148,9 @@ func DomainPolicyRemovedEventMapper(event eventstore.Event) (eventstore.Event, e
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *DomainPolicyRemovedEvent) AddUniqueConstraintChanges(usernameChanges []string, userLoginMustBeDomain, oldUserLoginMustBeDomain bool) {
|
||||
e.usernameChanges = usernameChanges
|
||||
e.userLoginMustBeDomain = userLoginMustBeDomain
|
||||
e.oldUserLoginMustBeDomain = oldUserLoginMustBeDomain
|
||||
}
|
||||
|
@@ -31,8 +31,8 @@ const (
|
||||
type HumanAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
userLoginMustBeDomain bool
|
||||
UserName string `json:"userName"`
|
||||
orgScopedUsername bool
|
||||
|
||||
FirstName string `json:"firstName,omitempty"`
|
||||
LastName string `json:"lastName,omitempty"`
|
||||
@@ -63,7 +63,7 @@ func (e *HumanAddedEvent) Payload() interface{} {
|
||||
}
|
||||
|
||||
func (e *HumanAddedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return []*eventstore.UniqueConstraint{NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.userLoginMustBeDomain)}
|
||||
return []*eventstore.UniqueConstraint{NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.orgScopedUsername)}
|
||||
}
|
||||
|
||||
func (e *HumanAddedEvent) AddAddressData(
|
||||
@@ -106,7 +106,7 @@ func NewHumanAddedEvent(
|
||||
preferredLanguage language.Tag,
|
||||
gender domain.Gender,
|
||||
emailAddress domain.EmailAddress,
|
||||
userLoginMustBeDomain bool,
|
||||
orgScopedUsername bool,
|
||||
) *HumanAddedEvent {
|
||||
return &HumanAddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@@ -114,15 +114,15 @@ func NewHumanAddedEvent(
|
||||
aggregate,
|
||||
HumanAddedType,
|
||||
),
|
||||
UserName: userName,
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
NickName: nickName,
|
||||
DisplayName: displayName,
|
||||
PreferredLanguage: preferredLanguage,
|
||||
Gender: gender,
|
||||
EmailAddress: emailAddress,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
UserName: userName,
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
NickName: nickName,
|
||||
DisplayName: displayName,
|
||||
PreferredLanguage: preferredLanguage,
|
||||
Gender: gender,
|
||||
EmailAddress: emailAddress,
|
||||
orgScopedUsername: orgScopedUsername,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,22 +139,24 @@ func HumanAddedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
}
|
||||
|
||||
type HumanRegisteredEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
UserName string `json:"userName"`
|
||||
userLoginMustBeDomain bool
|
||||
FirstName string `json:"firstName,omitempty"`
|
||||
LastName string `json:"lastName,omitempty"`
|
||||
NickName string `json:"nickName,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
PreferredLanguage language.Tag `json:"preferredLanguage,omitempty"`
|
||||
Gender domain.Gender `json:"gender,omitempty"`
|
||||
EmailAddress domain.EmailAddress `json:"email,omitempty"`
|
||||
PhoneNumber domain.PhoneNumber `json:"phone,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
Locality string `json:"locality,omitempty"`
|
||||
PostalCode string `json:"postalCode,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
StreetAddress string `json:"streetAddress,omitempty"`
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
orgScopedUsername bool
|
||||
|
||||
FirstName string `json:"firstName,omitempty"`
|
||||
LastName string `json:"lastName,omitempty"`
|
||||
NickName string `json:"nickName,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
PreferredLanguage language.Tag `json:"preferredLanguage,omitempty"`
|
||||
Gender domain.Gender `json:"gender,omitempty"`
|
||||
EmailAddress domain.EmailAddress `json:"email,omitempty"`
|
||||
PhoneNumber domain.PhoneNumber `json:"phone,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
Locality string `json:"locality,omitempty"`
|
||||
PostalCode string `json:"postalCode,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
StreetAddress string `json:"streetAddress,omitempty"`
|
||||
|
||||
// New events only use EncodedHash. However, the secret field
|
||||
// is preserved to handle events older than the switch to Passwap.
|
||||
@@ -170,7 +172,7 @@ func (e *HumanRegisteredEvent) Payload() interface{} {
|
||||
}
|
||||
|
||||
func (e *HumanRegisteredEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return []*eventstore.UniqueConstraint{NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.userLoginMustBeDomain)}
|
||||
return []*eventstore.UniqueConstraint{NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.orgScopedUsername)}
|
||||
}
|
||||
|
||||
func (e *HumanRegisteredEvent) AddAddressData(
|
||||
@@ -213,7 +215,7 @@ func NewHumanRegisteredEvent(
|
||||
preferredLanguage language.Tag,
|
||||
gender domain.Gender,
|
||||
emailAddress domain.EmailAddress,
|
||||
userLoginMustBeDomain bool,
|
||||
orgScopedUsername bool,
|
||||
userAgentID string,
|
||||
) *HumanRegisteredEvent {
|
||||
return &HumanRegisteredEvent{
|
||||
@@ -222,16 +224,16 @@ func NewHumanRegisteredEvent(
|
||||
aggregate,
|
||||
HumanRegisteredType,
|
||||
),
|
||||
UserName: userName,
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
NickName: nickName,
|
||||
DisplayName: displayName,
|
||||
PreferredLanguage: preferredLanguage,
|
||||
Gender: gender,
|
||||
EmailAddress: emailAddress,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
UserAgentID: userAgentID,
|
||||
UserName: userName,
|
||||
FirstName: firstName,
|
||||
LastName: lastName,
|
||||
NickName: nickName,
|
||||
DisplayName: displayName,
|
||||
PreferredLanguage: preferredLanguage,
|
||||
Gender: gender,
|
||||
EmailAddress: emailAddress,
|
||||
orgScopedUsername: orgScopedUsername,
|
||||
UserAgentID: userAgentID,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,8 +17,8 @@ const (
|
||||
type MachineAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
userLoginMustBeDomain bool
|
||||
UserName string `json:"userName"`
|
||||
orgScopedUsername bool
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
@@ -30,7 +30,7 @@ func (e *MachineAddedEvent) Payload() interface{} {
|
||||
}
|
||||
|
||||
func (e *MachineAddedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return []*eventstore.UniqueConstraint{NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.userLoginMustBeDomain)}
|
||||
return []*eventstore.UniqueConstraint{NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.orgScopedUsername)}
|
||||
}
|
||||
|
||||
func NewMachineAddedEvent(
|
||||
@@ -39,7 +39,7 @@ func NewMachineAddedEvent(
|
||||
userName,
|
||||
name,
|
||||
description string,
|
||||
userLoginMustBeDomain bool,
|
||||
orgScopedUsername bool,
|
||||
accessTokenType domain.OIDCTokenType,
|
||||
) *MachineAddedEvent {
|
||||
return &MachineAddedEvent{
|
||||
@@ -48,11 +48,11 @@ func NewMachineAddedEvent(
|
||||
aggregate,
|
||||
MachineAddedEventType,
|
||||
),
|
||||
UserName: userName,
|
||||
Name: name,
|
||||
Description: description,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
AccessTokenType: accessTokenType,
|
||||
UserName: userName,
|
||||
Name: name,
|
||||
Description: description,
|
||||
orgScopedUsername: orgScopedUsername,
|
||||
AccessTokenType: accessTokenType,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -27,9 +27,9 @@ const (
|
||||
UserUserNameChangedType = userEventTypePrefix + "username.changed"
|
||||
)
|
||||
|
||||
func NewAddUsernameUniqueConstraint(userName, resourceOwner string, userLoginMustBeDomain bool) *eventstore.UniqueConstraint {
|
||||
func NewAddUsernameUniqueConstraint(userName, resourceOwner string, orgScopedUsername bool) *eventstore.UniqueConstraint {
|
||||
uniqueUserName := userName
|
||||
if userLoginMustBeDomain {
|
||||
if orgScopedUsername {
|
||||
uniqueUserName = userName + resourceOwner
|
||||
}
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
@@ -38,9 +38,9 @@ func NewAddUsernameUniqueConstraint(userName, resourceOwner string, userLoginMus
|
||||
"Errors.User.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveUsernameUniqueConstraint(userName, resourceOwner string, userLoginMustBeDomain bool) *eventstore.UniqueConstraint {
|
||||
func NewRemoveUsernameUniqueConstraint(userName, resourceOwner string, orgScopedUsername bool) *eventstore.UniqueConstraint {
|
||||
uniqueUserName := userName
|
||||
if userLoginMustBeDomain {
|
||||
if orgScopedUsername {
|
||||
uniqueUserName = userName + resourceOwner
|
||||
}
|
||||
return eventstore.NewRemoveUniqueConstraint(
|
||||
@@ -48,6 +48,18 @@ func NewRemoveUsernameUniqueConstraint(userName, resourceOwner string, userLogin
|
||||
uniqueUserName)
|
||||
}
|
||||
|
||||
func NewUsernameUniqueConstraints(usernameChanges []string, resourceOwner string, orgScopedUsername, oldOrgScopedUsername bool) []*eventstore.UniqueConstraint {
|
||||
if len(usernameChanges) == 0 || oldOrgScopedUsername == orgScopedUsername {
|
||||
return []*eventstore.UniqueConstraint{}
|
||||
}
|
||||
changes := make([]*eventstore.UniqueConstraint, len(usernameChanges)*2)
|
||||
for i, username := range usernameChanges {
|
||||
changes[i*2] = NewRemoveUsernameUniqueConstraint(username, resourceOwner, oldOrgScopedUsername)
|
||||
changes[i*2+1] = NewAddUsernameUniqueConstraint(username, resourceOwner, orgScopedUsername)
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
type UserLockedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
}
|
||||
@@ -165,7 +177,7 @@ type UserRemovedEvent struct {
|
||||
|
||||
userName string
|
||||
externalIDPs []*domain.UserIDPLink
|
||||
loginMustBeDomain bool
|
||||
orgScopedUsername bool
|
||||
}
|
||||
|
||||
func (e *UserRemovedEvent) Payload() interface{} {
|
||||
@@ -175,7 +187,7 @@ func (e *UserRemovedEvent) Payload() interface{} {
|
||||
func (e *UserRemovedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
events := make([]*eventstore.UniqueConstraint, 0)
|
||||
if e.userName != "" {
|
||||
events = append(events, NewRemoveUsernameUniqueConstraint(e.userName, e.Aggregate().ResourceOwner, e.loginMustBeDomain))
|
||||
events = append(events, NewRemoveUsernameUniqueConstraint(e.userName, e.Aggregate().ResourceOwner, e.orgScopedUsername))
|
||||
}
|
||||
for _, idp := range e.externalIDPs {
|
||||
events = append(events, NewRemoveUserIDPLinkUniqueConstraint(idp.IDPConfigID, idp.ExternalUserID))
|
||||
@@ -188,7 +200,7 @@ func NewUserRemovedEvent(
|
||||
aggregate *eventstore.Aggregate,
|
||||
userName string,
|
||||
externalIDPs []*domain.UserIDPLink,
|
||||
userLoginMustBeDomain bool,
|
||||
orgScopedUsername bool,
|
||||
) *UserRemovedEvent {
|
||||
return &UserRemovedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@@ -198,7 +210,7 @@ func NewUserRemovedEvent(
|
||||
),
|
||||
userName: userName,
|
||||
externalIDPs: externalIDPs,
|
||||
loginMustBeDomain: userLoginMustBeDomain,
|
||||
orgScopedUsername: orgScopedUsername,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,10 +405,10 @@ func UserTokenRemovedEventMapper(event eventstore.Event) (eventstore.Event, erro
|
||||
type DomainClaimedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
oldUserName string
|
||||
userLoginMustBeDomain bool
|
||||
UserName string `json:"userName"`
|
||||
TriggeredAtOrigin string `json:"triggerOrigin,omitempty"`
|
||||
oldUserName string
|
||||
orgScopedUsername bool
|
||||
}
|
||||
|
||||
func (e *DomainClaimedEvent) Payload() interface{} {
|
||||
@@ -405,8 +417,8 @@ func (e *DomainClaimedEvent) Payload() interface{} {
|
||||
|
||||
func (e *DomainClaimedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
return []*eventstore.UniqueConstraint{
|
||||
NewRemoveUsernameUniqueConstraint(e.oldUserName, e.Aggregate().ResourceOwner, e.userLoginMustBeDomain),
|
||||
NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.userLoginMustBeDomain),
|
||||
NewRemoveUsernameUniqueConstraint(e.oldUserName, e.Aggregate().ResourceOwner, e.orgScopedUsername),
|
||||
NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.orgScopedUsername),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +431,7 @@ func NewDomainClaimedEvent(
|
||||
aggregate *eventstore.Aggregate,
|
||||
userName,
|
||||
oldUserName string,
|
||||
userLoginMustBeDomain bool,
|
||||
orgScopedUsername bool,
|
||||
) *DomainClaimedEvent {
|
||||
return &DomainClaimedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@@ -427,10 +439,10 @@ func NewDomainClaimedEvent(
|
||||
aggregate,
|
||||
UserDomainClaimedType,
|
||||
),
|
||||
UserName: userName,
|
||||
oldUserName: oldUserName,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
TriggeredAtOrigin: http.DomainContext(ctx).Origin(),
|
||||
UserName: userName,
|
||||
oldUserName: oldUserName,
|
||||
orgScopedUsername: orgScopedUsername,
|
||||
TriggeredAtOrigin: http.DomainContext(ctx).Origin(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,10 +492,11 @@ func DomainClaimedSentEventMapper(event eventstore.Event) (eventstore.Event, err
|
||||
type UsernameChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
oldUserName string
|
||||
userLoginMustBeDomain bool
|
||||
oldUserLoginMustBeDomain bool
|
||||
UserName string `json:"userName"`
|
||||
oldUserName string
|
||||
userLoginMustBeDomain bool
|
||||
oldUserLoginMustBeDomain bool
|
||||
organizationScopedUsernames bool
|
||||
}
|
||||
|
||||
func (e *UsernameChangedEvent) Payload() interface{} {
|
||||
@@ -491,9 +504,20 @@ func (e *UsernameChangedEvent) Payload() interface{} {
|
||||
}
|
||||
|
||||
func (e *UsernameChangedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
||||
newSetting := e.userLoginMustBeDomain || e.organizationScopedUsernames
|
||||
oldSetting := e.oldUserLoginMustBeDomain || e.organizationScopedUsernames
|
||||
|
||||
// changes only necessary if username changed or setting for usernames changed
|
||||
// if user login must be domain is set, there is a possibility that the username changes
|
||||
// organization scoped usernames are included here so that the unique constraint only gets changed if necessary
|
||||
if e.oldUserName == e.UserName &&
|
||||
newSetting == oldSetting {
|
||||
return []*eventstore.UniqueConstraint{}
|
||||
}
|
||||
|
||||
return []*eventstore.UniqueConstraint{
|
||||
NewRemoveUsernameUniqueConstraint(e.oldUserName, e.Aggregate().ResourceOwner, e.oldUserLoginMustBeDomain),
|
||||
NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, e.userLoginMustBeDomain),
|
||||
NewRemoveUsernameUniqueConstraint(e.oldUserName, e.Aggregate().ResourceOwner, oldSetting),
|
||||
NewAddUsernameUniqueConstraint(e.UserName, e.Aggregate().ResourceOwner, newSetting),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,6 +527,7 @@ func NewUsernameChangedEvent(
|
||||
oldUserName,
|
||||
newUserName string,
|
||||
userLoginMustBeDomain bool,
|
||||
organizationScopedUsernames bool,
|
||||
opts ...UsernameChangedEventOption,
|
||||
) *UsernameChangedEvent {
|
||||
event := &UsernameChangedEvent{
|
||||
@@ -511,10 +536,11 @@ func NewUsernameChangedEvent(
|
||||
aggregate,
|
||||
UserUserNameChangedType,
|
||||
),
|
||||
UserName: newUserName,
|
||||
oldUserName: oldUserName,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
oldUserLoginMustBeDomain: userLoginMustBeDomain,
|
||||
UserName: newUserName,
|
||||
oldUserName: oldUserName,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
oldUserLoginMustBeDomain: userLoginMustBeDomain,
|
||||
organizationScopedUsernames: organizationScopedUsernames,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(event)
|
||||
@@ -526,9 +552,9 @@ type UsernameChangedEventOption func(*UsernameChangedEvent)
|
||||
|
||||
// UsernameChangedEventWithPolicyChange signals that the change occurs because of / during a domain policy change
|
||||
// (will ensure the unique constraint change is handled correctly)
|
||||
func UsernameChangedEventWithPolicyChange() UsernameChangedEventOption {
|
||||
func UsernameChangedEventWithPolicyChange(oldUserLoginMustBeDomain bool) UsernameChangedEventOption {
|
||||
return func(e *UsernameChangedEvent) {
|
||||
e.oldUserLoginMustBeDomain = !e.userLoginMustBeDomain
|
||||
e.oldUserLoginMustBeDomain = oldUserLoginMustBeDomain
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user