feat: idps (#1188)

* add setup steps

* refactoring

* omitempty

* cleanup

* begin org

* create org

* setup org

* setup org

* merge

* fixes

* fixes

* fixes

* add project

* add oidc application

* fix app creation

* add resourceOwner to writemodels

* resource owner

* cleanup

* global org, iam project and iam member in setup

* logs

* logs

* logs

* cleanup

* Update internal/v2/command/project.go

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>

* check project state

* add org domain commands

* add org status changes and member commands

* fixes

* policies

* login policy

* fix iam project event

* mapper

* label policy

* change to command

* fix

* fix

* handle change event differently and lot of fixes

* idps

* fixes

* fixes

* fixes

* changedEvent handling

* fix change events

* remove creation date

Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com>
This commit is contained in:
Livio Amstutz
2021-01-20 11:06:52 +01:00
committed by GitHub
parent 3eb909c4b4
commit c2e6e782a8
42 changed files with 1070 additions and 348 deletions

View File

@@ -86,7 +86,7 @@ func writeModelToPasswordLockoutPolicy(wm *PasswordLockoutPolicyWriteModel) *dom
}
}
func writeModelToIDPConfig(wm *IAMIDPConfigWriteModel) *domain.IDPConfig {
func writeModelToIDPConfig(wm *IDPConfigWriteModel) *domain.IDPConfig {
return &domain.IDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
OIDCConfig: writeModelToIDPOIDCConfig(wm.OIDCConfig),

View File

@@ -55,7 +55,7 @@ func (r *CommandSide) AddDefaultIDPConfig(ctx context.Context, config *domain.ID
if err != nil {
return nil, err
}
return writeModelToIDPConfig(addedConfig), nil
return writeModelToIDPConfig(&addedConfig.IDPConfigWriteModel), nil
}
func (r *CommandSide) ChangeDefaultIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
@@ -78,44 +78,35 @@ func (r *CommandSide) ChangeDefaultIDPConfig(ctx context.Context, config *domain
if err != nil {
return nil, err
}
return writeModelToIDPConfig(existingIDP), nil
return writeModelToIDPConfig(&existingIDP.IDPConfigWriteModel), nil
}
func (r *CommandSide) DeactivateDefaultIDPConfig(ctx context.Context, idpID string) (*domain.IDPConfig, error) {
func (r *CommandSide) DeactivateDefaultIDPConfig(ctx context.Context, idpID string) error {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, idpID)
if err != nil {
return nil, err
return err
}
if existingIDP.State != domain.IDPConfigStateActive {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotActive")
return caos_errs.ThrowPreconditionFailed(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
return r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
}
func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, idpID string) (*domain.IDPConfig, error) {
func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, idpID string) error {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, idpID)
if err != nil {
return nil, err
return err
}
if existingIDP.State != domain.IDPConfigStateInactive {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mo0d", "Errors.IAM.IDPConfig.NotInactive")
return caos_errs.ThrowPreconditionFailed(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
return r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
}
func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string) error {

View File

@@ -6,6 +6,7 @@ import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
)
type IAMIDPConfigWriteModel struct {
@@ -88,16 +89,19 @@ func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
stylingType domain.IDPConfigStylingType,
) (*iam.IDPConfigChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewIDPConfigChangedEvent(ctx)
changedEvent.ConfigID = configID
changes := make([]idpconfig.IDPConfigChanges, 0)
if wm.Name != name {
hasChanged = true
changedEvent.Name = name
changes = append(changes, idpconfig.ChangeName(name))
}
if stylingType.Valid() && wm.StylingType != stylingType {
hasChanged = true
changedEvent.StylingType = stylingType
changes = append(changes, idpconfig.ChangeStyleType(stylingType))
}
return changedEvent, hasChanged
if len(changes) == 0 {
return nil, false
}
changeEvent, err := iam.NewIDPConfigChangedEvent(ctx, configID, changes)
if err != nil {
return nil, false
}
return changeEvent, true
}

View File

@@ -19,6 +19,7 @@ func (r *CommandSide) ChangeDefaultIDPOIDCConfig(ctx context.Context, config *do
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
ctx,
config.IDPConfigID,
config.ClientID,
config.Issuer,
config.ClientSecretString,

View File

@@ -8,14 +8,15 @@ import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
)
type IDPOIDCConfigWriteModel struct {
type IAMIDPOIDCConfigWriteModel struct {
OIDCConfigWriteModel
}
func NewIAMIDPOIDCConfigWriteModel(idpConfigID string) *IDPOIDCConfigWriteModel {
return &IDPOIDCConfigWriteModel{
func NewIAMIDPOIDCConfigWriteModel(idpConfigID string) *IAMIDPOIDCConfigWriteModel {
return &IAMIDPOIDCConfigWriteModel{
OIDCConfigWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: domain.IAMID,
@@ -26,7 +27,7 @@ func NewIAMIDPOIDCConfigWriteModel(idpConfigID string) *IDPOIDCConfigWriteModel
}
}
func (wm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
func (wm *IAMIDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.IDPOIDCConfigAddedEvent:
@@ -60,21 +61,22 @@ func (wm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader
}
}
func (wm *IDPOIDCConfigWriteModel) Reduce() error {
func (wm *IAMIDPOIDCConfigWriteModel) Reduce() error {
if err := wm.OIDCConfigWriteModel.Reduce(); err != nil {
return err
}
return wm.WriteModel.Reduce()
}
func (wm *IDPOIDCConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
func (wm *IAMIDPOIDCConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID).
ResourceOwner(wm.ResourceOwner)
}
func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
func (wm *IAMIDPOIDCConfigWriteModel) NewChangedEvent(
ctx context.Context,
idpConfigID,
clientID,
issuer,
clientSecretString string,
@@ -83,8 +85,8 @@ func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
userNameMapping domain.OIDCMappingField,
scopes ...string,
) (*iam.IDPOIDCConfigChangedEvent, bool, error) {
hasChanged := false
changedEvent := iam.NewIDPOIDCConfigChangedEvent(ctx)
changes := make([]idpconfig.OIDCConfigChanges, 0)
var clientSecret *crypto.CryptoValue
var err error
if clientSecretString != "" {
@@ -92,27 +94,29 @@ func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
if err != nil {
return nil, false, err
}
changedEvent.ClientSecret = clientSecret
changes = append(changes, idpconfig.ChangeClientSecret(clientSecret))
}
if wm.ClientID != clientID {
hasChanged = true
changedEvent.ClientID = clientID
changes = append(changes, idpconfig.ChangeClientID(clientID))
}
if wm.Issuer != issuer {
hasChanged = true
changedEvent.Issuer = issuer
changes = append(changes, idpconfig.ChangeIssuer(issuer))
}
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
hasChanged = true
changedEvent.IDPDisplayNameMapping = idpDisplayNameMapping
changes = append(changes, idpconfig.ChangeIDPDisplayNameMapping(idpDisplayNameMapping))
}
if userNameMapping.Valid() && wm.UserNameMapping != userNameMapping {
hasChanged = true
changedEvent.UserNameMapping = userNameMapping
changes = append(changes, idpconfig.ChangeUserNameMapping(userNameMapping))
}
if reflect.DeepEqual(wm.Scopes, scopes) {
hasChanged = true
changedEvent.Scopes = scopes
changes = append(changes, idpconfig.ChangeScopes(scopes))
}
return changedEvent, hasChanged, nil
if len(changes) == 0 {
return nil, false, nil
}
changeEvent, err := iam.NewIDPOIDCConfigChangedEvent(ctx, idpConfigID, changes)
if err != nil {
return nil, false, err
}
return changeEvent, true, nil
}

View File

@@ -62,11 +62,11 @@ func (rm *IDPConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.IDPConfigAdde
}
func (rm *IDPConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.IDPConfigChangedEvent) {
if e.Name != "" {
rm.Name = e.Name
if e.Name != nil {
rm.Name = *e.Name
}
if e.StylingType.Valid() {
rm.StylingType = e.StylingType
if e.StylingType != nil && e.StylingType.Valid() {
rm.StylingType = *e.StylingType
}
}

View File

@@ -52,19 +52,19 @@ func (wm *OIDCConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAd
}
func (wm *OIDCConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfigChangedEvent) {
if e.ClientID != "" {
wm.ClientID = e.ClientID
if e.ClientID != nil {
wm.ClientID = *e.ClientID
}
if e.Issuer != "" {
wm.Issuer = e.Issuer
if e.Issuer != nil {
wm.Issuer = *e.Issuer
}
if len(e.Scopes) > 0 {
wm.Scopes = e.Scopes
}
if e.IDPDisplayNameMapping.Valid() {
wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping
if e.IDPDisplayNameMapping != nil && e.IDPDisplayNameMapping.Valid() {
wm.IDPDisplayNameMapping = *e.IDPDisplayNameMapping
}
if e.UserNameMapping.Valid() {
wm.UserNameMapping = e.UserNameMapping
if e.UserNameMapping != nil && e.UserNameMapping.Valid() {
wm.UserNameMapping = *e.UserNameMapping
}
}

View File

@@ -0,0 +1,146 @@
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"
"github.com/caos/zitadel/internal/v2/repository/org"
org_repo "github.com/caos/zitadel/internal/v2/repository/org"
)
func (r *CommandSide) AddIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
if config.OIDCConfig == nil {
return nil, errors.ThrowInvalidArgument(nil, "Org-eUpQU", "Errors.idp.config.notset")
}
idpConfigID, err := r.idGenerator.Next()
if err != nil {
return nil, err
}
//TODO: check name unique on aggregate
addedConfig := NewOrgIDPConfigWriteModel(idpConfigID, config.AggregateID)
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.idpConfigSecretCrypto)
if err != nil {
return nil, err
}
orgAgg := OrgAggregateFromWriteModel(&addedConfig.WriteModel)
orgAgg.PushEvents(
org_repo.NewIDPConfigAddedEvent(
ctx,
idpConfigID,
config.Name,
config.Type,
config.StylingType,
),
)
orgAgg.PushEvents(
org_repo.NewIDPOIDCConfigAddedEvent(
ctx, config.OIDCConfig.ClientID,
idpConfigID,
config.OIDCConfig.Issuer,
clientSecret,
config.OIDCConfig.IDPDisplayNameMapping,
config.OIDCConfig.UsernameMapping,
config.OIDCConfig.Scopes...,
),
)
err = r.eventstore.PushAggregate(ctx, addedConfig, orgAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(&addedConfig.IDPConfigWriteModel), nil
}
func (r *CommandSide) ChangeIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, config.IDPConfigID, config.AggregateID)
if err != nil {
return nil, err
}
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
return nil, caos_errs.ThrowNotFound(nil, "Org-4M9so", "Errors.Org.IDPConfig.NotExisting")
}
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, config.IDPConfigID, config.Name, config.StylingType)
if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
}
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
orgAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingIDP, orgAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(&existingIDP.IDPConfigWriteModel), nil
}
func (r *CommandSide) DeactivateIDPConfig(ctx context.Context, idpID, orgID string) error {
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, idpID, orgID)
if err != nil {
return err
}
if existingIDP.State != domain.IDPConfigStateActive {
return caos_errs.ThrowPreconditionFailed(nil, "Org-4M9so", "Errors.Org.IDPConfig.NotActive")
}
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
orgAgg.PushEvents(org_repo.NewIDPConfigDeactivatedEvent(ctx, idpID))
return r.eventstore.PushAggregate(ctx, existingIDP, orgAgg)
}
func (r *CommandSide) ReactivateIDPConfig(ctx context.Context, idpID, orgID string) error {
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, idpID, orgID)
if err != nil {
return err
}
if existingIDP.State != domain.IDPConfigStateInactive {
return caos_errs.ThrowPreconditionFailed(nil, "Org-5Mo0d", "Errors.Org.IDPConfig.NotInactive")
}
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
orgAgg.PushEvents(org_repo.NewIDPConfigReactivatedEvent(ctx, idpID))
return r.eventstore.PushAggregate(ctx, existingIDP, orgAgg)
}
func (r *CommandSide) RemoveIDPConfig(ctx context.Context, idpID, orgID string) error {
_, err := r.pushIDPWriteModel(ctx, idpID, orgID, func(a *org.Aggregate, _ *OrgIDPConfigWriteModel) *org.Aggregate {
a.Aggregate = *a.PushEvents(org_repo.NewIDPConfigRemovedEvent(ctx, idpID))
return a
})
return err
}
func (r *CommandSide) pushIDPWriteModel(ctx context.Context, idpID, orgID string, eventSetter func(*org.Aggregate, *OrgIDPConfigWriteModel) *org.Aggregate) (*OrgIDPConfigWriteModel, error) {
writeModel := NewOrgIDPConfigWriteModel(idpID, orgID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
aggregate := eventSetter(OrgAggregateFromWriteModel(&writeModel.WriteModel), writeModel)
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
if err != nil {
return nil, err
}
return writeModel, nil
}
func (r *CommandSide) orgIDPConfigWriteModelByID(ctx context.Context, idpID, orgID string) (policy *OrgIDPConfigWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewOrgIDPConfigWriteModel(idpID, orgID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@@ -0,0 +1,107 @@
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/idpconfig"
"github.com/caos/zitadel/internal/v2/repository/org"
)
type OrgIDPConfigWriteModel struct {
IDPConfigWriteModel
}
func NewOrgIDPConfigWriteModel(configID, orgID string) *OrgIDPConfigWriteModel {
return &OrgIDPConfigWriteModel{
IDPConfigWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: orgID,
ResourceOwner: orgID,
},
ConfigID: configID,
},
}
}
func (wm *OrgIDPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
AggregateIDs(wm.AggregateID).
ResourceOwner(wm.ResourceOwner)
}
func (wm *OrgIDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *org.IDPConfigAddedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigAddedEvent)
case *org.IDPConfigChangedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigChangedEvent)
case *org.IDPConfigDeactivatedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
case *org.IDPConfigReactivatedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
case *org.IDPConfigRemovedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
case *org.IDPOIDCConfigAddedEvent:
if wm.ConfigID != e.IDPConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
case *org.IDPOIDCConfigChangedEvent:
if wm.ConfigID != e.IDPConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
}
}
}
func (wm *OrgIDPConfigWriteModel) Reduce() error {
return wm.IDPConfigWriteModel.Reduce()
}
func (wm *OrgIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventReader) error {
wm.AppendEvents(events...)
return wm.Reduce()
}
func (wm *OrgIDPConfigWriteModel) NewChangedEvent(
ctx context.Context,
configID,
name string,
stylingType domain.IDPConfigStylingType,
) (*org.IDPConfigChangedEvent, bool) {
changes := make([]idpconfig.IDPConfigChanges, 0)
if wm.Name != name {
changes = append(changes, idpconfig.ChangeName(name))
}
if stylingType.Valid() && wm.StylingType != stylingType {
changes = append(changes, idpconfig.ChangeStyleType(stylingType))
}
if len(changes) == 0 {
return nil, false
}
changeEvent, err := org.NewIDPConfigChangedEvent(ctx, configID, changes)
if err != nil {
return nil, false
}
return changeEvent, true
}

View File

@@ -0,0 +1,46 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/v2/domain"
)
func (r *CommandSide) ChangeIDPOIDCConfig(ctx context.Context, config *domain.OIDCIDPConfig) (*domain.OIDCIDPConfig, error) {
existingConfig := NewOrgIDPOIDCConfigWriteModel(config.IDPConfigID, config.AggregateID)
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, "Org-67J9d", "Errors.Org.IDPConfig.AlreadyExists")
}
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
ctx,
config.IDPConfigID,
config.ClientID,
config.Issuer,
config.ClientSecretString,
r.idpConfigSecretCrypto,
config.IDPDisplayNameMapping,
config.UsernameMapping,
config.Scopes...)
if err != nil {
return nil, err
}
if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
}
orgAgg := OrgAggregateFromWriteModel(&existingConfig.WriteModel)
orgAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingConfig, orgAgg)
if err != nil {
return nil, err
}
return writeModelToIDPOIDCConfig(&existingConfig.OIDCConfigWriteModel), nil
}

View File

@@ -0,0 +1,122 @@
package command
import (
"context"
"reflect"
"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"
"github.com/caos/zitadel/internal/v2/repository/org"
)
type IDPOIDCConfigWriteModel struct {
OIDCConfigWriteModel
}
func NewOrgIDPOIDCConfigWriteModel(idpConfigID, orgID string) *IDPOIDCConfigWriteModel {
return &IDPOIDCConfigWriteModel{
OIDCConfigWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: orgID,
ResourceOwner: orgID,
},
IDPConfigID: idpConfigID,
},
}
}
func (wm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *org.IDPOIDCConfigAddedEvent:
if wm.IDPConfigID != e.IDPConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
case *org.IDPOIDCConfigChangedEvent:
if wm.IDPConfigID != e.IDPConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
case *org.IDPConfigReactivatedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
case *org.IDPConfigDeactivatedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
case *org.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, org.AggregateType).
AggregateIDs(wm.AggregateID).
ResourceOwner(wm.ResourceOwner)
}
func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
ctx context.Context,
idpConfigID,
clientID,
issuer,
clientSecretString string,
secretCrypto crypto.Crypto,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
scopes ...string,
) (*org.IDPOIDCConfigChangedEvent, bool, error) {
changes := make([]idpconfig.OIDCConfigChanges, 0)
var clientSecret *crypto.CryptoValue
var err error
if clientSecretString != "" {
clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
if err != nil {
return nil, false, err
}
changes = append(changes, idpconfig.ChangeClientSecret(clientSecret))
}
if wm.ClientID != clientID {
changes = append(changes, idpconfig.ChangeClientID(clientID))
}
if wm.Issuer != issuer {
changes = append(changes, idpconfig.ChangeIssuer(issuer))
}
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
changes = append(changes, idpconfig.ChangeIDPDisplayNameMapping(idpDisplayNameMapping))
}
if userNameMapping.Valid() && wm.UserNameMapping != userNameMapping {
changes = append(changes, idpconfig.ChangeUserNameMapping(userNameMapping))
}
if reflect.DeepEqual(wm.Scopes, scopes) {
changes = append(changes, idpconfig.ChangeScopes(scopes))
}
if len(changes) == 0 {
return nil, false, nil
}
changeEvent, err := org.NewIDPOIDCConfigChangedEvent(ctx, idpConfigID, changes)
if err != nil {
return nil, false, err
}
return changeEvent, true, nil
}

View File

@@ -3,7 +3,8 @@ package domain
type OIDCMappingField int32
const (
OIDCMappingFieldPreferredLoginName OIDCMappingField = iota + 1
OIDCMappingFieldUnspecified OIDCMappingField = iota
OIDCMappingFieldPreferredLoginName
OIDCMappingFieldEmail
// count is for validation purposes
oidcMappingFieldCount

View File

@@ -80,11 +80,11 @@ func (rm *IDPConfigReadModel) reduceConfigAddedEvent(e *idpconfig.IDPConfigAdded
}
func (rm *IDPConfigReadModel) reduceConfigChangedEvent(e *idpconfig.IDPConfigChangedEvent) {
if e.Name != "" {
rm.Name = e.Name
if e.Name != nil {
rm.Name = *e.Name
}
if e.StylingType.Valid() {
rm.StylingType = e.StylingType
if e.StylingType != nil && e.StylingType.Valid() {
rm.StylingType = *e.StylingType
}
}

View File

@@ -43,19 +43,19 @@ func (rm *OIDCConfigReadModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAdd
}
func (rm *OIDCConfigReadModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfigChangedEvent) {
if e.ClientID != "" {
rm.ClientID = e.ClientID
if e.ClientID != nil {
rm.ClientID = *e.ClientID
}
if e.Issuer != "" {
rm.Issuer = e.Issuer
if e.Issuer != nil {
rm.Issuer = *e.Issuer
}
if len(e.Scopes) > 0 {
rm.Scopes = e.Scopes
}
if e.IDPDisplayNameMapping.Valid() {
rm.IDPDisplayNameMapping = e.IDPDisplayNameMapping
if e.IDPDisplayNameMapping != nil && e.IDPDisplayNameMapping.Valid() {
rm.IDPDisplayNameMapping = *e.IDPDisplayNameMapping
}
if e.UserNameMapping.Valid() {
rm.UserNameMapping = e.UserNameMapping
if e.UserNameMapping != nil && e.UserNameMapping.Valid() {
rm.UserNameMapping = *e.UserNameMapping
}
}

View File

@@ -2,6 +2,7 @@ package iam
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/v2/domain"
@@ -57,12 +58,18 @@ type IDPConfigChangedEvent struct {
func NewIDPConfigChangedEvent(
ctx context.Context,
) *IDPConfigChangedEvent {
return &IDPConfigChangedEvent{
IDPConfigChangedEvent: *idpconfig.NewIDPConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPConfigChangedEventType),
),
configID string,
changes []idpconfig.IDPConfigChanges,
) (*IDPConfigChangedEvent, error) {
changeEvent, err := idpconfig.NewIDPConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPConfigChangedEventType),
configID,
changes,
)
if err != nil {
return nil, err
}
return &IDPConfigChangedEvent{IDPConfigChangedEvent: *changeEvent}, nil
}
func IDPConfigChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {

View File

@@ -2,6 +2,7 @@ package iam
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
@@ -61,12 +62,18 @@ type IDPOIDCConfigChangedEvent struct {
func NewIDPOIDCConfigChangedEvent(
ctx context.Context,
) *IDPOIDCConfigChangedEvent {
return &IDPOIDCConfigChangedEvent{
OIDCConfigChangedEvent: *idpconfig.NewOIDCConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPOIDCConfigChangedEventType),
),
idpConfigID string,
changes []idpconfig.OIDCConfigChanges,
) (*IDPOIDCConfigChangedEvent, error) {
changeEvent, err := idpconfig.NewOIDCConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPOIDCConfigChangedEventType),
idpConfigID,
changes,
)
if err != nil {
return nil, err
}
return &IDPOIDCConfigChangedEvent{OIDCConfigChangedEvent: *changeEvent}, nil
}
func IDPOIDCConfigChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {

View File

@@ -2,6 +2,7 @@ package idpconfig
import (
"encoding/json"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
@@ -54,9 +55,9 @@ func IDPConfigAddedEventMapper(event *repository.Event) (eventstore.EventReader,
type IDPConfigChangedEvent struct {
eventstore.BaseEvent `json:"-"`
ConfigID string `json:"idpConfigId"`
Name string `json:"name,omitempty"`
StylingType domain.IDPConfigStylingType `json:"stylingType,omitempty"`
ConfigID string `json:"idpConfigId"`
Name *string `json:"name,omitempty"`
StylingType *domain.IDPConfigStylingType `json:"stylingType,omitempty"`
}
func (e *IDPConfigChangedEvent) Data() interface{} {
@@ -65,9 +66,33 @@ func (e *IDPConfigChangedEvent) Data() interface{} {
func NewIDPConfigChangedEvent(
base *eventstore.BaseEvent,
) *IDPConfigChangedEvent {
return &IDPConfigChangedEvent{
configID string,
changes []IDPConfigChanges,
) (*IDPConfigChangedEvent, error) {
if len(changes) == 0 {
return nil, errors.ThrowPreconditionFailed(nil, "IDPCONFIG-Dsg21", "Errors.NoChangesFound")
}
changeEvent := &IDPConfigChangedEvent{
BaseEvent: *base,
ConfigID: configID,
}
for _, change := range changes {
change(changeEvent)
}
return changeEvent, nil
}
type IDPConfigChanges func(*IDPConfigChangedEvent)
func ChangeName(name string) func(*IDPConfigChangedEvent) {
return func(e *IDPConfigChangedEvent) {
e.Name = &name
}
}
func ChangeStyleType(styleType domain.IDPConfigStylingType) func(*IDPConfigChangedEvent) {
return func(e *IDPConfigChangedEvent) {
e.StylingType = &styleType
}
}
@@ -87,7 +112,7 @@ func IDPConfigChangedEventMapper(event *repository.Event) (eventstore.EventReade
type IDPConfigDeactivatedEvent struct {
eventstore.BaseEvent `json:"-"`
ConfigID string `idpConfigId`
ConfigID string `json:"idpConfigId"`
}
func NewIDPConfigDeactivatedEvent(
@@ -121,7 +146,7 @@ func IDPConfigDeactivatedEventMapper(event *repository.Event) (eventstore.EventR
type IDPConfigReactivatedEvent struct {
eventstore.BaseEvent `json:"-"`
ConfigID string `idpConfigId`
ConfigID string `json:"idpConfigId"`
}
func NewIDPConfigReactivatedEvent(
@@ -155,7 +180,7 @@ func IDPConfigReactivatedEventMapper(event *repository.Event) (eventstore.EventR
type IDPConfigRemovedEvent struct {
eventstore.BaseEvent `json:"-"`
ConfigID string `idpConfigId`
ConfigID string `json:"idpConfigId"`
}
func NewIDPConfigRemovedEvent(

View File

@@ -2,6 +2,7 @@ package idpconfig
import (
"encoding/json"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
@@ -72,13 +73,13 @@ type OIDCConfigChangedEvent struct {
IDPConfigID string `json:"idpConfigId"`
ClientID string `json:"clientId,omitempty"`
ClientID *string `json:"clientId,omitempty"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
Issuer string `json:"issuer,omitempty"`
Issuer *string `json:"issuer,omitempty"`
Scopes []string `json:"scpoes,omitempty"`
IDPDisplayNameMapping domain.OIDCMappingField `json:"idpDisplayNameMapping,omitempty"`
UserNameMapping domain.OIDCMappingField `json:"usernameMapping,omitempty"`
IDPDisplayNameMapping *domain.OIDCMappingField `json:"idpDisplayNameMapping,omitempty"`
UserNameMapping *domain.OIDCMappingField `json:"usernameMapping,omitempty"`
}
func (e *OIDCConfigChangedEvent) Data() interface{} {
@@ -87,9 +88,57 @@ func (e *OIDCConfigChangedEvent) Data() interface{} {
func NewOIDCConfigChangedEvent(
base *eventstore.BaseEvent,
) *OIDCConfigChangedEvent {
return &OIDCConfigChangedEvent{
BaseEvent: *base,
idpConfigID string,
changes []OIDCConfigChanges,
) (*OIDCConfigChangedEvent, error) {
if len(changes) == 0 {
return nil, errors.ThrowPreconditionFailed(nil, "IDPCONFIG-ADzr5", "Errors.NoChangesFound")
}
changeEvent := &OIDCConfigChangedEvent{
BaseEvent: *base,
IDPConfigID: idpConfigID,
}
for _, change := range changes {
change(changeEvent)
}
return changeEvent, nil
}
type OIDCConfigChanges func(*OIDCConfigChangedEvent)
func ChangeClientID(clientID string) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.ClientID = &clientID
}
}
func ChangeClientSecret(secret *crypto.CryptoValue) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.ClientSecret = secret
}
}
func ChangeIssuer(issuer string) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.Issuer = &issuer
}
}
func ChangeIDPDisplayNameMapping(idpDisplayNameMapping domain.OIDCMappingField) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.IDPDisplayNameMapping = &idpDisplayNameMapping
}
}
func ChangeUserNameMapping(userNameMapping domain.OIDCMappingField) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.UserNameMapping = &userNameMapping
}
}
func ChangeScopes(scopes []string) func(*OIDCConfigChangedEvent) {
return func(e *OIDCConfigChangedEvent) {
e.Scopes = scopes
}
}

View File

@@ -0,0 +1,168 @@
package org
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
)
const (
IDPConfigAddedEventType eventstore.EventType = "org.idp.config.added"
IDPConfigChangedEventType eventstore.EventType = "org.idp.config.changed"
IDPConfigRemovedEventType eventstore.EventType = "org.idp.config.removed"
IDPConfigDeactivatedEventType eventstore.EventType = "org.idp.config.deactivated"
IDPConfigReactivatedEventType eventstore.EventType = "org.idp.config.reactivated"
)
type IDPConfigAddedEvent struct {
idpconfig.IDPConfigAddedEvent
}
func NewIDPConfigAddedEvent(
ctx context.Context,
configID string,
name string,
configType domain.IDPConfigType,
stylingType domain.IDPConfigStylingType,
) *IDPConfigAddedEvent {
return &IDPConfigAddedEvent{
IDPConfigAddedEvent: *idpconfig.NewIDPConfigAddedEvent(
eventstore.NewBaseEventForPush(
ctx,
IDPConfigAddedEventType,
),
configID,
name,
configType,
stylingType,
),
}
}
func IDPConfigAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := idpconfig.IDPConfigAddedEventMapper(event)
if err != nil {
return nil, err
}
return &IDPConfigAddedEvent{IDPConfigAddedEvent: *e.(*idpconfig.IDPConfigAddedEvent)}, nil
}
type IDPConfigChangedEvent struct {
idpconfig.IDPConfigChangedEvent
}
func NewIDPConfigChangedEvent(
ctx context.Context,
configID string,
changes []idpconfig.IDPConfigChanges,
) (*IDPConfigChangedEvent, error) {
changeEvent, err := idpconfig.NewIDPConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPConfigChangedEventType),
configID,
changes,
)
if err != nil {
return nil, err
}
return &IDPConfigChangedEvent{IDPConfigChangedEvent: *changeEvent}, nil
}
func IDPConfigChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := idpconfig.IDPConfigChangedEventMapper(event)
if err != nil {
return nil, err
}
return &IDPConfigChangedEvent{IDPConfigChangedEvent: *e.(*idpconfig.IDPConfigChangedEvent)}, nil
}
type IDPConfigRemovedEvent struct {
idpconfig.IDPConfigRemovedEvent
}
func NewIDPConfigRemovedEvent(
ctx context.Context,
configID string,
) *IDPConfigRemovedEvent {
return &IDPConfigRemovedEvent{
IDPConfigRemovedEvent: *idpconfig.NewIDPConfigRemovedEvent(
eventstore.NewBaseEventForPush(
ctx,
IDPConfigRemovedEventType,
),
configID,
),
}
}
func IDPConfigRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := idpconfig.IDPConfigRemovedEventMapper(event)
if err != nil {
return nil, err
}
return &IDPConfigRemovedEvent{IDPConfigRemovedEvent: *e.(*idpconfig.IDPConfigRemovedEvent)}, nil
}
type IDPConfigDeactivatedEvent struct {
idpconfig.IDPConfigDeactivatedEvent
}
func NewIDPConfigDeactivatedEvent(
ctx context.Context,
configID string,
) *IDPConfigDeactivatedEvent {
return &IDPConfigDeactivatedEvent{
IDPConfigDeactivatedEvent: *idpconfig.NewIDPConfigDeactivatedEvent(
eventstore.NewBaseEventForPush(
ctx,
IDPConfigDeactivatedEventType,
),
configID,
),
}
}
func IDPConfigDeactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := idpconfig.IDPConfigDeactivatedEventMapper(event)
if err != nil {
return nil, err
}
return &IDPConfigDeactivatedEvent{IDPConfigDeactivatedEvent: *e.(*idpconfig.IDPConfigDeactivatedEvent)}, nil
}
type IDPConfigReactivatedEvent struct {
idpconfig.IDPConfigReactivatedEvent
}
func NewIDPConfigReactivatedEvent(
ctx context.Context,
configID string,
) *IDPConfigReactivatedEvent {
return &IDPConfigReactivatedEvent{
IDPConfigReactivatedEvent: *idpconfig.NewIDPConfigReactivatedEvent(
eventstore.NewBaseEventForPush(
ctx,
IDPConfigReactivatedEventType,
),
configID,
),
}
}
func IDPConfigReactivatedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := idpconfig.IDPConfigReactivatedEventMapper(event)
if err != nil {
return nil, err
}
return &IDPConfigReactivatedEvent{IDPConfigReactivatedEvent: *e.(*idpconfig.IDPConfigReactivatedEvent)}, nil
}

View File

@@ -0,0 +1,86 @@
package org
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
)
const (
IDPOIDCConfigAddedEventType eventstore.EventType = "org.idp." + idpconfig.OIDCConfigAddedEventType
IDPOIDCConfigChangedEventType eventstore.EventType = "org.idp." + idpconfig.ConfigChangedEventType
)
type IDPOIDCConfigAddedEvent struct {
idpconfig.OIDCConfigAddedEvent
}
func NewIDPOIDCConfigAddedEvent(
ctx context.Context,
clientID,
idpConfigID,
issuer string,
clientSecret *crypto.CryptoValue,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
scopes ...string,
) *IDPOIDCConfigAddedEvent {
return &IDPOIDCConfigAddedEvent{
OIDCConfigAddedEvent: *idpconfig.NewOIDCConfigAddedEvent(
eventstore.NewBaseEventForPush(
ctx,
IDPOIDCConfigAddedEventType,
),
clientID,
idpConfigID,
issuer,
clientSecret,
idpDisplayNameMapping,
userNameMapping,
scopes...,
),
}
}
func IDPOIDCConfigAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := idpconfig.OIDCConfigAddedEventMapper(event)
if err != nil {
return nil, err
}
return &IDPOIDCConfigAddedEvent{OIDCConfigAddedEvent: *e.(*idpconfig.OIDCConfigAddedEvent)}, nil
}
type IDPOIDCConfigChangedEvent struct {
idpconfig.OIDCConfigChangedEvent
}
func NewIDPOIDCConfigChangedEvent(
ctx context.Context,
idpConfigID string,
changes []idpconfig.OIDCConfigChanges,
) (*IDPOIDCConfigChangedEvent, error) {
changeEvent, err := idpconfig.NewOIDCConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPOIDCConfigChangedEventType),
idpConfigID,
changes,
)
if err != nil {
return nil, err
}
return &IDPOIDCConfigChangedEvent{OIDCConfigChangedEvent: *changeEvent}, nil
}
func IDPOIDCConfigChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := idpconfig.OIDCConfigChangedEventMapper(event)
if err != nil {
return nil, err
}
return &IDPOIDCConfigChangedEvent{OIDCConfigChangedEvent: *e.(*idpconfig.OIDCConfigChangedEvent)}, nil
}