feat: Iam projection (#3074)

* feat: implement projection for iam and clean up code

* feat: add migration

* fix: remove unused tests

* fix: handler
This commit is contained in:
Fabi 2022-01-21 08:52:12 +01:00 committed by GitHub
parent 44d78df4d4
commit b363ddd707
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 375 additions and 2267 deletions

View File

@ -2,6 +2,7 @@ package spooler
import (
"database/sql"
"github.com/caos/zitadel/internal/command"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/eventstore/v1"

View File

@ -73,7 +73,6 @@ func Create(config Config, authZ authz.Config, q *query.Queries, authZRepo *auth
}
api.verifier = authz.Start(&repo)
api.health = authZRepo
api.auth = authRepo
api.admin = adminRepo
api.grpcServer = server.CreateServer(api.verifier, authZ, sd.DefaultLanguage)

View File

@ -8,6 +8,7 @@ import (
"github.com/caos/zitadel/internal/config/types"
v1 "github.com/caos/zitadel/internal/eventstore/v1"
"github.com/caos/zitadel/internal/eventstore/v1/query"
query2 "github.com/caos/zitadel/internal/query"
)
type Configs map[string]*Config
@ -29,11 +30,11 @@ func (h *handler) Eventstore() v1.Eventstore {
return h.es
}
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, systemDefaults sd.SystemDefaults) []query.Handler {
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, systemDefaults sd.SystemDefaults, queries *query2.Queries) []query.Handler {
return []query.Handler{
newUser(
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
systemDefaults.IamID),
systemDefaults.IamID, queries),
newUserSession(
handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount, es}),
newToken(
@ -45,10 +46,10 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}),
newIDPProvider(
handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es},
systemDefaults),
systemDefaults, queries),
newExternalIDP(
handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es},
systemDefaults),
systemDefaults, queries),
newRefreshToken(handler{view, bulkLimit, configs.cycleDuration("RefreshToken"), errorCount, es}),
newOrgProjectMapping(handler{view, bulkLimit, configs.cycleDuration("OrgProjectMapping"), errorCount, es}),
}

View File

@ -2,13 +2,10 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_model "github.com/caos/zitadel/internal/org/model"
"github.com/caos/zitadel/internal/org/repository/view"
query2 "github.com/caos/zitadel/internal/query"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
@ -30,15 +27,18 @@ type IDPProvider struct {
handler
systemDefaults systemdefaults.SystemDefaults
subscription *v1.Subscription
queries *query2.Queries
}
func newIDPProvider(
h handler,
defaults systemdefaults.SystemDefaults,
queries *query2.Queries,
) *IDPProvider {
idpProvider := &IDPProvider{
handler: h,
systemDefaults: defaults,
queries: queries,
}
idpProvider.subscribe()
@ -120,7 +120,7 @@ func (i *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
if err != nil {
return err
}
config := new(iam_model.IDPConfig)
config := new(query2.IDP)
if event.AggregateID == i.systemDefaults.IamID {
config, err = i.getDefaultIDPConfig(context.TODO(), esConfig.IDPConfigID)
} else {
@ -145,7 +145,7 @@ func (i *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
}
func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) {
var config *iam_model.IDPConfig
var config *query2.IDP
if provider.IDPProviderType == int32(iam_model.IDPProviderTypeSystem) {
config, err = i.getDefaultIDPConfig(context.Background(), provider.IDPConfigID)
} else {
@ -158,10 +158,14 @@ func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err er
return nil
}
func (i *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *iam_model.IDPConfig) {
func (i *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, config *query2.IDP) {
provider.Name = config.Name
provider.StylingType = int32(config.StylingType)
provider.IDPConfigType = int32(config.Type)
if config.OIDCIDP != nil {
provider.IDPConfigType = int32(domain.IDPConfigTypeOIDC)
} else if config.JWTIDP != nil {
provider.IDPConfigType = int32(domain.IDPConfigTypeJWT)
}
provider.IDPState = int32(config.State)
}
@ -174,63 +178,10 @@ func (i *IDPProvider) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateIDPProviderSpoolerRunTimestamp)
}
func (i *IDPProvider) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, errors.ThrowNotFound(nil, "EVENT-2m9fS", "Errors.IDP.NotExisting")
func (i *IDPProvider) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*query2.IDP, error) {
return i.queries.IDPByIDAndResourceOwner(ctx, idpConfigID, aggregateID)
}
func (i *IDPProvider) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: es_models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !errors.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, errors.ThrowNotFound(nil, "EVENT-6m0fS", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *IDPProvider) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *IDPProvider) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, errors.ThrowNotFound(nil, "EVENT-49O0f", "Errors.IDP.NotExisting")
func (u *IDPProvider) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*query2.IDP, error) {
return u.queries.IDPByIDAndResourceOwner(ctx, idpConfigID, domain.IAMID)
}

View File

@ -2,20 +2,18 @@ package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_model "github.com/caos/zitadel/internal/org/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
query2 "github.com/caos/zitadel/internal/query"
user_repo "github.com/caos/zitadel/internal/repository/user"
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
@ -29,15 +27,18 @@ type User struct {
handler
iamID string
subscription *v1.Subscription
queries *query2.Queries
}
func newUser(
handler handler,
iamID string,
queries *query2.Queries,
) *User {
h := &User{
handler: handler,
iamID: iamID,
queries: queries,
}
h.subscribe()
@ -178,7 +179,7 @@ func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
if err != nil {
return err
}
policy := org.OrgIamPolicy
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
@ -210,7 +211,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *es_models.Event) error {
if err != nil {
return err
}
policy := org.OrgIamPolicy
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
@ -232,7 +233,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) error {
if err != nil {
return err
}
policy := org.OrgIamPolicy
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
@ -283,30 +284,6 @@ func (u *User) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, er
return org_es_model.OrgToModel(esOrg), nil
}
func (u *User) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && errors.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *User) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) {
existingIAM, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if existingIAM.DefaultOrgIAMPolicy == nil {
return nil, errors.ThrowNotFound(nil, "EVENT-3m9fs", "Errors.IAM.OrgIAMPolicy.NotExisting")
}
return existingIAM.DefaultOrgIAMPolicy, nil
func (u *User) getDefaultOrgIAMPolicy(ctx context.Context) (*query2.OrgIAMPolicy, error) {
return u.queries.DefaultOrgIAMPolicy(ctx)
}

View File

@ -2,6 +2,7 @@ package handler
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/domain"
@ -9,15 +10,12 @@ import (
"github.com/caos/zitadel/internal/eventstore/v1"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
org_model "github.com/caos/zitadel/internal/org/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/org/repository/view"
query2 "github.com/caos/zitadel/internal/query"
"github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model"
)
@ -30,15 +28,18 @@ type ExternalIDP struct {
handler
systemDefaults systemdefaults.SystemDefaults
subscription *v1.Subscription
queries *query2.Queries
}
func newExternalIDP(
handler handler,
defaults systemdefaults.SystemDefaults,
queries *query2.Queries,
) *ExternalIDP {
h := &ExternalIDP{
handler: handler,
systemDefaults: defaults,
queries: queries,
}
h.subscribe()
@ -125,7 +126,7 @@ func (i *ExternalIDP) processIdpConfig(event *es_models.Event) (err error) {
switch event.Type {
case iam_es_model.IDPConfigChanged, org_es_model.IDPConfigChanged:
configView := new(iam_view_model.IDPConfigView)
config := new(iam_model.IDPConfig)
config := new(query2.IDP)
if event.Type == iam_es_model.IDPConfigChanged {
configView.AppendEvent(iam_model.IDPProviderTypeSystem, event)
} else {
@ -165,7 +166,7 @@ func (i *ExternalIDP) fillData(externalIDP *usr_view_model.ExternalIDPView) erro
return nil
}
func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *iam_model.IDPConfig) {
func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView, config *query2.IDP) {
externalIDP.IDPName = config.Name
}
@ -178,63 +179,10 @@ func (i *ExternalIDP) OnSuccess() error {
return spooler.HandleSuccess(i.view.UpdateExternalIDPSpoolerRunTimestamp)
}
func (i *ExternalIDP) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := i.getOrgByID(ctx, aggregateID)
if err != nil {
return nil, err
}
if _, i := existing.GetIDP(idpConfigID); i != nil {
return i, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2m9fS", "Errors.Org.IdpNotExisting")
func (i *ExternalIDP) getOrgIDPConfig(ctx context.Context, aggregateID, idpConfigID string) (*query2.IDP, error) {
return i.queries.IDPByIDAndResourceOwner(ctx, idpConfigID, aggregateID)
}
func (i *ExternalIDP) getOrgByID(ctx context.Context, orgID string) (*org_model.Org, error) {
query, err := view.OrgByIDQuery(orgID, 0)
if err != nil {
return nil, err
}
esOrg := &org_es_model.Org{
ObjectRoot: es_models.ObjectRoot{
AggregateID: orgID,
},
}
err = es_sdk.Filter(ctx, i.Eventstore().FilterEvents, esOrg.AppendEvents, query)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if esOrg.Sequence == 0 {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-6m0fS", "Errors.Org.NotFound")
}
return org_es_model.OrgToModel(esOrg), nil
}
func (u *ExternalIDP) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &iam_es_model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
}
func (u *ExternalIDP) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
existing, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if _, existingIDP := existing.GetIDP(idpConfigID); existingIDP != nil {
return existingIDP, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-mmk5d", "Errors.IAM.IdpNotExisting")
func (i *ExternalIDP) getDefaultIDPConfig(ctx context.Context, idpConfigID string) (*query2.IDP, error) {
return i.queries.IDPByIDAndResourceOwner(ctx, idpConfigID, domain.IAMID)
}

View File

@ -79,7 +79,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
statikLoginFS, err := fs.NewWithNamespace("login")
logging.Log("CONFI-20opp").OnError(err).Panic("unable to start login statik dir")
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults)
spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, systemDefaults, queries)
userRepo := eventstore.UserRepo{
SearchLimit: conf.SearchLimit,

View File

@ -4,6 +4,7 @@ import (
"database/sql"
v1 "github.com/caos/zitadel/internal/eventstore/v1"
"github.com/caos/zitadel/internal/query"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/handler"
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
@ -18,12 +19,12 @@ type SpoolerConfig struct {
Handlers handler.Configs
}
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, client *sql.DB, systemDefaults sd.SystemDefaults) *spooler.Spooler {
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, client *sql.DB, systemDefaults sd.SystemDefaults, queries *query.Queries) *spooler.Spooler {
spoolerConfig := spooler.Config{
Eventstore: es,
Locker: &locker{dbClient: client},
ConcurrentWorkers: c.ConcurrentWorkers,
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, systemDefaults),
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, systemDefaults, queries),
}
spool := spoolerConfig.New()
spool.Start()

View File

@ -1,22 +0,0 @@
package eventstore
import (
"context"
"github.com/caos/zitadel/internal/query"
"github.com/caos/zitadel/internal/iam/model"
)
type IamRepo struct {
IAMID string
IAMV2Query *query.Queries
}
func (repo *IamRepo) Health(ctx context.Context) error {
return nil
}
func (repo *IamRepo) IamByID(ctx context.Context) (*model.IAM, error) {
return repo.IAMV2Query.IAMByID(ctx, repo.IAMID)
}

View File

@ -27,7 +27,6 @@ type Config struct {
type EsRepository struct {
spooler *es_spol.Spooler
eventstore.UserGrantRepo
eventstore.IamRepo
eventstore.TokenVerifierRepo
}
@ -63,10 +62,6 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, qu
Auth: authZ,
Eventstore: es,
},
eventstore.IamRepo{
IAMID: systemDefaults.IamID,
IAMV2Query: queries,
},
eventstore.TokenVerifierRepo{
TokenVerificationKey: keyAlgorithm,
Eventstore: es,

View File

@ -1,11 +0,0 @@
package repository
import (
"context"
"github.com/caos/zitadel/internal/iam/model"
)
type IAMRepository interface {
Health(ctx context.Context) error
IAMByID(ctx context.Context, id string) (*model.IAM, error)
}

View File

@ -7,5 +7,4 @@ import (
type Repository interface {
Health(context.Context) error
UserGrantRepository
IAMRepository
}

View File

@ -24,45 +24,9 @@ const (
type IAM struct {
es_models.ObjectRoot
GlobalOrgID string
IAMProjectID string
SetUpDone domain.Step
SetUpStarted domain.Step
Members []*IAMMember
IDPs []*IDPConfig
DefaultLoginPolicy *LoginPolicy
DefaultLabelPolicy *LabelPolicy
DefaultOrgIAMPolicy *OrgIAMPolicy
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy
DefaultPasswordAgePolicy *PasswordAgePolicy
DefaultLockoutPolicy *LockoutPolicy
DefaultMailTemplate *MailTemplate
DefaultMailTexts []*MailText
}
func (iam *IAM) GetMember(userID string) (int, *IAMMember) {
for i, m := range iam.Members {
if m.UserID == userID {
return i, m
}
}
return -1, nil
}
func (iam *IAM) GetIDP(idpID string) (int, *IDPConfig) {
for i, idp := range iam.IDPs {
if idp.IDPConfigID == idpID {
return i, idp
}
}
return -1, nil
}
func (iam *IAM) GetDefaultMailText(mailTextType string, language string) (int, *MailText) {
for i, m := range iam.DefaultMailTexts {
if m.MailTextType == mailTextType && m.Language == language {
return i, m
}
}
return -1, nil
GlobalOrgID string
IAMProjectID string
SetUpDone domain.Step
SetUpStarted domain.Step
Members []*IAMMember
}

View File

@ -24,53 +24,19 @@ const (
type IAM struct {
es_models.ObjectRoot
SetUpStarted Step `json:"-"`
SetUpDone Step `json:"-"`
GlobalOrgID string `json:"globalOrgId,omitempty"`
IAMProjectID string `json:"iamProjectId,omitempty"`
Members []*IAMMember `json:"-"`
IDPs []*IDPConfig `json:"-"`
DefaultLoginPolicy *LoginPolicy `json:"-"`
DefaultLabelPolicy *LabelPolicy `json:"-"`
DefaultMailTemplate *MailTemplate `json:"-"`
DefaultOrgIAMPolicy *OrgIAMPolicy `json:"-"`
DefaultPasswordComplexityPolicy *PasswordComplexityPolicy `json:"-"`
DefaultPasswordAgePolicy *PasswordAgePolicy `json:"-"`
DefaultLockoutPolicy *LockoutPolicy `json:"-"`
SetUpStarted Step `json:"-"`
SetUpDone Step `json:"-"`
GlobalOrgID string `json:"globalOrgId,omitempty"`
IAMProjectID string `json:"iamProjectId,omitempty"`
}
func IAMToModel(iam *IAM) *model.IAM {
members := IAMMembersToModel(iam.Members)
idps := IDPConfigsToModel(iam.IDPs)
converted := &model.IAM{
ObjectRoot: iam.ObjectRoot,
SetUpStarted: domain.Step(iam.SetUpStarted),
SetUpDone: domain.Step(iam.SetUpDone),
GlobalOrgID: iam.GlobalOrgID,
IAMProjectID: iam.IAMProjectID,
Members: members,
IDPs: idps,
}
if iam.DefaultLoginPolicy != nil {
converted.DefaultLoginPolicy = LoginPolicyToModel(iam.DefaultLoginPolicy)
}
if iam.DefaultLabelPolicy != nil {
converted.DefaultLabelPolicy = LabelPolicyToModel(iam.DefaultLabelPolicy)
}
if iam.DefaultMailTemplate != nil {
converted.DefaultMailTemplate = MailTemplateToModel(iam.DefaultMailTemplate)
}
if iam.DefaultPasswordComplexityPolicy != nil {
converted.DefaultPasswordComplexityPolicy = PasswordComplexityPolicyToModel(iam.DefaultPasswordComplexityPolicy)
}
if iam.DefaultPasswordAgePolicy != nil {
converted.DefaultPasswordAgePolicy = PasswordAgePolicyToModel(iam.DefaultPasswordAgePolicy)
}
if iam.DefaultLockoutPolicy != nil {
converted.DefaultLockoutPolicy = LockoutPolicyToModel(iam.DefaultLockoutPolicy)
}
if iam.DefaultOrgIAMPolicy != nil {
converted.DefaultOrgIAMPolicy = OrgIAMPolicyToModel(iam.DefaultOrgIAMPolicy)
}
return converted
}
@ -112,68 +78,6 @@ func (i *IAM) AppendEvent(event *es_models.Event) (err error) {
case IAMProjectSet,
GlobalOrgSet:
err = i.SetData(event)
case IAMMemberAdded:
err = i.appendAddMemberEvent(event)
case IAMMemberChanged:
err = i.appendChangeMemberEvent(event)
case IAMMemberRemoved:
err = i.appendRemoveMemberEvent(event)
case IAMMemberCascadeRemoved:
err = i.appendRemoveMemberEvent(event)
case IDPConfigAdded:
return i.appendAddIDPConfigEvent(event)
case IDPConfigChanged:
return i.appendChangeIDPConfigEvent(event)
case IDPConfigRemoved:
return i.appendRemoveIDPConfigEvent(event)
case IDPConfigDeactivated:
return i.appendIDPConfigStateEvent(event, model.IDPConfigStateInactive)
case IDPConfigReactivated:
return i.appendIDPConfigStateEvent(event, model.IDPConfigStateActive)
case OIDCIDPConfigAdded:
return i.appendAddOIDCIDPConfigEvent(event)
case OIDCIDPConfigChanged:
return i.appendChangeOIDCIDPConfigEvent(event)
case LoginPolicyAdded:
return i.appendAddLoginPolicyEvent(event)
case LoginPolicyChanged:
return i.appendChangeLoginPolicyEvent(event)
case LoginPolicyIDPProviderAdded:
return i.appendAddIDPProviderToLoginPolicyEvent(event)
case LoginPolicyIDPProviderRemoved:
return i.appendRemoveIDPProviderFromLoginPolicyEvent(event)
case LoginPolicySecondFactorAdded:
return i.appendAddSecondFactorToLoginPolicyEvent(event)
case LoginPolicySecondFactorRemoved:
return i.appendRemoveSecondFactorFromLoginPolicyEvent(event)
case LoginPolicyMultiFactorAdded:
return i.appendAddMultiFactorToLoginPolicyEvent(event)
case LoginPolicyMultiFactorRemoved:
return i.appendRemoveMultiFactorFromLoginPolicyEvent(event)
case LabelPolicyAdded:
return i.appendAddLabelPolicyEvent(event)
case LabelPolicyChanged:
return i.appendChangeLabelPolicyEvent(event)
case MailTemplateAdded:
return i.appendAddMailTemplateEvent(event)
case MailTemplateChanged:
return i.appendChangeMailTemplateEvent(event)
case PasswordComplexityPolicyAdded:
return i.appendAddPasswordComplexityPolicyEvent(event)
case PasswordComplexityPolicyChanged:
return i.appendChangePasswordComplexityPolicyEvent(event)
case PasswordAgePolicyAdded:
return i.appendAddPasswordAgePolicyEvent(event)
case PasswordAgePolicyChanged:
return i.appendChangePasswordAgePolicyEvent(event)
case LockoutPolicyAdded:
return i.appendAddLockoutPolicyEvent(event)
case LockoutPolicyChanged:
return i.appendChangeLockoutPolicyEvent(event)
case OrgIAMPolicyAdded:
return i.appendAddOrgIAMPolicyEvent(event)
case OrgIAMPolicyChanged:
return i.appendChangeOrgIAMPolicyEvent(event)
}
return err

View File

@ -2,9 +2,9 @@ package model
import (
"encoding/json"
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/model"
)
type IAMMember struct {
@ -13,84 +13,6 @@ type IAMMember struct {
Roles []string `json:"roles,omitempty"`
}
func GetIAMMember(members []*IAMMember, id string) (int, *IAMMember) {
for i, m := range members {
if m.UserID == id {
return i, m
}
}
return -1, nil
}
func IAMMembersToModel(members []*IAMMember) []*model.IAMMember {
convertedMembers := make([]*model.IAMMember, len(members))
for i, m := range members {
convertedMembers[i] = IAMMemberToModel(m)
}
return convertedMembers
}
func IAMMembersFromModel(members []*model.IAMMember) []*IAMMember {
convertedMembers := make([]*IAMMember, len(members))
for i, m := range members {
convertedMembers[i] = IAMMemberFromModel(m)
}
return convertedMembers
}
func IAMMemberFromModel(member *model.IAMMember) *IAMMember {
return &IAMMember{
ObjectRoot: member.ObjectRoot,
UserID: member.UserID,
Roles: member.Roles,
}
}
func IAMMemberToModel(member *IAMMember) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: member.ObjectRoot,
UserID: member.UserID,
Roles: member.Roles,
}
}
func (iam *IAM) appendAddMemberEvent(event *es_models.Event) error {
member := &IAMMember{}
err := member.SetData(event)
if err != nil {
return err
}
member.ObjectRoot.CreationDate = event.CreationDate
iam.Members = append(iam.Members, member)
return nil
}
func (iam *IAM) appendChangeMemberEvent(event *es_models.Event) error {
member := &IAMMember{}
err := member.SetData(event)
if err != nil {
return err
}
if i, m := GetIAMMember(iam.Members, member.UserID); m != nil {
iam.Members[i] = member
}
return nil
}
func (iam *IAM) appendRemoveMemberEvent(event *es_models.Event) error {
member := &IAMMember{}
err := member.SetData(event)
if err != nil {
return err
}
if i, m := GetIAMMember(iam.Members, member.UserID); m != nil {
iam.Members[i] = iam.Members[len(iam.Members)-1]
iam.Members[len(iam.Members)-1] = nil
iam.Members = iam.Members[:len(iam.Members)-1]
}
return nil
}
func (m *IAMMember) SetData(event *es_models.Event) error {
m.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, m); err != nil {

View File

@ -1,118 +0,0 @@
package model
import (
"encoding/json"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"testing"
)
func TestAppendAddMemberEvent(t *testing.T) {
type args struct {
iam *IAM
member *IAMMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add member event",
args: args{
iam: &IAM{},
member: &IAMMember{UserID: "UserID", Roles: []string{"Role"}},
event: &es_models.Event{},
},
result: &IAM{Members: []*IAMMember{&IAMMember{UserID: "UserID", Roles: []string{"Role"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.iam.appendAddMemberEvent(tt.args.event)
if len(tt.args.iam.Members) != 1 {
t.Errorf("got wrong result should have one member actual: %v ", len(tt.args.iam.Members))
}
if tt.args.iam.Members[0] == tt.result.Members[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Members[0], tt.args.iam.Members[0])
}
})
}
}
func TestAppendChangeMemberEvent(t *testing.T) {
type args struct {
iam *IAM
member *IAMMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change member event",
args: args{
iam: &IAM{Members: []*IAMMember{&IAMMember{UserID: "UserID", Roles: []string{"Role"}}}},
member: &IAMMember{UserID: "UserID", Roles: []string{"ChangedRole"}},
event: &es_models.Event{},
},
result: &IAM{Members: []*IAMMember{&IAMMember{UserID: "UserID", Roles: []string{"ChangedRole"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.iam.appendChangeMemberEvent(tt.args.event)
if len(tt.args.iam.Members) != 1 {
t.Errorf("got wrong result should have one member actual: %v ", len(tt.args.iam.Members))
}
if tt.args.iam.Members[0] == tt.result.Members[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.Members[0], tt.args.iam.Members[0])
}
})
}
}
func TestAppendRemoveMemberEvent(t *testing.T) {
type args struct {
iam *IAM
member *IAMMember
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append remove member event",
args: args{
iam: &IAM{Members: []*IAMMember{&IAMMember{UserID: "UserID", Roles: []string{"Role"}}}},
member: &IAMMember{UserID: "UserID"},
event: &es_models.Event{},
},
result: &IAM{Members: []*IAMMember{}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.member != nil {
data, _ := json.Marshal(tt.args.member)
tt.args.event.Data = data
}
tt.args.iam.appendRemoveMemberEvent(tt.args.event)
if len(tt.args.iam.Members) != 0 {
t.Errorf("got wrong result should have no member actual: %v ", len(tt.args.iam.Members))
}
})
}
}

View File

@ -2,6 +2,7 @@ package model
import (
"encoding/json"
"github.com/caos/logging"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/model"
@ -52,29 +53,6 @@ func IDPConfigsToModel(idps []*IDPConfig) []*model.IDPConfig {
return convertedIDPConfigs
}
func IDPConfigsFromModel(idps []*model.IDPConfig) []*IDPConfig {
convertedIDPConfigs := make([]*IDPConfig, len(idps))
for i, idp := range idps {
convertedIDPConfigs[i] = IDPConfigFromModel(idp)
}
return convertedIDPConfigs
}
func IDPConfigFromModel(idp *model.IDPConfig) *IDPConfig {
converted := &IDPConfig{
ObjectRoot: idp.ObjectRoot,
IDPConfigID: idp.IDPConfigID,
Name: idp.Name,
State: int32(idp.State),
Type: int32(idp.Type),
StylingType: int32(idp.StylingType),
}
if idp.OIDCConfig != nil {
converted.OIDCIDPConfig = OIDCIDPConfigFromModel(idp.OIDCConfig)
}
return converted
}
func IDPConfigToModel(idp *IDPConfig) *model.IDPConfig {
converted := &model.IDPConfig{
ObjectRoot: idp.ObjectRoot,
@ -90,57 +68,6 @@ func IDPConfigToModel(idp *IDPConfig) *model.IDPConfig {
return converted
}
func (iam *IAM) appendAddIDPConfigEvent(event *es_models.Event) error {
idp := new(IDPConfig)
err := idp.SetData(event)
if err != nil {
return err
}
idp.ObjectRoot.CreationDate = event.CreationDate
iam.IDPs = append(iam.IDPs, idp)
return nil
}
func (iam *IAM) appendChangeIDPConfigEvent(event *es_models.Event) error {
idp := new(IDPConfig)
err := idp.SetData(event)
if err != nil {
return err
}
if i, idpConfig := GetIDPConfig(iam.IDPs, idp.IDPConfigID); idpConfig != nil {
iam.IDPs[i].SetData(event)
}
return nil
}
func (iam *IAM) appendRemoveIDPConfigEvent(event *es_models.Event) error {
idp := new(IDPConfig)
err := idp.SetData(event)
if err != nil {
return err
}
if i, idpConfig := GetIDPConfig(iam.IDPs, idp.IDPConfigID); idpConfig != nil {
iam.IDPs[i] = iam.IDPs[len(iam.IDPs)-1]
iam.IDPs[len(iam.IDPs)-1] = nil
iam.IDPs = iam.IDPs[:len(iam.IDPs)-1]
}
return nil
}
func (iam *IAM) appendIDPConfigStateEvent(event *es_models.Event, state model.IDPConfigState) error {
idp := new(IDPConfig)
err := idp.SetData(event)
if err != nil {
return err
}
if i, idpConfig := GetIDPConfig(iam.IDPs, idp.IDPConfigID); idpConfig != nil {
idpConfig.State = int32(state)
iam.IDPs[i] = idpConfig
}
return nil
}
func (c *IDPConfig) SetData(event *es_models.Event) error {
c.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, c); err != nil {

View File

@ -1,9 +1,6 @@
package model
import (
"encoding/json"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/model"
"testing"
)
@ -50,164 +47,3 @@ func TestIdpConfigChanges(t *testing.T) {
})
}
}
func TestAppendAddIdpConfigEvent(t *testing.T) {
type args struct {
iam *IAM
idp *IDPConfig
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add idp config event",
args: args{
iam: &IAM{},
idp: &IDPConfig{Name: "IDPConfig"},
event: &es_models.Event{},
},
result: &IAM{IDPs: []*IDPConfig{&IDPConfig{Name: "IDPConfig"}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.idp != nil {
data, _ := json.Marshal(tt.args.idp)
tt.args.event.Data = data
}
tt.args.iam.appendAddIDPConfigEvent(tt.args.event)
if len(tt.args.iam.IDPs) != 1 {
t.Errorf("got wrong result should have one idpConfig actual: %v ", len(tt.args.iam.IDPs))
}
if tt.args.iam.IDPs[0] == tt.result.IDPs[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.IDPs[0], tt.args.iam.IDPs[0])
}
})
}
}
func TestAppendChangeIdpConfigEvent(t *testing.T) {
type args struct {
iam *IAM
idpConfig *IDPConfig
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change idp config event",
args: args{
iam: &IAM{IDPs: []*IDPConfig{&IDPConfig{Name: "IDPConfig"}}},
idpConfig: &IDPConfig{Name: "IDPConfig Change"},
event: &es_models.Event{},
},
result: &IAM{IDPs: []*IDPConfig{&IDPConfig{Name: "IDPConfig Change"}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.idpConfig != nil {
data, _ := json.Marshal(tt.args.idpConfig)
tt.args.event.Data = data
}
tt.args.iam.appendChangeIDPConfigEvent(tt.args.event)
if len(tt.args.iam.IDPs) != 1 {
t.Errorf("got wrong result should have one idpConfig actual: %v ", len(tt.args.iam.IDPs))
}
if tt.args.iam.IDPs[0] == tt.result.IDPs[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.IDPs[0], tt.args.iam.IDPs[0])
}
})
}
}
func TestAppendRemoveIDPEvent(t *testing.T) {
type args struct {
iam *IAM
idp *IDPConfig
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append remove idp config event",
args: args{
iam: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", Name: "IDPConfig"}}},
idp: &IDPConfig{IDPConfigID: "IDPConfigID", Name: "IDPConfig"},
event: &es_models.Event{},
},
result: &IAM{IDPs: []*IDPConfig{}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.idp != nil {
data, _ := json.Marshal(tt.args.idp)
tt.args.event.Data = data
}
tt.args.iam.appendRemoveIDPConfigEvent(tt.args.event)
if len(tt.args.iam.IDPs) != 0 {
t.Errorf("got wrong result should have no apps actual: %v ", len(tt.args.iam.IDPs))
}
})
}
}
func TestAppendAppStateEvent(t *testing.T) {
type args struct {
iam *IAM
idp *IDPConfig
event *es_models.Event
state model.IDPConfigState
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append deactivate application event",
args: args{
iam: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", Name: "IDPConfig", State: int32(model.IDPConfigStateActive)}}},
idp: &IDPConfig{IDPConfigID: "IDPConfigID"},
event: &es_models.Event{},
state: model.IDPConfigStateInactive,
},
result: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", Name: "IDPConfig", State: int32(model.IDPConfigStateInactive)}}},
},
{
name: "append reactivate application event",
args: args{
iam: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", Name: "IDPConfig", State: int32(model.IDPConfigStateInactive)}}},
idp: &IDPConfig{IDPConfigID: "IDPConfigID"},
event: &es_models.Event{},
state: model.IDPConfigStateActive,
},
result: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", Name: "IDPConfig", State: int32(model.IDPConfigStateActive)}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.idp != nil {
data, _ := json.Marshal(tt.args.idp)
tt.args.event.Data = data
}
tt.args.iam.appendIDPConfigStateEvent(tt.args.event, tt.args.state)
if len(tt.args.iam.IDPs) != 1 {
t.Errorf("got wrong result should have one idpConfig actual: %v ", len(tt.args.iam.IDPs))
}
if tt.args.iam.IDPs[0] == tt.result.IDPs[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.IDPs[0], tt.args.iam.IDPs[0])
}
})
}
}

View File

@ -38,20 +38,6 @@ func LabelPolicyToModel(policy *LabelPolicy) *iam_model.LabelPolicy {
}
}
func (i *IAM) appendAddLabelPolicyEvent(event *es_models.Event) error {
i.DefaultLabelPolicy = new(LabelPolicy)
err := i.DefaultLabelPolicy.SetDataLabel(event)
if err != nil {
return err
}
i.DefaultLabelPolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangeLabelPolicyEvent(event *es_models.Event) error {
return i.DefaultLabelPolicy.SetDataLabel(event)
}
func (p *LabelPolicy) SetDataLabel(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {

View File

@ -1,88 +0,0 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestAppendAddLabelPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LabelPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add label policy event",
args: args{
iam: new(IAM),
policy: &LabelPolicy{PrimaryColor: "000000", BackgroundColor: "FFFFFF"},
event: new(es_models.Event),
},
result: &IAM{DefaultLabelPolicy: &LabelPolicy{PrimaryColor: "000000", BackgroundColor: "FFFFFF"}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddLabelPolicyEvent(tt.args.event)
if tt.result.DefaultLabelPolicy.PrimaryColor != tt.args.iam.DefaultLabelPolicy.PrimaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.PrimaryColor, tt.args.iam.DefaultLabelPolicy.PrimaryColor)
}
if tt.result.DefaultLabelPolicy.BackgroundColor != tt.args.iam.DefaultLabelPolicy.BackgroundColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.BackgroundColor, tt.args.iam.DefaultLabelPolicy.BackgroundColor)
}
})
}
}
func TestAppendChangeLabelPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LabelPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change label policy event",
args: args{
iam: &IAM{DefaultLabelPolicy: &LabelPolicy{
PrimaryColor: "000001", BackgroundColor: "FFFFF0",
}},
policy: &LabelPolicy{PrimaryColor: "000000", BackgroundColor: "FFFFFF"},
event: &es_models.Event{},
},
result: &IAM{DefaultLabelPolicy: &LabelPolicy{
PrimaryColor: "000000", BackgroundColor: "FFFFFF",
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangeLabelPolicyEvent(tt.args.event)
if tt.result.DefaultLabelPolicy.PrimaryColor != tt.args.iam.DefaultLabelPolicy.PrimaryColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.PrimaryColor, tt.args.iam.DefaultLabelPolicy.PrimaryColor)
}
if tt.result.DefaultLabelPolicy.BackgroundColor != tt.args.iam.DefaultLabelPolicy.BackgroundColor {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLabelPolicy.BackgroundColor, tt.args.iam.DefaultLabelPolicy.BackgroundColor)
}
})
}
}

View File

@ -37,20 +37,6 @@ func (p *LockoutPolicy) Changes(changed *LockoutPolicy) map[string]interface{} {
return changes
}
func (i *IAM) appendAddLockoutPolicyEvent(event *es_models.Event) error {
i.DefaultLockoutPolicy = new(LockoutPolicy)
err := i.DefaultLockoutPolicy.SetData(event)
if err != nil {
return err
}
i.DefaultLockoutPolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangeLockoutPolicyEvent(event *es_models.Event) error {
return i.DefaultLockoutPolicy.SetData(event)
}
func (p *LockoutPolicy) SetData(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {

View File

@ -1,8 +1,6 @@
package model
import (
"encoding/json"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"testing"
)
@ -49,80 +47,3 @@ func TestPasswordLockoutPolicyChanges(t *testing.T) {
})
}
}
func TestAppendAddPasswordLockoutPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LockoutPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add password lockout policy event",
args: args{
iam: new(IAM),
policy: &LockoutPolicy{MaxPasswordAttempts: 10, ShowLockOutFailures: true},
event: new(es_models.Event),
},
result: &IAM{DefaultLockoutPolicy: &LockoutPolicy{MaxPasswordAttempts: 10, ShowLockOutFailures: true}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddLockoutPolicyEvent(tt.args.event)
if tt.result.DefaultLockoutPolicy.MaxPasswordAttempts != tt.args.iam.DefaultLockoutPolicy.MaxPasswordAttempts {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLockoutPolicy.MaxPasswordAttempts, tt.args.iam.DefaultLockoutPolicy.MaxPasswordAttempts)
}
if tt.result.DefaultLockoutPolicy.ShowLockOutFailures != tt.args.iam.DefaultLockoutPolicy.ShowLockOutFailures {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLockoutPolicy.ShowLockOutFailures, tt.args.iam.DefaultLockoutPolicy.ShowLockOutFailures)
}
})
}
}
func TestAppendChangePasswordLockoutPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LockoutPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change password lockout policy event",
args: args{
iam: &IAM{DefaultLockoutPolicy: &LockoutPolicy{
MaxPasswordAttempts: 10,
}},
policy: &LockoutPolicy{MaxPasswordAttempts: 5},
event: &es_models.Event{},
},
result: &IAM{DefaultLockoutPolicy: &LockoutPolicy{
MaxPasswordAttempts: 5,
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangeLockoutPolicyEvent(tt.args.event)
if tt.result.DefaultLockoutPolicy.MaxPasswordAttempts != tt.args.iam.DefaultLockoutPolicy.MaxPasswordAttempts {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLockoutPolicy.MaxPasswordAttempts, tt.args.iam.DefaultLockoutPolicy.MaxPasswordAttempts)
}
})
}
}

View File

@ -79,14 +79,6 @@ func IDPProvidersToModel(members []*IDPProvider) []*iam_model.IDPProvider {
return convertedProviders
}
func IDOProvidersFromModel(members []*iam_model.IDPProvider) []*IDPProvider {
convertedProviders := make([]*IDPProvider, len(members))
for i, m := range members {
convertedProviders[i] = IDPProviderFromModel(m)
}
return convertedProviders
}
func IDPProviderToModel(provider *IDPProvider) *iam_model.IDPProvider {
return &iam_model.IDPProvider{
ObjectRoot: provider.ObjectRoot,
@ -95,26 +87,6 @@ func IDPProviderToModel(provider *IDPProvider) *iam_model.IDPProvider {
}
}
func IDPProviderFromModel(provider *iam_model.IDPProvider) *IDPProvider {
return &IDPProvider{
ObjectRoot: provider.ObjectRoot,
Type: int32(provider.Type),
IDPConfigID: provider.IDPConfigID,
}
}
func SecondFactorsFromModel(mfas []domain.SecondFactorType) []int32 {
convertedMFAs := make([]int32, len(mfas))
for i, mfa := range mfas {
convertedMFAs[i] = int32(mfa)
}
return convertedMFAs
}
func SecondFactorFromModel(mfa domain.SecondFactorType) *MFA {
return &MFA{MFAType: int32(mfa)}
}
func SecondFactorsToModel(mfas []int32) []domain.SecondFactorType {
convertedMFAs := make([]domain.SecondFactorType, len(mfas))
for i, mfa := range mfas {
@ -123,18 +95,6 @@ func SecondFactorsToModel(mfas []int32) []domain.SecondFactorType {
return convertedMFAs
}
func MultiFactorsFromModel(mfas []iam_model.MultiFactorType) []int32 {
convertedMFAs := make([]int32, len(mfas))
for i, mfa := range mfas {
convertedMFAs[i] = int32(mfa)
}
return convertedMFAs
}
func MultiFactorFromModel(mfa iam_model.MultiFactorType) *MFA {
return &MFA{MFAType: int32(mfa)}
}
func MultiFactorsToModel(mfas []int32) []domain.MultiFactorType {
convertedMFAs := make([]domain.MultiFactorType, len(mfas))
for i, mfa := range mfas {
@ -164,96 +124,6 @@ func (p *LoginPolicy) Changes(changed *LoginPolicy) map[string]interface{} {
return changes
}
func (i *IAM) appendAddLoginPolicyEvent(event *es_models.Event) error {
i.DefaultLoginPolicy = new(LoginPolicy)
err := i.DefaultLoginPolicy.SetData(event)
if err != nil {
return err
}
i.DefaultLoginPolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangeLoginPolicyEvent(event *es_models.Event) error {
return i.DefaultLoginPolicy.SetData(event)
}
func (iam *IAM) appendAddIDPProviderToLoginPolicyEvent(event *es_models.Event) error {
provider := new(IDPProvider)
err := provider.SetData(event)
if err != nil {
return err
}
provider.ObjectRoot.CreationDate = event.CreationDate
iam.DefaultLoginPolicy.IDPProviders = append(iam.DefaultLoginPolicy.IDPProviders, provider)
return nil
}
func (iam *IAM) appendRemoveIDPProviderFromLoginPolicyEvent(event *es_models.Event) error {
provider := new(IDPProvider)
err := provider.SetData(event)
if err != nil {
return err
}
if i, m := GetIDPProvider(iam.DefaultLoginPolicy.IDPProviders, provider.IDPConfigID); m != nil {
iam.DefaultLoginPolicy.IDPProviders[i] = iam.DefaultLoginPolicy.IDPProviders[len(iam.DefaultLoginPolicy.IDPProviders)-1]
iam.DefaultLoginPolicy.IDPProviders[len(iam.DefaultLoginPolicy.IDPProviders)-1] = nil
iam.DefaultLoginPolicy.IDPProviders = iam.DefaultLoginPolicy.IDPProviders[:len(iam.DefaultLoginPolicy.IDPProviders)-1]
return nil
}
return nil
}
func (iam *IAM) appendAddSecondFactorToLoginPolicyEvent(event *es_models.Event) error {
mfa := new(MFA)
err := mfa.SetData(event)
if err != nil {
return err
}
iam.DefaultLoginPolicy.SecondFactors = append(iam.DefaultLoginPolicy.SecondFactors, mfa.MFAType)
return nil
}
func (iam *IAM) appendRemoveSecondFactorFromLoginPolicyEvent(event *es_models.Event) error {
mfa := new(MFA)
err := mfa.SetData(event)
if err != nil {
return err
}
if i, m := GetMFA(iam.DefaultLoginPolicy.SecondFactors, mfa.MFAType); m != 0 {
iam.DefaultLoginPolicy.SecondFactors[i] = iam.DefaultLoginPolicy.SecondFactors[len(iam.DefaultLoginPolicy.SecondFactors)-1]
iam.DefaultLoginPolicy.SecondFactors[len(iam.DefaultLoginPolicy.SecondFactors)-1] = 0
iam.DefaultLoginPolicy.SecondFactors = iam.DefaultLoginPolicy.SecondFactors[:len(iam.DefaultLoginPolicy.SecondFactors)-1]
return nil
}
return nil
}
func (iam *IAM) appendAddMultiFactorToLoginPolicyEvent(event *es_models.Event) error {
mfa := new(MFA)
err := mfa.SetData(event)
if err != nil {
return err
}
iam.DefaultLoginPolicy.MultiFactors = append(iam.DefaultLoginPolicy.MultiFactors, mfa.MFAType)
return nil
}
func (iam *IAM) appendRemoveMultiFactorFromLoginPolicyEvent(event *es_models.Event) error {
mfa := new(MFA)
err := mfa.SetData(event)
if err != nil {
return err
}
if i, m := GetMFA(iam.DefaultLoginPolicy.MultiFactors, mfa.MFAType); m != 0 {
iam.DefaultLoginPolicy.MultiFactors[i] = iam.DefaultLoginPolicy.MultiFactors[len(iam.DefaultLoginPolicy.MultiFactors)-1]
iam.DefaultLoginPolicy.MultiFactors[len(iam.DefaultLoginPolicy.MultiFactors)-1] = 0
iam.DefaultLoginPolicy.MultiFactors = iam.DefaultLoginPolicy.MultiFactors[:len(iam.DefaultLoginPolicy.MultiFactors)-1]
return nil
}
return nil
}
func (p *LoginPolicy) SetData(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {

View File

@ -1,431 +0,0 @@
package model
import (
"encoding/json"
"testing"
"github.com/caos/zitadel/internal/domain"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/model"
)
func TestLoginPolicyChanges(t *testing.T) {
type args struct {
existing *LoginPolicy
new *LoginPolicy
}
type res struct {
changesLen int
}
tests := []struct {
name string
args args
res res
}{
{
name: "loginpolicy all attributes change",
args: args{
existing: &LoginPolicy{AllowUsernamePassword: false, AllowRegister: false, AllowExternalIdp: false, ForceMFA: false},
new: &LoginPolicy{AllowUsernamePassword: true, AllowRegister: true, AllowExternalIdp: true, ForceMFA: true},
},
res: res{
changesLen: 4,
},
},
{
name: "no changes",
args: args{
existing: &LoginPolicy{AllowUsernamePassword: false, AllowRegister: false, AllowExternalIdp: false, ForceMFA: false},
new: &LoginPolicy{AllowUsernamePassword: false, AllowRegister: false, AllowExternalIdp: false, ForceMFA: false},
},
res: res{
changesLen: 0,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
changes := tt.args.existing.Changes(tt.args.new)
if len(changes) != tt.res.changesLen {
t.Errorf("got wrong changes len: expected: %v, actual: %v ", tt.res.changesLen, len(changes))
}
})
}
}
func TestAppendAddLoginPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LoginPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add login policy event",
args: args{
iam: new(IAM),
policy: &LoginPolicy{AllowUsernamePassword: true, AllowRegister: true, AllowExternalIdp: true, ForceMFA: true},
event: new(es_models.Event),
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{AllowUsernamePassword: true, AllowRegister: true, AllowExternalIdp: true, ForceMFA: true}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddLoginPolicyEvent(tt.args.event)
if tt.result.DefaultLoginPolicy.AllowUsernamePassword != tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowUsernamePassword, tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword)
}
if tt.result.DefaultLoginPolicy.AllowRegister != tt.args.iam.DefaultLoginPolicy.AllowRegister {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowRegister, tt.args.iam.DefaultLoginPolicy.AllowRegister)
}
if tt.result.DefaultLoginPolicy.AllowExternalIdp != tt.args.iam.DefaultLoginPolicy.AllowExternalIdp {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowExternalIdp, tt.args.iam.DefaultLoginPolicy.AllowExternalIdp)
}
if tt.result.DefaultLoginPolicy.ForceMFA != tt.args.iam.DefaultLoginPolicy.ForceMFA {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.ForceMFA, tt.args.iam.DefaultLoginPolicy.ForceMFA)
}
})
}
}
func TestAppendChangeLoginPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *LoginPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change login policy event",
args: args{
iam: &IAM{DefaultLoginPolicy: &LoginPolicy{
AllowExternalIdp: false,
AllowRegister: false,
AllowUsernamePassword: false,
ForceMFA: false,
}},
policy: &LoginPolicy{AllowUsernamePassword: true, AllowRegister: true, AllowExternalIdp: true, ForceMFA: true},
event: &es_models.Event{},
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{
AllowExternalIdp: true,
AllowRegister: true,
AllowUsernamePassword: true,
ForceMFA: true,
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangeLoginPolicyEvent(tt.args.event)
if tt.result.DefaultLoginPolicy.AllowUsernamePassword != tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowUsernamePassword, tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword)
}
if tt.result.DefaultLoginPolicy.AllowRegister != tt.args.iam.DefaultLoginPolicy.AllowRegister {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowRegister, tt.args.iam.DefaultLoginPolicy.AllowRegister)
}
if tt.result.DefaultLoginPolicy.AllowExternalIdp != tt.args.iam.DefaultLoginPolicy.AllowExternalIdp {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowExternalIdp, tt.args.iam.DefaultLoginPolicy.AllowExternalIdp)
}
if tt.result.DefaultLoginPolicy.ForceMFA != tt.args.iam.DefaultLoginPolicy.ForceMFA {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.ForceMFA, tt.args.iam.DefaultLoginPolicy.ForceMFA)
}
})
}
}
func TestAppendAddIdpToPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
provider *IDPProvider
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add idp to login policy event",
args: args{
iam: &IAM{DefaultLoginPolicy: &LoginPolicy{AllowExternalIdp: true, AllowRegister: true, AllowUsernamePassword: true}},
provider: &IDPProvider{Type: int32(model.IDPProviderTypeSystem), IDPConfigID: "IDPConfigID"},
event: &es_models.Event{},
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{
AllowExternalIdp: true,
AllowRegister: true,
AllowUsernamePassword: true,
IDPProviders: []*IDPProvider{
{IDPConfigID: "IDPConfigID", Type: int32(model.IDPProviderTypeSystem)},
}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.provider != nil {
data, _ := json.Marshal(tt.args.provider)
tt.args.event.Data = data
}
tt.args.iam.appendAddIDPProviderToLoginPolicyEvent(tt.args.event)
if tt.result.DefaultLoginPolicy.AllowUsernamePassword != tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword {
t.Errorf("got wrong result AllowUsernamePassword: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowUsernamePassword, tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword)
}
if tt.result.DefaultLoginPolicy.AllowRegister != tt.args.iam.DefaultLoginPolicy.AllowRegister {
t.Errorf("got wrong result AllowRegister: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowRegister, tt.args.iam.DefaultLoginPolicy.AllowRegister)
}
if tt.result.DefaultLoginPolicy.AllowExternalIdp != tt.args.iam.DefaultLoginPolicy.AllowExternalIdp {
t.Errorf("got wrong result AllowExternalIDP: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowExternalIdp, tt.args.iam.DefaultLoginPolicy.AllowExternalIdp)
}
if len(tt.result.DefaultLoginPolicy.IDPProviders) != len(tt.args.iam.DefaultLoginPolicy.IDPProviders) {
t.Errorf("got wrong idp provider len: expected: %v, actual: %v ", len(tt.result.DefaultLoginPolicy.IDPProviders), len(tt.args.iam.DefaultLoginPolicy.IDPProviders))
}
if tt.result.DefaultLoginPolicy.IDPProviders[0].Type != tt.args.provider.Type {
t.Errorf("got wrong idp provider type: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.IDPProviders[0].Type, tt.args.provider.Type)
}
if tt.result.DefaultLoginPolicy.IDPProviders[0].IDPConfigID != tt.args.provider.IDPConfigID {
t.Errorf("got wrong idp provider idpconfigid: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.IDPProviders[0].IDPConfigID, tt.args.provider.IDPConfigID)
}
})
}
}
func TestRemoveIdpToPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
provider *IDPProvider
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add idp to login policy event",
args: args{
iam: &IAM{
DefaultLoginPolicy: &LoginPolicy{
AllowExternalIdp: true,
AllowRegister: true,
AllowUsernamePassword: true,
IDPProviders: []*IDPProvider{
{IDPConfigID: "IDPConfigID", Type: int32(model.IDPProviderTypeSystem)},
}}},
provider: &IDPProvider{Type: int32(model.IDPProviderTypeSystem), IDPConfigID: "IDPConfigID"},
event: &es_models.Event{},
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{
AllowExternalIdp: true,
AllowRegister: true,
AllowUsernamePassword: true,
IDPProviders: []*IDPProvider{}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.provider != nil {
data, _ := json.Marshal(tt.args.provider)
tt.args.event.Data = data
}
tt.args.iam.appendRemoveIDPProviderFromLoginPolicyEvent(tt.args.event)
if tt.result.DefaultLoginPolicy.AllowUsernamePassword != tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword {
t.Errorf("got wrong result AllowUsernamePassword: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowUsernamePassword, tt.args.iam.DefaultLoginPolicy.AllowUsernamePassword)
}
if tt.result.DefaultLoginPolicy.AllowRegister != tt.args.iam.DefaultLoginPolicy.AllowRegister {
t.Errorf("got wrong result AllowRegister: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowRegister, tt.args.iam.DefaultLoginPolicy.AllowRegister)
}
if tt.result.DefaultLoginPolicy.AllowExternalIdp != tt.args.iam.DefaultLoginPolicy.AllowExternalIdp {
t.Errorf("got wrong result AllowExternalIDP: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.AllowExternalIdp, tt.args.iam.DefaultLoginPolicy.AllowExternalIdp)
}
if len(tt.result.DefaultLoginPolicy.IDPProviders) != len(tt.args.iam.DefaultLoginPolicy.IDPProviders) {
t.Errorf("got wrong idp provider len: expected: %v, actual: %v ", len(tt.result.DefaultLoginPolicy.IDPProviders), len(tt.args.iam.DefaultLoginPolicy.IDPProviders))
}
})
}
}
func TestAppendAddSecondFactorToPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
mfa *MFA
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add second factor to login policy event",
args: args{
iam: &IAM{DefaultLoginPolicy: &LoginPolicy{AllowExternalIdp: true, AllowRegister: true, AllowUsernamePassword: true}},
mfa: &MFA{MFAType: int32(domain.SecondFactorTypeOTP)},
event: &es_models.Event{},
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{
SecondFactors: []int32{
int32(domain.SecondFactorTypeOTP),
}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.mfa != nil {
data, _ := json.Marshal(tt.args.mfa)
tt.args.event.Data = data
}
tt.args.iam.appendAddSecondFactorToLoginPolicyEvent(tt.args.event)
if len(tt.result.DefaultLoginPolicy.SecondFactors) != len(tt.args.iam.DefaultLoginPolicy.SecondFactors) {
t.Errorf("got wrong second factors len: expected: %v, actual: %v ", len(tt.result.DefaultLoginPolicy.SecondFactors), len(tt.args.iam.DefaultLoginPolicy.SecondFactors))
}
if tt.result.DefaultLoginPolicy.SecondFactors[0] != tt.args.mfa.MFAType {
t.Errorf("got wrong second factor: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.SecondFactors[0], tt.args.mfa)
}
})
}
}
func TestRemoveSecondFactorToPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
mfa *MFA
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append remove second factor to login policy event",
args: args{
iam: &IAM{
DefaultLoginPolicy: &LoginPolicy{
SecondFactors: []int32{
int32(domain.SecondFactorTypeOTP),
}}},
mfa: &MFA{MFAType: int32(domain.SecondFactorTypeOTP)},
event: &es_models.Event{},
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{
AllowExternalIdp: true,
AllowRegister: true,
AllowUsernamePassword: true,
SecondFactors: []int32{}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.mfa != nil {
data, _ := json.Marshal(tt.args.mfa)
tt.args.event.Data = data
}
tt.args.iam.appendRemoveSecondFactorFromLoginPolicyEvent(tt.args.event)
if len(tt.result.DefaultLoginPolicy.SecondFactors) != len(tt.args.iam.DefaultLoginPolicy.SecondFactors) {
t.Errorf("got wrong second factor len: expected: %v, actual: %v ", len(tt.result.DefaultLoginPolicy.SecondFactors), len(tt.args.iam.DefaultLoginPolicy.SecondFactors))
}
})
}
}
func TestAppendAddMultiFactorToPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
mfa *MFA
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add mfa to login policy event",
args: args{
iam: &IAM{DefaultLoginPolicy: &LoginPolicy{AllowExternalIdp: true, AllowRegister: true, AllowUsernamePassword: true}},
mfa: &MFA{MFAType: int32(model.MultiFactorTypeU2FWithPIN)},
event: &es_models.Event{},
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{
MultiFactors: []int32{
int32(model.MultiFactorTypeU2FWithPIN),
}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.mfa != nil {
data, _ := json.Marshal(tt.args.mfa)
tt.args.event.Data = data
}
tt.args.iam.appendAddMultiFactorToLoginPolicyEvent(tt.args.event)
if len(tt.result.DefaultLoginPolicy.MultiFactors) != len(tt.args.iam.DefaultLoginPolicy.MultiFactors) {
t.Errorf("got wrong mfas len: expected: %v, actual: %v ", len(tt.result.DefaultLoginPolicy.MultiFactors), len(tt.args.iam.DefaultLoginPolicy.MultiFactors))
}
if tt.result.DefaultLoginPolicy.MultiFactors[0] != tt.args.mfa.MFAType {
t.Errorf("got wrong mfa: expected: %v, actual: %v ", tt.result.DefaultLoginPolicy.MultiFactors[0], tt.args.mfa)
}
})
}
}
func TestRemoveMultiFactorToPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
mfa *MFA
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append remove mfa to login policy event",
args: args{
iam: &IAM{
DefaultLoginPolicy: &LoginPolicy{
MultiFactors: []int32{
int32(model.MultiFactorTypeU2FWithPIN),
}}},
mfa: &MFA{MFAType: int32(model.MultiFactorTypeU2FWithPIN)},
event: &es_models.Event{},
},
result: &IAM{DefaultLoginPolicy: &LoginPolicy{
AllowExternalIdp: true,
AllowRegister: true,
AllowUsernamePassword: true,
MultiFactors: []int32{}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.mfa != nil {
data, _ := json.Marshal(tt.args.mfa)
tt.args.event.Data = data
}
tt.args.iam.appendRemoveMultiFactorFromLoginPolicyEvent(tt.args.event)
if len(tt.result.DefaultLoginPolicy.MultiFactors) != len(tt.args.iam.DefaultLoginPolicy.MultiFactors) {
t.Errorf("got wrong mfa len: expected: %v, actual: %v ", len(tt.result.DefaultLoginPolicy.MultiFactors), len(tt.args.iam.DefaultLoginPolicy.MultiFactors))
}
})
}
}

View File

@ -23,14 +23,6 @@ func MailTemplateToModel(template *MailTemplate) *iam_model.MailTemplate {
}
}
func MailTemplateFromModel(template *iam_model.MailTemplate) *MailTemplate {
return &MailTemplate{
ObjectRoot: template.ObjectRoot,
State: int32(template.State),
Template: template.Template,
}
}
func (p *MailTemplate) Changes(changed *MailTemplate) map[string]interface{} {
changes := make(map[string]interface{}, 1)
if b64.StdEncoding.EncodeToString(changed.Template) != b64.StdEncoding.EncodeToString(p.Template) {
@ -40,20 +32,6 @@ func (p *MailTemplate) Changes(changed *MailTemplate) map[string]interface{} {
return changes
}
func (i *IAM) appendAddMailTemplateEvent(event *es_models.Event) error {
i.DefaultMailTemplate = new(MailTemplate)
err := i.DefaultMailTemplate.SetDataLabel(event)
if err != nil {
return err
}
i.DefaultMailTemplate.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangeMailTemplateEvent(event *es_models.Event) error {
return i.DefaultMailTemplate.SetDataLabel(event)
}
func (p *MailTemplate) SetDataLabel(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {

View File

@ -1,10 +1,7 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestMailTemplateChanges(t *testing.T) {
@ -50,77 +47,3 @@ func TestMailTemplateChanges(t *testing.T) {
})
}
}
func TestAppendAddMailTemplateEvent(t *testing.T) {
type args struct {
iam *IAM
policy *MailTemplate
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add label policy event",
args: args{
iam: new(IAM),
policy: &MailTemplate{Template: []byte("<!doctype html>")},
event: new(es_models.Event),
},
result: &IAM{DefaultMailTemplate: &MailTemplate{Template: []byte("<!doctype html>")}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddMailTemplateEvent(tt.args.event)
if string(tt.result.DefaultMailTemplate.Template) != string(tt.args.iam.DefaultMailTemplate.Template) {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTemplate.Template, tt.args.iam.DefaultMailTemplate.Template)
}
})
}
}
func TestAppendChangeMailTemplateEvent(t *testing.T) {
type args struct {
iam *IAM
policy *MailTemplate
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change label policy event",
args: args{
iam: &IAM{DefaultMailTemplate: &MailTemplate{
Template: []byte("<doctype html>"),
}},
policy: &MailTemplate{Template: []byte("<!doctype html>")},
event: &es_models.Event{},
},
result: &IAM{DefaultMailTemplate: &MailTemplate{
Template: []byte("<!doctype html>"),
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangeMailTemplateEvent(tt.args.event)
if string(tt.result.DefaultMailTemplate.Template) != string(tt.args.iam.DefaultMailTemplate.Template) {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultMailTemplate.Template, tt.args.iam.DefaultMailTemplate.Template)
}
})
}
}

View File

@ -2,12 +2,13 @@ package model
import (
"encoding/json"
"reflect"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/crypto"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/model"
"github.com/lib/pq"
"reflect"
)
type OIDCIDPConfig struct {
@ -45,19 +46,6 @@ func (c *OIDCIDPConfig) Changes(changed *OIDCIDPConfig) map[string]interface{} {
return changes
}
func OIDCIDPConfigFromModel(config *model.OIDCIDPConfig) *OIDCIDPConfig {
return &OIDCIDPConfig{
ObjectRoot: config.ObjectRoot,
IDPConfigID: config.IDPConfigID,
ClientID: config.ClientID,
ClientSecret: config.ClientSecret,
Issuer: config.Issuer,
Scopes: config.Scopes,
IDPDisplayNameMapping: int32(config.IDPDisplayNameMapping),
UsernameMapping: int32(config.UsernameMapping),
}
}
func OIDCIDPConfigToModel(config *OIDCIDPConfig) *model.OIDCIDPConfig {
return &model.OIDCIDPConfig{
ObjectRoot: config.ObjectRoot,
@ -71,33 +59,6 @@ func OIDCIDPConfigToModel(config *OIDCIDPConfig) *model.OIDCIDPConfig {
}
}
func (iam *IAM) appendAddOIDCIDPConfigEvent(event *es_models.Event) error {
config := new(OIDCIDPConfig)
err := config.SetData(event)
if err != nil {
return err
}
config.ObjectRoot.CreationDate = event.CreationDate
if i, idpConfig := GetIDPConfig(iam.IDPs, config.IDPConfigID); idpConfig != nil {
iam.IDPs[i].Type = int32(model.IDPConfigTypeOIDC)
iam.IDPs[i].OIDCIDPConfig = config
}
return nil
}
func (iam *IAM) appendChangeOIDCIDPConfigEvent(event *es_models.Event) error {
config := new(OIDCIDPConfig)
err := config.SetData(event)
if err != nil {
return err
}
if i, idpConfig := GetIDPConfig(iam.IDPs, config.IDPConfigID); idpConfig != nil {
iam.IDPs[i].OIDCIDPConfig.SetData(event)
}
return nil
}
func (o *OIDCIDPConfig) SetData(event *es_models.Event) error {
o.ObjectRoot.AppendEvent(event)
if err := json.Unmarshal(event.Data, o); err != nil {

View File

@ -1,10 +1,9 @@
package model
import (
"encoding/json"
"github.com/caos/zitadel/internal/crypto"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"testing"
"github.com/caos/zitadel/internal/crypto"
)
func TestOIDCIdpConfigChanges(t *testing.T) {
@ -72,85 +71,3 @@ func TestOIDCIdpConfigChanges(t *testing.T) {
})
}
}
func TestAppendAddOIDCIdpConfigEvent(t *testing.T) {
type args struct {
iam *IAM
config *OIDCIDPConfig
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add oidc idp config event",
args: args{
iam: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID"}}},
config: &OIDCIDPConfig{IDPConfigID: "IDPConfigID", ClientID: "ClientID"},
event: &es_models.Event{},
},
result: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", OIDCIDPConfig: &OIDCIDPConfig{IDPConfigID: "IDPConfigID", ClientID: "ClientID"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.config != nil {
data, _ := json.Marshal(tt.args.config)
tt.args.event.Data = data
}
tt.args.iam.appendAddOIDCIDPConfigEvent(tt.args.event)
if len(tt.args.iam.IDPs) != 1 {
t.Errorf("got wrong result should have one idpConfig actual: %v ", len(tt.args.iam.IDPs))
}
if tt.args.iam.IDPs[0].OIDCIDPConfig == nil {
t.Errorf("got wrong result should have oidc config actual: %v ", tt.args.iam.IDPs[0].OIDCIDPConfig)
}
if tt.args.iam.IDPs[0] == tt.result.IDPs[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.IDPs[0], tt.args.iam.IDPs[0])
}
})
}
}
func TestAppendChangeOIDCIdpConfigEvent(t *testing.T) {
type args struct {
iam *IAM
config *OIDCIDPConfig
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change oidc idp config event",
args: args{
iam: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", OIDCIDPConfig: &OIDCIDPConfig{IDPConfigID: "IDPConfigID", ClientID: "ClientID"}}}},
config: &OIDCIDPConfig{IDPConfigID: "IDPConfigID", ClientID: "ClientID Changed"},
event: &es_models.Event{},
},
result: &IAM{IDPs: []*IDPConfig{&IDPConfig{IDPConfigID: "IDPConfigID", OIDCIDPConfig: &OIDCIDPConfig{IDPConfigID: "IDPConfigID", ClientID: "ClientID Changed"}}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.config != nil {
data, _ := json.Marshal(tt.args.config)
tt.args.event.Data = data
}
tt.args.iam.appendChangeOIDCIDPConfigEvent(tt.args.event)
if len(tt.args.iam.IDPs) != 1 {
t.Errorf("got wrong result should have one idpConfig actual: %v ", len(tt.args.iam.IDPs))
}
if tt.args.iam.IDPs[0].OIDCIDPConfig == nil {
t.Errorf("got wrong result should have oidc config actual: %v ", tt.args.iam.IDPs[0].OIDCIDPConfig)
}
if tt.args.iam.IDPs[0] == tt.result.IDPs[0] {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.IDPs[0], tt.args.iam.IDPs[0])
}
})
}
}

View File

@ -32,20 +32,6 @@ func (p *OrgIAMPolicy) Changes(changed *OrgIAMPolicy) map[string]interface{} {
return changes
}
func (i *IAM) appendAddOrgIAMPolicyEvent(event *es_models.Event) error {
i.DefaultOrgIAMPolicy = new(OrgIAMPolicy)
err := i.DefaultOrgIAMPolicy.SetData(event)
if err != nil {
return err
}
i.DefaultOrgIAMPolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangeOrgIAMPolicyEvent(event *es_models.Event) error {
return i.DefaultOrgIAMPolicy.SetData(event)
}
func (p *OrgIAMPolicy) SetData(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {

View File

@ -1,10 +1,7 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestOrgIAMPolicyChanges(t *testing.T) {
@ -50,77 +47,3 @@ func TestOrgIAMPolicyChanges(t *testing.T) {
})
}
}
func TestAppendAddOrgIAMPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *OrgIAMPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add org iam policy event",
args: args{
iam: new(IAM),
policy: &OrgIAMPolicy{UserLoginMustBeDomain: true},
event: new(es_models.Event),
},
result: &IAM{DefaultOrgIAMPolicy: &OrgIAMPolicy{UserLoginMustBeDomain: true}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddOrgIAMPolicyEvent(tt.args.event)
if tt.result.DefaultOrgIAMPolicy.UserLoginMustBeDomain != tt.args.iam.DefaultOrgIAMPolicy.UserLoginMustBeDomain {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultOrgIAMPolicy.UserLoginMustBeDomain, tt.args.iam.DefaultOrgIAMPolicy.UserLoginMustBeDomain)
}
})
}
}
func TestAppendChangeOrgIAMPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *OrgIAMPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change org iam policy event",
args: args{
iam: &IAM{DefaultOrgIAMPolicy: &OrgIAMPolicy{
UserLoginMustBeDomain: true,
}},
policy: &OrgIAMPolicy{UserLoginMustBeDomain: false},
event: &es_models.Event{},
},
result: &IAM{DefaultOrgIAMPolicy: &OrgIAMPolicy{
UserLoginMustBeDomain: false,
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangeOrgIAMPolicyEvent(tt.args.event)
if tt.result.DefaultOrgIAMPolicy.UserLoginMustBeDomain != tt.args.iam.DefaultOrgIAMPolicy.UserLoginMustBeDomain {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultOrgIAMPolicy.UserLoginMustBeDomain, tt.args.iam.DefaultOrgIAMPolicy.UserLoginMustBeDomain)
}
})
}
}

View File

@ -37,20 +37,6 @@ func (p *PasswordAgePolicy) Changes(changed *PasswordAgePolicy) map[string]inter
return changes
}
func (i *IAM) appendAddPasswordAgePolicyEvent(event *es_models.Event) error {
i.DefaultPasswordAgePolicy = new(PasswordAgePolicy)
err := i.DefaultPasswordAgePolicy.SetData(event)
if err != nil {
return err
}
i.DefaultPasswordAgePolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangePasswordAgePolicyEvent(event *es_models.Event) error {
return i.DefaultPasswordAgePolicy.SetData(event)
}
func (p *PasswordAgePolicy) SetData(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {

View File

@ -1,8 +1,6 @@
package model
import (
"encoding/json"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"testing"
)
@ -49,80 +47,3 @@ func TestPasswordAgePolicyChanges(t *testing.T) {
})
}
}
func TestAppendAddPasswordAgePolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *PasswordAgePolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add password age policy event",
args: args{
iam: new(IAM),
policy: &PasswordAgePolicy{MaxAgeDays: 10, ExpireWarnDays: 10},
event: new(es_models.Event),
},
result: &IAM{DefaultPasswordAgePolicy: &PasswordAgePolicy{MaxAgeDays: 10, ExpireWarnDays: 10}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddPasswordAgePolicyEvent(tt.args.event)
if tt.result.DefaultPasswordAgePolicy.MaxAgeDays != tt.args.iam.DefaultPasswordAgePolicy.MaxAgeDays {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordAgePolicy.MaxAgeDays, tt.args.iam.DefaultPasswordAgePolicy.MaxAgeDays)
}
if tt.result.DefaultPasswordAgePolicy.ExpireWarnDays != tt.args.iam.DefaultPasswordAgePolicy.ExpireWarnDays {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordAgePolicy.ExpireWarnDays, tt.args.iam.DefaultPasswordAgePolicy.ExpireWarnDays)
}
})
}
}
func TestAppendChangePasswordAgePolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *PasswordAgePolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change password age policy event",
args: args{
iam: &IAM{DefaultPasswordAgePolicy: &PasswordAgePolicy{
MaxAgeDays: 10,
}},
policy: &PasswordAgePolicy{MaxAgeDays: 5},
event: &es_models.Event{},
},
result: &IAM{DefaultPasswordAgePolicy: &PasswordAgePolicy{
MaxAgeDays: 5,
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangePasswordAgePolicyEvent(tt.args.event)
if tt.result.DefaultPasswordAgePolicy.MaxAgeDays != tt.args.iam.DefaultPasswordAgePolicy.MaxAgeDays {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordAgePolicy.MaxAgeDays, tt.args.iam.DefaultPasswordAgePolicy.MaxAgeDays)
}
})
}
}

View File

@ -31,20 +31,6 @@ func PasswordComplexityPolicyToModel(policy *PasswordComplexityPolicy) *iam_mode
}
}
func (i *IAM) appendAddPasswordComplexityPolicyEvent(event *es_models.Event) error {
i.DefaultPasswordComplexityPolicy = new(PasswordComplexityPolicy)
err := i.DefaultPasswordComplexityPolicy.SetData(event)
if err != nil {
return err
}
i.DefaultPasswordComplexityPolicy.ObjectRoot.CreationDate = event.CreationDate
return nil
}
func (i *IAM) appendChangePasswordComplexityPolicyEvent(event *es_models.Event) error {
return i.DefaultPasswordComplexityPolicy.SetData(event)
}
func (p *PasswordComplexityPolicy) SetData(event *es_models.Event) error {
err := json.Unmarshal(event.Data, p)
if err != nil {

View File

@ -1,94 +0,0 @@
package model
import (
"encoding/json"
"testing"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestAppendAddPasswordComplexityPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *PasswordComplexityPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append add password complexity policy event",
args: args{
iam: new(IAM),
policy: &PasswordComplexityPolicy{MinLength: 10, HasUppercase: true, HasLowercase: true, HasNumber: true, HasSymbol: true},
event: new(es_models.Event),
},
result: &IAM{DefaultPasswordComplexityPolicy: &PasswordComplexityPolicy{MinLength: 10, HasUppercase: true, HasLowercase: true, HasNumber: true, HasSymbol: true}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendAddPasswordComplexityPolicyEvent(tt.args.event)
if tt.result.DefaultPasswordComplexityPolicy.MinLength != tt.args.iam.DefaultPasswordComplexityPolicy.MinLength {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordComplexityPolicy.MinLength, tt.args.iam.DefaultPasswordComplexityPolicy.MinLength)
}
if tt.result.DefaultPasswordComplexityPolicy.HasUppercase != tt.args.iam.DefaultPasswordComplexityPolicy.HasUppercase {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordComplexityPolicy.HasUppercase, tt.args.iam.DefaultPasswordComplexityPolicy.HasUppercase)
}
if tt.result.DefaultPasswordComplexityPolicy.HasLowercase != tt.args.iam.DefaultPasswordComplexityPolicy.HasLowercase {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordComplexityPolicy.HasLowercase, tt.args.iam.DefaultPasswordComplexityPolicy.HasLowercase)
}
if tt.result.DefaultPasswordComplexityPolicy.HasNumber != tt.args.iam.DefaultPasswordComplexityPolicy.HasNumber {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordComplexityPolicy.HasNumber, tt.args.iam.DefaultPasswordComplexityPolicy.HasNumber)
}
if tt.result.DefaultPasswordComplexityPolicy.HasSymbol != tt.args.iam.DefaultPasswordComplexityPolicy.HasSymbol {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordComplexityPolicy.HasSymbol, tt.args.iam.DefaultPasswordComplexityPolicy.HasSymbol)
}
})
}
}
func TestAppendChangePasswordComplexityPolicyEvent(t *testing.T) {
type args struct {
iam *IAM
policy *PasswordComplexityPolicy
event *es_models.Event
}
tests := []struct {
name string
args args
result *IAM
}{
{
name: "append change password complexity policy event",
args: args{
iam: &IAM{DefaultPasswordComplexityPolicy: &PasswordComplexityPolicy{
MinLength: 10,
}},
policy: &PasswordComplexityPolicy{MinLength: 5},
event: &es_models.Event{},
},
result: &IAM{DefaultPasswordComplexityPolicy: &PasswordComplexityPolicy{
MinLength: 5,
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.args.policy != nil {
data, _ := json.Marshal(tt.args.policy)
tt.args.event.Data = data
}
tt.args.iam.appendChangePasswordComplexityPolicyEvent(tt.args.event)
if tt.result.DefaultPasswordComplexityPolicy.MinLength != tt.args.iam.DefaultPasswordComplexityPolicy.MinLength {
t.Errorf("got wrong result: expected: %v, actual: %v ", tt.result.DefaultPasswordComplexityPolicy.MinLength, tt.args.iam.DefaultPasswordComplexityPolicy.MinLength)
}
})
}
}

View File

@ -44,6 +44,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
newNotifyUser(
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
systemDefaults.IamID,
queries,
),
newNotification(
handler{view, bulkLimit, configs.cycleDuration("Notification"), errorCount, es},

View File

@ -3,14 +3,11 @@ package handler
import (
"context"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1"
es_sdk "github.com/caos/zitadel/internal/eventstore/v1/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
iam_view "github.com/caos/zitadel/internal/iam/repository/view"
org_view "github.com/caos/zitadel/internal/org/repository/view"
query2 "github.com/caos/zitadel/internal/query"
"github.com/caos/logging"
@ -31,15 +28,18 @@ type NotifyUser struct {
handler
iamID string
subscription *v1.Subscription
queries *query2.Queries
}
func newNotifyUser(
handler handler,
iamID string,
queries *query2.Queries,
) *NotifyUser {
h := &NotifyUser{
handler: handler,
iamID: iamID,
queries: queries,
}
h.subscribe()
@ -170,7 +170,7 @@ func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *es_models.Event) error {
if err != nil {
return err
}
policy := org.OrgIamPolicy
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
@ -196,7 +196,7 @@ func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) e
if err != nil {
return err
}
policy := org.OrgIamPolicy
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
@ -225,7 +225,7 @@ func (u *NotifyUser) fillLoginNames(user *view_model.NotifyUser) (err error) {
if err != nil {
return err
}
policy := org.OrgIamPolicy
policy := new(query2.OrgIAMPolicy)
if policy == nil {
policy, err = u.getDefaultOrgIAMPolicy(context.Background())
if err != nil {
@ -268,30 +268,6 @@ func (u *NotifyUser) getOrgByID(ctx context.Context, orgID string) (*org_model.O
return org_es_model.OrgToModel(esOrg), nil
}
func (u *NotifyUser) getIAMByID(ctx context.Context) (*iam_model.IAM, error) {
query, err := iam_view.IAMByIDQuery(domain.IAMID, 0)
if err != nil {
return nil, err
}
iam := &model.IAM{
ObjectRoot: es_models.ObjectRoot{
AggregateID: domain.IAMID,
},
}
err = es_sdk.Filter(ctx, u.Eventstore().FilterEvents, iam.AppendEvents, query)
if err != nil && caos_errs.IsNotFound(err) && iam.Sequence == 0 {
return nil, err
}
return model.IAMToModel(iam), nil
}
func (u *NotifyUser) getDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicy, error) {
existingIAM, err := u.getIAMByID(ctx)
if err != nil {
return nil, err
}
if existingIAM.DefaultOrgIAMPolicy == nil {
return nil, caos_errs.ThrowNotFound(nil, "EVENT-2Fj8s", "Errors.IAM.OrgIAMPolicy.NotExisting")
}
return existingIAM.DefaultOrgIAMPolicy, nil
func (u *NotifyUser) getDefaultOrgIAMPolicy(ctx context.Context) (*query2.OrgIAMPolicy, error) {
return u.queries.DefaultOrgIAMPolicy(ctx)
}

View File

@ -1,7 +1,6 @@
package query
import (
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/iam/model"
@ -9,177 +8,11 @@ import (
func readModelToIAM(readModel *ReadModel) *model.IAM {
return &model.IAM{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel),
GlobalOrgID: readModel.GlobalOrgID,
IAMProjectID: readModel.ProjectID,
SetUpDone: readModel.SetUpDone,
SetUpStarted: readModel.SetUpStarted,
Members: readModelToMembers(&readModel.Members),
DefaultLabelPolicy: readModelToLabelPolicy(&readModel.DefaultLabelPolicy),
DefaultLoginPolicy: readModelToLoginPolicy(&readModel.DefaultLoginPolicy),
DefaultOrgIAMPolicy: readModelToOrgIAMPolicy(&readModel.DefaultOrgIAMPolicy),
DefaultPasswordAgePolicy: readModelToPasswordAgePolicy(&readModel.DefaultPasswordAgePolicy),
DefaultPasswordComplexityPolicy: readModelToPasswordComplexityPolicy(&readModel.DefaultPasswordComplexityPolicy),
DefaultLockoutPolicy: readModelToPasswordLockoutPolicy(&readModel.DefaultPasswordLockoutPolicy),
IDPs: readModelToIDPConfigs(&readModel.IDPs),
}
}
func readModelToIDPConfigView(rm *IAMIDPConfigReadModel) *domain.IDPConfigView {
converted := &domain.IDPConfigView{
AggregateID: rm.AggregateID,
ChangeDate: rm.ChangeDate,
CreationDate: rm.CreationDate,
IDPConfigID: rm.ConfigID,
IDPProviderType: rm.ProviderType,
IsOIDC: rm.OIDCConfig != nil,
Name: rm.Name,
Sequence: rm.ProcessedSequence,
State: rm.State,
StylingType: rm.StylingType,
}
if rm.OIDCConfig != nil {
converted.OIDCClientID = rm.OIDCConfig.ClientID
converted.OIDCClientSecret = rm.OIDCConfig.ClientSecret
converted.OIDCIDPDisplayNameMapping = rm.OIDCConfig.IDPDisplayNameMapping
converted.OIDCIssuer = rm.OIDCConfig.Issuer
converted.OIDCScopes = rm.OIDCConfig.Scopes
converted.OIDCUsernameMapping = rm.OIDCConfig.UserNameMapping
converted.OAuthAuthorizationEndpoint = rm.OIDCConfig.AuthorizationEndpoint
converted.OAuthTokenEndpoint = rm.OIDCConfig.TokenEndpoint
}
if rm.JWTConfig != nil {
converted.JWTEndpoint = rm.JWTConfig.JWTEndpoint
converted.JWTIssuer = rm.JWTConfig.Issuer
converted.JWTKeysEndpoint = rm.JWTConfig.KeysEndpoint
}
return converted
}
func readModelToMember(readModel *MemberReadModel) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel),
Roles: readModel.Roles,
UserID: readModel.UserID,
}
}
func readModelToMembers(readModel *IAMMembersReadModel) []*model.IAMMember {
members := make([]*model.IAMMember, len(readModel.Members))
for i, member := range readModel.Members {
members[i] = &model.IAMMember{
ObjectRoot: readModelToObjectRoot(member.ReadModel),
Roles: member.Roles,
UserID: member.UserID,
}
}
return members
}
func readModelToLabelPolicy(readModel *IAMLabelPolicyReadModel) *model.LabelPolicy {
return &model.LabelPolicy{
ObjectRoot: readModelToObjectRoot(readModel.LabelPolicyReadModel.ReadModel),
PrimaryColor: readModel.PrimaryColor,
BackgroundColor: readModel.BackgroundColor,
WarnColor: readModel.WarnColor,
FontColor: readModel.FontColor,
PrimaryColorDark: readModel.PrimaryColorDark,
BackgroundColorDark: readModel.BackgroundColorDark,
WarnColorDark: readModel.WarnColorDark,
FontColorDark: readModel.FontColorDark,
Default: true,
}
}
func readModelToLoginPolicy(readModel *IAMLoginPolicyReadModel) *model.LoginPolicy {
return &model.LoginPolicy{
ObjectRoot: readModelToObjectRoot(readModel.LoginPolicyReadModel.ReadModel),
AllowExternalIdp: readModel.AllowExternalIDP,
AllowRegister: readModel.AllowRegister,
AllowUsernamePassword: readModel.AllowUserNamePassword,
Default: true,
}
}
func readModelToOrgIAMPolicy(readModel *IAMOrgIAMPolicyReadModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: readModelToObjectRoot(readModel.OrgIAMPolicyReadModel.ReadModel),
UserLoginMustBeDomain: readModel.UserLoginMustBeDomain,
Default: true,
}
}
func readModelToPasswordAgePolicy(readModel *IAMPasswordAgePolicyReadModel) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: readModelToObjectRoot(readModel.PasswordAgePolicyReadModel.ReadModel),
ExpireWarnDays: readModel.ExpireWarnDays,
MaxAgeDays: readModel.MaxAgeDays,
}
}
func readModelToPasswordComplexityPolicy(readModel *IAMPasswordComplexityPolicyReadModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: readModelToObjectRoot(readModel.PasswordComplexityPolicyReadModel.ReadModel),
HasLowercase: readModel.HasLowercase,
HasNumber: readModel.HasNumber,
HasSymbol: readModel.HasSymbol,
HasUppercase: readModel.HasUpperCase,
MinLength: readModel.MinLength,
}
}
func readModelToPasswordLockoutPolicy(readModel *IAMLockoutPolicyReadModel) *model.LockoutPolicy {
return &model.LockoutPolicy{
ObjectRoot: readModelToObjectRoot(readModel.LockoutPolicyReadModel.ReadModel),
MaxPasswordAttempts: readModel.MaxAttempts,
ShowLockOutFailures: readModel.ShowLockOutFailures,
}
}
func readModelToIDPConfigs(rm *IAMIDPConfigsReadModel) []*model.IDPConfig {
configs := make([]*model.IDPConfig, len(rm.Configs))
for i, config := range rm.Configs {
configs[i] = readModelToIDPConfig(&IAMIDPConfigReadModel{IDPConfigReadModel: *config})
}
return configs
}
func readModelToIDPConfig(rm *IAMIDPConfigReadModel) *model.IDPConfig {
config := &model.IDPConfig{
ObjectRoot: readModelToObjectRoot(rm.ReadModel),
IDPConfigID: rm.ConfigID,
Name: rm.Name,
State: model.IDPConfigState(rm.State),
StylingType: model.IDPStylingType(rm.StylingType),
}
if rm.OIDCConfig != nil {
config.OIDCConfig = readModelToIDPOIDCConfig(rm.OIDCConfig)
}
if rm.JWTConfig != nil {
config.JWTIDPConfig = readModelToIDPJWTConfig(rm.JWTConfig)
}
return config
}
func readModelToIDPOIDCConfig(rm *OIDCConfigReadModel) *model.OIDCIDPConfig {
return &model.OIDCIDPConfig{
ObjectRoot: readModelToObjectRoot(rm.ReadModel),
ClientID: rm.ClientID,
ClientSecret: rm.ClientSecret,
ClientSecretString: string(rm.ClientSecret.Crypted),
IDPConfigID: rm.IDPConfigID,
IDPDisplayNameMapping: model.OIDCMappingField(rm.IDPDisplayNameMapping),
Issuer: rm.Issuer,
Scopes: rm.Scopes,
UsernameMapping: model.OIDCMappingField(rm.UserNameMapping),
}
}
func readModelToIDPJWTConfig(rm *JWTConfigReadModel) *model.JWTIDPConfig {
return &model.JWTIDPConfig{
ObjectRoot: readModelToObjectRoot(rm.ReadModel),
IDPConfigID: rm.IDPConfigID,
JWTEndpoint: rm.JWTEndpoint,
Issuer: rm.Issuer,
KeysEndpoint: rm.KeysEndpoint,
ObjectRoot: readModelToObjectRoot(readModel.ReadModel),
GlobalOrgID: readModel.GlobalOrgID,
IAMProjectID: readModel.ProjectID,
SetUpDone: readModel.SetUpDone,
SetUpStarted: readModel.SetUpStarted,
}
}

View File

@ -0,0 +1,122 @@
package projection
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/handler"
"github.com/caos/zitadel/internal/eventstore/handler/crdb"
"github.com/caos/zitadel/internal/repository/iam"
)
type IAMProjection struct {
crdb.StatementHandler
}
const (
IAMProjectionTable = "zitadel.projections.iam"
)
func NewIAMProjection(ctx context.Context, config crdb.StatementHandlerConfig) *IAMProjection {
p := &IAMProjection{}
config.ProjectionName = IAMProjectionTable
config.Reducers = p.reducers()
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
return p
}
func (p *IAMProjection) reducers() []handler.AggregateReducer {
return []handler.AggregateReducer{
{
Aggregate: iam.AggregateType,
EventRedusers: []handler.EventReducer{
{
Event: iam.GlobalOrgSetEventType,
Reduce: p.reduceGlobalOrgSet,
},
{
Event: iam.ProjectSetEventType,
Reduce: p.reduceIAMProjectSet,
},
{
Event: iam.SetupStartedEventType,
Reduce: p.reduceSetupEvent,
},
{
Event: iam.SetupDoneEventType,
Reduce: p.reduceSetupEvent,
},
},
},
}
}
type IAMColumn string
const (
IAMColumnID = "id"
IAMColumnChangeDate = "change_date"
IAMColumnGlobalOrgID = "global_org_id"
IAMColumnProjectID = "iam_project_id"
IAMColumnSequence = "sequence"
IAMColumnSetUpStarted = "setup_started"
IAMColumnSetUpDone = "setup_done"
)
func (p *IAMProjection) reduceGlobalOrgSet(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*iam.GlobalOrgSetEvent)
if !ok {
logging.LogWithFields("HANDL-3n89fs", "seq", event.Sequence(), "expectedType", iam.GlobalOrgSetEventType).Error("wrong event type")
return nil, errors.ThrowInvalidArgument(nil, "HANDL-2n9f2", "reduce.wrong.event.type")
}
return crdb.NewUpsertStatement(
e,
[]handler.Column{
handler.NewCol(IAMColumnID, e.Aggregate().ID),
handler.NewCol(IAMColumnChangeDate, e.CreationDate()),
handler.NewCol(IAMColumnSequence, e.Sequence()),
handler.NewCol(IAMColumnGlobalOrgID, e.OrgID),
},
), nil
}
func (p *IAMProjection) reduceIAMProjectSet(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*iam.ProjectSetEvent)
if !ok {
logging.LogWithFields("HANDL-2j9fw", "seq", event.Sequence(), "expectedType", iam.ProjectSetEventType).Error("wrong event type")
return nil, errors.ThrowInvalidArgument(nil, "HANDL-30o0e", "reduce.wrong.event.type")
}
return crdb.NewUpsertStatement(
e,
[]handler.Column{
handler.NewCol(IAMColumnID, e.Aggregate().ID),
handler.NewCol(IAMColumnChangeDate, e.CreationDate()),
handler.NewCol(IAMColumnSequence, e.Sequence()),
handler.NewCol(IAMColumnProjectID, e.ProjectID),
},
), nil
}
func (p *IAMProjection) reduceSetupEvent(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*iam.SetupStepEvent)
if !ok {
logging.LogWithFields("HANDL-39fjw", "seq", event.Sequence(), "expectedTypes", []eventstore.EventType{iam.SetupDoneEventType, iam.SetupStartedEventType}).Error("wrong event type")
return nil, errors.ThrowInvalidArgument(nil, "HANDL-d9nfw", "reduce.wrong.event.type")
}
columns := []handler.Column{
handler.NewCol(IAMColumnID, e.Aggregate().ID),
handler.NewCol(IAMColumnChangeDate, e.CreationDate()),
handler.NewCol(IAMColumnSequence, e.Sequence()),
}
if e.EventType == iam.SetupStartedEventType {
columns = append(columns, handler.NewCol(IAMColumnSetUpStarted, e.Step))
} else {
columns = append(columns, handler.NewCol(IAMColumnSetUpDone, e.Step))
}
return crdb.NewUpsertStatement(
e,
columns,
), nil
}

View File

@ -0,0 +1,158 @@
package projection
import (
"testing"
"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/handler"
"github.com/caos/zitadel/internal/eventstore/repository"
"github.com/caos/zitadel/internal/repository/iam"
)
func TestIAMProjection_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: "reduceGlobalOrgSet",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.GlobalOrgSetEventType),
iam.AggregateType,
[]byte(`{"globalOrgId": "orgid"}`),
), iam.GlobalOrgSetMapper),
},
reduce: (&IAMProjection{}).reduceGlobalOrgSet,
want: wantReduce{
projection: IAMProjectionTable,
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.iam (id, change_date, sequence, global_org_id) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
uint64(15),
"orgid",
},
},
},
},
},
},
{
name: "reduceGlobalOrgSet",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.ProjectSetEventType),
iam.AggregateType,
[]byte(`{"iamProjectId": "project-id"}`),
), iam.ProjectSetMapper),
},
reduce: (&IAMProjection{}).reduceIAMProjectSet,
want: wantReduce{
projection: IAMProjectionTable,
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.iam (id, change_date, sequence, iam_project_id) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
uint64(15),
"project-id",
},
},
},
},
},
},
{
name: "reduceSetupStarted",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.SetupStartedEventType),
iam.AggregateType,
[]byte(`{"Step": 1}`),
), iam.SetupStepMapper),
},
reduce: (&IAMProjection{}).reduceSetupEvent,
want: wantReduce{
projection: IAMProjectionTable,
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.iam (id, change_date, sequence, setup_started) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
uint64(15),
domain.Step1,
},
},
},
},
},
},
{
name: "reduceSetupDone",
args: args{
event: getEvent(testEvent(
repository.EventType(iam.SetupDoneEventType),
iam.AggregateType,
[]byte(`{"Step": 1}`),
), iam.SetupStepMapper),
},
reduce: (&IAMProjection{}).reduceSetupEvent,
want: wantReduce{
projection: IAMProjectionTable,
aggregateType: eventstore.AggregateType("iam"),
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPSERT INTO zitadel.projections.iam (id, change_date, sequence, setup_done) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
uint64(15),
domain.Step1,
},
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
event := baseEvent(t)
got, err := tt.reduce(event)
if _, ok := err.(errors.InvalidArgument); !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, tt.want)
})
}
}

View File

@ -67,6 +67,7 @@ func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, co
NewUserGrantProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["user_grants"]))
NewUserMetadataProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["user_metadata"]))
NewUserAuthMethodProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["user_auth_method"]))
NewIAMProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["iam"]))
_, err := NewKeyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["keys"]), defaults.KeyConfig, keyChan)
return err

View File

@ -4,7 +4,7 @@ import (
"encoding/json"
"time"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/query"
"github.com/caos/logging"
"github.com/lib/pq"
@ -99,7 +99,7 @@ func (u *NotifyUser) GenerateLoginName(domain string, appendDomain bool) string
return u.UserName + "@" + domain
}
func (u *NotifyUser) SetLoginNames(policy *iam_model.OrgIAMPolicy, domains []*org_model.OrgDomain) {
func (u *NotifyUser) SetLoginNames(policy *query.OrgIAMPolicy, domains []*org_model.OrgDomain) {
loginNames := make([]string, 0)
for _, d := range domains {
if d.Verified {

View File

@ -6,13 +6,13 @@ import (
"time"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/query"
"github.com/lib/pq"
req_model "github.com/caos/zitadel/internal/auth_request/model"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
org_model "github.com/caos/zitadel/internal/org/model"
user_repo "github.com/caos/zitadel/internal/repository/user"
"github.com/caos/zitadel/internal/user/model"
@ -227,7 +227,7 @@ func (u *UserView) GenerateLoginName(domain string, appendDomain bool) string {
return u.UserName + "@" + domain
}
func (u *UserView) SetLoginNames(policy *iam_model.OrgIAMPolicy, domains []*org_model.OrgDomain) {
func (u *UserView) SetLoginNames(policy *query.OrgIAMPolicy, domains []*org_model.OrgDomain) {
loginNames := make([]string, 0)
for _, d := range domains {
if d.Verified {

View File

@ -0,0 +1,12 @@
CREATE TABLE zitadel.projections.iam (
id STRING NOT NULL
, change_date TIMESTAMPTZ NOT NULL
, sequence INT8 NOT NULL
, global_org_id STRING DEFAULT ''
, iam_project_id STRING DEFAULT ''
, setup_started SMALLINT DEFAULT 0
, setup_done SMALLINT DEFAULT 0
, PRIMARY KEY (id)
);