mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-12 11:04:25 +00:00
try with writemodel
This commit is contained in:
parent
147782332f
commit
4d6497f6c1
@ -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{}
|
||||||
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
|
||||||
|
m, err := member.NewChangedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
MemberChangedEventType,
|
||||||
|
),
|
||||||
|
¤t.WriteModel,
|
||||||
|
&changed.WriteModel,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &MemberChangedEvent{
|
return &MemberChangedEvent{
|
||||||
ChangedEvent: *member.NewChangedEvent(
|
ChangedEvent: *m,
|
||||||
eventstore.NewBaseEventForPush(
|
}, nil
|
||||||
ctx,
|
|
||||||
MemberChangedEventType,
|
|
||||||
),
|
|
||||||
userID,
|
|
||||||
roles...,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemberRemovedEvent(
|
func NewMemberRemovedEvent(
|
||||||
|
@ -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
|
||||||
|
@ -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
|
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 *ChangedEdvent) CheckPrevious() bool {
|
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
|
||||||
}
|
}
|
||||||
|
@ -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"`
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
|
||||||
roles...,
|
|
||||||
),
|
),
|
||||||
|
¤t.WriteModel,
|
||||||
|
&changed.WriteModel,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return &MemberChangedEvent{
|
||||||
|
ChangedEvent: *event,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemberRemovedEvent(
|
func NewMemberRemovedEvent(
|
||||||
|
Loading…
Reference in New Issue
Block a user