try with writemodel

This commit is contained in:
adlerhurst 2020-11-18 21:22:15 +01:00
parent 147782332f
commit 4d6497f6c1
12 changed files with 232 additions and 67 deletions

View File

@ -115,3 +115,7 @@ func readModelToMember(readModel *member.ReadModel) *model.IAMMember {
UserID: readModel.UserID, UserID: readModel.UserID,
} }
} }
func writeModelFromMember(member *model.IAMMember) *member.WriteModel {
return &member.WriteModel{}
}

View File

@ -54,13 +54,13 @@ func (r *Repository) ChangeIAMMember(ctx context.Context, member *iam_model.IAMM
return nil, err return nil, err
} }
_, currentMember := iam.Members.MemberByUserID(member.UserID) existingMember, err := r.memberWriteModelByID(ctx, member.AggregateID, member.UserID)
if currentMember == nil { if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-GPhuz", "Errors.IAM.MemberNotExisting") return nil, err
} }
iamAgg := iam_repo.AggregateFromReadModel(iam). iamAgg := iam_repo.AggregateFromReadModel(iam).
PushEvents(iam_repo.NewMemberChangedEvent(ctx, member.UserID, member.Roles...)) PushMemberChanged(ctx, existingMember, nil)
events, err := r.eventstore.PushAggregates(ctx, iamAgg) events, err := r.eventstore.PushAggregates(ctx, iamAgg)
if err != nil { if err != nil {

View File

@ -3,10 +3,12 @@ package iam
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/tracing" "github.com/caos/zitadel/internal/tracing"
iam_repo "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/member"
) )
type Repository struct { type Repository struct {
@ -46,3 +48,52 @@ func (r *Repository) iamByID(ctx context.Context, id string) (_ *iam_repo.ReadMo
return readModel, nil return readModel, 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) }()
query := eventstore.NewSearchQueryFactory(eventstore.ColumnsEvent, iam_repo.AggregateType).AggregateIDs(iamID)
writeModel := new(memberWriteModel)
err = r.eventstore.FilterToReducer(ctx, query, writeModel)
if err != nil {
return nil, err
}
if writeModel.isDeleted {
return nil, errors.ThrowNotFound(nil, "IAM-D8JxR", "Errors.NotFound")
}
return &writeModel.MemberWriteModel, nil
}
type memberWriteModel struct {
iam_repo.MemberWriteModel
userID string
isDeleted bool
}
func (wm *memberWriteModel) AppendEvents(events ...eventstore.EventReader) error {
for _, event := range events {
switch e := event.(type) {
case *member.AddedEvent:
if e.UserID == wm.userID {
wm.isDeleted = false
wm.MemberWriteModel.AppendEvents(event)
}
case *member.ChangedEvent:
if e.UserID == wm.userID {
wm.MemberWriteModel.AppendEvents(event)
}
case *member.RemovedEvent:
if e.UserID == wm.userID {
wm.isDeleted = true
wm.MemberWriteModel = iam_repo.MemberWriteModel{}
}
}
}
return nil
}

View File

@ -3,6 +3,7 @@ package iam
import ( import (
"context" "context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
) )
@ -29,7 +30,13 @@ func NewAggregate(
) *Aggregate { ) *Aggregate {
return &Aggregate{ return &Aggregate{
Aggregate: *eventstore.NewAggregate(id, AggregateType, resourceOwner, AggregateVersion, previousSequence), Aggregate: *eventstore.NewAggregate(
id,
AggregateType,
resourceOwner,
AggregateVersion,
previousSequence,
),
} }
} }
@ -46,8 +53,14 @@ func (a *Aggregate) PushMemberAdded(ctx context.Context, userID string, roles ..
return a return a
} }
func (a *Aggregate) PushMemberChanged(ctx context.Context, userID string, roles ...string) *Aggregate { func (a *Aggregate) PushMemberChanged(ctx context.Context, current, changed *MemberWriteModel) *Aggregate {
a.Aggregate = *a.PushEvents(NewMemberChangedEvent(ctx, userID, roles...)) e, err := NewMemberChangedEvent(ctx, current, changed)
if err != nil {
logging.Log("IAM-KH21C").OnError(err).Warn("unable to push member changed")
return a
}
a.Aggregate = *a.PushEvents(e)
return a return a
} }

View File

@ -13,7 +13,13 @@ var (
MemberRemovedEventType = iamEventTypePrefix + member.RemovedEventType MemberRemovedEventType = iamEventTypePrefix + member.RemovedEventType
) )
type MemberReadModel member.ReadModel type MemberWriteModel struct {
member.WriteModel
}
type MemberReadModel struct {
member.ReadModel
}
func (rm *MemberReadModel) AppendEvents(events ...eventstore.EventReader) (err error) { func (rm *MemberReadModel) AppendEvents(events ...eventstore.EventReader) (err error) {
for _, event := range events { for _, event := range events {
@ -60,20 +66,25 @@ func NewMemberAddedEvent(
func NewMemberChangedEvent( func NewMemberChangedEvent(
ctx context.Context, ctx context.Context,
userID string, current,
roles ...string, changed *MemberWriteModel,
) *MemberChangedEvent { ) (*MemberChangedEvent, error) {
return &MemberChangedEvent{ m, err := member.NewChangedEvent(
ChangedEvent: *member.NewChangedEvent(
eventstore.NewBaseEventForPush( eventstore.NewBaseEventForPush(
ctx, ctx,
MemberChangedEventType, MemberChangedEventType,
), ),
userID, &current.WriteModel,
roles..., &changed.WriteModel,
), )
if err != nil {
return nil, err
} }
return &MemberChangedEvent{
ChangedEvent: *m,
}, nil
} }
func NewMemberRemovedEvent( func NewMemberRemovedEvent(

View File

@ -2,30 +2,40 @@ package idp
import "github.com/caos/zitadel/internal/eventstore/v2" import "github.com/caos/zitadel/internal/eventstore/v2"
type AddedEvent struct { type ConfigAddedEvent struct {
eventstore.BaseEvent eventstore.BaseEvent
ID string `idpConfigId` ID string `json:"idpConfigId"`
Name string `name` Name string `json:"name"`
Type ConfigType `json:"idpType,omitempty"`
StylingType StylingType `json:"stylingType,omitempty"`
} }
func NewAddedEvent( func NewAddedEvent(
base *eventstore.BaseEvent, base *eventstore.BaseEvent,
configID string, configID string,
name string, name string,
) *AddedEvent { configType ConfigType,
stylingType StylingType,
) *ConfigAddedEvent {
return &AddedEvent{ return &ConfigAddedEvent{
BaseEvent: *base, BaseEvent: *base,
ID: configID, ID: configID,
Name: name, Name: name,
StylingType: stylingType,
Type: configType,
} }
} }
func (e *AddedEvent) CheckPrevious() bool { func (e *ConfigAddedEvent) CheckPrevious() bool {
return true return true
} }
func (e *AddedEvent) Data() interface{} { func (e *ConfigAddedEvent) Data() interface{} {
return e return e
} }
type ConfigType uint32
type StylingType uint32

View File

@ -1,35 +1,51 @@
package idp package idp
import "github.com/caos/zitadel/internal/eventstore/v2" import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
)
type ChangedEdvent struct { type ConfigChangedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
current *ConfigAggregate ID string `json:"idpConfigId"`
changed *ConfigAggregate StylingType StylingType `json:"stylingType,omitempty"`
Name string `json:"name"` hasChanged bool
} }
func ChangedEvent( func NewConfigChangedEvent(
base *eventstore.BaseEvent, base *eventstore.BaseEvent,
current *ConfigAggregate, current *ConfigAggregate,
changed *ConfigAggregate, changed *ConfigAggregate,
) (*ChangedEdvent, error) { ) (*ConfigChangedEvent, error) {
//TODO: who to handle chanes?
return &ChangedEdvent{ change := &ConfigChangedEvent{
BaseEvent: *base, BaseEvent: *base,
current: current,
changed: changed,
}, nil
} }
func (e *ChangedEdvent) CheckPrevious() bool { if current.ConfigID != changed.ConfigID {
change.ID = changed.ConfigID
change.hasChanged = true
}
if current.StylingType != changed.StylingType {
change.StylingType = changed.StylingType
change.hasChanged = true
}
if !change.hasChanged {
return nil, errors.ThrowPreconditionFailed(nil, "IDP-UBJbB", "Errors.NoChanges")
}
return change, nil
}
func (e *ConfigChangedEvent) CheckPrevious() bool {
return true return true
} }
func (e *ChangedEdvent) Data() interface{} { func (e *ConfigChangedEvent) Data() interface{} {
if e.current.Name != e.changed.Name { if e.current.Name != e.changed.Name {
e.Name = e.changed.Name e.Name = e.changed.Name
} }

View File

@ -1,3 +1,15 @@
package oidc package oidc
type AddedEvent struct{} import "github.com/caos/zitadel/internal/crypto"
type AddedEvent struct {
eventstore.BaseEvent
IDPConfigID string `json:"idpConfigId"`
ClientID string `json:"clientId"`
Secret *crypto.CryptoValue `json:"clientSecret"`
Issuer string `json:"issuer"`
Scopes []string `json:"scpoes"`
IDPDisplayNameMapping int32 `json:"idpDisplayNameMapping,omitempty"`
UsernameMapping int32 `json:"usernameMapping,omitempty"`
}

View File

@ -9,8 +9,10 @@ type Aggregate struct {
Roles []string Roles []string
} }
func NewMemberAggregate(userID string) *ReadModel { func NewAggregate(aggregate *eventstore.Aggregate, userID string, roles ...string) *Aggregate {
return &ReadModel{ return &Aggregate{
ReadModel: *eventstore.NewReadModel(), Aggregate: *aggregate,
Roles: roles,
UserID: userID,
} }
} }

View File

@ -2,6 +2,8 @@ package member
import ( import (
"encoding/json" "encoding/json"
"reflect"
"sort"
"github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
@ -15,8 +17,10 @@ const (
type ChangedEvent struct { type ChangedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
Roles []string `json:"roles"` Roles []string `json:"roles,omitempty"`
UserID string `json:"userId"` UserID string `json:"userId,omitempty"`
hasChanged bool
} }
func (e *ChangedEvent) CheckPrevious() bool { func (e *ChangedEvent) CheckPrevious() bool {
@ -29,15 +33,32 @@ func (e *ChangedEvent) Data() interface{} {
func NewChangedEvent( func NewChangedEvent(
base *eventstore.BaseEvent, base *eventstore.BaseEvent,
userID string, current,
roles ...string, changed *WriteModel,
) *ChangedEvent { ) (*ChangedEvent, error) {
return &ChangedEvent{ change := &ChangedEvent{
BaseEvent: *base, BaseEvent: *base,
Roles: roles,
UserID: userID,
} }
if current.UserID != changed.UserID {
change.UserID = changed.UserID
change.hasChanged = true
}
sort.Strings(current.Roles)
sort.Strings(changed.Roles)
if !reflect.DeepEqual(current.Roles, changed.Roles) {
change.Roles = changed.Roles
change.hasChanged = true
}
if !change.hasChanged {
return nil, errors.ThrowPreconditionFailed(nil, "MEMBE-SeKlD", "Errors.NoChanges")
}
return change, nil
} }
func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) { func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error) {

View File

@ -2,6 +2,8 @@ package member
import "github.com/caos/zitadel/internal/eventstore/v2" import "github.com/caos/zitadel/internal/eventstore/v2"
//ReadModel represenets the default member view.
// It's computed from events.
type ReadModel struct { type ReadModel struct {
eventstore.ReadModel eventstore.ReadModel
@ -9,6 +11,7 @@ type ReadModel struct {
Roles []string Roles []string
} }
//NewMemberReadModel is the default constructor of ReadModel
func NewMemberReadModel(userID string) *ReadModel { func NewMemberReadModel(userID string) *ReadModel {
return &ReadModel{ return &ReadModel{
ReadModel: *eventstore.NewReadModel(), ReadModel: *eventstore.NewReadModel(),
@ -16,6 +19,7 @@ func NewMemberReadModel(userID string) *ReadModel {
} }
} }
//Reduce extends eventstore.ReadModel
func (rm *ReadModel) Reduce() error { func (rm *ReadModel) Reduce() error {
for _, event := range rm.Events { for _, event := range rm.Events {
switch e := event.(type) { switch e := event.(type) {
@ -29,3 +33,7 @@ func (rm *ReadModel) Reduce() error {
} }
return rm.ReadModel.Reduce() return rm.ReadModel.Reduce()
} }
//WriteModel is used to create events
// It has no computed fields and represents the data
type WriteModel ReadModel

View File

@ -18,6 +18,19 @@ var (
MemberRemovedEventType = orgEventTypePrefix + member.RemovedEventType MemberRemovedEventType = orgEventTypePrefix + member.RemovedEventType
) )
type MemberWriteModel struct {
member.WriteModel
}
// func NewMemberAggregate(userID string) *MemberAggregate {
// return &MemberAggregate{
// Aggregate: member.NewAggregate(
// eventstore.NewAggregate(userID, MemberAggregateType, "RO", AggregateVersion, 0),
// ),
// // Aggregate: member.NewMemberAggregate(userID),
// }
// }
type MembersReadModel struct { type MembersReadModel struct {
members.ReadModel members.ReadModel
} }
@ -81,20 +94,24 @@ func NewMemberAddedEvent(
func NewMemberChangedEvent( func NewMemberChangedEvent(
ctx context.Context, ctx context.Context,
userID string, current,
roles ...string, changed *MemberWriteModel,
) *MemberChangedEvent { ) (*MemberChangedEvent, error) {
return &MemberChangedEvent{ event, err := member.NewChangedEvent(
ChangedEvent: *member.NewChangedEvent(
eventstore.NewBaseEventForPush( eventstore.NewBaseEventForPush(
ctx, ctx,
MemberChangedEventType, MemberChangedEventType,
), ),
userID, &current.WriteModel,
roles..., &changed.WriteModel,
), )
if err != nil {
return nil, err
} }
return &MemberChangedEvent{
ChangedEvent: *event,
}, nil
} }
func NewMemberRemovedEvent( func NewMemberRemovedEvent(