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,
}
}
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
}
_, currentMember := iam.Members.MemberByUserID(member.UserID)
if currentMember == nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-GPhuz", "Errors.IAM.MemberNotExisting")
existingMember, err := r.memberWriteModelByID(ctx, member.AggregateID, member.UserID)
if err != nil {
return nil, err
}
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)
if err != nil {

View File

@ -3,10 +3,12 @@ package iam
import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/member"
)
type Repository struct {
@ -46,3 +48,52 @@ func (r *Repository) iamByID(ctx context.Context, id string) (_ *iam_repo.ReadMo
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 (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/v2"
)
@ -29,7 +30,13 @@ func NewAggregate(
) *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
}
func (a *Aggregate) PushMemberChanged(ctx context.Context, userID string, roles ...string) *Aggregate {
a.Aggregate = *a.PushEvents(NewMemberChangedEvent(ctx, userID, roles...))
func (a *Aggregate) PushMemberChanged(ctx context.Context, current, changed *MemberWriteModel) *Aggregate {
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
}

View File

@ -13,7 +13,13 @@ var (
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) {
for _, event := range events {
@ -60,20 +66,25 @@ func NewMemberAddedEvent(
func NewMemberChangedEvent(
ctx context.Context,
userID string,
roles ...string,
) *MemberChangedEvent {
current,
changed *MemberWriteModel,
) (*MemberChangedEvent, error) {
return &MemberChangedEvent{
ChangedEvent: *member.NewChangedEvent(
m, err := member.NewChangedEvent(
eventstore.NewBaseEventForPush(
ctx,
MemberChangedEventType,
),
userID,
roles...,
),
&current.WriteModel,
&changed.WriteModel,
)
if err != nil {
return nil, err
}
return &MemberChangedEvent{
ChangedEvent: *m,
}, nil
}
func NewMemberRemovedEvent(

View File

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

View File

@ -1,35 +1,51 @@
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:"-"`
current *ConfigAggregate
changed *ConfigAggregate
ID string `json:"idpConfigId"`
StylingType StylingType `json:"stylingType,omitempty"`
Name string `json:"name"`
hasChanged bool
}
func ChangedEvent(
func NewConfigChangedEvent(
base *eventstore.BaseEvent,
current *ConfigAggregate,
changed *ConfigAggregate,
) (*ChangedEdvent, error) {
//TODO: who to handle chanes?
) (*ConfigChangedEvent, error) {
return &ChangedEdvent{
change := &ConfigChangedEvent{
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
}
func (e *ChangedEdvent) Data() interface{} {
func (e *ConfigChangedEvent) Data() interface{} {
if e.current.Name != e.changed.Name {
e.Name = e.changed.Name
}

View File

@ -1,3 +1,15 @@
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
}
func NewMemberAggregate(userID string) *ReadModel {
return &ReadModel{
ReadModel: *eventstore.NewReadModel(),
func NewAggregate(aggregate *eventstore.Aggregate, userID string, roles ...string) *Aggregate {
return &Aggregate{
Aggregate: *aggregate,
Roles: roles,
UserID: userID,
}
}

View File

@ -2,6 +2,8 @@ package member
import (
"encoding/json"
"reflect"
"sort"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
@ -15,8 +17,10 @@ const (
type ChangedEvent struct {
eventstore.BaseEvent `json:"-"`
Roles []string `json:"roles"`
UserID string `json:"userId"`
Roles []string `json:"roles,omitempty"`
UserID string `json:"userId,omitempty"`
hasChanged bool
}
func (e *ChangedEvent) CheckPrevious() bool {
@ -29,15 +33,32 @@ func (e *ChangedEvent) Data() interface{} {
func NewChangedEvent(
base *eventstore.BaseEvent,
userID string,
roles ...string,
) *ChangedEvent {
current,
changed *WriteModel,
) (*ChangedEvent, error) {
return &ChangedEvent{
change := &ChangedEvent{
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) {

View File

@ -2,6 +2,8 @@ package member
import "github.com/caos/zitadel/internal/eventstore/v2"
//ReadModel represenets the default member view.
// It's computed from events.
type ReadModel struct {
eventstore.ReadModel
@ -9,6 +11,7 @@ type ReadModel struct {
Roles []string
}
//NewMemberReadModel is the default constructor of ReadModel
func NewMemberReadModel(userID string) *ReadModel {
return &ReadModel{
ReadModel: *eventstore.NewReadModel(),
@ -16,6 +19,7 @@ func NewMemberReadModel(userID string) *ReadModel {
}
}
//Reduce extends eventstore.ReadModel
func (rm *ReadModel) Reduce() error {
for _, event := range rm.Events {
switch e := event.(type) {
@ -29,3 +33,7 @@ func (rm *ReadModel) Reduce() error {
}
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
)
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 {
members.ReadModel
}
@ -81,20 +94,24 @@ func NewMemberAddedEvent(
func NewMemberChangedEvent(
ctx context.Context,
userID string,
roles ...string,
) *MemberChangedEvent {
current,
changed *MemberWriteModel,
) (*MemberChangedEvent, error) {
return &MemberChangedEvent{
ChangedEvent: *member.NewChangedEvent(
event, err := member.NewChangedEvent(
eventstore.NewBaseEventForPush(
ctx,
MemberChangedEventType,
),
userID,
roles...,
),
&current.WriteModel,
&changed.WriteModel,
)
if err != nil {
return nil, err
}
return &MemberChangedEvent{
ChangedEvent: *event,
}, nil
}
func NewMemberRemovedEvent(