new pkg structure (#1150)

* fix: split command query side

* fix: split command query side

* fix: members in correct pkg structure

* fix: label policy in correct pkg structure

* fix: structure

* fix: structure of login policy

* fix: identityprovider structure

* fix: org iam policy structure

* fix: password age policy structure

* fix: password complexity policy structure

* fix: password lockout policy structure

* fix: idp structure

* fix: user events structure

* fix: user write model

* fix: profile email changed command

* fix: address changed command

* fix: user states

* fix: user

* fix: org structure and add human

* begin iam setup command side

* setup

* step2

* step2

* fix: add user

* step2

* isvalid

* fix: folder structure v2 business

Co-authored-by: Fabiennne <fabienne.gerschwiler@gmail.com>
This commit is contained in:
Livio Amstutz 2021-01-04 14:52:13 +01:00 committed by GitHub
parent 762941f0ea
commit 21ffe1b0cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
260 changed files with 7917 additions and 6570 deletions

View File

@ -161,8 +161,8 @@ func startSetup(configPaths []string, localDevMode bool) {
ctx := context.Background()
setup, err := setup.StartSetup(conf.Eventstore, conf.SystemDefaults)
setup, err := setup.StartSetupV2(conf.Eventstore, conf.SystemDefaults)
logging.Log("SERVE-fD252").OnError(err).Panic("failed to start setup")
err = setup.Execute(ctx, conf.SetUp)
err = setup.ExecuteV2(ctx, conf.SetUp)
logging.Log("SERVE-djs3R").OnError(err).Panic("failed to execute setup")
}

View File

@ -26,53 +26,53 @@ SetUp:
Step1:
GlobalOrg: 'Global'
IAMProject: 'Zitadel'
DefaultLoginPolicy:
AllowUsernamePassword: true
AllowRegister: true
AllowExternalIdp: true
Orgs:
- Name: 'Global'
Domain: 'global.caos.ch'
Default: true
OrgIamPolicy: true
Users:
- FirstName: 'Global Org'
LastName: 'Administrator'
UserName: 'zitadel-global-org-admin@caos.ch'
Email: 'zitadel-global-org-admin@caos.ch'
Password: 'Password1!'
Owners:
- 'zitadel-global-org-admin@caos.ch'
- Name: 'CAOS AG'
Domain: 'caos.ch'
Users:
- FirstName: 'Zitadel'
LastName: 'Administrator'
UserName: 'zitadel-admin'
Email: 'zitadel-admin@caos.ch'
Password: 'Password1!'
Owners:
- 'zitadel-admin@caos.ch'
Projects:
- Name: 'Zitadel'
OIDCApps:
- Name: 'Management-API'
- Name: 'Auth-API'
- Name: 'Admin-API'
- Name: 'Zitadel Console'
RedirectUris:
- '$ZITADEL_CONSOLE/auth/callback'
PostLogoutRedirectUris:
- '$ZITADEL_CONSOLE/signedout'
ResponseTypes:
- $ZITADEL_CONSOLE_RESPONSE_TYPE
GrantTypes:
- $ZITADEL_CONSOLE_GRANT_TYPE
ApplicationType: 'USER_AGENT'
AuthMethodType: 'NONE'
DevMode: $ZITADEL_CONSOLE_DEV_MODE
Owners:
- 'zitadel-admin@caos.ch'
# DefaultLoginPolicy:
# AllowUsernamePassword: true
# AllowRegister: true
# AllowExternalIdp: true
# Orgs:
# - Name: 'Global'
# Domain: 'global.caos.ch'
# Default: true
# OrgIamPolicy: true
# Users:
# - FirstName: 'Global Org'
# LastName: 'Administrator'
# UserName: 'zitadel-global-org-admin@caos.ch'
# Email: 'zitadel-global-org-admin@caos.ch'
# Password: 'Password1!'
# Owners:
# - 'zitadel-global-org-admin@caos.ch'
# - Name: 'CAOS AG'
# Domain: 'caos.ch'
# Users:
# - FirstName: 'Zitadel'
# LastName: 'Administrator'
# UserName: 'zitadel-admin'
# Email: 'zitadel-admin@caos.ch'
# Password: 'Password1!'
# Owners:
# - 'zitadel-admin@caos.ch'
# Projects:
# - Name: 'Zitadel'
# OIDCApps:
# - Name: 'Management-API'
# - Name: 'Auth-API'
# - Name: 'Admin-API'
# - Name: 'Zitadel Console'
# RedirectUris:
# - '$ZITADEL_CONSOLE/auth/callback'
# PostLogoutRedirectUris:
# - '$ZITADEL_CONSOLE/signedout'
# ResponseTypes:
# - $ZITADEL_CONSOLE_RESPONSE_TYPE
# GrantTypes:
# - $ZITADEL_CONSOLE_GRANT_TYPE
# ApplicationType: 'USER_AGENT'
# AuthMethodType: 'NONE'
# DevMode: $ZITADEL_CONSOLE_DEV_MODE
# Owners:
# - 'zitadel-admin@caos.ch'
Step2:
DefaultPasswordComplexityPolicy:
MinLength: 8

View File

@ -2,6 +2,7 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
"strings"
caos_errs "github.com/caos/zitadel/internal/errors"
@ -18,7 +19,7 @@ import (
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
"github.com/caos/zitadel/internal/v2/command"
)
type IAMRepository struct {
@ -30,7 +31,8 @@ type IAMRepository struct {
SystemDefaults systemdefaults.SystemDefaults
Roles []string
IAMV2 *iam_business.Repository
IAMV2Command *command.CommandSide
IAMV2Query *query.QuerySide
}
func (repo *IAMRepository) IAMMemberByID(ctx context.Context, iamID, userID string) (*iam_model.IAMMemberView, error) {
@ -43,24 +45,24 @@ func (repo *IAMRepository) IAMMemberByID(ctx context.Context, iamID, userID stri
func (repo *IAMRepository) AddIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
member.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddMember(ctx, member)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddIAMMember(ctx, member)
}
return repo.IAMEventstore.AddIAMMember(ctx, member)
}
func (repo *IAMRepository) ChangeIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
member.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangeMember(ctx, member)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeIAMMember(ctx, member)
}
return repo.IAMEventstore.ChangeIAMMember(ctx, member)
}
func (repo *IAMRepository) RemoveIAMMember(ctx context.Context, userID string) error {
member := iam_model.NewIAMMember(repo.SystemDefaults.IamID, userID)
if repo.IAMV2 != nil {
return repo.IAMV2.RemoveMember(ctx, member)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.RemoveIAMMember(ctx, member)
}
return repo.IAMEventstore.RemoveIAMMember(ctx, member)
}
@ -97,8 +99,8 @@ func (repo *IAMRepository) GetIAMMemberRoles() []string {
}
func (repo *IAMRepository) IDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error) {
if repo.IAMV2 != nil {
return repo.IAMV2.IDPConfigByID(ctx, repo.SystemDefaults.IamID, idpConfigID)
if repo.IAMV2Command != nil {
return repo.IAMV2Query.DefaultIDPConfigByID(ctx, repo.SystemDefaults.IamID, idpConfigID)
}
idp, err := repo.View.IDPConfigByID(idpConfigID)
@ -110,37 +112,37 @@ func (repo *IAMRepository) IDPConfigByID(ctx context.Context, idpConfigID string
func (repo *IAMRepository) AddOIDCIDPConfig(ctx context.Context, idp *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
idp.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddIDPConfig(ctx, idp)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddDefaultIDPConfig(ctx, idp)
}
return repo.IAMEventstore.AddIDPConfig(ctx, idp)
}
func (repo *IAMRepository) ChangeIDPConfig(ctx context.Context, idp *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
idp.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangeIDPConfig(ctx, idp)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultIDPConfig(ctx, idp)
}
return repo.IAMEventstore.ChangeIDPConfig(ctx, idp)
}
func (repo *IAMRepository) DeactivateIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
if repo.IAMV2 != nil {
return repo.IAMV2.DeactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.DeactivateDefaultIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
}
return repo.IAMEventstore.DeactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
}
func (repo *IAMRepository) ReactivateIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
if repo.IAMV2 != nil {
return repo.IAMV2.ReactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ReactivateDefaultIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
}
return repo.IAMEventstore.ReactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
}
func (repo *IAMRepository) RemoveIDPConfig(ctx context.Context, idpConfigID string) error {
// if repo.IAMV2 != nil {
// return repo.IAMV2.
// if repo.IAMV2Command != nil {
// return repo.IAMV2Command.
// }
aggregates := make([]*es_models.Aggregate, 0)
idp := iam_model.NewIDPConfig(repo.SystemDefaults.IamID, idpConfigID)
@ -184,8 +186,8 @@ func (repo *IAMRepository) RemoveIDPConfig(ctx context.Context, idpConfigID stri
func (repo *IAMRepository) ChangeOidcIDPConfig(ctx context.Context, oidcConfig *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) {
oidcConfig.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangeIDPOIDCConfig(ctx, oidcConfig)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultIDPOIDCConfig(ctx, oidcConfig)
}
return repo.IAMEventstore.ChangeIDPOIDCConfig(ctx, oidcConfig)
}
@ -238,16 +240,16 @@ func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_mode
func (repo *IAMRepository) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddLabelPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddDefaultLabelPolicy(ctx, policy)
}
return repo.IAMEventstore.AddLabelPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangeLabelPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultLabelPolicy(ctx, policy)
}
return repo.IAMEventstore.ChangeLabelPolicy(ctx, policy)
}
@ -279,16 +281,16 @@ func (repo *IAMRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_mode
func (repo *IAMRepository) AddDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddLoginPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddDefaultLoginPolicy(ctx, policy)
}
return repo.IAMEventstore.AddLoginPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangeLoginPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultLoginPolicy(ctx, policy)
}
return repo.IAMEventstore.ChangeLoginPolicy(ctx, policy)
}
@ -317,8 +319,8 @@ func (repo *IAMRepository) SearchDefaultIDPProviders(ctx context.Context, reques
func (repo *IAMRepository) AddIDPProviderToLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
provider.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddIDPProviderToLoginPolicy(ctx, provider)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddIDPProviderToDefaultLoginPolicy(ctx, provider)
}
return repo.IAMEventstore.AddIDPProviderToLoginPolicy(ctx, provider)
}
@ -360,15 +362,15 @@ func (repo *IAMRepository) SearchDefaultSecondFactors(ctx context.Context) (*iam
}
func (repo *IAMRepository) AddSecondFactorToLoginPolicy(ctx context.Context, mfa iam_model.SecondFactorType) (iam_model.SecondFactorType, error) {
if repo.IAMV2 != nil {
return repo.IAMV2.AddSecondFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddSecondFactorToDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
return repo.IAMEventstore.AddSecondFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
func (repo *IAMRepository) RemoveSecondFactorFromLoginPolicy(ctx context.Context, mfa iam_model.SecondFactorType) error {
if repo.IAMV2 != nil {
return repo.IAMV2.RemoveSecondFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.RemoveSecondFactorFromDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
return repo.IAMEventstore.RemoveSecondFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
@ -385,15 +387,15 @@ func (repo *IAMRepository) SearchDefaultMultiFactors(ctx context.Context) (*iam_
}
func (repo *IAMRepository) AddMultiFactorToLoginPolicy(ctx context.Context, mfa iam_model.MultiFactorType) (iam_model.MultiFactorType, error) {
if repo.IAMV2 != nil {
return repo.IAMV2.AddMultiFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddMultiFactorToDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
return repo.IAMEventstore.AddMultiFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
func (repo *IAMRepository) RemoveMultiFactorFromLoginPolicy(ctx context.Context, mfa iam_model.MultiFactorType) error {
if repo.IAMV2 != nil {
return repo.IAMV2.RemoveMultiFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.RemoveMultiFactorFromDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
return repo.IAMEventstore.RemoveMultiFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
}
@ -425,16 +427,16 @@ func (repo *IAMRepository) GetDefaultPasswordComplexityPolicy(ctx context.Contex
func (repo *IAMRepository) AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddPasswordComplexityPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddDefaultPasswordComplexityPolicy(ctx, policy)
}
return repo.IAMEventstore.AddPasswordComplexityPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangePasswordComplexityPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultPasswordComplexityPolicy(ctx, policy)
}
return repo.IAMEventstore.ChangePasswordComplexityPolicy(ctx, policy)
}
@ -466,16 +468,16 @@ func (repo *IAMRepository) GetDefaultPasswordAgePolicy(ctx context.Context) (*ia
func (repo *IAMRepository) AddDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddPasswordAgePolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddDefaultPasswordAgePolicy(ctx, policy)
}
return repo.IAMEventstore.AddPasswordAgePolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangePasswordAgePolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultPasswordAgePolicy(ctx, policy)
}
return repo.IAMEventstore.ChangePasswordAgePolicy(ctx, policy)
}
@ -507,16 +509,16 @@ func (repo *IAMRepository) GetDefaultPasswordLockoutPolicy(ctx context.Context)
func (repo *IAMRepository) AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddPasswordLockoutPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddDefaultPasswordLockoutPolicy(ctx, policy)
}
return repo.IAMEventstore.AddPasswordLockoutPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangePasswordLockoutPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultPasswordLockoutPolicy(ctx, policy)
}
return repo.IAMEventstore.ChangePasswordLockoutPolicy(ctx, policy)
}
@ -548,16 +550,16 @@ func (repo *IAMRepository) GetOrgIAMPolicy(ctx context.Context) (*iam_model.OrgI
func (repo *IAMRepository) AddDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.AddOrgIAMPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.AddDefaultOrgIAMPolicy(ctx, policy)
}
return repo.IAMEventstore.AddOrgIAMPolicy(ctx, policy)
}
func (repo *IAMRepository) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil {
return repo.IAMV2.ChangeOrgIAMPolicy(ctx, policy)
if repo.IAMV2Command != nil {
return repo.IAMV2Command.ChangeDefaultOrgIAMPolicy(ctx, policy)
}
return repo.IAMEventstore.ChangeOrgIAMPolicy(ctx, policy)
}

View File

@ -2,6 +2,8 @@ package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/v2/command"
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/eventstore"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/handler"
@ -14,7 +16,6 @@ import (
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
)
type Config struct {
@ -65,7 +66,11 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
if err != nil {
return nil, err
}
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
iamV2Command, err := command.StartCommandSide(&command.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
@ -90,7 +95,8 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
SystemDefaults: systemDefaults,
SearchLimit: conf.SearchLimit,
Roles: roles,
IAMV2: iamV2,
IAMV2Command: iamV2Command,
IAMV2Query: iamV2Query,
},
AdministratorRepo: eventstore.AdministratorRepo{
View: view,

View File

@ -6,6 +6,7 @@ import (
auth_es "github.com/caos/zitadel/internal/auth/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/metrics"
"github.com/caos/zitadel/internal/telemetry/metrics/otel"
"github.com/caos/zitadel/internal/v2/domain"
view_model "github.com/caos/zitadel/internal/view/model"
"go.opentelemetry.io/otel/api/metric"
"net/http"
@ -98,10 +99,10 @@ func (a *API) healthHandler() http.Handler {
if err != nil && !errors.IsNotFound(err) {
return errors.ThrowPreconditionFailed(err, "API-dsgT2", "IAM SETUP CHECK FAILED")
}
if iam == nil || iam.SetUpStarted < iam_model.StepCount-1 {
if iam == nil || iam.SetUpStarted < domain.StepCount-1 {
return errors.ThrowPreconditionFailed(nil, "API-HBfs3", "IAM NOT SET UP")
}
if iam.SetUpDone < iam_model.StepCount-1 {
if iam.SetUpDone < domain.StepCount-1 {
return errors.ThrowPreconditionFailed(nil, "API-DASs2", "IAM SETUP RUNNING")
}
return nil

View File

@ -2,6 +2,7 @@ package management
import (
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/pkg/grpc/management"
)
@ -14,11 +15,11 @@ func iamFromModel(iam *iam_model.IAM) *management.Iam {
}
}
func iamSetupStepFromModel(step iam_model.Step) management.IamSetupStep {
func iamSetupStepFromModel(step domain.Step) management.IamSetupStep {
switch step {
case iam_model.Step1:
case domain.Step1:
return management.IamSetupStep_iam_setup_step_1
case iam_model.Step2:
case domain.Step2:
return management.IamSetupStep_iam_setup_step_2
// case iam_model.Step3:
// return management.IamSetupStep_iam_setup_step_3

View File

@ -2,17 +2,17 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/iam/model"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
)
type IAMRepository struct {
IAMID string
IAMV2 *iam_business.Repository
IAMV2QuerySide *query.QuerySide
}
func (repo *IAMRepository) GetIAM(ctx context.Context) (*model.IAM, error) {
return repo.IAMV2.IAMByID(ctx, repo.IAMID)
return repo.IAMV2QuerySide.IAMByID(ctx, repo.IAMID)
}

View File

@ -5,13 +5,13 @@ import (
"strings"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/model"
@ -25,6 +25,7 @@ import (
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
grant_es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
)
type UserGrant struct {
@ -308,7 +309,7 @@ func (u *UserGrant) setIamProjectID() error {
return err
}
if iam.SetUpDone < iam_model.StepCount-1 {
if iam.SetUpDone < domain.StepCount-1 {
return caos_errs.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done")
}
u.iamProjectID = iam.IAMProjectID

View File

@ -20,7 +20,7 @@ import (
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
"github.com/caos/zitadel/internal/v2/query"
)
type Config struct {
@ -110,7 +110,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, au
return nil, err
}
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
@ -182,8 +182,8 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, au
SystemDefaults: systemDefaults,
},
eventstore.IAMRepository{
IAMID: systemDefaults.IamID,
IAMV2: iamV2,
IAMID: systemDefaults.IamID,
IAMV2QuerySide: iamV2Query,
},
}, nil
}

View File

@ -2,17 +2,17 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/iam/model"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
)
type IamRepo struct {
IAMID string
IAMEvents *iam_event.IAMEventstore
IAMV2 *iam_business.Repository
IAMV2Query *query.QuerySide
}
func (repo *IamRepo) Health(ctx context.Context) error {
@ -20,5 +20,5 @@ func (repo *IamRepo) Health(ctx context.Context) error {
}
func (repo *IamRepo) IamByID(ctx context.Context) (*model.IAM, error) {
return repo.IAMV2.IAMByID(ctx, repo.IAMID)
return repo.IAMV2Query.IAMByID(ctx, repo.IAMID)
}

View File

@ -6,10 +6,10 @@ import (
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
grant_model "github.com/caos/zitadel/internal/usergrant/model"
"github.com/caos/zitadel/internal/usergrant/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
)
type UserGrantRepo struct {
@ -72,7 +72,7 @@ func (repo *UserGrantRepo) FillIamProjectID(ctx context.Context) error {
if err != nil {
return err
}
if iam.SetUpDone < iam_model.StepCount-1 {
if iam.SetUpDone < domain.StepCount-1 {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-skiwS", "Setup not done")
}
repo.IamProjectID = iam.IAMProjectID

View File

@ -12,12 +12,12 @@ import (
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
)
type UserGrant struct {
@ -224,7 +224,7 @@ func (u *UserGrant) setIamProjectID() error {
if err != nil {
return err
}
if iam.SetUpDone < iam_model.StepCount-1 {
if iam.SetUpDone < domain.StepCount-1 {
return caos_errs.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done")
}
u.iamProjectID = iam.IAMProjectID

View File

@ -2,6 +2,7 @@ package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
@ -19,7 +20,6 @@ import (
"github.com/caos/zitadel/internal/id"
es_key "github.com/caos/zitadel/internal/key/repository/eventsourcing"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
)
type Config struct {
@ -79,7 +79,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults) (*
if err != nil {
return nil, err
}
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
iamV2, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
@ -96,9 +96,9 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults) (*
IamEvents: iam,
},
eventstore.IamRepo{
IAMID: systemDefaults.IamID,
IAMEvents: iam,
IAMV2: iamV2,
IAMID: systemDefaults.IamID,
IAMEvents: iam,
IAMV2Query: iamV2,
},
eventstore.TokenVerifierRepo{
//TODO: Add Token Verification Key

View File

@ -59,7 +59,7 @@ func (data *Data) createTemplate(templateName string, file *os.File) {
}
func readErrorName() (errorName string) {
flag.StringVar(&errorName, "Name", "", "Type of the error (e.g. Internal)")
flag.StringVar(&errorName, "Name", "", "KeyType of the error (e.g. Internal)")
flag.Parse()
return errorName
}

View File

@ -3,7 +3,7 @@ package eventstore
type aggregater interface {
//ID returns the aggreagte id
ID() string
//Type returns the aggregate type
//KeyType returns the aggregate type
Type() AggregateType
//Events returns the events which will be pushed
Events() []EventPusher
@ -74,7 +74,7 @@ func (a *Aggregate) ID() string {
return a.id
}
//Type implements aggregater
//KeyType implements aggregater
func (a *Aggregate) Type() AggregateType {
return a.typ
}

View File

@ -9,7 +9,7 @@ type EventPusher interface {
EditorService() string
//EditorUser is the user who wants to push the event
EditorUser() string
//Type must return an event type which should be unique in the aggregate
//KeyType must return an event type which should be unique in the aggregate
Type() EventType
//Data returns the payload of the event. It represent the changed fields by the event
// valid types are:
@ -25,7 +25,7 @@ type EventReader interface {
EditorService() string
//EditorUser is the user who pushed the event
EditorUser() string
//Type is the type of the event
//KeyType is the type of the event
Type() EventType
AggregateID() string

View File

@ -36,7 +36,7 @@ func (e *BaseEvent) EditorUser() string {
return e.User
}
//Type implements EventPusher
//KeyType implements EventPusher
func (e *BaseEvent) Type() EventType {
return e.EventType
}

View File

@ -6,7 +6,7 @@ import (
"log"
)
//ReadModel is the minimum representation of a View model.
//MemberReadModel is the minimum representation of a View model.
// it might be saved in a database or in memory
type ReadModel struct {
ProcessedSequence uint64

View File

@ -2,7 +2,7 @@ package eventstore
import "time"
//ReadModel is the minimum representation of a View model.
//MemberReadModel is the minimum representation of a View model.
// It implements a basic reducer
// it might be saved in a database or in memory
type ReadModel struct {

View File

@ -26,7 +26,7 @@ type Event struct {
// time drifts in different services could cause integrity problems
CreationDate time.Time
//Type describes the cause of the event (e.g. user.added)
//KeyType describes the cause of the event (e.g. user.added)
// it should always be in past-form
Type EventType

View File

@ -2,7 +2,7 @@ package eventstore
import "time"
//WriteModel is the minimum representation of a command side view model.
//MemberWriteModel is the minimum representation of a command side view model.
// It implements a basic reducer
// it's purpose is to reduce events to create new ones
type WriteModel struct {

View File

@ -2,6 +2,7 @@ package model
import (
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/v2/domain"
)
type Step int
@ -23,8 +24,8 @@ type IAM struct {
es_models.ObjectRoot
GlobalOrgID string
IAMProjectID string
SetUpDone Step
SetUpStarted Step
SetUpDone domain.Step
SetUpStarted domain.Step
Members []*IAMMember
IDPs []*IDPConfig
DefaultLoginPolicy *LoginPolicy

View File

@ -22,6 +22,8 @@ type PasswordComplexityPolicy struct {
HasUppercase bool
HasNumber bool
HasSymbol bool
Default bool
}
func (p *PasswordComplexityPolicy) IsValid() error {
@ -30,3 +32,26 @@ func (p *PasswordComplexityPolicy) IsValid() error {
}
return nil
}
func (p *PasswordComplexityPolicy) Check(password string) error {
if p.MinLength != 0 && uint64(len(password)) < p.MinLength {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-HuJf6", "Errors.User.PasswordComplexityPolicy.MinLength")
}
if p.HasLowercase && !hasStringLowerCase(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-co3Xw", "Errors.User.PasswordComplexityPolicy.HasLower")
}
if p.HasUppercase && !hasStringUpperCase(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-VoaRj", "Errors.User.PasswordComplexityPolicy.HasUpper")
}
if p.HasNumber && !hasNumber(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-ZBv4H", "Errors.User.PasswordComplexityPolicy.HasNumber")
}
if p.HasSymbol && !hasSymbol(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-ZDLwA", "Errors.User.PasswordComplexityPolicy.HasSymbol")
}
return nil
}

View File

@ -73,49 +73,49 @@ func (es *IAMEventstore) IAMEventsByID(ctx context.Context, id string, sequence
return es.FilterEvents(ctx, query)
}
func (es *IAMEventstore) StartSetup(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := es.IAMByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if iam != nil && (iam.SetUpStarted >= step || iam.SetUpStarted != iam.SetUpDone) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "Setup already started")
}
if iam == nil {
iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: iamID}}
}
iam.SetUpStarted = step
repoIAM := model.IAMFromModel(iam)
createAggregate := IAMSetupStartedAggregate(es.AggregateCreator(), repoIAM)
err = es_sdk.Push(ctx, es.PushAggregates, repoIAM.AppendEvents, createAggregate)
if err != nil {
return nil, err
}
es.iamCache.cacheIAM(repoIAM)
return model.IAMToModel(repoIAM), nil
}
func (es *IAMEventstore) SetupDone(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := es.IAMByID(ctx, iamID)
if err != nil {
return nil, err
}
iam.SetUpDone = step
repoIam := model.IAMFromModel(iam)
createAggregate := IAMSetupDoneAggregate(es.AggregateCreator(), repoIam)
err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, createAggregate)
if err != nil {
return nil, err
}
es.iamCache.cacheIAM(repoIam)
return model.IAMToModel(repoIam), nil
}
//func (es *IAMEventstore) StartSetup(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
// iam, err := es.IAMByID(ctx, iamID)
// if err != nil && !caos_errs.IsNotFound(err) {
// return nil, err
// }
//
// if iam != nil && (iam.SetUpStarted >= step || iam.SetUpStarted != iam.SetUpDone) {
// return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "Setup already started")
// }
//
// if iam == nil {
// iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: iamID}}
// }
// iam.SetUpStarted = step
// repoIAM := model.IAMFromModel(iam)
//
// createAggregate := IAMSetupStartedAggregate(es.AggregateCreator(), repoIAM)
// err = es_sdk.Push(ctx, es.PushAggregates, repoIAM.AppendEvents, createAggregate)
// if err != nil {
// return nil, err
// }
//
// es.iamCache.cacheIAM(repoIAM)
// return model.IAMToModel(repoIAM), nil
//}
//
//func (es *IAMEventstore) SetupDone(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
// iam, err := es.IAMByID(ctx, iamID)
// if err != nil {
// return nil, err
// }
// iam.SetUpDone = step
//
// repoIam := model.IAMFromModel(iam)
// createAggregate := IAMSetupDoneAggregate(es.AggregateCreator(), repoIam)
// err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, createAggregate)
// if err != nil {
// return nil, err
// }
//
// es.iamCache.cacheIAM(repoIam)
// return model.IAMToModel(repoIam), nil
//}
func (es *IAMEventstore) PrepareSetupDone(ctx context.Context, iam *model.IAM, aggregate *models.Aggregate, step iam_model.Step) (*model.IAM, *models.Aggregate, func(ctx context.Context, aggregates ...*models.Aggregate) error, error) {
iam.SetUpDone = model.Step(step)

View File

@ -1562,7 +1562,7 @@ func TestAddIdpProviderToLoginPolicy(t *testing.T) {
t.Errorf("got wrong result IDPConfigID: expected: %v, actual: %v ", tt.res.result.IDPConfigID, result.IDPConfigID)
}
if result.Type != tt.res.result.Type {
t.Errorf("got wrong result Type: expected: %v, actual: %v ", tt.res.result.Type, result.Type)
t.Errorf("got wrong result KeyType: expected: %v, actual: %v ", tt.res.result.Type, result.Type)
}
})
}

View File

@ -7,6 +7,7 @@ import (
caos_errs "github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
)
const (
@ -75,8 +76,8 @@ func IAMToModel(iam *IAM) *model.IAM {
idps := IDPConfigsToModel(iam.IDPs)
converted := &model.IAM{
ObjectRoot: iam.ObjectRoot,
SetUpStarted: model.Step(iam.SetUpStarted),
SetUpDone: model.Step(iam.SetUpDone),
SetUpStarted: domain.Step(iam.SetUpStarted),
SetUpDone: domain.Step(iam.SetUpDone),
GlobalOrgID: iam.GlobalOrgID,
IAMProjectID: iam.IAMProjectID,
Members: members,

View File

@ -2,15 +2,15 @@ package eventstore
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
)
type IAMRepository struct {
IAMV2 *iam_business.Repository
IAMV2Query *query.QuerySide
}
func (repo *IAMRepository) IAMByID(ctx context.Context, id string) (*iam_model.IAM, error) {
return repo.IAMV2.IAMByID(ctx, id)
return repo.IAMV2Query.IAMByID(ctx, id)
}

View File

@ -2,6 +2,7 @@ package eventsourcing
import (
"context"
"github.com/caos/zitadel/internal/v2/query"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/config/types"
@ -17,7 +18,6 @@ import (
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
es_grant "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
)
type Config struct {
@ -75,7 +75,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe
if err != nil {
return nil, err
}
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
@ -98,7 +98,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe
UserRepo: eventstore.UserRepo{es, conf.SearchLimit, user, org, usergrant, view, systemDefaults},
UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, usergrant, view},
IAMRepository: eventstore.IAMRepository{
IAMV2: iamV2,
IAMV2Query: iamV2Query,
},
}, nil
}

View File

@ -32,9 +32,9 @@ func (msg *EmailMessage) GetContent() string {
}
//default mime-type is html
mime := "MIME-version: 1.0;" + lineBreak + "Content-Type: text/html; charset=\"UTF-8\";" + lineBreak + lineBreak
mime := "MIME-version: 1.0;" + lineBreak + "Content-KeyType: text/html; charset=\"UTF-8\";" + lineBreak + lineBreak
if !isHTML(msg.Content) {
mime = "MIME-version: 1.0;" + lineBreak + "Content-Type: text/plain; charset=\"UTF-8\";" + lineBreak + lineBreak
mime = "MIME-version: 1.0;" + lineBreak + "Content-KeyType: text/plain; charset=\"UTF-8\";" + lineBreak + lineBreak
}
subject := "Subject: " + msg.Subject + lineBreak
message += subject + mime + lineBreak + msg.Content

View File

@ -2637,7 +2637,7 @@ func TestAddIdpProviderToLoginPolicy(t *testing.T) {
t.Errorf("got wrong result IDPConfigID: expected: %v, actual: %v ", tt.res.result.IDPConfigID, result.IDPConfigID)
}
if result.Type != tt.res.result.Type {
t.Errorf("got wrong result Type: expected: %v, actual: %v ", tt.res.result.Type, result.Type)
t.Errorf("got wrong result KeyType: expected: %v, actual: %v ", tt.res.result.Type, result.Type)
}
})
}

View File

@ -314,7 +314,7 @@ func TestLoginPolicyIdpProviderAddedAggregate(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
agg, err := LoginPolicyIDPProviderAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "IAMID")(tt.args.ctx)
agg, err := LoginPolicyIDPProviderAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "iamID")(tt.args.ctx)
if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err)
return
@ -509,7 +509,7 @@ func TestLoginPolicySecondFactorAddedAggregate(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
agg, err := LoginPolicySecondFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "IAMID")(tt.args.ctx)
agg, err := LoginPolicySecondFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "iamID")(tt.args.ctx)
if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err)
return
@ -682,7 +682,7 @@ func TestLoginPolicyMultiFactorAddedAggregate(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
agg, err := LoginPolicyMultiFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "IAMID")(tt.args.ctx)
agg, err := LoginPolicyMultiFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "iamID")(tt.args.ctx)
if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err)
return

View File

@ -7,28 +7,28 @@ import (
type IAMSetUp struct {
Step1 *Step1
Step2 *Step2
Step3 *Step3
Step4 *Step4
Step5 *Step5
Step6 *Step6
Step7 *Step7
Step8 *Step8
//Step2 *Step2
//Step3 *Step3
//Step4 *Step4
//Step5 *Step5
//Step6 *Step6
//Step7 *Step7
//Step8 *Step8
}
func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) {
steps := make([]step, 0)
func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]stepV2, error) {
steps := make([]stepV2, 0)
missingSteps := make([]iam_model.Step, 0)
for _, step := range []step{
for _, step := range []stepV2{
setup.Step1,
setup.Step2,
setup.Step3,
setup.Step4,
setup.Step5,
setup.Step6,
setup.Step7,
setup.Step8,
//setup.Step2,
//setup.Step3,
//setup.Step4,
//setup.Step5,
//setup.Step6,
//setup.Step7,
//setup.Step8,
} {
if step.step() <= currentDone {
continue

View File

@ -3,24 +3,12 @@ package setup
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
proj_model "github.com/caos/zitadel/internal/project/model"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/v2/command"
)
type Setup struct {
@ -29,6 +17,8 @@ type Setup struct {
OrgEvents *org_event.OrgEventstore
UserEvents *usr_event.UserEventstore
ProjectEvents *proj_event.ProjectEventstore
Commands *command.CommandSide
}
const (
@ -48,168 +38,169 @@ const (
OIDCAuthMethodTypePost = "POST"
)
func StartSetup(esConfig es_int.Config, sd systemdefaults.SystemDefaults) (*Setup, error) {
setup := &Setup{
iamID: sd.IamID,
}
es, err := es_int.Start(esConfig)
if err != nil {
return nil, err
}
setup.IamEvents, err = es_iam.StartIAM(es_iam.IAMConfig{
Eventstore: es,
Cache: esConfig.Cache,
}, sd)
if err != nil {
return nil, err
}
setup.OrgEvents = es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: sd.Domain}, sd)
setup.ProjectEvents, err = es_proj.StartProject(es_proj.ProjectConfig{
Eventstore: es,
Cache: esConfig.Cache,
}, sd)
if err != nil {
return nil, err
}
setup.UserEvents, err = es_usr.StartUser(es_usr.UserConfig{
Eventstore: es,
Cache: esConfig.Cache,
}, sd)
if err != nil {
return nil, err
}
return setup, nil
}
func (s *Setup) Execute(ctx context.Context, setUpConfig IAMSetUp) error {
logging.Log("SETUP-hwG32").Info("starting setup")
iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return err
}
if iam != nil && (iam.SetUpDone == iam_model.StepCount-1 || iam.SetUpStarted != iam.SetUpDone) {
logging.Log("SETUP-cWEsn").Info("all steps done")
return nil
}
if iam == nil {
iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: s.iamID}}
}
steps, err := setUpConfig.steps(iam.SetUpDone)
if err != nil || len(steps) == 0 {
return err
}
ctx = setSetUpContextData(ctx, s.iamID)
for _, step := range steps {
step.init(s)
if step.step() != iam.SetUpDone+1 {
logging.LogWithFields("SETUP-rxRM1", "step", step.step(), "previous", iam.SetUpDone).Warn("wrong step order")
return errors.ThrowPreconditionFailed(nil, "SETUP-wwAqO", "too few steps for this zitadel verison")
}
iam, err = s.IamEvents.StartSetup(ctx, s.iamID, step.step())
if err != nil {
return err
}
iam, err = step.execute(ctx)
if err != nil {
return err
}
err = s.validateExecutedStep(ctx)
if err != nil {
return err
}
}
logging.Log("SETUP-ds31h").Info("setup done")
return nil
}
func (s *Setup) validateExecutedStep(ctx context.Context) error {
iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
if err != nil {
return err
}
if iam.SetUpStarted != iam.SetUpDone {
return errors.ThrowInternal(nil, "SETUP-QeukK", "started step is not equal to done")
}
return nil
}
func getOIDCResponseTypes(responseTypes []string) []proj_model.OIDCResponseType {
types := make([]proj_model.OIDCResponseType, len(responseTypes))
for i, t := range responseTypes {
types[i] = getOIDCResponseType(t)
}
return types
}
func getOIDCResponseType(responseType string) proj_model.OIDCResponseType {
switch responseType {
case OIDCResponseTypeCode:
return proj_model.OIDCResponseTypeCode
case OIDCResponseTypeIDToken:
return proj_model.OIDCResponseTypeIDToken
case OIDCResponseTypeToken:
return proj_model.OIDCResponseTypeIDTokenToken
}
return proj_model.OIDCResponseTypeCode
}
func getOIDCGrantTypes(grantTypes []string) []proj_model.OIDCGrantType {
types := make([]proj_model.OIDCGrantType, len(grantTypes))
for i, t := range grantTypes {
types[i] = getOIDCGrantType(t)
}
return types
}
func getOIDCGrantType(grantTypes string) proj_model.OIDCGrantType {
switch grantTypes {
case OIDCGrantTypeAuthorizationCode:
return proj_model.OIDCGrantTypeAuthorizationCode
case OIDCGrantTypeImplicit:
return proj_model.OIDCGrantTypeImplicit
case OIDCGrantTypeRefreshToken:
return proj_model.OIDCGrantTypeRefreshToken
}
return proj_model.OIDCGrantTypeAuthorizationCode
}
func getOIDCApplicationType(appType string) proj_model.OIDCApplicationType {
switch appType {
case OIDCApplicationTypeNative:
return proj_model.OIDCApplicationTypeNative
case OIDCApplicationTypeUserAgent:
return proj_model.OIDCApplicationTypeUserAgent
case OIDCApplicationTypeWeb:
return proj_model.OIDCApplicationTypeWeb
}
return proj_model.OIDCApplicationTypeWeb
}
func getOIDCAuthMethod(authMethod string) proj_model.OIDCAuthMethodType {
switch authMethod {
case OIDCAuthMethodTypeNone:
return proj_model.OIDCAuthMethodTypeNone
case OIDCAuthMethodTypeBasic:
return proj_model.OIDCAuthMethodTypeBasic
case OIDCAuthMethodTypePost:
return proj_model.OIDCAuthMethodTypePost
}
return proj_model.OIDCAuthMethodTypeBasic
}
//
//func StartSetup(esConfig es_int.Config, sd systemdefaults.SystemDefaults) (*Setup, error) {
// setup := &Setup{
// iamID: sd.IamID,
// }
// es, err := es_int.Start(esConfig)
// if err != nil {
// return nil, err
// }
//
// setup.IamEvents, err = es_iam.StartIAM(es_iam.IAMConfig{
// Eventstore: es,
// Cache: esConfig.Cache,
// }, sd)
// if err != nil {
// return nil, err
// }
//
// setup.OrgEvents = es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: sd.Domain}, sd)
//
// setup.ProjectEvents, err = es_proj.StartProject(es_proj.ProjectConfig{
// Eventstore: es,
// Cache: esConfig.Cache,
// }, sd)
// if err != nil {
// return nil, err
// }
//
// setup.UserEvents, err = es_usr.StartUser(es_usr.UserConfig{
// Eventstore: es,
// Cache: esConfig.Cache,
// }, sd)
// if err != nil {
// return nil, err
// }
//
// return setup, nil
//}
//
//func (s *Setup) Execute(ctx context.Context, setUpConfig IAMSetUp) error {
// logging.Log("SETUP-hwG32").Info("starting setup")
//
// iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
// if err != nil && !caos_errs.IsNotFound(err) {
// return err
// }
// if iam != nil && (iam.SetUpDone == domain.Step(iam_model.StepCount)-1 || iam.SetUpStarted != iam.SetUpDone) {
// logging.Log("SETUP-cWEsn").Info("all steps done")
// return nil
// }
//
// if iam == nil {
// iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: s.iamID}}
// }
//
// steps, err := setUpConfig.steps(iam_model.Step(iam.SetUpDone))
// if err != nil || len(steps) == 0 {
// return err
// }
//
// ctx = setSetUpContextData(ctx, s.iamID)
//
// for _, step := range steps {
// step.init(s)
// if step.step() != iam_model.Step(iam.SetUpDone)+1 {
// logging.LogWithFields("SETUP-rxRM1", "step", step.step(), "previous", iam.SetUpDone).Warn("wrong step order")
// return errors.ThrowPreconditionFailed(nil, "SETUP-wwAqO", "too few steps for this zitadel verison")
// }
// iam, err = s.IamEvents.StartSetup(ctx, s.iamID, step.step())
// if err != nil {
// return err
// }
//
// iam, err = step.execute(ctx)
// if err != nil {
// return err
// }
//
// err = s.validateExecutedStep(ctx)
// if err != nil {
// return err
// }
// }
//
// logging.Log("SETUP-ds31h").Info("setup done")
// return nil
//}
//
//func (s *Setup) validateExecutedStep(ctx context.Context) error {
// iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
// if err != nil {
// return err
// }
// if iam.SetUpStarted != iam.SetUpDone {
// return errors.ThrowInternal(nil, "SETUP-QeukK", "started step is not equal to done")
// }
// return nil
//}
//
//func getOIDCResponseTypes(responseTypes []string) []proj_model.OIDCResponseType {
// types := make([]proj_model.OIDCResponseType, len(responseTypes))
// for i, t := range responseTypes {
// types[i] = getOIDCResponseType(t)
// }
// return types
//}
//
//func getOIDCResponseType(responseType string) proj_model.OIDCResponseType {
// switch responseType {
// case OIDCResponseTypeCode:
// return proj_model.OIDCResponseTypeCode
// case OIDCResponseTypeIDToken:
// return proj_model.OIDCResponseTypeIDToken
// case OIDCResponseTypeToken:
// return proj_model.OIDCResponseTypeIDTokenToken
// }
// return proj_model.OIDCResponseTypeCode
//}
//
//func getOIDCGrantTypes(grantTypes []string) []proj_model.OIDCGrantType {
// types := make([]proj_model.OIDCGrantType, len(grantTypes))
// for i, t := range grantTypes {
// types[i] = getOIDCGrantType(t)
// }
// return types
//}
//
//func getOIDCGrantType(grantTypes string) proj_model.OIDCGrantType {
// switch grantTypes {
// case OIDCGrantTypeAuthorizationCode:
// return proj_model.OIDCGrantTypeAuthorizationCode
// case OIDCGrantTypeImplicit:
// return proj_model.OIDCGrantTypeImplicit
// case OIDCGrantTypeRefreshToken:
// return proj_model.OIDCGrantTypeRefreshToken
// }
// return proj_model.OIDCGrantTypeAuthorizationCode
//}
//
//func getOIDCApplicationType(appType string) proj_model.OIDCApplicationType {
// switch appType {
// case OIDCApplicationTypeNative:
// return proj_model.OIDCApplicationTypeNative
// case OIDCApplicationTypeUserAgent:
// return proj_model.OIDCApplicationTypeUserAgent
// case OIDCApplicationTypeWeb:
// return proj_model.OIDCApplicationTypeWeb
// }
// return proj_model.OIDCApplicationTypeWeb
//}
//
//func getOIDCAuthMethod(authMethod string) proj_model.OIDCAuthMethodType {
// switch authMethod {
// case OIDCAuthMethodTypeNone:
// return proj_model.OIDCAuthMethodTypeNone
// case OIDCAuthMethodTypeBasic:
// return proj_model.OIDCAuthMethodTypeBasic
// case OIDCAuthMethodTypePost:
// return proj_model.OIDCAuthMethodTypePost
// }
// return proj_model.OIDCAuthMethodTypeBasic
//}
//
func setSetUpContextData(ctx context.Context, orgID string) context.Context {
return authz.SetCtxData(ctx, authz.CtxData{UserID: SetupUser, OrgID: orgID})
}

104
internal/setup/setup_v2.go Normal file
View File

@ -0,0 +1,104 @@
package setup
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/v2/command"
"github.com/caos/zitadel/internal/v2/domain"
)
func StartSetupV2(esConfig es_int.Config, sd systemdefaults.SystemDefaults) (*Setup, error) {
setup := &Setup{
iamID: sd.IamID,
}
es, err := es_int.Start(esConfig)
if err != nil {
return nil, err
}
setup.IamEvents, err = es_iam.StartIAM(es_iam.IAMConfig{
Eventstore: es,
Cache: esConfig.Cache,
}, sd)
if err != nil {
return nil, err
}
setup.Commands, err = command.StartCommandSide(&command.Config{
Eventstore: es.V2(),
SystemDefaults: sd,
})
if err != nil {
return nil, err
}
return setup, nil
}
func (s *Setup) ExecuteV2(ctx context.Context, setUpConfig IAMSetUp) error {
logging.Log("SETUP-JAK2q").Info("starting setup")
iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return err
}
if iam != nil && (iam.SetUpDone == domain.StepCount-1 || iam.SetUpStarted != iam.SetUpDone) {
logging.Log("SETUP-VA2k1").Info("all steps done")
return nil
}
if iam == nil {
iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: s.iamID}}
}
steps, err := setUpConfig.steps(iam_model.Step(iam.SetUpDone))
if err != nil || len(steps) == 0 {
return err
}
ctx = setSetUpContextData(ctx, s.iamID)
for _, step := range steps {
//step.init(s)
if step.step() != iam_model.Step(iam.SetUpDone+1) {
logging.LogWithFields("SETUP-rxRM1", "step", step.step(), "previous", iam.SetUpDone).Warn("wrong step order")
return caos_errs.ThrowPreconditionFailed(nil, "SETUP-wwAqO", "too few steps for this zitadel verison")
}
iam, err = s.Commands.StartSetup(ctx, s.iamID, domain.Step(step.step()))
if err != nil {
return err
}
err = step.execute(ctx, iam.AggregateID, *s.Commands)
if err != nil {
return err
}
err = s.validateExecutedStep(ctx)
if err != nil {
return err
}
}
logging.Log("SETUP-ds31h").Info("setup done")
return nil
}
func (s *Setup) validateExecutedStep(ctx context.Context) error {
iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
if err != nil {
return err
}
if iam.SetUpStarted != iam.SetUpDone {
return caos_errs.ThrowInternal(nil, "SETUP-QeukK", "started step is not equal to done")
}
return nil
}

View File

@ -4,6 +4,7 @@ import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/command"
)
type step interface {
@ -12,3 +13,9 @@ type step interface {
init(*Setup)
isNil() bool
}
type stepV2 interface {
step() iam_model.Step
execute(context.Context, string, command.CommandSide) error
isNil() bool
}

View File

@ -4,322 +4,287 @@ import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
org_model "github.com/caos/zitadel/internal/org/model"
proj_model "github.com/caos/zitadel/internal/project/model"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/command"
)
type Step1 struct {
GlobalOrg string
IAMProject string
DefaultLoginPolicy LoginPolicy
Orgs []Org
Owners []string
//GlobalOrg string
//IAMProject string
//DefaultLoginPolicy LoginPolicy
//Orgs []Org
//Owners []string
command.Step1
setup *Setup
createdUsers map[string]*usr_model.User
createdOrgs map[string]*org_model.Org
createdProjects map[string]*proj_model.Project
pwComplexityPolicy *iam_model.PasswordComplexityPolicyView
//setup *Setup
//createdUsers map[string]*usr_model.User
//createdOrgs map[string]*org_model.Org
//createdProjects map[string]*proj_model.Project
//pwComplexityPolicy *iam_model.PasswordComplexityPolicyView
}
func (s *Step1) isNil() bool {
return s == nil
}
func (step *Step1) step() iam_model.Step {
func (s *Step1) step() iam_model.Step {
return iam_model.Step1
}
func (step *Step1) init(setup *Setup) {
step.setup = setup
step.createdUsers = make(map[string]*usr_model.User)
step.createdOrgs = make(map[string]*org_model.Org)
step.createdProjects = make(map[string]*proj_model.Project)
}
//func (s *Step1) init(setup *Setup) {
// s.setup = setup
// s.createdUsers = make(map[string]*usr_model.User)
// s.createdOrgs = make(map[string]*org_model.Org)
// s.createdProjects = make(map[string]*proj_model.Project)
//}
func (step *Step1) execute(ctx context.Context) (*iam_model.IAM, error) {
err := step.loginPolicy(ctx, step.DefaultLoginPolicy)
func (s *Step1) execute(ctx context.Context, iamID string, commands command.CommandSide) error {
err := commands.SetupStep1(ctx, iamID, s.Step1)
if err != nil {
logging.Log("SETUP-Hdu8S").WithError(err).Error("unable to create login policy")
return nil, err
}
step.pwComplexityPolicy = new(iam_model.PasswordComplexityPolicyView)
err = step.orgs(ctx, step.Orgs)
if err != nil {
logging.Log("SETUP-p4oWq").WithError(err).Error("unable to set up orgs")
return nil, err
}
ctx = setSetUpContextData(ctx, step.setup.iamID)
err = step.iamOwners(ctx, step.Owners)
if err != nil {
logging.Log("SETUP-WHr01").WithError(err).Error("unable to set up iam owners")
return nil, err
}
err = step.setGlobalOrg(ctx, step.GlobalOrg)
if err != nil {
logging.Log("SETUP-0874m").WithError(err).Error("unable to set global org")
return nil, err
}
err = step.setIamProject(ctx, step.IAMProject)
if err != nil {
logging.Log("SETUP-kaWjq").WithError(err).Error("unable to set zitadel project")
return nil, err
}
iam, err := step.setup.IamEvents.SetupDone(ctx, step.setup.iamID, step.step())
if err != nil {
logging.Log("SETUP-de342").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
return nil, err
}
return iam, nil
}
func (step *Step1) loginPolicy(ctx context.Context, policy LoginPolicy) error {
logging.Log("SETUP-4djul").Info("setting up login policy")
loginPolicy := &iam_model.LoginPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: step.setup.iamID,
},
AllowRegister: policy.AllowRegister,
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIdp,
}
_, err := step.setup.IamEvents.AddLoginPolicy(ctx, loginPolicy)
return err
}
func (step *Step1) orgs(ctx context.Context, orgs []Org) error {
logging.Log("SETUP-dsTh3").Info("setting up orgs")
for _, iamOrg := range orgs {
org, err := step.org(ctx, iamOrg)
if err != nil {
logging.LogWithFields("SETUP-IlLif", "Org", iamOrg.Name).WithError(err).Error("unable to create org")
return err
}
step.createdOrgs[iamOrg.Name] = org
logging.LogWithFields("SETUP-HR2gh", "name", org.Name, "ID", org.AggregateID).Info("created organisation")
var policy *iam_model.OrgIAMPolicyView
if iamOrg.OrgIamPolicy {
policy, err = step.iamorgpolicy(ctx, org)
if err != nil {
logging.LogWithFields("SETUP-IlLif", "Org IAM Policy", iamOrg.Name).WithError(err).Error("unable to create iam org policy")
return err
}
} else {
policy = &iam_model.OrgIAMPolicyView{
UserLoginMustBeDomain: true,
}
}
ctx = setSetUpContextData(ctx, org.AggregateID)
err = step.users(ctx, iamOrg.Users, policy)
if err != nil {
logging.LogWithFields("SETUP-8zfwz", "Org", iamOrg.Name).WithError(err).Error("unable to set up org users")
return err
}
err = step.orgOwners(ctx, org, iamOrg.Owners)
if err != nil {
logging.LogWithFields("SETUP-0874m", "Org", iamOrg.Name).WithError(err).Error("unable to set up org owners")
return err
}
err = step.projects(ctx, iamOrg.Projects, step.createdUsers[iamOrg.Owners[0]].AggregateID)
if err != nil {
logging.LogWithFields("SETUP-wUzqY", "Org", iamOrg.Name).WithError(err).Error("unable to set up org projects")
return err
}
}
logging.Log("SETUP-dgjT4").Info("orgs set up")
return nil
}
func (step *Step1) org(ctx context.Context, org Org) (*org_model.Org, error) {
ctx = setSetUpContextData(ctx, "")
createOrg := &org_model.Org{
Name: org.Name,
Domains: []*org_model.OrgDomain{{Domain: org.Domain}},
}
return step.setup.OrgEvents.CreateOrg(ctx, createOrg, nil)
}
func (step *Step1) iamorgpolicy(ctx context.Context, org *org_model.Org) (*iam_model.OrgIAMPolicyView, error) {
ctx = setSetUpContextData(ctx, org.AggregateID)
policy := &iam_model.OrgIAMPolicy{
ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID},
UserLoginMustBeDomain: false,
}
createdpolicy, err := step.setup.OrgEvents.AddOrgIAMPolicy(ctx, policy)
if err != nil {
return nil, err
}
return &iam_model.OrgIAMPolicyView{
AggregateID: org.AggregateID,
UserLoginMustBeDomain: createdpolicy.UserLoginMustBeDomain,
}, nil
}
func (step *Step1) iamOwners(ctx context.Context, owners []string) error {
logging.Log("SETUP-dtxfj").Info("setting iam owners")
for _, iamOwner := range owners {
user, ok := step.createdUsers[iamOwner]
if !ok {
logging.LogWithFields("SETUP-8siew", "Owner", iamOwner).Error("unable to add user to iam members")
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-su6L3", "unable to add user to iam members")
}
_, err := step.setup.IamEvents.AddIAMMember(ctx, &iam_model.IAMMember{ObjectRoot: models.ObjectRoot{AggregateID: step.setup.iamID}, UserID: user.AggregateID, Roles: []string{"IAM_OWNER"}})
if err != nil {
logging.Log("SETUP-LM7rI").WithError(err).Error("unable to add iam administrator to iam members as owner")
return err
}
}
logging.Log("SETUP-fg5aq").Info("iam owners set")
return nil
}
func (step *Step1) setGlobalOrg(ctx context.Context, globalOrgName string) error {
logging.Log("SETUP-dsj75").Info("setting global org")
globalOrg, ok := step.createdOrgs[globalOrgName]
if !ok {
logging.LogWithFields("SETUP-FBhs9", "GlobalOrg", globalOrgName).Error("global org not created")
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-4GwU7", "global org not created: %v", globalOrgName)
}
if _, err := step.setup.IamEvents.SetGlobalOrg(ctx, step.setup.iamID, globalOrg.AggregateID); err != nil {
logging.Log("SETUP-uGMA3").WithError(err).Error("unable to set global org on iam")
logging.Log("SETUP-de342").WithField("step", s.step()).WithError(err).Error("unable to finish setup")
return err
}
logging.Log("SETUP-d32h1").Info("global org set")
return nil
}
func (step *Step1) setIamProject(ctx context.Context, iamProjectName string) error {
logging.Log("SETUP-HE3qa").Info("setting iam project")
iamProject, ok := step.createdProjects[iamProjectName]
if !ok {
logging.LogWithFields("SETUP-SJFWP", "IAM Project", iamProjectName).Error("iam project created")
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-sGmQt", "iam project not created: %v", iamProjectName)
}
if _, err := step.setup.IamEvents.SetIAMProject(ctx, step.setup.iamID, iamProject.AggregateID); err != nil {
logging.Log("SETUP-i1pNh").WithError(err).Error("unable to set iam project on iam")
return err
}
logging.Log("SETUP-d7WEU").Info("iam project set")
return nil
}
func (step *Step1) users(ctx context.Context, users []User, orgPolicy *iam_model.OrgIAMPolicyView) error {
for _, user := range users {
created, err := step.user(ctx, user, orgPolicy)
if err != nil {
logging.LogWithFields("SETUP-9soer", "Email", user.Email).WithError(err).Error("unable to create iam user")
return err
}
step.createdUsers[user.Email] = created
}
return nil
}
func (step *Step1) user(ctx context.Context, user User, orgPolicy *iam_model.OrgIAMPolicyView) (*usr_model.User, error) {
createUser := &usr_model.User{
UserName: user.UserName,
Human: &usr_model.Human{
Profile: &usr_model.Profile{
FirstName: user.FirstName,
LastName: user.LastName,
},
Email: &usr_model.Email{
EmailAddress: user.Email,
IsEmailVerified: true,
},
Password: &usr_model.Password{
SecretString: user.Password,
},
},
}
return step.setup.UserEvents.CreateUser(ctx, createUser, step.pwComplexityPolicy, orgPolicy)
}
func (step *Step1) orgOwners(ctx context.Context, org *org_model.Org, owners []string) error {
for _, orgOwner := range owners {
user, ok := step.createdUsers[orgOwner]
if !ok {
logging.LogWithFields("SETUP-s9ilr", "Owner", orgOwner).Error("unable to add user to org members")
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-s0prs", "unable to add user to org members: %v", orgOwner)
}
err := step.orgOwner(ctx, org, user)
if err != nil {
logging.Log("SETUP-s90oe").WithError(err).Error("unable to add global org admin to members of global org")
return err
}
}
return nil
}
func (step *Step1) orgOwner(ctx context.Context, org *org_model.Org, user *usr_model.User) error {
addMember := &org_model.OrgMember{
ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID},
UserID: user.AggregateID,
Roles: []string{OrgOwnerRole},
}
_, err := step.setup.OrgEvents.AddOrgMember(ctx, addMember)
return err
}
func (step *Step1) projects(ctx context.Context, projects []Project, ownerID string) error {
ctxData := authz.GetCtxData(ctx)
ctxData.UserID = ownerID
projectCtx := authz.SetCtxData(ctx, ctxData)
for _, project := range projects {
createdProject, err := step.project(projectCtx, project)
if err != nil {
return err
}
step.createdProjects[createdProject.Name] = createdProject
for _, oidc := range project.OIDCApps {
app, err := step.oidcApp(ctx, createdProject, oidc)
if err != nil {
return err
}
logging.LogWithFields("SETUP-asd32f", "name", app.Name, "clientID", app.OIDCConfig.ClientID).Info("created OIDC application")
}
}
return nil
}
func (step *Step1) project(ctx context.Context, project Project) (*proj_model.Project, error) {
addProject := &proj_model.Project{
Name: project.Name,
}
return step.setup.ProjectEvents.CreateProject(ctx, addProject, false)
}
func (step *Step1) oidcApp(ctx context.Context, project *proj_model.Project, oidc OIDCApp) (*proj_model.Application, error) {
addOIDCApp := &proj_model.Application{
ObjectRoot: models.ObjectRoot{AggregateID: project.AggregateID},
Name: oidc.Name,
OIDCConfig: &proj_model.OIDCConfig{
RedirectUris: oidc.RedirectUris,
ResponseTypes: getOIDCResponseTypes(oidc.ResponseTypes),
GrantTypes: getOIDCGrantTypes(oidc.GrantTypes),
ApplicationType: getOIDCApplicationType(oidc.ApplicationType),
AuthMethodType: getOIDCAuthMethod(oidc.AuthMethodType),
PostLogoutRedirectUris: oidc.PostLogoutRedirectUris,
DevMode: oidc.DevMode,
},
}
return step.setup.ProjectEvents.AddApplication(ctx, addOIDCApp)
}
//
//func (step *Step1) loginPolicy(ctx context.Context, policy LoginPolicy) error {
// logging.Log("SETUP-4djul").Info("setting up login policy")
// loginPolicy := &iam_model.LoginPolicy{
// ObjectRoot: models.ObjectRoot{
// AggregateID: step.setup.iamID,
// },
// AllowRegister: policy.AllowRegister,
// AllowUsernamePassword: policy.AllowUsernamePassword,
// AllowExternalIdp: policy.AllowExternalIdp,
// }
// _, err := step.setup.Commands.AddDefaultLoginPolicy(ctx, loginPolicy)
// return err
//}
//
//func (step *Step1) orgs(ctx context.Context, orgs []Org) error {
// logging.Log("SETUP-dsTh3").Info("setting up orgs")
// for _, iamOrg := range orgs {
// org, err := step.org(ctx, iamOrg)
// if err != nil {
// logging.LogWithFields("SETUP-IlLif", "Org", iamOrg.Name).WithError(err).Error("unable to create org")
// return err
// }
// step.createdOrgs[iamOrg.Name] = org
// logging.LogWithFields("SETUP-HR2gh", "name", org.Name, "ID", org.AggregateID).Info("created organisation")
//
// var policy *iam_model.OrgIAMPolicyView
// if iamOrg.OrgIamPolicy {
// policy, err = step.iamorgpolicy(ctx, org)
// if err != nil {
// logging.LogWithFields("SETUP-IlLif", "Org IAM Policy", iamOrg.Name).WithError(err).Error("unable to create iam org policy")
// return err
// }
// } else {
// policy = &iam_model.OrgIAMPolicyView{
// UserLoginMustBeDomain: true,
// }
// }
//
// ctx = setSetUpContextData(ctx, org.AggregateID)
// err = step.users(ctx, iamOrg.Users, policy)
// if err != nil {
// logging.LogWithFields("SETUP-8zfwz", "Org", iamOrg.Name).WithError(err).Error("unable to set up org users")
// return err
// }
//
// err = step.orgOwners(ctx, org, iamOrg.Owners)
// if err != nil {
// logging.LogWithFields("SETUP-0874m", "Org", iamOrg.Name).WithError(err).Error("unable to set up org owners")
// return err
// }
//
// err = step.projects(ctx, iamOrg.Projects, step.createdUsers[iamOrg.Owners[0]].AggregateID)
// if err != nil {
// logging.LogWithFields("SETUP-wUzqY", "Org", iamOrg.Name).WithError(err).Error("unable to set up org projects")
// return err
// }
// }
// logging.Log("SETUP-dgjT4").Info("orgs set up")
// return nil
//}
//
//func (step *Step1) org(ctx context.Context, org Org) (*org_model.Org, error) {
// ctx = setSetUpContextData(ctx, "")
// createOrg := &org_model.Org{
// Name: org.Name,
// Domains: []*org_model.OrgDomain{{Domain: org.Domain}},
// }
// return step.setup.OrgEvents.CreateOrg(ctx, createOrg, nil)
//}
//
//func (step *Step1) iamorgpolicy(ctx context.Context, org *org_model.Org) (*iam_model.OrgIAMPolicyView, error) {
// ctx = setSetUpContextData(ctx, org.AggregateID)
// policy := &iam_model.OrgIAMPolicy{
// ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID},
// UserLoginMustBeDomain: false,
// }
// createdpolicy, err := step.setup.OrgEvents.AddOrgIAMPolicy(ctx, policy)
// if err != nil {
// return nil, err
// }
// return &iam_model.OrgIAMPolicyView{
// AggregateID: org.AggregateID,
// UserLoginMustBeDomain: createdpolicy.UserLoginMustBeDomain,
// }, nil
//}
//
//func (step *Step1) iamOwners(ctx context.Context, owners []string) error {
// logging.Log("SETUP-dtxfj").Info("setting iam owners")
// for _, iamOwner := range owners {
// user, ok := step.createdUsers[iamOwner]
// if !ok {
// logging.LogWithFields("SETUP-8siew", "Owner", iamOwner).Error("unable to add user to iam members")
// return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-su6L3", "unable to add user to iam members")
// }
// _, err := step.setup.Commands.AddIAMMember(ctx, &iam_model.IAMMember{ObjectRoot: models.ObjectRoot{AggregateID: step.setup.iamID}, UserID: user.AggregateID, Roles: []string{"IAM_OWNER"}})
// if err != nil {
// logging.Log("SETUP-LM7rI").WithError(err).Error("unable to add iam administrator to iam members as owner")
// return err
// }
// }
// logging.Log("SETUP-fg5aq").Info("iam owners set")
// return nil
//}
//
//func (step *Step1) setGlobalOrg(ctx context.Context, globalOrgName string) error {
// logging.Log("SETUP-dsj75").Info("setting global org")
// globalOrg, ok := step.createdOrgs[globalOrgName]
// if !ok {
// logging.LogWithFields("SETUP-FBhs9", "GlobalOrg", globalOrgName).Error("global org not created")
// return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-4GwU7", "global org not created: %v", globalOrgName)
// }
//
// if _, err := step.setup.IamEvents.SetGlobalOrg(ctx, step.setup.iamID, globalOrg.AggregateID); err != nil {
// logging.Log("SETUP-uGMA3").WithError(err).Error("unable to set global org on iam")
// return err
// }
// logging.Log("SETUP-d32h1").Info("global org set")
// return nil
//}
//
//func (step *Step1) setIamProject(ctx context.Context, iamProjectName string) error {
// logging.Log("SETUP-HE3qa").Info("setting iam project")
// iamProject, ok := step.createdProjects[iamProjectName]
// if !ok {
// logging.LogWithFields("SETUP-SJFWP", "IAM Project", iamProjectName).Error("iam project created")
// return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-sGmQt", "iam project not created: %v", iamProjectName)
// }
//
// if _, err := step.setup.IamEvents.SetIAMProject(ctx, step.setup.iamID, iamProject.AggregateID); err != nil {
// logging.Log("SETUP-i1pNh").WithError(err).Error("unable to set iam project on iam")
// return err
// }
// logging.Log("SETUP-d7WEU").Info("iam project set")
// return nil
//}
//
//func (step *Step1) users(ctx context.Context, users []User, orgPolicy *iam_model.OrgIAMPolicyView) error {
// for _, user := range users {
// created, err := step.user(ctx, user, orgPolicy)
// if err != nil {
// logging.LogWithFields("SETUP-9soer", "Email", user.Email).WithError(err).Error("unable to create iam user")
// return err
// }
// step.createdUsers[user.Email] = created
// }
// return nil
//}
//
//func (step *Step1) user(ctx context.Context, user User, orgPolicy *iam_model.OrgIAMPolicyView) (*usr_model.User, error) {
// createUser := &usr_model.User{
// UserName: user.UserName,
// Human: &usr_model.Human{
// Profile: &usr_model.Profile{
// FirstName: user.FirstName,
// LastName: user.LastName,
// },
// Email: &usr_model.Email{
// EmailAddress: user.Email,
// IsEmailVerified: true,
// },
// Password: &usr_model.Password{
// SecretString: user.Password,
// },
// },
// }
// return step.setup.UserEvents.CreateUser(ctx, createUser, step.pwComplexityPolicy, orgPolicy)
//}
//
//func (step *Step1) orgOwners(ctx context.Context, org *org_model.Org, owners []string) error {
// for _, orgOwner := range owners {
// user, ok := step.createdUsers[orgOwner]
// if !ok {
// logging.LogWithFields("SETUP-s9ilr", "Owner", orgOwner).Error("unable to add user to org members")
// return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-s0prs", "unable to add user to org members: %v", orgOwner)
// }
// err := step.orgOwner(ctx, org, user)
// if err != nil {
// logging.Log("SETUP-s90oe").WithError(err).Error("unable to add global org admin to members of global org")
// return err
// }
// }
// return nil
//}
//
//func (step *Step1) orgOwner(ctx context.Context, org *org_model.Org, user *usr_model.User) error {
// addMember := &org_model.OrgMember{
// ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID},
// UserID: user.AggregateID,
// Roles: []string{OrgOwnerRole},
// }
// _, err := step.setup.OrgEvents.AddOrgMember(ctx, addMember)
// return err
//}
//
//func (step *Step1) projects(ctx context.Context, projects []Project, ownerID string) error {
// ctxData := authz.GetCtxData(ctx)
// ctxData.UserID = ownerID
// projectCtx := authz.SetCtxData(ctx, ctxData)
//
// for _, project := range projects {
// createdProject, err := step.project(projectCtx, project)
// if err != nil {
// return err
// }
// step.createdProjects[createdProject.Name] = createdProject
// for _, oidc := range project.OIDCApps {
// app, err := step.oidcApp(ctx, createdProject, oidc)
// if err != nil {
// return err
// }
// logging.LogWithFields("SETUP-asd32f", "name", app.Name, "clientID", app.OIDCConfig.ClientID).Info("created OIDC application")
// }
// }
// return nil
//}
//
//func (step *Step1) project(ctx context.Context, project Project) (*proj_model.Project, error) {
// addProject := &proj_model.Project{
// Name: project.Name,
// }
// return step.setup.ProjectEvents.CreateProject(ctx, addProject, false)
//}
//
//func (step *Step1) oidcApp(ctx context.Context, project *proj_model.Project, oidc OIDCApp) (*proj_model.Application, error) {
// addOIDCApp := &proj_model.Application{
// ObjectRoot: models.ObjectRoot{AggregateID: project.AggregateID},
// Name: oidc.Name,
// OIDCConfig: &proj_model.OIDCConfig{
// RedirectUris: oidc.RedirectUris,
// ResponseTypes: getOIDCResponseTypes(oidc.ResponseTypes),
// GrantTypes: getOIDCGrantTypes(oidc.GrantTypes),
// ApplicationType: getOIDCApplicationType(oidc.ApplicationType),
// AuthMethodType: getOIDCAuthMethod(oidc.AuthMethodType),
// PostLogoutRedirectUris: oidc.PostLogoutRedirectUris,
// DevMode: oidc.DevMode,
// },
// }
// return step.setup.ProjectEvents.AddApplication(ctx, addOIDCApp)
//}

View File

@ -2,11 +2,13 @@ package setup
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/v2/command"
)
type Step2 struct {
@ -27,23 +29,25 @@ func (step *Step2) init(setup *Setup) {
step.setup = setup
}
func (step *Step2) execute(ctx context.Context) (*iam_model.IAM, error) {
iam, agg, err := step.passwordComplexityPolicy(ctx, &step.DefaultPasswordComplexityPolicy)
if err != nil {
logging.Log("SETUP-Ms9fl").WithField("step", step.step()).WithError(err).Error("unable to finish setup (pw complexity policy)")
return nil, err
}
iam, agg, push, err := step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step())
if err != nil {
logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)")
return nil, err
}
err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg)
if err != nil {
logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
return nil, err
}
return iam_es_model.IAMToModel(iam), nil
func (step *Step2) execute(ctx context.Context, commands command.CommandSide) error {
//commands.SetupStep2(ctx, )
//iam, agg, err := step.passwordComplexityPolicy(ctx, &step.DefaultPasswordComplexityPolicy)
//if err != nil {
// logging.Log("SETUP-Ms9fl").WithField("step", step.step()).WithError(err).Error("unable to finish setup (pw complexity policy)")
// return nil, err
//}
//iam, agg, push, err := step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step())
//if err != nil {
// logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)")
// return nil, err
//}
//err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg)
//if err != nil {
// logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
// return nil, err
//}
//return iam_es_model.IAMToModel(iam), nil
return nil
}
func (step *Step2) passwordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_es_model.IAM, *models.Aggregate, error) {

View File

@ -17,15 +17,21 @@ Errors:
NotLocked: Benutzer ist nicht gesperrt
NoChanges: Keine Änderungen gefunden
InitCodeNotFound: Kein Initialisierungs Code gefunden
ProfileNotFound: Profil nicht gefunden
ProfileInvalid: Profildaten sind ungültig
EmailNotFound: Email nicht gefunden
EmailInvalid: Email ist ungültig
EmailAlreadyVerified: Email ist bereits verifiziert
Profile:
NotFound: Profil nicht gefunden
NotChanged: Profile nicht verändert
Invalid: Profildaten sind ungültig
Email:
NotFound: Email nicht gefunden
Invalid: Email ist ungültig
AlreadyVerified: Email ist bereits verifiziert
NotChanged: Email wurde nicht geändert
PhoneNotFound: Telfonnummer nicht gefunden
PhoneInvalid: Telefonnummer ist ungültig
PhoneAlreadyVerified: Telefonnummer bereits verifiziert
AddressNotFound: Addresse nicht gefunden
Address:
NotFound: Addresse nicht gefunden
NotChanged: Addresse wurde nicht geändert
NotHuman: Der Benutzer muss eine Person sein
NotMachine: Der Benutzer muss technisch sein
NotAllowedToLink: Der Benutzer darf nicht mit einem externen Login Provider verlinkt werden
@ -164,6 +170,8 @@ Errors:
GrantHasNotExistingRole: Eine der Rollen existiert nicht auf dem Projekt
UserIDMisisng: User ID fehlt
IAM:
Member:
RolesNotChanged: Rollen wurden nicht verändert
MemberInvalid: Member ist ungültig
MemberAlreadyExisting: Member existiert bereits
MemberNotExisting: Member existiert nicht
@ -179,6 +187,7 @@ Errors:
IdpProviderInvalid: Idp Provider ist ungültig
LoginPolicy:
NotFound: Default Login Policy konnte nicht gefunden
NotChanged: Default Login Policy wurde nicht verändert
NotExisting: Default Login Policy existiert nicht
AlreadyExists: Default Login Policy existiert bereits
IdpProviderAlreadyExisting: Idp Provider existiert bereits
@ -187,28 +196,41 @@ Errors:
AlreadyExists: Multifaktor existiert bereits
NotExisting: Multifaktor existiert nicht
Unspecified: Multifaktor ungültig
IDP:
AlreadyExists: Identitäts Provider existiert bereits
NotExisting: Identitäts Provider existiert nicht
IDPConfig:
AlreadyExists: Identitäts Provider Konfiguration existiert bereits
NotExisting: Identitäts Provider Konfiguration existiert nicht
NotInactive: Identitäts Provider Konfiguration nicht inaktive
NotActive: Identitäts Provider Konfiguration nicht aktive
LabelPolicy:
NotFound: Default Private Label Policy konnte nicht gefunden
NotChanged: Default Private Label Policy wurde nicht verändert
PasswordComplexityPolicy:
NotFound: Default Password Complexity Policy konnte nicht gefunden werden
NotExisting: Default Password Complexity Policy existiert nicht
AlreadyExists: Default Password Complexity Policy existiert bereits
Empty: Default Password Complexity Policy leer
NotChanged: Default Password Complexity Policy wurde nicht verändert
PasswordAgePolicy:
NotFound: Default Password Age Policy konnte nicht gefunden werden
NotExisting: Default Password Age Policy existiert nicht
AlreadyExists: Default Password Age Policy existiert bereits
Empty: Default Password Age Policy leer
NotChanged: Default Password Age Policy wurde nicht verändert
PasswordLockoutPolicy:
NotFound: Default Password Lockout Policy konnte nicht gefunden werden
NotExisting: Default Password Lockout Policy existiert nicht
AlreadyExists: Default Password Lockout Policy existiert bereits
Empty: Default Password Lockout Policy leer
NotChanged: Default Password Lockout Policy wurde nicht verändert
OrgIAMPolicy:
NotFound: Default Org IAM Policy konnte nicht gefunden werden
NotExisting: Default Org IAM Policy existiert nicht
AlreadyExists: Default Org IAM Policy existiert bereits
Empty: Default Org IAM Policy leer
NotChanged: Default Org IAM Policy wurde nicht verändert
Policy:
AlreadyExists: Policy existiert bereits
UserGrant:

View File

@ -17,15 +17,21 @@ Errors:
NotLocked: User is not locked
NoChanges: No changes found
InitCodeNotFound: Initialization Code not found
ProfileNotFound: Profile not found
ProfileInvalid: Profildata invalid
EmailNotFound: Email not found
EmailInvalid: Email is invalid
EmailAlreadyVerified: Email is alredy verified
Profile:
NotFound: Profile not found
NotChanged: Profile not changed
Invalid: Profildata invalid
Email:
NotFound: Email not found
Invalid: Email is invalid
AlreadyVerified: Email is alredy verified
NotChanged: Email not changed
PhoneNotFound: Phone not found
PhoneInvalid: Phone is invalid
PhoneAlreadyVerified: Phone already verified
AddressNotFound: Address not found
Address:
NotFound: Address not found
NotChanged: Address not changed
NotHuman: The User must be personal
NotMachine: The User must be technical
NotAllowedToLink: User is not allowed to link with external login provider
@ -164,6 +170,8 @@ Errors:
GrantHasNotExistingRole: One role doesn't exist on project
UserIDMisisng: User ID missing
IAM:
Member:
RolesNotChanged: Roles habe not been changed
MemberInvalid: Member is invalid
MemberAlreadyExisting: Member already exists
MemberNotExisting: Member does not exist
@ -179,6 +187,7 @@ Errors:
IdpProviderInvalid: Idp Provider is invalid
LoginPolicy:
NotFound: Default Login Policy not found
NotChanged: Default Login Policy has not been changed
NotExisting: Default Login Policy not existig
AlreadyExists: Default Login Policy already exists
IdpProviderAlreadyExisting: Idp Provider already existing
@ -187,28 +196,38 @@ Errors:
AlreadyExists: Multifactor already exists
NotExisting: Multifactor not existing
Unspecified: Multifactor invalid
IDPConfig:
AlreadyExists: Identity Provider Configuration already exists
NotExisting: Identity Provider Configuration doesn't exist
NotInactive: Identity Provider Configuration not inactive
NotActive: Identity Provider Configuration not active
LabelPolicy:
NotFound: Default Private Label Policy not found
NotChanged: Default Private Label Policy has not been changed
PasswordComplexityPolicy:
NotFound: Default Private Label Policy not found
NotExisting: Default Password Complexity Policy not existing
AlreadyExists: Default Password Complexity Policy already existing
Empty: Default Password Complexity Policy empty
NotChanged: Default Password Complexity Policy has not been changed
PasswordAgePolicy:
NotFound: Default Password Age Policy not found
NotExisting: Default Password Age Policy not existing
AlreadyExists: Default Password Age Policy already existing
Empty: Default Password Age Policy empty
NotChanged: Default Password Age Policy has not been changed
PasswordLockoutPolicy:
NotFound: Default Password Lockout Policy not found
NotExisting: Default Password Lockout Policy not existing
AlreadyExists: Default Password Lockout Policy already existing
Empty: Default Password Lockout Policy empty
NotChanged: Default Password Lockout Policy has not been changed
OrgIAMPolicy:
NotFound: Org IAM Policy not found
Empty: Org IAM Policy is empty
NotExisting: Org IAM Policy not existing
AlreadyExists: Org IAM Policy already exists
NotChanged: Org IAM Policy has not been changed
Policy:
AlreadyExists: Policy already exists
UserGrant:

View File

@ -2,6 +2,8 @@ package model
import (
"bytes"
caos_errors "github.com/caos/zitadel/internal/errors"
"strings"
"time"
iam_model "github.com/caos/zitadel/internal/iam/model"
@ -11,6 +13,8 @@ import (
)
type Human struct {
es_models.ObjectRoot
*Password
*Profile
*Email
@ -44,6 +48,19 @@ const (
GenderDiverse
)
func (u *Human) CheckOrgIAMPolicy(userName string, policy *iam_model.OrgIAMPolicy) error {
if policy == nil {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-zSH7j", "Errors.Users.OrgIamPolicyNil")
}
if policy.UserLoginMustBeDomain && strings.Contains(userName, "@") {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-se4sJ", "Errors.User.EmailAsUsernameNotAllowed")
}
if !policy.UserLoginMustBeDomain && u.Profile != nil && userName == "" && u.Email != nil {
userName = u.EmailAddress
}
return nil
}
func (u *Human) SetNamesAsDisplayname() {
if u.Profile != nil && u.DisplayName == "" && u.FirstName != "" && u.LastName != "" {
u.DisplayName = u.FirstName + " " + u.LastName

View File

@ -862,13 +862,13 @@ func (es *UserEventstore) ProfileByID(ctx context.Context, userID string) (*usr_
if user.Profile != nil {
return user.Profile, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-dk23f", "Errors.User.ProfileNotFound")
return nil, caos_errs.ThrowNotFound(nil, "EVENT-dk23f", "Errors.User.Profile.NotFound")
}
func (es *UserEventstore) ChangeProfile(ctx context.Context, profile *usr_model.Profile) (*usr_model.Profile, error) {
profile.SetNamesAsDisplayname()
if !profile.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-d82i3", "Errors.User.ProfileInvalid")
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-d82i3", "Errors.User.Profile.Invalid")
}
user, err := es.HumanByID(ctx, profile.AggregateID)
if err != nil {
@ -897,12 +897,12 @@ func (es *UserEventstore) EmailByID(ctx context.Context, userID string) (*usr_mo
if user.Email != nil {
return user.Email, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-dki89", "Errors.User.EmailNotFound")
return nil, caos_errs.ThrowNotFound(nil, "EVENT-dki89", "Errors.User.Email.NotFound")
}
func (es *UserEventstore) ChangeEmail(ctx context.Context, email *usr_model.Email) (*usr_model.Email, error) {
if !email.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-lco09", "Errors.User.EmailInvalid")
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-lco09", "Errors.User.Email.Invalid")
}
user, err := es.HumanByID(ctx, email.AggregateID)
if err != nil {
@ -975,10 +975,10 @@ func (es *UserEventstore) CreateEmailVerificationCode(ctx context.Context, userI
return errors.ThrowPreconditionFailed(nil, "EVENT-E3fbw", "Errors.User.NotInitialised")
}
if user.Email == nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.EmailNotFound")
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.Email.NotFound")
}
if user.IsEmailVerified {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.EmailAlreadyVerified")
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.Email.AlreadyVerified")
}
emailCode := new(usr_model.EmailCode)
@ -1158,7 +1158,7 @@ func (es *UserEventstore) AddressByID(ctx context.Context, userID string) (*usr_
if user.Address != nil {
return user.Address, nil
}
return nil, caos_errs.ThrowNotFound(nil, "EVENT-so9wa", "Errors.User.AddressNotFound")
return nil, caos_errs.ThrowNotFound(nil, "EVENT-so9wa", "Errors.User.Address.NotFound")
}
func (es *UserEventstore) ChangeAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) {

View File

@ -1,280 +0,0 @@
package iam
import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/label"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/login"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/login/idpprovider"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/org_iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_age"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_complexity"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_lockout"
"github.com/caos/zitadel/internal/v2/repository/idp/oidc"
"github.com/caos/zitadel/internal/v2/repository/member"
)
func readModelToIAM(readModel *iam_repo.ReadModel) *model.IAM {
return &model.IAM{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel),
GlobalOrgID: readModel.GlobalOrgID,
IAMProjectID: readModel.ProjectID,
SetUpDone: model.Step(readModel.SetUpDone),
SetUpStarted: model.Step(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),
DefaultPasswordLockoutPolicy: readModelToPasswordLockoutPolicy(&readModel.DefaultPasswordLockoutPolicy),
IDPs: readModelToIDPConfigs(&readModel.IDPs),
}
}
func readModelToMembers(readModel *iam_repo.MembersReadModel) []*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 *label.ReadModel) *model.LabelPolicy {
return &model.LabelPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
PrimaryColor: readModel.PrimaryColor,
SecondaryColor: readModel.SecondaryColor,
Default: true,
//TODO: State: int32,
}
}
func readModelToLoginPolicy(readModel *login.ReadModel) *model.LoginPolicy {
return &model.LoginPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
AllowExternalIdp: readModel.AllowExternalIDP,
AllowRegister: readModel.AllowRegister,
AllowUsernamePassword: readModel.AllowUserNamePassword,
Default: true,
//TODO: IDPProviders: []*model.IDPProvider,
//TODO: State: int32,
}
}
func readModelToOrgIAMPolicy(readModel *org_iam.ReadModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
UserLoginMustBeDomain: readModel.UserLoginMustBeDomain,
Default: true,
//TODO: State: int32,
}
}
func readModelToPasswordAgePolicy(readModel *password_age.ReadModel) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
ExpireWarnDays: uint64(readModel.ExpireWarnDays),
MaxAgeDays: uint64(readModel.MaxAgeDays),
//TODO: State: int32,
}
}
func readModelToPasswordComplexityPolicy(readModel *password_complexity.ReadModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
HasLowercase: readModel.HasLowercase,
HasNumber: readModel.HasNumber,
HasSymbol: readModel.HasSymbol,
HasUppercase: readModel.HasUpperCase,
MinLength: uint64(readModel.MinLength),
//TODO: State: int32,
}
}
func readModelToPasswordLockoutPolicy(readModel *password_lockout.ReadModel) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
MaxAttempts: uint64(readModel.MaxAttempts),
ShowLockOutFailures: readModel.ShowLockOutFailures,
//TODO: State: int32,
}
}
func readModelToObjectRoot(readModel eventstore.ReadModel) models.ObjectRoot {
return models.ObjectRoot{
AggregateID: readModel.AggregateID,
ChangeDate: readModel.ChangeDate,
CreationDate: readModel.CreationDate,
ResourceOwner: readModel.ResourceOwner,
Sequence: readModel.ProcessedSequence,
}
}
func writeModelToObjectRoot(writeModel eventstore.WriteModel) models.ObjectRoot {
return models.ObjectRoot{
AggregateID: writeModel.AggregateID,
ChangeDate: writeModel.ChangeDate,
ResourceOwner: writeModel.ResourceOwner,
Sequence: writeModel.ProcessedSequence,
}
}
func readModelToMember(readModel *member.ReadModel) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel),
Roles: readModel.Roles,
UserID: readModel.UserID,
}
}
func writeModelToMember(writeModel *iam.MemberWriteModel) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel.WriteModel),
Roles: writeModel.Roles,
UserID: writeModel.UserID,
}
}
func writeModelToLoginPolicy(wm *login.WriteModel) *model.LoginPolicy {
return &model.LoginPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
AllowUsernamePassword: wm.AllowUserNamePassword,
AllowRegister: wm.AllowRegister,
AllowExternalIdp: wm.AllowExternalIDP,
ForceMFA: wm.ForceMFA,
PasswordlessType: model.PasswordlessType(wm.PasswordlessType),
}
}
func writeModelToLabelPolicy(wm *label.WriteModel) *model.LabelPolicy {
return &model.LabelPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
PrimaryColor: wm.PrimaryColor,
SecondaryColor: wm.SecondaryColor,
}
}
func writeModelToOrgIAMPolicy(wm *org_iam.WriteModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
}
}
func writeModelToPasswordAgePolicy(wm *password_age.WriteModel) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
MaxAgeDays: wm.MaxAgeDays,
ExpireWarnDays: wm.ExpireWarnDays,
}
}
func writeModelToPasswordComplexityPolicy(wm *password_complexity.WriteModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
MinLength: wm.MinLength,
HasLowercase: wm.HasLowercase,
HasUppercase: wm.HasUpperCase,
HasNumber: wm.HasNumber,
HasSymbol: wm.HasSymbol,
}
}
func writeModelToPasswordLockoutPolicy(wm *password_lockout.WriteModel) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
MaxAttempts: wm.MaxAttempts,
ShowLockOutFailures: wm.ShowLockOutFailures,
}
}
func readModelToIDPConfigView(rm *iam.IDPConfigReadModel) *model.IDPConfigView {
return &model.IDPConfigView{
AggregateID: rm.AggregateID,
ChangeDate: rm.ChangeDate,
CreationDate: rm.CreationDate,
IDPConfigID: rm.ConfigID,
IDPProviderType: model.IDPProviderType(rm.ProviderType),
IsOIDC: rm.OIDCConfig != nil,
Name: rm.Name,
OIDCClientID: rm.OIDCConfig.ClientID,
OIDCClientSecret: rm.OIDCConfig.ClientSecret,
OIDCIDPDisplayNameMapping: model.OIDCMappingField(rm.OIDCConfig.IDPDisplayNameMapping),
OIDCIssuer: rm.OIDCConfig.Issuer,
OIDCScopes: rm.OIDCConfig.Scopes,
OIDCUsernameMapping: model.OIDCMappingField(rm.OIDCConfig.UserNameMapping),
Sequence: rm.ProcessedSequence,
State: model.IDPConfigState(rm.State),
StylingType: model.IDPStylingType(rm.StylingType),
}
}
func readModelToIDPConfigs(rm *iam.IDPConfigsReadModel) []*model.IDPConfig {
configs := make([]*model.IDPConfig, len(rm.Configs))
for i, config := range rm.Configs {
configs[i] = readModelToIDPConfig(&iam.IDPConfigReadModel{ConfigReadModel: *config})
}
return configs
}
func readModelToIDPConfig(rm *iam.IDPConfigReadModel) *model.IDPConfig {
return &model.IDPConfig{
ObjectRoot: readModelToObjectRoot(rm.ReadModel),
OIDCConfig: readModelToIDPOIDCConfig(rm.OIDCConfig),
IDPConfigID: rm.ConfigID,
Name: rm.Name,
State: model.IDPConfigState(rm.State),
StylingType: model.IDPStylingType(rm.StylingType),
}
}
func readModelToIDPOIDCConfig(rm *oidc.ConfigReadModel) *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 writeModelToIDPConfig(wm *iam.IDPConfigWriteModel) *model.IDPConfig {
return &model.IDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
OIDCConfig: writeModelToIDPOIDCConfig(wm.OIDCConfig),
IDPConfigID: wm.ConfigID,
Name: wm.Name,
State: model.IDPConfigState(wm.State),
StylingType: model.IDPStylingType(wm.StylingType),
}
}
func writeModelToIDPOIDCConfig(wm *oidc.ConfigWriteModel) *model.OIDCIDPConfig {
return &model.OIDCIDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
ClientID: wm.ClientID,
IDPConfigID: wm.IDPConfigID,
IDPDisplayNameMapping: model.OIDCMappingField(wm.IDPDisplayNameMapping),
Issuer: wm.Issuer,
Scopes: wm.Scopes,
UsernameMapping: model.OIDCMappingField(wm.UserNameMapping),
}
}
func writeModelToIDPProvider(wm *idpprovider.WriteModel) *model.IDPProvider {
return &model.IDPProvider{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
IDPConfigID: wm.IDPConfigID,
Type: model.IDPProviderType(wm.IDPProviderType),
}
}

View File

@ -1,130 +0,0 @@
package iam
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/idp"
"github.com/caos/zitadel/internal/v2/repository/idp/oidc"
)
func (r *Repository) IDPConfigByID(ctx context.Context, iamID, idpConfigID string) (*iam_model.IDPConfigView, error) {
idpConfig := iam.NewIDPConfigReadModel(iamID, idpConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpConfig)
if err != nil {
return nil, err
}
return readModelToIDPConfigView(idpConfig), nil
}
func (r *Repository) AddIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
if config.OIDCConfig == nil {
return nil, errors.ThrowInvalidArgument(nil, "IAM-eUpQU", "Errors.idp.config.notset")
}
idpConfigID, err := r.idGenerator.Next()
if err != nil {
return nil, err
}
//TODO: check name unique on aggregate
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.secretCrypto)
if err != nil {
return nil, err
}
writeModel, err := r.pushIDPWriteModel(ctx, config.AggregateID, idpConfigID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.
PushIDPConfigAdded(
ctx,
idpConfigID,
config.Name,
idp.ConfigType(config.Type),
idp.StylingType(config.StylingType)).
PushIDPOIDCConfigAdded(
ctx,
config.OIDCConfig.ClientID,
idpConfigID,
config.OIDCConfig.Issuer,
clientSecret,
oidc.MappingField(config.OIDCConfig.IDPDisplayNameMapping),
oidc.MappingField(config.OIDCConfig.UsernameMapping),
config.OIDCConfig.Scopes...)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) ChangeIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, config.AggregateID, config.IDPConfigID, func(a *iam.Aggregate, writeModel *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigChanged(
ctx,
writeModel,
config.IDPConfigID,
config.Name,
idp.ConfigType(config.Type),
idp.StylingType(config.StylingType))
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) DeactivateIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigDeactivated(ctx, idpID)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) ReactivateIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigReactivated(ctx, idpID)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) RemoveIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigRemoved(ctx, idpID)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) pushIDPWriteModel(ctx context.Context, iamID, idpID string, eventSetter func(*iam.Aggregate, *iam.IDPConfigWriteModel) *iam.Aggregate) (*iam.IDPConfigWriteModel, error) {
writeModel := iam.NewIDPConfigWriteModel(iamID, idpID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
aggregate := eventSetter(iam.AggregateFromWriteModel(&writeModel.WriteModel), writeModel)
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,44 +0,0 @@
package iam
import (
"context"
"github.com/caos/zitadel/internal/crypto"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/idp/oidc"
)
func (r *Repository) ChangeIDPOIDCConfig(ctx context.Context, config *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) {
writeModel := iam.NewIDPOIDCConfigWriteModel(config.AggregateID, config.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
var clientSecret *crypto.CryptoValue
if config.ClientSecretString != "" {
clientSecret, err = crypto.Crypt([]byte(config.ClientSecretString), r.secretCrypto)
if err != nil {
return nil, err
}
}
aggregate := iam.AggregateFromWriteModel(&writeModel.WriteModel).
PushIDPOIDCConfigChanged(
ctx,
writeModel,
config.ClientID,
config.Issuer,
clientSecret,
oidc.MappingField(config.IDPDisplayNameMapping),
oidc.MappingField(config.UsernameMapping),
config.Scopes...)
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
if err != nil {
return nil, err
}
return writeModelToIDPOIDCConfig(&writeModel.ConfigWriteModel), nil
}

View File

@ -1,60 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/org_iam"
)
func (r *Repository) AddOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
addedPolicy := org_iam.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.OrgIAMPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(addedPolicy), nil
}
func (r *Repository) ChangeOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushOrgIAMPolicyChangedFromExisting(ctx, existingPolicy, policy.UserLoginMustBeDomain)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(existingPolicy), nil
}
func (r *Repository) orgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *org_iam.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := org_iam.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,69 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/label"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
func (r *Repository) AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mv0s", "Errors.IAM.LabelPolicyInvalid")
}
addedPolicy := label.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushLabelPolicyAddedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(addedPolicy), nil
}
func (r *Repository) ChangeLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LabelPolicyInvalid")
}
existingPolicy, err := r.labelPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushLabelPolicyChangedFromExisting(ctx, existingPolicy, policy.PrimaryColor, policy.SecondaryColor)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(existingPolicy), nil
}
func (r *Repository) labelPolicyWriteModelByID(ctx context.Context, iamID string) (policy *label.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := label.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,160 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
iam_login "github.com/caos/zitadel/internal/v2/repository/iam/policy/login"
iam_factor "github.com/caos/zitadel/internal/v2/repository/iam/policy/login/factors"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/login/idpprovider"
"github.com/caos/zitadel/internal/v2/repository/policy/login"
"github.com/caos/zitadel/internal/v2/repository/policy/login/factors"
idpprovider2 "github.com/caos/zitadel/internal/v2/repository/policy/login/idpprovider"
)
func (r *Repository) AddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mv0s", "Errors.IAM.LoginPolicyInvalid")
}
addedPolicy := iam_login.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushLoginPolicyAddedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, login.PasswordlessType(policy.PasswordlessType))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(addedPolicy), nil
}
func (r *Repository) ChangeLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LoginPolicyInvalid")
}
existingPolicy, err := r.loginPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushLoginPolicyChangedFromExisting(ctx, existingPolicy, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, login.PasswordlessType(policy.PasswordlessType))
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(existingPolicy), nil
}
func (r *Repository) AddIDPProviderToLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
writeModel := idpprovider.NewWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.WriteModel.WriteModel).
PushLoginPolicyIDPProviderAddedEvent(ctx, idpProvider.IDPConfigID, idpprovider2.Type(idpProvider.Type))
if err = r.eventstore.PushAggregate(ctx, writeModel, aggregate); err != nil {
return nil, err
}
return writeModelToIDPProvider(writeModel), nil
}
func (r *Repository) RemoveIDPProviderFromLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) error {
writeModel := idpprovider.NewWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.WriteModel.WriteModel).
PushLoginPolicyIDPProviderAddedEvent(ctx, idpProvider.IDPConfigID, idpprovider2.Type(idpProvider.Type))
return r.eventstore.PushAggregate(ctx, writeModel, aggregate)
}
func (r *Repository) AddSecondFactorToLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) (iam_model.SecondFactorType, error) {
writeModel := iam_factor.NewSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.SecondFactorWriteModel.WriteModel).
PushLoginPolicySecondFactorAdded(ctx, factors.SecondFactorType(secondFactor))
if err = r.eventstore.PushAggregate(ctx, writeModel, aggregate); err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
return iam_model.SecondFactorType(writeModel.MFAType), nil
}
func (r *Repository) RemoveSecondFactorFromLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) error {
writeModel := iam_factor.NewSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.SecondFactorWriteModel.WriteModel).
PushLoginPolicySecondFactorRemoved(ctx, factors.SecondFactorType(secondFactor))
return r.eventstore.PushAggregate(ctx, writeModel, aggregate)
}
func (r *Repository) AddMultiFactorToLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.MultiFactorType) (iam_model.MultiFactorType, error) {
writeModel := iam_factor.NewMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.MultiFactoryWriteModel.WriteModel).
PushLoginPolicyMultiFactorAdded(ctx, factors.MultiFactorType(secondFactor))
if err = r.eventstore.PushAggregate(ctx, writeModel, aggregate); err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
return iam_model.MultiFactorType(writeModel.MultiFactoryWriteModel.MFAType), nil
}
func (r *Repository) RemoveMultiFactorFromLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.MultiFactorType) error {
writeModel := iam_factor.NewMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.MultiFactoryWriteModel.WriteModel).
PushLoginPolicyMultiFactorRemoved(ctx, factors.MultiFactorType(secondFactor))
return r.eventstore.PushAggregate(ctx, writeModel, aggregate)
}
func (r *Repository) loginPolicyWriteModelByID(ctx context.Context, iamID string) (policy *iam_login.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := iam_login.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,60 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_age"
)
func (r *Repository) AddPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
addedPolicy := password_age.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-6L0pd", "Errors.IAM.PasswordAgePolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushPasswordAgePolicyAddedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(addedPolicy), nil
}
func (r *Repository) ChangePasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
existingPolicy, err := r.passwordAgePolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushPasswordAgePolicyChangedFromExisting(ctx, existingPolicy, policy.ExpireWarnDays, policy.MaxAgeDays)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(existingPolicy), nil
}
func (r *Repository) passwordAgePolicyWriteModelByID(ctx context.Context, iamID string) (policy *password_age.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := password_age.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,68 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_complexity"
)
func (r *Repository) AddPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
addedPolicy := password_complexity.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordComplexityPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushPasswordComplexityPolicyAddedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(addedPolicy), nil
}
func (r *Repository) ChangePasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
existingPolicy, err := r.passwordComplexityPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushPasswordComplexityPolicyChangedFromExisting(ctx, existingPolicy, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(existingPolicy), nil
}
func (r *Repository) passwordComplexityPolicyWriteModelByID(ctx context.Context, iamID string) (policy *password_complexity.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := password_complexity.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,60 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_lockout"
)
func (r *Repository) AddPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
addedPolicy := password_lockout.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0olDf", "Errors.IAM.PasswordLockoutPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushPasswordLockoutPolicyAddedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(addedPolicy), nil
}
func (r *Repository) ChangePasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
existingPolicy, err := r.passwordLockoutPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushPasswordLockoutPolicyChangedFromExisting(ctx, existingPolicy, policy.MaxAttempts, policy.ShowLockOutFailures)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(existingPolicy), nil
}
func (r *Repository) passwordLockoutPolicyWriteModelByID(ctx context.Context, iamID string) (policy *password_lockout.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := password_lockout.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,50 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *Repository) StartSetup(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := r.setup(ctx, iamID, iam_repo.Step(step), iam_repo.NewSetupStepStartedEvent(ctx, iam_repo.Step(step)))
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-zx03n", "Setup start failed")
}
return iam, nil
}
func (r *Repository) SetupDone(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := r.setup(ctx, iamID, iam_repo.Step(step), iam_repo.NewSetupStepDoneEvent(ctx, iam_repo.Step(step)))
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-zx03n", "Setup start failed")
}
return iam, nil
}
func (r *Repository) setup(ctx context.Context, iamID string, step iam_repo.Step, event eventstore.EventPusher) (*iam_model.IAM, error) {
iam, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if iam != nil && (iam.SetUpStarted >= iam_repo.Step(step) || iam.SetUpStarted != iam.SetUpDone) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "setup error")
}
aggregate := iam_repo.AggregateFromReadModel(iam).
PushEvents(event)
events, err := r.eventstore.PushAggregates(ctx, aggregate)
if err != nil {
return nil, err
}
if err = iam.AppendAndReduce(events...); err != nil {
return nil, err
}
return readModelToIAM(iam), nil
}

View File

@ -1,99 +0,0 @@
package org
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
type Repository struct {
eventstore *eventstore.Eventstore
}
type Config struct {
Eventstore *eventstore.Eventstore
}
func StartRepository(config *Config) *Repository {
return &Repository{
eventstore: config.Eventstore,
}
}
func (r *Repository) GetMyOrgIamPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
return nil, nil
}
func (r *Repository) GetLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
return nil, nil
}
func (r *Repository) AddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
return nil, nil
}
func (r *Repository) ChangeLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
return nil, nil
}
func (r *Repository) RemoveLoginPolicy(ctx context.Context) error {
return nil
}
func (r *Repository) SearchIDPProviders(ctx context.Context, request *iam_model.IDPProviderSearchRequest) (*iam_model.IDPProviderSearchResponse, error) {
return nil, nil
}
func (r *Repository) AddIDPProviderToLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
return nil, nil
}
func (r *Repository) RemoveIDPProviderFromLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) error {
return nil
}
func (r *Repository) GetPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) {
return nil, nil
}
func (r *Repository) AddPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
return nil, nil
}
func (r *Repository) ChangePasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
return nil, nil
}
func (r *Repository) RemovePasswordComplexityPolicy(ctx context.Context) error {
return nil
}
func (r *Repository) GetPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error) {
return nil, nil
}
func (r *Repository) AddPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
return nil, nil
}
func (r *Repository) ChangePasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
return nil, nil
}
func (r *Repository) RemovePasswordAgePolicy(ctx context.Context) error {
return nil
}
func (r *Repository) GetPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error) {
return nil, nil
}
func (r *Repository) AddPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
return nil, nil
}
func (r *Repository) ChangePasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
return nil, nil
}
func (r *Repository) RemovePasswordLockoutPolicy(ctx context.Context) error {
return nil
}

View File

@ -0,0 +1,72 @@
package command
import (
"context"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/id"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
type CommandSide struct {
eventstore *eventstore.Eventstore
idGenerator id.Generator
iamID string
idpConfigSecretCrypto crypto.Crypto
userPasswordAlg crypto.HashAlgorithm
initializeUserCode crypto.Generator
emailVerificationCode crypto.Generator
phoneVerificationCode crypto.Generator
passwordVerificationCode crypto.Generator
machineKeyAlg crypto.EncryptionAlgorithm
machineKeySize int
}
type Config struct {
Eventstore *eventstore.Eventstore
SystemDefaults sd.SystemDefaults
}
func StartCommandSide(config *Config) (repo *CommandSide, err error) {
repo = &CommandSide{
eventstore: config.Eventstore,
idGenerator: id.SonyFlakeGenerator,
iamID: config.SystemDefaults.IamID,
}
iam_repo.RegisterEventMappers(repo.eventstore)
repo.idpConfigSecretCrypto, err = crypto.NewAESCrypto(config.SystemDefaults.IDPConfigVerificationKey)
if err != nil {
return nil, err
}
aesCrypto, err := crypto.NewAESCrypto(config.SystemDefaults.UserVerificationKey)
if err != nil {
return nil, err
}
repo.initializeUserCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.InitializeUserCode, aesCrypto)
repo.emailVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.EmailVerificationCode, aesCrypto)
repo.phoneVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.PhoneVerificationCode, aesCrypto)
repo.passwordVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.PasswordVerificationCode, aesCrypto)
repo.userPasswordAlg = crypto.NewBCrypt(config.SystemDefaults.SecretGenerators.PasswordSaltCost)
repo.machineKeyAlg = aesCrypto
repo.machineKeySize = int(config.SystemDefaults.SecretGenerators.MachineKeySize)
return repo, nil
}
func (r *CommandSide) iamByID(ctx context.Context, id string) (_ *IAMWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMriteModel(id)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,118 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/iam/model"
)
func writeModelToObjectRoot(writeModel eventstore.WriteModel) models.ObjectRoot {
return models.ObjectRoot{
AggregateID: writeModel.AggregateID,
ChangeDate: writeModel.ChangeDate,
ResourceOwner: writeModel.ResourceOwner,
Sequence: writeModel.ProcessedSequence,
}
}
func writeModelToIAM(wm *IAMWriteModel) *model.IAM {
return &model.IAM{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
SetUpStarted: wm.SetUpStarted,
SetUpDone: wm.SetUpDone,
GlobalOrgID: wm.GlobalOrgID,
IAMProjectID: wm.ProjectID,
}
}
func writeModelToMember(writeModel *IAMMemberWriteModel) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: writeModelToObjectRoot(writeModel.MemberWriteModel.WriteModel),
Roles: writeModel.Roles,
UserID: writeModel.UserID,
}
}
func writeModelToLoginPolicy(wm *IAMLoginPolicyWriteModel) *model.LoginPolicy {
return &model.LoginPolicy{
ObjectRoot: writeModelToObjectRoot(wm.LoginPolicyWriteModel.WriteModel),
AllowUsernamePassword: wm.AllowUserNamePassword,
AllowRegister: wm.AllowRegister,
AllowExternalIdp: wm.AllowExternalIDP,
ForceMFA: wm.ForceMFA,
PasswordlessType: model.PasswordlessType(wm.PasswordlessType),
}
}
func writeModelToLabelPolicy(wm *IAMLabelPolicyWriteModel) *model.LabelPolicy {
return &model.LabelPolicy{
ObjectRoot: writeModelToObjectRoot(wm.LabelPolicyWriteModel.WriteModel),
PrimaryColor: wm.PrimaryColor,
SecondaryColor: wm.SecondaryColor,
}
}
func writeModelToOrgIAMPolicy(wm *IAMOrgIAMPolicyWriteModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
}
}
func writeModelToPasswordAgePolicy(wm *IAMPasswordAgePolicyWriteModel) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordAgePolicyWriteModel.WriteModel),
MaxAgeDays: wm.MaxAgeDays,
ExpireWarnDays: wm.ExpireWarnDays,
}
}
func writeModelToPasswordComplexityPolicy(wm *IAMPasswordComplexityPolicyWriteModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordComplexityPolicyWriteModel.WriteModel),
MinLength: wm.MinLength,
HasLowercase: wm.HasLowercase,
HasUppercase: wm.HasUpperCase,
HasNumber: wm.HasNumber,
HasSymbol: wm.HasSymbol,
}
}
func writeModelToPasswordLockoutPolicy(wm *IAMPasswordLockoutPolicyWriteModel) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordLockoutPolicyWriteModel.WriteModel),
MaxAttempts: wm.MaxAttempts,
ShowLockOutFailures: wm.ShowLockOutFailures,
}
}
func writeModelToIDPConfig(wm *IAMIDPConfigWriteModel) *model.IDPConfig {
return &model.IDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
OIDCConfig: writeModelToIDPOIDCConfig(wm.OIDCConfig),
IDPConfigID: wm.ConfigID,
Name: wm.Name,
State: model.IDPConfigState(wm.State),
StylingType: model.IDPStylingType(wm.StylingType),
}
}
func writeModelToIDPOIDCConfig(wm *OIDCConfigWriteModel) *model.OIDCIDPConfig {
return &model.OIDCIDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
ClientID: wm.ClientID,
IDPConfigID: wm.IDPConfigID,
IDPDisplayNameMapping: model.OIDCMappingField(wm.IDPDisplayNameMapping),
Issuer: wm.Issuer,
Scopes: wm.Scopes,
UsernameMapping: model.OIDCMappingField(wm.UserNameMapping),
}
}
func writeModelToIDPProvider(wm *IAMIdentityProviderWriteModel) *model.IDPProvider {
return &model.IDPProvider{
ObjectRoot: writeModelToObjectRoot(wm.IdentityProviderWriteModel.WriteModel),
IDPConfigID: wm.IDPConfigID,
Type: model.IDPProviderType(wm.IDPProviderType),
}
}

View File

@ -0,0 +1,159 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
if config.OIDCConfig == nil {
return nil, errors.ThrowInvalidArgument(nil, "IAM-eUpQU", "Errors.idp.config.notset")
}
idpConfigID, err := r.idGenerator.Next()
if err != nil {
return nil, err
}
//TODO: check name unique on aggregate
addedConfig := NewIAMIDPConfigWriteModel(config.AggregateID, idpConfigID)
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.idpConfigSecretCrypto)
if err != nil {
return nil, err
}
iamAgg := IAMAggregateFromWriteModel(&addedConfig.WriteModel)
iamAgg.PushEvents(
iam_repo.NewIDPConfigAddedEvent(
ctx,
idpConfigID,
config.Name,
domain.IDPConfigType(config.Type),
domain.IDPConfigStylingType(config.StylingType),
),
)
iamAgg.PushEvents(
iam_repo.NewIDPOIDCConfigAddedEvent(
ctx, config.OIDCConfig.ClientID,
idpConfigID,
config.OIDCConfig.Issuer,
clientSecret,
domain.OIDCMappingField(config.OIDCConfig.IDPDisplayNameMapping),
domain.OIDCMappingField(config.OIDCConfig.UsernameMapping),
config.OIDCConfig.Scopes...,
),
)
err = r.eventstore.PushAggregate(ctx, addedConfig, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(addedConfig), nil
}
func (r *CommandSide) ChangeDefaultIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, config.AggregateID, config.IDPConfigID)
if err != nil {
return nil, err
}
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotExisting")
}
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, config.IDPConfigID, config.Name, domain.IDPConfigStylingType(config.StylingType))
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(existingIDP), nil
}
func (r *CommandSide) DeactivateDefaultIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, iamID, idpID)
if err != nil {
return nil, err
}
if existingIDP.State != domain.IDPConfigStateActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotActive")
}
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
iamAgg.PushEvents(iam_repo.NewIDPConfigDeactivatedEvent(ctx, idpID))
err = r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(existingIDP), nil
}
func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, iamID, idpID)
if err != nil {
return nil, err
}
if existingIDP.State != domain.IDPConfigStateInactive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-5Mo0d", "Errors.IAM.IDPConfig.NotInactive")
}
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
iamAgg.PushEvents(iam_repo.NewIDPConfigReactivatedEvent(ctx, idpID))
err = r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(existingIDP), nil
}
func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushDefaultIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *IAMIDPConfigWriteModel) *iam.Aggregate {
a.Aggregate = *a.PushEvents(iam_repo.NewIDPConfigRemovedEvent(ctx, idpID))
return a
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *CommandSide) pushDefaultIDPWriteModel(ctx context.Context, iamID, idpID string, eventSetter func(*iam.Aggregate, *IAMIDPConfigWriteModel) *iam.Aggregate) (*IAMIDPConfigWriteModel, error) {
writeModel := NewIAMIDPConfigWriteModel(iamID, idpID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
aggregate := eventSetter(IAMAggregateFromWriteModel(&writeModel.WriteModel), writeModel)
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
if err != nil {
return nil, err
}
return writeModel, nil
}
func (r *CommandSide) iamIDPConfigWriteModelByID(ctx context.Context, iamID, idpID string) (policy *IAMIDPConfigWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMIDPConfigWriteModel(iamID, idpID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,100 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMIDPConfigWriteModel struct {
IDPConfigWriteModel
}
func NewIAMIDPConfigWriteModel(iamID, configID string) *IAMIDPConfigWriteModel {
return &IAMIDPConfigWriteModel{
IDPConfigWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
ConfigID: configID,
},
}
}
func (wm *IAMIDPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}
func (wm *IAMIDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.IDPConfigAddedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigAddedEvent)
case *iam.IDPConfigChangedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigChangedEvent)
case *iam.IDPConfigDeactivatedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
case *iam.IDPConfigReactivatedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
case *iam.IDPConfigRemovedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
case *iam.IDPOIDCConfigAddedEvent:
if wm.ConfigID != e.IDPConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
case *iam.IDPOIDCConfigChangedEvent:
if wm.ConfigID != e.IDPConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
}
}
}
func (wm *IAMIDPConfigWriteModel) Reduce() error {
return wm.IDPConfigWriteModel.Reduce()
}
func (wm *IAMIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventReader) error {
wm.AppendEvents(events...)
return wm.Reduce()
}
func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
ctx context.Context,
configID,
name string,
stylingType domain.IDPConfigStylingType,
) (*iam.IDPConfigChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewIDPConfigChangedEvent(ctx)
changedEvent.ConfigID = configID
if wm.Name != name {
hasChanged = true
changedEvent.Name = name
}
if stylingType.Valid() && wm.StylingType != stylingType {
hasChanged = true
changedEvent.StylingType = stylingType
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,47 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/v2/domain"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
func (r *CommandSide) ChangeDefaultIDPOIDCConfig(ctx context.Context, config *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) {
existingConfig := NewIDPOIDCConfigWriteModel(config.AggregateID, config.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, existingConfig)
if err != nil {
return nil, err
}
if existingConfig.State == domain.IDPConfigStateRemoved || existingConfig.State == domain.IDPConfigStateUnspecified {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-67J9d", "Errors.IAM.IDPConfig.AlreadyExists")
}
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
ctx,
config.ClientID,
config.Issuer,
config.ClientSecretString,
r.idpConfigSecretCrypto,
domain.OIDCMappingField(config.IDPDisplayNameMapping),
domain.OIDCMappingField(config.UsernameMapping),
config.Scopes...)
if err != nil {
return nil, err
}
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingConfig.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingConfig, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPOIDCConfig(&existingConfig.OIDCConfigWriteModel), nil
}

View File

@ -0,0 +1,115 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
"reflect"
)
type IDPOIDCConfigWriteModel struct {
OIDCConfigWriteModel
}
func NewIDPOIDCConfigWriteModel(iamID, idpConfigID string) *IDPOIDCConfigWriteModel {
return &IDPOIDCConfigWriteModel{
OIDCConfigWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
IDPConfigID: idpConfigID,
},
}
}
func (wm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.IDPOIDCConfigAddedEvent:
if wm.IDPConfigID != e.IDPConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
case *iam.IDPOIDCConfigChangedEvent:
if wm.IDPConfigID != e.IDPConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
case *iam.IDPConfigReactivatedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
case *iam.IDPConfigDeactivatedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
case *iam.IDPConfigRemovedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
default:
wm.OIDCConfigWriteModel.AppendEvents(e)
}
}
}
func (wm *IDPOIDCConfigWriteModel) Reduce() error {
if err := wm.OIDCConfigWriteModel.Reduce(); err != nil {
return err
}
return wm.WriteModel.Reduce()
}
func (wm *IDPOIDCConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}
func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
ctx context.Context,
clientID,
issuer,
clientSecretString string,
secretCrypto crypto.Crypto,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
scopes ...string,
) (*iam.IDPOIDCConfigChangedEvent, bool, error) {
hasChanged := false
changedEvent := iam.NewIDPOIDCConfigChangedEvent(ctx)
var clientSecret *crypto.CryptoValue
var err error
if clientSecretString != "" {
clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
if err != nil {
return nil, false, err
}
changedEvent.ClientSecret = clientSecret
}
if wm.ClientID != clientID {
hasChanged = true
changedEvent.ClientID = clientID
}
if wm.Issuer != issuer {
hasChanged = true
changedEvent.Issuer = issuer
}
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
hasChanged = true
changedEvent.IDPDisplayNameMapping = idpDisplayNameMapping
}
if userNameMapping.Valid() && wm.UserNameMapping != userNameMapping {
hasChanged = true
changedEvent.UserNameMapping = userNameMapping
}
if reflect.DeepEqual(wm.Scopes, scopes) {
hasChanged = true
changedEvent.Scopes = scopes
}
return changedEvent, hasChanged, nil
}

View File

@ -1,7 +1,8 @@
package iam
package command
import (
"context"
"reflect"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
@ -10,14 +11,14 @@ import (
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *Repository) AddMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
func (r *CommandSide) AddIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
//TODO: check if roles valid
if !member.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-W8m4l", "Errors.IAM.MemberInvalid")
}
addedMember := iam_repo.NewMemberWriteModel(member.AggregateID, member.UserID)
addedMember := NewIAMMemberWriteModel(member.AggregateID, member.UserID)
err := r.eventstore.FilterToQueryReducer(ctx, addedMember)
if err != nil {
return nil, err
@ -26,8 +27,8 @@ func (r *Repository) AddMember(ctx context.Context, member *iam_model.IAMMember)
return nil, errors.ThrowAlreadyExists(nil, "IAM-PtXi1", "Errors.IAM.Member.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedMember.WriteModel.WriteModel).
PushMemberAdded(ctx, member.UserID, member.Roles...)
iamAgg := IAMAggregateFromWriteModel(&addedMember.MemberWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewMemberAddedEvent(ctx, member.UserID, member.Roles...))
err = r.eventstore.PushAggregate(ctx, addedMember, iamAgg)
if err != nil {
@ -37,23 +38,26 @@ func (r *Repository) AddMember(ctx context.Context, member *iam_model.IAMMember)
return writeModelToMember(addedMember), nil
}
//ChangeMember updates an existing member
func (r *Repository) ChangeMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
//ChangeIAMMember updates an existing member
func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
//TODO: check if roles valid
if !member.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-LiaZi", "Errors.IAM.MemberInvalid")
}
existingMember, err := r.memberWriteModelByID(ctx, member.AggregateID, member.UserID)
existingMember, err := r.iamMemberWriteModelByID(ctx, member.AggregateID, member.UserID)
if err != nil {
return nil, err
}
iam := iam_repo.AggregateFromWriteModel(&existingMember.WriteModel.WriteModel).
PushMemberChangedFromExisting(ctx, existingMember, member.Roles...)
if reflect.DeepEqual(existingMember.Roles, member.Roles) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-LiaZi", "Errors.IAM.Member.RolesNotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingMember.MemberWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewMemberChangedEvent(ctx, member.UserID, member.Roles...))
events, err := r.eventstore.PushAggregates(ctx, iam)
events, err := r.eventstore.PushAggregates(ctx, iamAgg)
if err != nil {
return nil, err
}
@ -66,8 +70,8 @@ func (r *Repository) ChangeMember(ctx context.Context, member *iam_model.IAMMemb
return writeModelToMember(existingMember), nil
}
func (r *Repository) RemoveMember(ctx context.Context, member *iam_model.IAMMember) error {
m, err := r.memberWriteModelByID(ctx, member.AggregateID, member.UserID)
func (r *CommandSide) RemoveIAMMember(ctx context.Context, member *iam_model.IAMMember) error {
m, err := r.iamMemberWriteModelByID(ctx, member.AggregateID, member.UserID)
if err != nil && !errors.IsNotFound(err) {
return err
}
@ -75,30 +79,17 @@ func (r *Repository) RemoveMember(ctx context.Context, member *iam_model.IAMMemb
return nil
}
iamAgg := iam_repo.AggregateFromWriteModel(&m.WriteModel.WriteModel).
PushEvents(iam_repo.NewMemberRemovedEvent(ctx, member.UserID))
iamAgg := IAMAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewMemberRemovedEvent(ctx, member.UserID))
return r.eventstore.PushAggregate(ctx, m, iamAgg)
}
func (r *Repository) MemberByID(ctx context.Context, iamID, userID string) (member *iam_repo.MemberReadModel, err error) {
func (r *CommandSide) iamMemberWriteModelByID(ctx context.Context, iamID, userID string) (member *IAMMemberWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
member = iam_repo.NewMemberReadModel(iamID, userID)
err = r.eventstore.FilterToQueryReducer(ctx, member)
if err != nil {
return nil, err
}
return member, nil
}
func (r *Repository) memberWriteModelByID(ctx context.Context, iamID, userID string) (member *iam_repo.MemberWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := iam_repo.NewMemberWriteModel(iamID, userID)
writeModel := NewIAMMemberWriteModel(iamID, userID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err

View File

@ -0,0 +1,52 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMMemberWriteModel struct {
MemberWriteModel
}
func NewIAMMemberWriteModel(iamID, userID string) *IAMMemberWriteModel {
return &IAMMemberWriteModel{
MemberWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
UserID: userID,
},
}
}
func (wm *IAMMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.MemberAddedEvent:
if e.UserID != wm.MemberWriteModel.UserID {
continue
}
wm.MemberWriteModel.AppendEvents(&e.MemberAddedEvent)
case *iam.MemberChangedEvent:
if e.UserID != wm.MemberWriteModel.UserID {
continue
}
wm.MemberWriteModel.AppendEvents(&e.MemberChangedEvent)
case *iam.MemberRemovedEvent:
if e.UserID != wm.MemberWriteModel.UserID {
continue
}
wm.MemberWriteModel.AppendEvents(&e.MemberRemovedEvent)
}
}
}
func (wm *IAMMemberWriteModel) Reduce() error {
return wm.MemberWriteModel.Reduce()
}
func (wm *IAMMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.MemberWriteModel.AggregateID)
}

View File

@ -0,0 +1,77 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMWriteModel struct {
eventstore.WriteModel
SetUpStarted domain.Step
SetUpDone domain.Step
GlobalOrgID string
ProjectID string
}
func NewIAMriteModel(iamID string) *IAMWriteModel {
return &IAMWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
}
}
func (wm *IAMWriteModel) AppendEvents(events ...eventstore.EventReader) {
wm.WriteModel.AppendEvents(events...)
//for _, event := range events {
// switch e := event.(type) {
// case *iam.LabelPolicyAddedEvent:
// wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyAddedEvent)
// case *iam.LabelPolicyChangedEvent:
// wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyChangedEvent)
// }
//}
}
func (wm *IAMWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *iam.ProjectSetEvent:
wm.ProjectID = e.ProjectID
case *iam.GlobalOrgSetEvent:
wm.GlobalOrgID = e.OrgID
case *iam.SetupStepEvent:
if e.Done {
wm.SetUpDone = e.Step
} else {
wm.SetUpStarted = e.Step
}
}
}
return nil
}
func (wm *IAMWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}
//
//func (wm *IAMLabelPolicyWriteModel) HasChanged(primaryColor, secondaryColor string) bool {
// if primaryColor != "" && wm.PrimaryColor != primaryColor {
// return true
// }
// if secondaryColor != "" && wm.SecondaryColor != secondaryColor {
// return true
// }
// return false
//}
func IAMAggregateFromWriteModel(wm *eventstore.WriteModel) *iam.Aggregate {
return &iam.Aggregate{
Aggregate: *eventstore.AggregateFromWriteModel(wm, iam.AggregateType, iam.AggregateVersion),
}
}

View File

@ -0,0 +1,76 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mv0s", "Errors.IAM.LabelPolicyInvalid")
}
addedPolicy := NewIAMLabelPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLabelPolicyAddedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LabelPolicyInvalid")
}
existingPolicy, err := r.defaultLabelPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultLabelPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMLabelPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMLabelPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,60 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMLabelPolicyWriteModel struct {
LabelPolicyWriteModel
}
func NewIAMLabelPolicyWriteModel(iamID string) *IAMLabelPolicyWriteModel {
return &IAMLabelPolicyWriteModel{
LabelPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMLabelPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LabelPolicyAddedEvent:
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyAddedEvent)
case *iam.LabelPolicyChangedEvent:
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyChangedEvent)
}
}
}
func (wm *IAMLabelPolicyWriteModel) Reduce() error {
return wm.LabelPolicyWriteModel.Reduce()
}
func (wm *IAMLabelPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.LabelPolicyWriteModel.AggregateID)
}
func (wm *IAMLabelPolicyWriteModel) NewChangedEvent(
ctx context.Context,
primaryColor,
secondaryColor string,
) (*iam.LabelPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewLabelPolicyChangedEvent(ctx)
if wm.PrimaryColor != primaryColor {
hasChanged = true
changedEvent.PrimaryColor = primaryColor
}
if wm.SecondaryColor != secondaryColor {
hasChanged = true
changedEvent.SecondaryColor = secondaryColor
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,183 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
addedPolicy := NewIAMLoginPolicyWriteModel(policy.AggregateID)
iamAgg, err := r.addDefaultLoginPolicy(ctx, addedPolicy, policy)
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(addedPolicy), nil
}
func (r *CommandSide) addDefaultLoginPolicy(ctx context.Context, addedPolicy *IAMLoginPolicyWriteModel, policy *iam_model.LoginPolicy) (*iam_repo.Aggregate, error) {
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.LoginPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicyAddedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType)))
return iamAgg, nil
}
func (r *CommandSide) ChangeDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LoginPolicyInvalid")
}
existingPolicy, err := r.defaultLoginPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-M0sif", "Errors.IAM.LoginPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType))
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(existingPolicy), nil
}
func (r *CommandSide) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
idpModel := NewIAMIdentityProviderWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
if err != nil {
return nil, err
}
if idpModel.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.IDP.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&idpModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewIdentityProviderAddedEvent(ctx, idpProvider.IDPConfigID, domain.IdentityProviderType(idpProvider.Type)))
if err = r.eventstore.PushAggregate(ctx, idpModel, iamAgg); err != nil {
return nil, err
}
return writeModelToIDPProvider(idpModel), nil
}
func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) error {
idpModel := NewIAMIdentityProviderWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
if err != nil {
return err
}
if !idpModel.IsActive {
return caos_errs.ThrowAlreadyExists(nil, "IAM-39fjs", "Errors.IAM.LoginPolicy.IDP.NotExisting")
}
iamAgg := IAMAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID))
return r.eventstore.PushAggregate(ctx, idpModel, iamAgg)
}
func (r *CommandSide) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) (iam_model.SecondFactorType, error) {
secondFactorModel := NewIAMSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
if err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
if secondFactorModel.IsActive {
return iam_model.SecondFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicySecondFactorAddedEvent(ctx, domain.SecondFactorType(secondFactor)))
if err = r.eventstore.PushAggregate(ctx, secondFactorModel, iamAgg); err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
return iam_model.SecondFactorType(secondFactorModel.MFAType), nil
}
func (r *CommandSide) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) error {
secondFactorModel := NewIAMSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
if err != nil {
return err
}
if !secondFactorModel.IsActive {
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.NotExisting")
}
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicySecondFactorRemovedEvent(ctx, domain.SecondFactorType(secondFactor)))
return r.eventstore.PushAggregate(ctx, secondFactorModel, iamAgg)
}
func (r *CommandSide) AddMultiFactorToDefaultLoginPolicy(ctx context.Context, iamID string, multiFactor iam_model.MultiFactorType) (iam_model.MultiFactorType, error) {
multiFactorModel := NewIAMMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
if err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
if multiFactorModel.IsActive {
return iam_model.MultiFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicyMultiFactorAddedEvent(ctx, domain.MultiFactorType(multiFactor)))
if err = r.eventstore.PushAggregate(ctx, multiFactorModel, iamAgg); err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
return iam_model.MultiFactorType(multiFactorModel.MultiFactoryWriteModel.MFAType), nil
}
func (r *CommandSide) RemoveMultiFactorFromDefaultLoginPolicy(ctx context.Context, iamID string, multiFactor iam_model.MultiFactorType) error {
multiFactorModel := NewIAMMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
if err != nil {
return err
}
if multiFactorModel.IsActive {
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9df", "Errors.IAM.LoginPolicy.MFA.NotExisting")
}
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicyMultiFactorRemovedEvent(ctx, domain.MultiFactorType(multiFactor)))
return r.eventstore.PushAggregate(ctx, multiFactorModel, iamAgg)
}
func (r *CommandSide) defaultLoginPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMLoginPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMLoginPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,70 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMSecondFactorWriteModel struct {
SecondFactorWriteModel
}
func NewIAMSecondFactorWriteModel(iamID string) *IAMSecondFactorWriteModel {
return &IAMSecondFactorWriteModel{
SecondFactorWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMSecondFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LoginPolicySecondFactorAddedEvent:
wm.WriteModel.AppendEvents(&e.SecondFactorAddedEvent)
}
}
}
func (wm *IAMSecondFactorWriteModel) Reduce() error {
return wm.WriteModel.Reduce()
}
func (wm *IAMSecondFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.WriteModel.AggregateID)
}
type IAMMultiFactorWriteModel struct {
MultiFactoryWriteModel
}
func NewIAMMultiFactorWriteModel(iamID string) *IAMMultiFactorWriteModel {
return &IAMMultiFactorWriteModel{
MultiFactoryWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMMultiFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LoginPolicyMultiFactorAddedEvent:
wm.WriteModel.AppendEvents(&e.MultiFactorAddedEvent)
}
}
}
func (wm *IAMMultiFactorWriteModel) Reduce() error {
return wm.WriteModel.Reduce()
}
func (wm *IAMMultiFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.WriteModel.AggregateID)
}

View File

@ -0,0 +1,42 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMIdentityProviderWriteModel struct {
IdentityProviderWriteModel
}
func NewIAMIdentityProviderWriteModel(iamID, idpConfigID string) *IAMIdentityProviderWriteModel {
return &IAMIdentityProviderWriteModel{
IdentityProviderWriteModel: IdentityProviderWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
IDPConfigID: idpConfigID,
},
}
}
func (wm *IAMIdentityProviderWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.IdentityProviderAddedEvent:
if e.IDPConfigID != wm.IDPConfigID {
continue
}
wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderAddedEvent)
}
}
}
func (wm *IAMIdentityProviderWriteModel) Reduce() error {
return wm.IdentityProviderWriteModel.Reduce()
}
func (wm *IAMIdentityProviderWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}

View File

@ -0,0 +1,80 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMLoginPolicyWriteModel struct {
LoginPolicyWriteModel
}
func NewIAMLoginPolicyWriteModel(iamID string) *IAMLoginPolicyWriteModel {
return &IAMLoginPolicyWriteModel{
LoginPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMLoginPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LoginPolicyAddedEvent:
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyAddedEvent)
case *iam.LoginPolicyChangedEvent:
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyChangedEvent)
}
}
}
func (wm *IAMLoginPolicyWriteModel) IsValid() bool {
return wm.AggregateID != ""
}
func (wm *IAMLoginPolicyWriteModel) Reduce() error {
return wm.LoginPolicyWriteModel.Reduce()
}
func (wm *IAMLoginPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.LoginPolicyWriteModel.AggregateID)
}
func (wm *IAMLoginPolicyWriteModel) NewChangedEvent(
ctx context.Context,
allowUsernamePassword,
allowRegister,
allowExternalIDP,
forceMFA bool,
passwordlessType domain.PasswordlessType,
) (*iam.LoginPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewLoginPolicyChangedEvent(ctx)
if wm.AllowUserNamePassword == allowUsernamePassword {
hasChanged = true
changedEvent.AllowUserNamePassword = allowUsernamePassword
}
if wm.AllowRegister == allowRegister {
hasChanged = true
changedEvent.AllowRegister = allowRegister
}
if wm.AllowExternalIDP == allowExternalIDP {
hasChanged = true
changedEvent.AllowExternalIDP = allowExternalIDP
}
if wm.ForceMFA != forceMFA {
hasChanged = true
changedEvent.ForceMFA = forceMFA
}
if passwordlessType.Valid() && wm.PasswordlessType != passwordlessType {
hasChanged = true
changedEvent.PasswordlessType = passwordlessType
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,77 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) GetDefaultOrgIAMPolicy(ctx context.Context, aggregateID string) (*iam_model.OrgIAMPolicy, error) {
policyWriteModel := NewIAMOrgIAMPolicyWriteModel(aggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
if err != nil {
return nil, err
}
policy := writeModelToOrgIAMPolicy(policyWriteModel)
policy.Default = true
return policy, nil
}
func (r *CommandSide) AddDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
addedPolicy := NewIAMOrgIAMPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.OrgIAMPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
existingPolicy, err := r.defaultOrgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0Pl0d", "Errors.IAM.OrgIAMPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultOrgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMOrgIAMPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMOrgIAMPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,51 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMOrgIAMPolicyWriteModel struct {
PolicyOrgIAMWriteModel
}
func NewIAMOrgIAMPolicyWriteModel(iamID string) *IAMOrgIAMPolicyWriteModel {
return &IAMOrgIAMPolicyWriteModel{
PolicyOrgIAMWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMOrgIAMPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.OrgIAMPolicyAddedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyAddedEvent)
case *iam.OrgIAMPolicyChangedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyChangedEvent)
}
}
}
func (wm *IAMOrgIAMPolicyWriteModel) Reduce() error {
return wm.PolicyOrgIAMWriteModel.Reduce()
}
func (wm *IAMOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PolicyOrgIAMWriteModel.AggregateID)
}
func (wm *IAMOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLoginMustBeDomain bool) (*iam.OrgIAMPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewOrgIAMPolicyChangedEvent(ctx)
if wm.UserLoginMustBeDomain != userLoginMustBeDomain {
hasChanged = true
changedEvent.UserLoginMustBeDomain = userLoginMustBeDomain
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,67 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
addedPolicy := NewIAMPasswordAgePolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.PasswordAgePolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PasswordAgePolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewPasswordAgePolicyAddedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
existingPolicy, err := r.defaultPasswordAgePolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordAgePolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(existingPolicy), nil
}
func (r *CommandSide) defaultPasswordAgePolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMPasswordAgePolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMPasswordAgePolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,55 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMPasswordAgePolicyWriteModel struct {
PasswordAgePolicyWriteModel
}
func NewIAMPasswordAgePolicyWriteModel(iamID string) *IAMPasswordAgePolicyWriteModel {
return &IAMPasswordAgePolicyWriteModel{
PasswordAgePolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMPasswordAgePolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.PasswordAgePolicyAddedEvent:
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyAddedEvent)
case *iam.PasswordAgePolicyChangedEvent:
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyChangedEvent)
}
}
}
func (wm *IAMPasswordAgePolicyWriteModel) Reduce() error {
return wm.PasswordAgePolicyWriteModel.Reduce()
}
func (wm *IAMPasswordAgePolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PasswordAgePolicyWriteModel.AggregateID)
}
func (wm *IAMPasswordAgePolicyWriteModel) NewChangedEvent(ctx context.Context, expireWarnDays, maxAgeDays uint64) (*iam.PasswordAgePolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewPasswordAgePolicyChangedEvent(ctx)
if wm.ExpireWarnDays != expireWarnDays {
hasChanged = true
changedEvent.ExpireWarnDays = expireWarnDays
}
if wm.MaxAgeDays != maxAgeDays {
hasChanged = true
changedEvent.MaxAgeDays = maxAgeDays
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,94 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) GetDefaultPasswordComplexityPolicy(ctx context.Context, aggregateID string) (*iam_model.PasswordComplexityPolicy, error) {
policyWriteModel := NewIAMPasswordComplexityPolicyWriteModel(aggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
if err != nil {
return nil, err
}
policy := writeModelToPasswordComplexityPolicy(policyWriteModel)
policy.Default = true
return policy, nil
}
func (r *CommandSide) AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
addedPolicy := NewIAMPasswordComplexityPolicyWriteModel(policy.AggregateID)
iamAgg, err := r.addDefaultPasswordComplexityPolicy(ctx, addedPolicy, policy)
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(addedPolicy), nil
}
func (r *CommandSide) addDefaultPasswordComplexityPolicy(ctx context.Context, addedPolicy *IAMPasswordComplexityPolicyWriteModel, policy *iam_model.PasswordComplexityPolicy) (*iam_repo.Aggregate, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordComplexityPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewPasswordComplexityPolicyAddedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol))
return iamAgg, nil
}
func (r *CommandSide) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
existingPolicy, err := r.defaultPasswordComplexityPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultPasswordComplexityPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMPasswordComplexityPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMPasswordComplexityPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,75 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMPasswordComplexityPolicyWriteModel struct {
PasswordComplexityPolicyWriteModel
}
func NewIAMPasswordComplexityPolicyWriteModel(iamID string) *IAMPasswordComplexityPolicyWriteModel {
return &IAMPasswordComplexityPolicyWriteModel{
PasswordComplexityPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMPasswordComplexityPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.PasswordComplexityPolicyAddedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent)
case *iam.PasswordComplexityPolicyChangedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent)
}
}
}
func (wm *IAMPasswordComplexityPolicyWriteModel) Reduce() error {
return wm.PasswordComplexityPolicyWriteModel.Reduce()
}
func (wm *IAMPasswordComplexityPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PasswordComplexityPolicyWriteModel.AggregateID)
}
func (wm *IAMPasswordComplexityPolicyWriteModel) NewChangedEvent(
ctx context.Context,
minLength uint64,
hasLowercase,
hasUppercase,
hasNumber,
hasSymbol bool,
) (*iam.PasswordComplexityPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewPasswordComplexityPolicyChangedEvent(ctx)
if wm.MinLength != minLength {
hasChanged = true
changedEvent.MinLength = minLength
}
if wm.HasLowercase != hasLowercase {
hasChanged = true
changedEvent.HasLowercase = hasLowercase
}
if wm.HasUpperCase != hasUppercase {
hasChanged = true
changedEvent.HasUpperCase = hasUppercase
}
if wm.HasNumber != hasNumber {
hasChanged = true
changedEvent.HasNumber = hasNumber
}
if wm.HasSymbol != hasSymbol {
hasChanged = true
changedEvent.HasSymbol = hasSymbol
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,67 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
addedPolicy := NewIAMPasswordLockoutPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0olDf", "Errors.IAM.PasswordLockoutPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewPasswordLockoutPolicyAddedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
existingPolicy, err := r.defaultPasswordLockoutPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordLockoutPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.PasswordLockoutPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultPasswordLockoutPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMPasswordLockoutPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMPasswordLockoutPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,55 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMPasswordLockoutPolicyWriteModel struct {
PasswordLockoutPolicyWriteModel
}
func NewIAMPasswordLockoutPolicyWriteModel(iamID string) *IAMPasswordLockoutPolicyWriteModel {
return &IAMPasswordLockoutPolicyWriteModel{
PasswordLockoutPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMPasswordLockoutPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.PasswordLockoutPolicyAddedEvent:
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyAddedEvent)
case *iam.PasswordLockoutPolicyChangedEvent:
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyChangedEvent)
}
}
}
func (wm *IAMPasswordLockoutPolicyWriteModel) Reduce() error {
return wm.PasswordLockoutPolicyWriteModel.Reduce()
}
func (wm *IAMPasswordLockoutPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PasswordLockoutPolicyWriteModel.AggregateID)
}
func (wm *IAMPasswordLockoutPolicyWriteModel) NewChangedEvent(ctx context.Context, maxAttempts uint64, showLockoutFailure bool) (*iam.PasswordLockoutPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewPasswordLockoutPolicyChangedEvent(ctx)
if wm.MaxAttempts != maxAttempts {
hasChanged = true
changedEvent.MaxAttempts = maxAttempts
}
if wm.ShowLockOutFailures != showLockoutFailure {
hasChanged = true
changedEvent.ShowLockOutFailures = showLockoutFailure
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,29 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type IdentityProviderWriteModel struct {
eventstore.WriteModel
IDPConfigID string
IDPProviderType domain.IdentityProviderType
IsActive bool
}
func (wm *IdentityProviderWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *policy.IdentityProviderAddedEvent:
wm.IDPConfigID = e.IDPConfigID
wm.IDPProviderType = e.IDPProviderType
wm.IsActive = true
case *policy.IdentityProviderRemovedEvent:
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()
}

View File

@ -0,0 +1,75 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
)
type IDPConfigWriteModel struct {
eventstore.WriteModel
State domain.IDPConfigState
ConfigID string
Name string
StylingType domain.IDPConfigStylingType
OIDCConfig *OIDCConfigWriteModel
}
func (rm *IDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
rm.WriteModel.AppendEvents(events...)
for _, event := range events {
switch event.(type) {
case *idpconfig.OIDCConfigAddedEvent:
rm.OIDCConfig = new(OIDCConfigWriteModel)
rm.OIDCConfig.AppendEvents(event)
case *idpconfig.OIDCConfigChangedEvent:
rm.OIDCConfig.AppendEvents(event)
}
}
}
func (rm *IDPConfigWriteModel) Reduce() error {
for _, event := range rm.Events {
switch e := event.(type) {
case *idpconfig.IDPConfigAddedEvent:
rm.reduceConfigAddedEvent(e)
case *idpconfig.IDPConfigChangedEvent:
rm.reduceConfigChangedEvent(e)
case *idpconfig.IDPConfigDeactivatedEvent:
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateInactive)
case *idpconfig.IDPConfigReactivatedEvent:
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateActive)
case *idpconfig.IDPConfigRemovedEvent:
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateRemoved)
}
}
if rm.OIDCConfig != nil {
if err := rm.OIDCConfig.Reduce(); err != nil {
return err
}
}
return rm.WriteModel.Reduce()
}
func (rm *IDPConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.IDPConfigAddedEvent) {
rm.ConfigID = e.ConfigID
rm.Name = e.Name
rm.StylingType = e.StylingType
rm.State = domain.IDPConfigStateActive
}
func (rm *IDPConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.IDPConfigChangedEvent) {
if e.Name != "" {
rm.Name = e.Name
}
if e.StylingType.Valid() {
rm.StylingType = e.StylingType
}
}
func (rm *IDPConfigWriteModel) reduceConfigStateChanged(configID string, state domain.IDPConfigState) {
rm.State = state
}

View File

@ -0,0 +1,37 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/member"
)
type MemberWriteModel struct {
eventstore.WriteModel
UserID string
Roles []string
IsActive bool
}
func NewMemberWriteModel(userID string) *MemberWriteModel {
return &MemberWriteModel{
UserID: userID,
}
}
func (wm *MemberWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *member.MemberAddedEvent:
wm.UserID = e.UserID
wm.Roles = e.Roles
wm.IsActive = true
case *member.MemberChangedEvent:
wm.Roles = e.Roles
case *member.MemberRemovedEvent:
wm.Roles = nil
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()
}

View File

@ -1,11 +1,13 @@
package oidc
package command
import (
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
)
type ConfigWriteModel struct {
type OIDCConfigWriteModel struct {
eventstore.WriteModel
IDPConfigID string
@ -14,24 +16,31 @@ type ConfigWriteModel struct {
Issuer string
Scopes []string
IDPDisplayNameMapping MappingField
UserNameMapping MappingField
IDPDisplayNameMapping domain.OIDCMappingField
UserNameMapping domain.OIDCMappingField
State domain.IDPConfigState
}
func (wm *ConfigWriteModel) Reduce() error {
func (wm *OIDCConfigWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *ConfigAddedEvent:
case *idpconfig.OIDCConfigAddedEvent:
wm.reduceConfigAddedEvent(e)
case *ConfigChangedEvent:
case *idpconfig.OIDCConfigChangedEvent:
wm.reduceConfigChangedEvent(e)
case *idpconfig.IDPConfigDeactivatedEvent:
wm.State = domain.IDPConfigStateInactive
case *idpconfig.IDPConfigReactivatedEvent:
wm.State = domain.IDPConfigStateActive
case *idpconfig.IDPConfigRemovedEvent:
wm.State = domain.IDPConfigStateRemoved
}
}
return wm.WriteModel.Reduce()
}
func (wm *ConfigWriteModel) reduceConfigAddedEvent(e *ConfigAddedEvent) {
func (wm *OIDCConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAddedEvent) {
wm.IDPConfigID = e.IDPConfigID
wm.ClientID = e.ClientID
wm.ClientSecret = e.ClientSecret
@ -39,9 +48,10 @@ func (wm *ConfigWriteModel) reduceConfigAddedEvent(e *ConfigAddedEvent) {
wm.Scopes = e.Scopes
wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping
wm.UserNameMapping = e.UserNameMapping
wm.State = domain.IDPConfigStateActive
}
func (wm *ConfigWriteModel) reduceConfigChangedEvent(e *ConfigChangedEvent) {
func (wm *OIDCConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfigChangedEvent) {
if e.ClientID != "" {
wm.ClientID = e.ClientID
}

View File

@ -0,0 +1,23 @@
package command
import (
"github.com/caos/zitadel/internal/iam/model"
)
func orgWriteModelToOrgIAMPolicy(wm *ORGOrgIAMPolicyWriteModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
}
}
func orgWriteModelToPasswordComplexityPolicy(wm *OrgPasswordComplexityPolicyWriteModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordComplexityPolicyWriteModel.WriteModel),
MinLength: wm.MinLength,
HasLowercase: wm.HasLowercase,
HasUppercase: wm.HasUpperCase,
HasNumber: wm.HasNumber,
HasSymbol: wm.HasSymbol,
}
}

View File

@ -0,0 +1,5 @@
package command
type OrgMemberWriteModel struct {
MemberWriteModel
}

View File

@ -0,0 +1,12 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/org"
)
func ORGAggregateFromWriteModel(wm *eventstore.WriteModel) *org.Aggregate {
return &org.Aggregate{
Aggregate: *eventstore.AggregateFromWriteModel(wm, org.AggregateType, org.AggregateVersion),
}
}

View File

@ -0,0 +1,78 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) GetOrgIAMPolicy(ctx context.Context, orgID string) (*iam_model.OrgIAMPolicy, error) {
policy := NewORGOrgIAMPolicyWriteModel(orgID)
err := r.eventstore.FilterToQueryReducer(ctx, policy)
if err != nil {
return nil, err
}
if policy.IsActive {
return orgWriteModelToOrgIAMPolicy(policy), nil
}
return r.GetDefaultOrgIAMPolicy(ctx, r.iamID)
}
func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
addedPolicy := NewORGOrgIAMPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
}
orgAgg := ORGAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
orgAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg)
if err != nil {
return nil, err
}
return orgWriteModelToOrgIAMPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-2N9sd", "Errors.Org.OrgIAMPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
}
orgAgg := ORGAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
orgAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg)
if err != nil {
return nil, err
}
return orgWriteModelToOrgIAMPolicy(existingPolicy), nil
}
func (r *CommandSide) orgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *ORGOrgIAMPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewORGOrgIAMPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,51 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/org"
)
type ORGOrgIAMPolicyWriteModel struct {
PolicyOrgIAMWriteModel
}
func NewORGOrgIAMPolicyWriteModel(orgID string) *ORGOrgIAMPolicyWriteModel {
return &ORGOrgIAMPolicyWriteModel{
PolicyOrgIAMWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: orgID,
},
},
}
}
func (wm *ORGOrgIAMPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *org.OrgIAMPolicyAddedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyAddedEvent)
case *org.OrgIAMPolicyChangedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyChangedEvent)
}
}
}
func (wm *ORGOrgIAMPolicyWriteModel) Reduce() error {
return wm.PolicyOrgIAMWriteModel.Reduce()
}
func (wm *ORGOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
AggregateIDs(wm.PolicyOrgIAMWriteModel.AggregateID)
}
func (wm *ORGOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLoginMustBeDomain bool) (*org.OrgIAMPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := org.NewOrgIAMPolicyChangedEvent(ctx)
if wm.UserLoginMustBeDomain != userLoginMustBeDomain {
hasChanged = true
changedEvent.UserLoginMustBeDomain = userLoginMustBeDomain
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,18 @@
package command
import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
func (r *CommandSide) GetOrgPasswordComplexityPolicy(ctx context.Context, orgID string) (*iam_model.PasswordComplexityPolicy, error) {
policy := NewOrgPasswordComplexityPolicyWriteModel(orgID)
err := r.eventstore.FilterToQueryReducer(ctx, policy)
if err != nil {
return nil, err
}
if policy.IsActive {
return orgWriteModelToPasswordComplexityPolicy(policy), nil
}
return r.GetDefaultPasswordComplexityPolicy(ctx, r.iamID)
}

View File

@ -0,0 +1,75 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/org"
)
type OrgPasswordComplexityPolicyWriteModel struct {
PasswordComplexityPolicyWriteModel
}
func NewOrgPasswordComplexityPolicyWriteModel(iamID string) *OrgPasswordComplexityPolicyWriteModel {
return &OrgPasswordComplexityPolicyWriteModel{
PasswordComplexityPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *OrgPasswordComplexityPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *org.PasswordComplexityPolicyAddedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent)
case *org.PasswordComplexityPolicyChangedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent)
}
}
}
func (wm *OrgPasswordComplexityPolicyWriteModel) Reduce() error {
return wm.PasswordComplexityPolicyWriteModel.Reduce()
}
func (wm *OrgPasswordComplexityPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
AggregateIDs(wm.PasswordComplexityPolicyWriteModel.AggregateID)
}
func (wm *OrgPasswordComplexityPolicyWriteModel) NewChangedEvent(
ctx context.Context,
minLength uint64,
hasLowercase,
hasUppercase,
hasNumber,
hasSymbol bool,
) (*org.PasswordComplexityPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := org.NewPasswordComplexityPolicyChangedEvent(ctx)
if wm.MinLength != minLength {
hasChanged = true
changedEvent.MinLength = minLength
}
if wm.HasLowercase != hasLowercase {
hasChanged = true
changedEvent.HasLowercase = hasLowercase
}
if wm.HasUpperCase != hasUppercase {
hasChanged = true
changedEvent.HasUpperCase = hasUppercase
}
if wm.HasNumber != hasNumber {
hasChanged = true
changedEvent.HasNumber = hasNumber
}
if wm.HasSymbol != hasSymbol {
hasChanged = true
changedEvent.HasSymbol = hasSymbol
}
return changedEvent, hasChanged
}

View File

@ -1,25 +1,30 @@
package label
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type WriteModel struct {
type LabelPolicyWriteModel struct {
eventstore.WriteModel
PrimaryColor string
SecondaryColor string
IsActive bool
}
func (wm *WriteModel) Reduce() error {
func (wm *LabelPolicyWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *AddedEvent:
case *policy.LabelPolicyAddedEvent:
wm.PrimaryColor = e.PrimaryColor
wm.SecondaryColor = e.SecondaryColor
case *ChangedEvent:
wm.IsActive = true
case *policy.LabelPolicyChangedEvent:
wm.PrimaryColor = e.PrimaryColor
wm.SecondaryColor = e.SecondaryColor
case *policy.LabelPolicyRemovedEvent:
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()

View File

@ -1,19 +1,26 @@
package factors
package command
import "github.com/caos/zitadel/internal/eventstore/v2"
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type SecondFactorWriteModel struct {
eventstore.WriteModel
MFAType SecondFactorType
MFAType domain.SecondFactorType
IsActive bool
}
func (wm *SecondFactorWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *SecondFactorAddedEvent:
case *policy.SecondFactorAddedEvent:
wm.MFAType = e.MFAType
case *SecondFactorRemovedEvent:
wm.IsActive = true
case *policy.SecondFactorRemovedEvent:
wm.MFAType = e.MFAType
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()
@ -21,16 +28,19 @@ func (wm *SecondFactorWriteModel) Reduce() error {
type MultiFactoryWriteModel struct {
eventstore.WriteModel
MFAType MultiFactorType
MFAType domain.MultiFactorType
IsActive bool
}
func (wm *MultiFactoryWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *MultiFactorAddedEvent:
case *policy.MultiFactorAddedEvent:
wm.MFAType = e.MFAType
case *MultiFactorRemovedEvent:
wm.IsActive = true
case *policy.MultiFactorRemovedEvent:
wm.MFAType = e.MFAType
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()

View File

@ -1,34 +1,40 @@
package login
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type WriteModel struct {
type LoginPolicyWriteModel struct {
eventstore.WriteModel
AllowUserNamePassword bool
AllowRegister bool
AllowExternalIDP bool
ForceMFA bool
PasswordlessType PasswordlessType
PasswordlessType domain.PasswordlessType
IsActive bool
}
func (wm *WriteModel) Reduce() error {
func (wm *LoginPolicyWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *AddedEvent:
case *policy.LoginPolicyAddedEvent:
wm.AllowRegister = e.AllowRegister
wm.AllowUserNamePassword = e.AllowUserNamePassword
wm.AllowExternalIDP = e.AllowExternalIDP
wm.ForceMFA = e.ForceMFA
wm.PasswordlessType = e.PasswordlessType
case *ChangedEvent:
wm.IsActive = true
case *policy.LoginPolicyChangedEvent:
wm.AllowRegister = e.AllowRegister
wm.AllowUserNamePassword = e.AllowUserNamePassword
wm.AllowExternalIDP = e.AllowExternalIDP
wm.ForceMFA = e.ForceMFA
wm.PasswordlessType = e.PasswordlessType
case *policy.LoginPolicyRemovedEvent:
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()

View File

@ -0,0 +1,26 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type PolicyOrgIAMWriteModel struct {
eventstore.WriteModel
UserLoginMustBeDomain bool
IsActive bool
}
func (wm *PolicyOrgIAMWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *policy.OrgIAMPolicyAddedEvent:
wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain
wm.IsActive = true
case *policy.OrgIAMPolicyChangedEvent:
wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain
}
}
return wm.WriteModel.Reduce()
}

View File

@ -1,25 +1,30 @@
package password_age
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type WriteModel struct {
type PasswordAgePolicyWriteModel struct {
eventstore.WriteModel
ExpireWarnDays uint64
MaxAgeDays uint64
IsActive bool
}
func (wm *WriteModel) Reduce() error {
func (wm *PasswordAgePolicyWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *AddedEvent:
case *policy.PasswordAgePolicyAddedEvent:
wm.ExpireWarnDays = e.ExpireWarnDays
wm.MaxAgeDays = e.MaxAgeDays
case *ChangedEvent:
wm.IsActive = true
case *policy.PasswordAgePolicyChangedEvent:
wm.ExpireWarnDays = e.ExpireWarnDays
wm.MaxAgeDays = e.MaxAgeDays
case *policy.PasswordAgePolicyRemovedEvent:
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()

View File

@ -1,10 +1,11 @@
package password_complexity
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type WriteModel struct {
type PasswordComplexityPolicyWriteModel struct {
eventstore.WriteModel
MinLength uint64
@ -12,23 +13,27 @@ type WriteModel struct {
HasUpperCase bool
HasNumber bool
HasSymbol bool
IsActive bool
}
func (wm *WriteModel) Reduce() error {
func (wm *PasswordComplexityPolicyWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *AddedEvent:
case *policy.PasswordComplexityPolicyAddedEvent:
wm.MinLength = e.MinLength
wm.HasLowercase = e.HasLowercase
wm.HasUpperCase = e.HasUpperCase
wm.HasNumber = e.HasNumber
wm.HasSymbol = e.HasSymbol
case *ChangedEvent:
wm.IsActive = true
case *policy.PasswordComplexityPolicyChangedEvent:
wm.MinLength = e.MinLength
wm.HasLowercase = e.HasLowercase
wm.HasUpperCase = e.HasUpperCase
wm.HasNumber = e.HasNumber
wm.HasSymbol = e.HasSymbol
case *policy.PasswordComplexityPolicyRemovedEvent:
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()

View File

@ -1,25 +1,30 @@
package password_lockout
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type WriteModel struct {
type PasswordLockoutPolicyWriteModel struct {
eventstore.WriteModel
MaxAttempts uint64
ShowLockOutFailures bool
IsActive bool
}
func (wm *WriteModel) Reduce() error {
func (wm *PasswordLockoutPolicyWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *AddedEvent:
case *policy.PasswordLockoutPolicyAddedEvent:
wm.MaxAttempts = e.MaxAttempts
wm.ShowLockOutFailures = e.ShowLockOutFailures
case *ChangedEvent:
wm.IsActive = true
case *policy.PasswordLockoutPolicyChangedEvent:
wm.MaxAttempts = e.MaxAttempts
wm.ShowLockOutFailures = e.ShowLockOutFailures
case *policy.PasswordLockoutPolicyRemovedEvent:
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()

View File

@ -0,0 +1,65 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) StartSetup(ctx context.Context, iamID string, step domain.Step) (*iam_model.IAM, error) {
iamWriteModel, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if iamWriteModel.SetUpStarted >= step || iamWriteModel.SetUpStarted != iamWriteModel.SetUpDone {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "setup error")
}
aggregate := IAMAggregateFromWriteModel(&iamWriteModel.WriteModel).PushEvents(iam_repo.NewSetupStepStartedEvent(ctx, step))
err = r.eventstore.PushAggregate(ctx, iamWriteModel, aggregate)
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-Grgh1", "Setup start failed")
}
return writeModelToIAM(iamWriteModel), nil
}
//func (r *CommandSide) setupDone(ctx context.Context, iamAgg *iam_repo.Aggregate, event eventstore.EventPusher, aggregates ...eventstore.Aggregater) error {
// aggregate := iamAgg.PushEvents(event)
//
// aggregates = append(aggregates, aggregate)
// _, err := r.eventstore.PushAggregates(ctx, aggregates...)
// if err != nil {
// return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Dgd2", "Setup done failed")
// }
// return nil
//}
//
////TODO: should not use readmodel
//func (r *CommandSide) setup(ctx context.Context, iamID string, step iam_repo.Step, event eventstore.EventPusher) (*iam_model.IAM, error) {
// iam, err := r.iamByID(ctx, iamID)
// if err != nil && !caos_errs.IsNotFound(err) {
// return nil, err
// }
//
// if iam != nil && (iam.SetUpStarted >= iam_repo.Step(step) || iam.SetUpStarted != iam.SetUpDone) {
// return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "setup error")
// }
//
// aggregate := query.AggregateFromReadModel(iam).
// PushEvents(event)
//
// events, err := r.eventstore.PushAggregates(ctx, aggregate)
// if err != nil {
// return nil, err
// }
//
// if err = iam.AppendAndReduce(events...); err != nil {
// return nil, err
// }
// return nil, nil
// //TODO: return write model
// //return readModelToIAM(iam), nil
//}

View File

@ -0,0 +1,107 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
type Step1 struct {
GlobalOrg string
IAMProject string
DefaultLoginPolicy LoginPolicy //*iam_model.LoginPolicy
Orgs []Org
Owners []string
//setup *Setup
//createdUsers map[string]*usr_model.User
//createdOrgs map[string]*org_model.Org
//createdProjects map[string]*proj_model.Project
//pwComplexityPolicy *iam_model.PasswordComplexityPolicyView
}
type LoginPolicy struct {
AllowRegister bool
AllowUsernamePassword bool
AllowExternalIdp bool
}
type User struct {
FirstName string
LastName string
UserName string
Email string
Password string
}
type Org struct {
Name string
Domain string
OrgIamPolicy bool
Users []User
Owners []string
Projects []Project
}
type Project struct {
Name string
Users []User
Members []string
OIDCApps []OIDCApp
}
type OIDCApp struct {
Name string
RedirectUris []string
ResponseTypes []string
GrantTypes []string
ApplicationType string
AuthMethodType string
PostLogoutRedirectUris []string
DevMode bool
}
func (r *CommandSide) SetupStep1(ctx context.Context, iamID string, step1 Step1) error {
iam, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return err
}
//create default login policy
iamAgg, err := r.addDefaultLoginPolicy(ctx,
NewIAMLoginPolicyWriteModel(iam.AggregateID),
&iam_model.LoginPolicy{
AllowUsernamePassword: step1.DefaultLoginPolicy.AllowUsernamePassword,
AllowRegister: step1.DefaultLoginPolicy.AllowRegister,
AllowExternalIdp: step1.DefaultLoginPolicy.AllowExternalIdp,
})
if err != nil {
return err
}
//create orgs
//create projects
//create applications
//set iam owners
//set global org
//set iam project id
/*aggregates:
iam:
default login policy
iam owner
org:
default
caos
zitadel
*/
iamAgg.PushEvents(iam_repo.NewSetupStepDoneEvent(ctx, domain.Step1))
_, err = r.eventstore.PushAggregates(ctx, iamAgg)
if err != nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Gr2hh", "Setup Step1 failed")
}
return nil
}

View File

@ -0,0 +1,38 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
type Step2 struct {
DefaultPasswordComplexityPolicy iam_model.PasswordComplexityPolicy
}
func (r *CommandSide) SetupStep2(ctx context.Context, iamID string, step Step2) error {
iam, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return err
}
iamAgg, err := r.addDefaultPasswordComplexityPolicy(ctx, NewIAMPasswordComplexityPolicyWriteModel(iam.AggregateID), &iam_model.PasswordComplexityPolicy{
MinLength: step.DefaultPasswordComplexityPolicy.MinLength,
HasLowercase: step.DefaultPasswordComplexityPolicy.HasLowercase,
HasUppercase: step.DefaultPasswordComplexityPolicy.HasUppercase,
HasNumber: step.DefaultPasswordComplexityPolicy.HasNumber,
HasSymbol: step.DefaultPasswordComplexityPolicy.HasSymbol,
})
if err != nil {
return err
}
iamAgg.PushEvents(iam_repo.NewSetupStepDoneEvent(ctx, domain.Step1))
_, err = r.eventstore.PushAggregates(ctx, iamAgg)
if err != nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-HR2na", "Setup Step2 failed")
}
return nil
}

123
internal/v2/command/user.go Normal file
View File

@ -0,0 +1,123 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/user"
)
func (r *CommandSide) AddUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
if !user.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2N9fs", "Errors.User.Invalid")
}
if user.Human != nil {
human, err := r.AddHuman(ctx, user.ResourceOwner, user.UserName, user.Human)
if err != nil {
return nil, err
}
return &usr_model.User{UserName: user.UserName, Human: human}, nil
} else if user.Machine != nil {
}
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined")
}
func (r *CommandSide) DeactivateUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3M9ds", "Errors.User.NotFound")
}
if existingUser.UserState == domain.UserStateInactive {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5M0sf", "Errors.User.AlreadyInactive")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserDeactivatedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) ReactivateUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-4M0sd", "Errors.User.NotFound")
}
if existingUser.UserState != domain.UserStateInactive {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-6M0sf", "Errors.User.NotInactive")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserReactivatedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) LockUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-5M9fs", "Errors.User.NotFound")
}
if existingUser.UserState != domain.UserStateActive && existingUser.UserState != domain.UserStateInitial {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.ShouldBeActiveOrInitial")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserLockedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) UnlockUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-M0dos", "Errors.User.NotFound")
}
if existingUser.UserState != domain.UserStateLocked {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0ds", "Errors.User.NotLocked")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserUnlockedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) userWriteModelByID(ctx context.Context, userID string) (writeModel *UserWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewUserWriteModel(userID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,62 @@
package command
import (
"github.com/caos/zitadel/internal/user/model"
)
func writeModelToUser(wm *UserWriteModel) *model.User {
return &model.User{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
UserName: wm.UserName,
State: model.UserState(wm.UserState),
}
}
func writeModelToHuman(wm *HumanWriteModel) *model.Human {
return &model.Human{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
Profile: &model.Profile{
FirstName: wm.FirstName,
LastName: wm.LastName,
NickName: wm.NickName,
DisplayName: wm.DisplayName,
PreferredLanguage: wm.PreferredLanguage,
Gender: model.Gender(wm.Gender),
},
Email: &model.Email{
EmailAddress: wm.Email,
IsEmailVerified: wm.IsEmailVerified,
},
}
}
func writeModelToProfile(wm *HumanProfileWriteModel) *model.Profile {
return &model.Profile{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
FirstName: wm.FirstName,
LastName: wm.LastName,
NickName: wm.NickName,
DisplayName: wm.DisplayName,
PreferredLanguage: wm.PreferredLanguage,
Gender: model.Gender(wm.Gender),
}
}
func writeModelToEmail(wm *HumanEmailWriteModel) *model.Email {
return &model.Email{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
EmailAddress: wm.Email,
IsEmailVerified: wm.IsEmailVerified,
}
}
func writeModelToAddress(wm *HumanAddressWriteModel) *model.Address {
return &model.Address{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
Country: wm.Country,
Locality: wm.Locality,
PostalCode: wm.PostalCode,
Region: wm.Region,
StreetAddress: wm.StreetAddress,
}
}

View File

@ -0,0 +1,71 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/user"
)
func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, human *usr_model.Human) (*usr_model.Human, error) {
if !human.IsValid() {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
}
userID, err := r.idGenerator.Next()
if err != nil {
return nil, err
}
human.AggregateID = userID
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
if err != nil {
return nil, err
}
//pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID)
//if err != nil {
// return nil, err
//}
addedHuman := NewHumanWriteModel(human.AggregateID)
//TODO: Check Unique Username
human.CheckOrgIAMPolicy(username, orgIAMPolicy)
human.SetNamesAsDisplayname()
//human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true)
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
userAgg.PushEvents(
user.NewHumanAddedEvent(
ctx,
username,
human.FirstName,
human.LastName,
human.NickName,
human.DisplayName,
human.PreferredLanguage,
domain.Gender(human.Gender),
human.EmailAddress,
human.PhoneNumber,
human.Country,
human.Locality,
human.PostalCode,
human.Region,
human.StreetAddress,
),
)
//TODO: HashPassword If existing
//TODO: Generate Init Code if needed
//TODO: Generate Phone Code if needed
if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified {
userAgg.PushEvents(user.NewHumanEmailVerifiedEvent(ctx))
}
if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified {
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
}
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
if err != nil {
return nil, err
}
return writeModelToHuman(addedHuman), nil
}

View File

@ -0,0 +1,44 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
)
func (r *CommandSide) ChangeHumanAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) {
existingAddress, err := r.addressWriteModel(ctx, address.AggregateID)
if err != nil {
return nil, err
}
if existingAddress.UserState == domain.UserStateUnspecified || existingAddress.UserState == domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-0pLdo", "Errors.User.Address.NotFound")
}
changedEvent, hasChanged := existingAddress.NewChangedEvent(ctx, address.Country, address.Locality, address.PostalCode, address.Region, address.StreetAddress)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3M0cs", "Errors.User.Address.NotChanged")
}
userAgg := UserAggregateFromWriteModel(&existingAddress.WriteModel)
userAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingAddress, userAgg)
if err != nil {
return nil, err
}
return writeModelToAddress(existingAddress), nil
}
func (r *CommandSide) addressWriteModel(ctx context.Context, userID string) (writeModel *HumanAddressWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewHumanAddressWriteModel(userID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

Some files were not shown because too many files have changed in this diff Show More