feat: migrate unique constraints v1 to v2 (#1274)

* fix: unique migration

* fix: unique migration

* fix: remove migrations

* fix: member events
This commit is contained in:
Fabi 2021-02-15 13:31:24 +01:00 committed by GitHub
parent 3bc3ef1f2c
commit ee86eb4399
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 630 additions and 173 deletions

View File

@ -179,3 +179,5 @@ SetUp:
Greeting: Hello {{.FirstName}} {{.LastName}}, Greeting: Hello {{.FirstName}} {{.LastName}},
Text: The domain {{.Domain}} has been claimed by an organisation. Your current user {{.Username}} is not part of this organisation. Therefore you'll have to change your email when you login. We have created a temporary username ({{.TempUsername}}) for this login. Text: The domain {{.Domain}} has been claimed by an organisation. Your current user {{.Username}} is not part of this organisation. Therefore you'll have to change your email when you login. We have created a temporary username ({{.TempUsername}}) for this login.
ButtonText: Login ButtonText: Login
Step11:
MigrateV1EventstoreToV2: true

View File

@ -6,16 +6,17 @@ import (
) )
type IAMSetUp struct { type IAMSetUp struct {
Step1 *command.Step1 Step1 *command.Step1
Step2 *command.Step2 Step2 *command.Step2
Step3 *command.Step3 Step3 *command.Step3
Step4 *command.Step4 Step4 *command.Step4
Step5 *command.Step5 Step5 *command.Step5
Step6 *command.Step6 Step6 *command.Step6
Step7 *command.Step7 Step7 *command.Step7
Step8 *command.Step8 Step8 *command.Step8
Step9 *command.Step9 Step9 *command.Step9
Step10 *command.Step10 Step10 *command.Step10
Step11 *command.Step11
} }
func (setup *IAMSetUp) Steps(currentDone domain.Step) ([]command.Step, error) { func (setup *IAMSetUp) Steps(currentDone domain.Step) ([]command.Step, error) {
@ -32,6 +33,7 @@ func (setup *IAMSetUp) Steps(currentDone domain.Step) ([]command.Step, error) {
setup.Step8, setup.Step8,
setup.Step9, setup.Step9,
setup.Step10, setup.Step10,
setup.Step11,
} { } {
if step.Step() <= currentDone { if step.Step() <= currentDone {
continue continue

View File

@ -290,6 +290,8 @@ Errors:
NotInactive: Benutzer Berechtigung ist nicht deaktiviert NotInactive: Benutzer Berechtigung ist nicht deaktiviert
NoPermissionForProject: Benutzer hat keine Rechte auf diesem Projekt NoPermissionForProject: Benutzer hat keine Rechte auf diesem Projekt
RoleKeyNotFound: Rolle konnte nicht gefunden werden RoleKeyNotFound: Rolle konnte nicht gefunden werden
Member:
AlreadyExists: Member existiert bereits
IDPConfig: IDPConfig:
AlreadyExists: IDP Konfiguration mit diesem Name existiert bereits AlreadyExists: IDP Konfiguration mit diesem Name existiert bereits
Changes: Changes:

View File

@ -286,6 +286,8 @@ Errors:
NotInactive: User grant is not deactivated NotInactive: User grant is not deactivated
NoPermissionForProject: User has no permissions on this project NoPermissionForProject: User has no permissions on this project
RoleKeyNotFound: Role not found RoleKeyNotFound: Role not found
Member:
AlreadyExists: Member already exists
IDPConfig: IDPConfig:
AlreadyExists: IDP Configuration with this name already exists AlreadyExists: IDP Configuration with this name already exists
Changes: Changes:

View File

@ -66,7 +66,7 @@ func (r *CommandSide) ChangeDefaultIDPConfig(ctx context.Context, config *domain
return nil, caos_errs.ThrowNotFound(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotExisting") return nil, caos_errs.ThrowNotFound(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotExisting")
} }
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, config.IDPConfigID, config.Name, config.StylingType) changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, existingIDP.ResourceOwner, config.IDPConfigID, config.Name, config.StylingType)
if !hasChanged { if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged") return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
} }

View File

@ -84,13 +84,16 @@ func (wm *IAMIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventRead
func (wm *IAMIDPConfigWriteModel) NewChangedEvent( func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
ctx context.Context, ctx context.Context,
resourceOwner,
configID, configID,
name string, name string,
stylingType domain.IDPConfigStylingType, stylingType domain.IDPConfigStylingType,
) (*iam.IDPConfigChangedEvent, bool) { ) (*iam.IDPConfigChangedEvent, bool) {
changes := make([]idpconfig.IDPConfigChanges, 0) changes := make([]idpconfig.IDPConfigChanges, 0)
oldName := ""
if wm.Name != name { if wm.Name != name {
oldName = wm.Name
changes = append(changes, idpconfig.ChangeName(name)) changes = append(changes, idpconfig.ChangeName(name))
} }
if stylingType.Valid() && wm.StylingType != stylingType { if stylingType.Valid() && wm.StylingType != stylingType {
@ -99,7 +102,7 @@ func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
if len(changes) == 0 { if len(changes) == 0 {
return nil, false return nil, false
} }
changeEvent, err := iam.NewIDPConfigChangedEvent(ctx, configID, changes) changeEvent, err := iam.NewIDPConfigChangedEvent(ctx, resourceOwner, configID, oldName, changes)
if err != nil { if err != nil {
return nil, false return nil, false
} }

View File

@ -42,7 +42,7 @@ func (r *CommandSide) addIAMMember(ctx context.Context, iamAgg *iam_repo.Aggrega
return errors.ThrowAlreadyExists(nil, "IAM-sdgQ4", "Errors.IAM.Member.AlreadyExists") return errors.ThrowAlreadyExists(nil, "IAM-sdgQ4", "Errors.IAM.Member.AlreadyExists")
} }
iamAgg.PushEvents(iam_repo.NewMemberAddedEvent(ctx, member.UserID, member.Roles...)) iamAgg.PushEvents(iam_repo.NewMemberAddedEvent(ctx, iamAgg.ID(), member.UserID, member.Roles...))
return nil return nil
} }
@ -89,7 +89,7 @@ func (r *CommandSide) RemoveIAMMember(ctx context.Context, userID string) error
} }
iamAgg := IAMAggregateFromWriteModel(&m.MemberWriteModel.WriteModel) iamAgg := IAMAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewMemberRemovedEvent(ctx, userID)) iamAgg.PushEvents(iam_repo.NewMemberRemovedEvent(ctx, iamAgg.ID(), userID))
return r.eventstore.PushAggregate(ctx, m, iamAgg) return r.eventstore.PushAggregate(ctx, m, iamAgg)
} }

View File

@ -27,14 +27,6 @@ func NewIAMWriteModel() *IAMWriteModel {
func (wm *IAMWriteModel) AppendEvents(events ...eventstore.EventReader) { func (wm *IAMWriteModel) AppendEvents(events ...eventstore.EventReader) {
wm.WriteModel.AppendEvents(events...) 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 { func (wm *IAMWriteModel) Reduce() error {
@ -61,17 +53,6 @@ func (wm *IAMWriteModel) Query() *eventstore.SearchQueryBuilder {
ResourceOwner(wm.ResourceOwner) ResourceOwner(wm.ResourceOwner)
} }
//
//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 { func IAMAggregateFromWriteModel(wm *eventstore.WriteModel) *iam.Aggregate {
return &iam.Aggregate{ return &iam.Aggregate{
Aggregate: *eventstore.AggregateFromWriteModel(wm, iam.AggregateType, iam.AggregateVersion), Aggregate: *eventstore.AggregateFromWriteModel(wm, iam.AggregateType, iam.AggregateVersion),

View File

@ -67,7 +67,13 @@ func (r *CommandSide) ChangeIDPConfig(ctx context.Context, config *domain.IDPCon
return nil, caos_errs.ThrowNotFound(nil, "Org-4M9so", "Errors.Org.IDPConfig.NotExisting") return nil, caos_errs.ThrowNotFound(nil, "Org-4M9so", "Errors.Org.IDPConfig.NotExisting")
} }
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, config.IDPConfigID, config.Name, config.StylingType) changedEvent, hasChanged := existingIDP.NewChangedEvent(
ctx,
existingIDP.ResourceOwner,
config.IDPConfigID,
config.Name,
config.StylingType)
if !hasChanged { if !hasChanged {
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged") return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
} }

View File

@ -84,13 +84,16 @@ func (wm *OrgIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventRead
func (wm *OrgIDPConfigWriteModel) NewChangedEvent( func (wm *OrgIDPConfigWriteModel) NewChangedEvent(
ctx context.Context, ctx context.Context,
resourceOwner,
configID, configID,
name string, name string,
stylingType domain.IDPConfigStylingType, stylingType domain.IDPConfigStylingType,
) (*org.IDPConfigChangedEvent, bool) { ) (*org.IDPConfigChangedEvent, bool) {
changes := make([]idpconfig.IDPConfigChanges, 0) changes := make([]idpconfig.IDPConfigChanges, 0)
oldName := ""
if wm.Name != name { if wm.Name != name {
oldName = wm.Name
changes = append(changes, idpconfig.ChangeName(name)) changes = append(changes, idpconfig.ChangeName(name))
} }
if stylingType.Valid() && wm.StylingType != stylingType { if stylingType.Valid() && wm.StylingType != stylingType {
@ -99,7 +102,7 @@ func (wm *OrgIDPConfigWriteModel) NewChangedEvent(
if len(changes) == 0 { if len(changes) == 0 {
return nil, false return nil, false
} }
changeEvent, err := org.NewIDPConfigChangedEvent(ctx, configID, changes) changeEvent, err := org.NewIDPConfigChangedEvent(ctx, resourceOwner, configID, oldName, changes)
if err != nil { if err != nil {
return nil, false return nil, false
} }

View File

@ -42,7 +42,7 @@ func (r *CommandSide) addOrgMember(ctx context.Context, orgAgg *org.Aggregate, a
return errors.ThrowAlreadyExists(nil, "Org-PtXi1", "Errors.Org.Member.AlreadyExists") return errors.ThrowAlreadyExists(nil, "Org-PtXi1", "Errors.Org.Member.AlreadyExists")
} }
orgAgg.PushEvents(org.NewMemberAddedEvent(ctx, member.UserID, member.Roles...)) orgAgg.PushEvents(org.NewMemberAddedEvent(ctx, orgAgg.ID(), member.UserID, member.Roles...))
return nil return nil
} }
@ -89,7 +89,7 @@ func (r *CommandSide) RemoveOrgMember(ctx context.Context, orgID, userID string)
} }
orgAgg := OrgAggregateFromWriteModel(&m.MemberWriteModel.WriteModel) orgAgg := OrgAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
orgAgg.PushEvents(org.NewMemberRemovedEvent(ctx, userID)) orgAgg.PushEvents(org.NewMemberRemovedEvent(ctx, orgAgg.ID(), userID))
return r.eventstore.PushAggregate(ctx, m, orgAgg) return r.eventstore.PushAggregate(ctx, m, orgAgg)
} }

View File

@ -84,7 +84,7 @@ func (r *CommandSide) ChangeProject(ctx context.Context, projectChange *domain.P
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.Project.NotFound") return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.Project.NotFound")
} }
changedEvent, hasChanged, err := existingProject.NewChangedEvent(ctx, projectChange.Name, projectChange.ProjectRoleAssertion, projectChange.ProjectRoleCheck) changedEvent, hasChanged, err := existingProject.NewChangedEvent(ctx, existingProject.ResourceOwner, projectChange.Name, projectChange.ProjectRoleAssertion, projectChange.ProjectRoleCheck)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -141,7 +141,7 @@ func (r *CommandSide) ReactivateProject(ctx context.Context, projectID string, r
} }
projectAgg := ProjectAggregateFromWriteModel(&existingProject.WriteModel) projectAgg := ProjectAggregateFromWriteModel(&existingProject.WriteModel)
projectAgg.PushEvents(project.NewProjectDeactivatedEvent(ctx)) projectAgg.PushEvents(project.NewProjectReactivatedEvent(ctx))
return r.eventstore.PushAggregate(ctx, existingProject, projectAgg) return r.eventstore.PushAggregate(ctx, existingProject, projectAgg)
} }

View File

@ -8,7 +8,6 @@ import (
"github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/domain" "github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/project" "github.com/caos/zitadel/internal/v2/repository/project"
"github.com/caos/zitadel/internal/v2/repository/usergrant"
"reflect" "reflect"
) )
@ -123,7 +122,7 @@ func (r *CommandSide) removeRoleFromProjectGrant(ctx context.Context, projectAgg
) )
} else { } else {
projectAgg.PushEvents( projectAgg.PushEvents(
usergrant.NewUserGrantCascadeChangedEvent(ctx, existingProjectGrant.RoleKeys), project.NewGrantCascadeChangedEvent(ctx, projectGrantID, existingProjectGrant.RoleKeys),
) )
} }

View File

@ -46,7 +46,7 @@ func (r *CommandSide) addProjectMember(ctx context.Context, projectAgg *project.
return errors.ThrowAlreadyExists(nil, "PROJECT-PtXi1", "Errors.Project.Member.AlreadyExists") return errors.ThrowAlreadyExists(nil, "PROJECT-PtXi1", "Errors.Project.Member.AlreadyExists")
} }
projectAgg.PushEvents(project.NewProjectMemberAddedEvent(ctx, member.UserID, member.Roles...)) projectAgg.PushEvents(project.NewProjectMemberAddedEvent(ctx, projectAgg.ID(), member.UserID, member.Roles...))
return nil return nil
} }
@ -93,7 +93,7 @@ func (r *CommandSide) RemoveProjectMember(ctx context.Context, projectID, userID
} }
projectAgg := ProjectAggregateFromWriteModel(&m.MemberWriteModel.WriteModel) projectAgg := ProjectAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
projectAgg.PushEvents(project.NewProjectMemberRemovedEvent(ctx, userID)) projectAgg.PushEvents(project.NewProjectMemberRemovedEvent(ctx, projectAgg.ID(), userID))
return r.eventstore.PushAggregate(ctx, m, projectAgg) return r.eventstore.PushAggregate(ctx, m, projectAgg)
} }

View File

@ -72,6 +72,7 @@ func (wm *ProjectWriteModel) Query() *eventstore.SearchQueryBuilder {
func (wm *ProjectWriteModel) NewChangedEvent( func (wm *ProjectWriteModel) NewChangedEvent(
ctx context.Context, ctx context.Context,
resourceOwner,
name string, name string,
projectRoleAssertion, projectRoleAssertion,
projectRoleCheck bool, projectRoleCheck bool,
@ -79,7 +80,9 @@ func (wm *ProjectWriteModel) NewChangedEvent(
changes := make([]project.ProjectChanges, 0) changes := make([]project.ProjectChanges, 0)
var err error var err error
oldName := ""
if wm.Name != name { if wm.Name != name {
oldName = wm.Name
changes = append(changes, project.ChangeName(name)) changes = append(changes, project.ChangeName(name))
} }
if wm.ProjectRoleAssertion != projectRoleAssertion { if wm.ProjectRoleAssertion != projectRoleAssertion {
@ -91,7 +94,7 @@ func (wm *ProjectWriteModel) NewChangedEvent(
if len(changes) == 0 { if len(changes) == 0 {
return nil, false, nil return nil, false, nil
} }
changeEvent, err := project.NewProjectChangeEvent(ctx, changes) changeEvent, err := project.NewProjectChangeEvent(ctx, resourceOwner, oldName, changes)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }

View File

@ -51,7 +51,6 @@ func (r *CommandSide) addProjectRoles(ctx context.Context, projectAgg *project.A
projectRole.DisplayName, projectRole.DisplayName,
projectRole.Group, projectRole.Group,
projectID, projectID,
resourceOwner,
), ),
) )
} }
@ -107,7 +106,7 @@ func (r *CommandSide) RemoveProjectRole(ctx context.Context, projectID, key, res
} }
aggregates := make([]eventstore.Aggregater, 0) aggregates := make([]eventstore.Aggregater, 0)
projectAgg := ProjectAggregateFromWriteModel(&existingRole.WriteModel) projectAgg := ProjectAggregateFromWriteModel(&existingRole.WriteModel)
projectAgg.PushEvents(project.NewRoleRemovedEvent(ctx, key, projectID, existingRole.ResourceOwner)) projectAgg.PushEvents(project.NewRoleRemovedEvent(ctx, key, projectID))
for _, projectGrantID := range cascadingProjectGrantIds { for _, projectGrantID := range cascadingProjectGrantIds {
_, err = r.removeRoleFromProjectGrant(ctx, projectAgg, projectID, projectGrantID, key, true) _, err = r.removeRoleFromProjectGrant(ctx, projectAgg, projectID, projectGrantID, key, true)
if err != nil { if err != nil {

View File

@ -0,0 +1,35 @@
package command
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
type Step11 struct {
MigrateV1EventstoreToV2 bool
}
func (s *Step11) Step() domain.Step {
return domain.Step11
}
func (s *Step11) execute(ctx context.Context, commandSide *CommandSide) error {
return commandSide.SetupStep11(ctx, s)
}
func (r *CommandSide) SetupStep11(ctx context.Context, step *Step11) error {
fn := func(iam *IAMWriteModel) (*iam_repo.Aggregate, error) {
iamAgg := IAMAggregateFromWriteModel(&iam.WriteModel)
uniqueConstraints := NewUniqueConstraintReadModel(ctx, r)
err := r.eventstore.FilterToQueryReducer(ctx, uniqueConstraints)
if err != nil {
return nil, err
}
iamAgg.PushEvents(iam_repo.NewMigrateUniqueConstraintEvent(ctx, uniqueConstraints.UniqueConstraints))
logging.Log("SETUP-M9fsd").Info("migrate v1 eventstore to v2")
return iamAgg, nil
}
return r.setup(ctx, step, fn)
}

View File

@ -0,0 +1,255 @@
package command
import (
"context"
"github.com/caos/logging"
"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"
"github.com/caos/zitadel/internal/v2/repository/member"
"github.com/caos/zitadel/internal/v2/repository/org"
"github.com/caos/zitadel/internal/v2/repository/policy"
"github.com/caos/zitadel/internal/v2/repository/project"
"github.com/caos/zitadel/internal/v2/repository/user"
"github.com/caos/zitadel/internal/v2/repository/usergrant"
)
type UniqueConstraintReadModel struct {
eventstore.WriteModel
UniqueConstraints []*domain.UniqueConstraintMigration
commandProvider commandProvider
ctx context.Context
}
type commandProvider interface {
getOrgIAMPolicy(ctx context.Context, orgID string) (*domain.OrgIAMPolicy, error)
}
func NewUniqueConstraintReadModel(ctx context.Context, provider commandProvider) *UniqueConstraintReadModel {
return &UniqueConstraintReadModel{
ctx: ctx,
commandProvider: provider,
}
}
func (rm *UniqueConstraintReadModel) AppendEvents(events ...eventstore.EventReader) {
rm.WriteModel.AppendEvents(events...)
}
func (rm *UniqueConstraintReadModel) Reduce() error {
for _, event := range rm.Events {
switch e := event.(type) {
case *org.OrgAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.AggregateID(), org.NewAddOrgNameUniqueConstraint(e.Name))
case *org.OrgChangedEvent:
rm.changeUniqueConstraint(e.AggregateID(), e.AggregateID(), org.NewAddOrgNameUniqueConstraint(e.Name))
case *org.DomainVerificationAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.AggregateID(), org.NewAddOrgNameUniqueConstraint(e.Domain))
case *org.DomainRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.AggregateID(), org.UniqueOrgDomain)
case *iam.IDPConfigAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(e.Name, e.ResourceOwner()))
case *iam.IDPConfigChangedEvent:
rm.changeUniqueConstraint(e.AggregateID(), e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(*e.Name, e.ResourceOwner()))
case *iam.IDPConfigRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.ConfigID, idpconfig.UniqueIDPConfigNameType)
case *org.IDPConfigAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(e.Name, e.ResourceOwner()))
case *org.IDPConfigChangedEvent:
rm.changeUniqueConstraint(e.AggregateID(), e.ConfigID, idpconfig.NewAddIDPConfigNameUniqueConstraint(*e.Name, e.ResourceOwner()))
case *org.IDPConfigRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.ConfigID, idpconfig.UniqueIDPConfigNameType)
case *iam.MailTextAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.MailTextType+e.Language, policy.NewAddMailTextUniqueConstraint(e.AggregateID(), e.MailTextType, e.Language))
case *org.MailTextAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.MailTextType+e.Language, policy.NewAddMailTextUniqueConstraint(e.AggregateID(), e.MailTextType, e.Language))
case *org.MailTextRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.MailTextType+e.Language, policy.UniqueMailText)
case *project.ProjectAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.AggregateID(), project.NewAddProjectNameUniqueConstraint(e.Name, e.ResourceOwner()))
case *project.ProjectChangeEvent:
rm.changeUniqueConstraint(e.AggregateID(), e.AggregateID(), project.NewAddProjectNameUniqueConstraint(*e.Name, e.ResourceOwner()))
case *project.ProjectRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.AggregateID(), project.UniqueProjectnameType)
case *project.ApplicationAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.AppID, project.NewAddApplicationUniqueConstraint(e.Name, e.AggregateID()))
case *project.ApplicationChangedEvent:
rm.changeUniqueConstraint(e.AggregateID(), e.AppID, project.NewAddApplicationUniqueConstraint(e.Name, e.AggregateID()))
case *project.ApplicationRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.AppID, project.UniqueAppNameType)
case *project.GrantAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.GrantID, project.NewAddProjectGrantUniqueConstraint(e.GrantedOrgID, e.AggregateID()))
case *project.GrantRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.GrantID, project.UniqueGrantType)
case *project.GrantMemberAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.GrantID+e.UserID, project.NewAddProjectGrantMemberUniqueConstraint(e.AggregateID(), e.UserID, e.GrantID))
case *project.GrantMemberRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.GrantID+e.UserID, project.UniqueProjectGrantMemberType)
case *project.RoleAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.Key, project.NewAddProjectRoleUniqueConstraint(e.Key, e.AggregateID()))
case *project.RoleRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.Key, project.UniqueRoleType)
case *user.HumanAddedEvent:
policy, err := rm.commandProvider.getOrgIAMPolicy(rm.ctx, e.ResourceOwner())
if err != nil {
logging.Log("COMMAND-0k9Gs").WithError(err).Error("could not read policy for human added event unique constraint")
continue
}
rm.addUniqueConstraint(e.AggregateID(), e.AggregateID(), user.NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), policy.UserLoginMustBeDomain))
case *user.HumanRegisteredEvent:
policy, err := rm.commandProvider.getOrgIAMPolicy(rm.ctx, e.ResourceOwner())
if err != nil {
logging.Log("COMMAND-m9fod").WithError(err).Error("could not read policy for human registered event unique constraint")
continue
}
rm.addUniqueConstraint(e.AggregateID(), e.AggregateID(), user.NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), policy.UserLoginMustBeDomain))
case *user.MachineAddedEvent:
policy, err := rm.commandProvider.getOrgIAMPolicy(rm.ctx, e.ResourceOwner())
if err != nil {
logging.Log("COMMAND-2n8vs").WithError(err).Error("could not read policy for machine added event unique constraint")
continue
}
rm.addUniqueConstraint(e.AggregateID(), e.AggregateID(), user.NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), policy.UserLoginMustBeDomain))
case *user.UserRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.AggregateID(), user.UniqueUsername)
case *user.UsernameChangedEvent:
policy, err := rm.commandProvider.getOrgIAMPolicy(rm.ctx, e.ResourceOwner())
if err != nil {
logging.Log("COMMAND-5n8gk").WithError(err).Error("could not read policy for username changed event unique constraint")
continue
}
rm.changeUniqueConstraint(e.AggregateID(), e.AggregateID(), user.NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), policy.UserLoginMustBeDomain))
case *user.DomainClaimedEvent:
policy, err := rm.commandProvider.getOrgIAMPolicy(rm.ctx, e.ResourceOwner())
if err != nil {
logging.Log("COMMAND-xb8uf").WithError(err).Error("could not read policy for domain claimed event unique constraint")
continue
}
rm.changeUniqueConstraint(e.AggregateID(), e.AggregateID(), user.NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), policy.UserLoginMustBeDomain))
case *user.HumanExternalIDPAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.IDPConfigID+e.ExternalUserID, user.NewAddExternalIDPUniqueConstraint(e.IDPConfigID, e.ExternalUserID))
case *user.HumanExternalIDPRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.IDPConfigID+e.ExternalUserID, user.UniqueExternalIDPType)
case *user.HumanExternalIDPCascadeRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.IDPConfigID+e.ExternalUserID, user.UniqueExternalIDPType)
case *usergrant.UserGrantAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.AggregateID(), usergrant.NewAddUserGrantUniqueConstraint(e.ResourceOwner(), e.UserID, e.ProjectID, e.ProjectGrantID))
case *usergrant.UserGrantRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.AggregateID(), usergrant.UniqueUserGrant)
case *usergrant.UserGrantCascadeRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.AggregateID(), usergrant.UniqueUserGrant)
case *iam.MemberAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.UserID, member.NewAddMemberUniqueConstraint(e.AggregateID(), e.UserID))
case *iam.MemberRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.UserID, member.UniqueMember)
case *org.MemberAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.UserID, member.NewAddMemberUniqueConstraint(e.AggregateID(), e.UserID))
case *org.MemberRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.UserID, member.UniqueMember)
case *project.MemberAddedEvent:
rm.addUniqueConstraint(e.AggregateID(), e.UserID, member.NewAddMemberUniqueConstraint(e.AggregateID(), e.UserID))
case *project.MemberRemovedEvent:
rm.removeUniqueConstraint(e.AggregateID(), e.UserID, member.UniqueMember)
}
}
return nil
}
func (rm *UniqueConstraintReadModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
AggregateIDs(rm.AggregateID).
ResourceOwner(rm.ResourceOwner).
EventTypes(
org.OrgAddedEventType,
org.OrgChangedEventType,
org.OrgDomainVerifiedEventType,
org.OrgDomainRemovedEventType,
iam.IDPConfigAddedEventType,
iam.IDPConfigChangedEventType,
iam.IDPConfigRemovedEventType,
org.IDPConfigAddedEventType,
org.IDPConfigChangedEventType,
org.IDPConfigRemovedEventType,
iam.MailTextAddedEventType,
org.MailTextAddedEventType,
org.MailTextRemovedEventType,
project.ProjectAddedType,
project.ProjectChangedType,
project.ProjectRemovedType,
project.ApplicationAddedType,
project.ApplicationChangedType,
project.ApplicationRemovedType,
project.GrantAddedType,
project.GrantRemovedType,
project.GrantMemberAddedType,
project.GrantMemberRemovedType,
project.RoleAddedType,
project.RoleRemovedType,
user.HumanAddedType,
user.HumanRegisteredType,
user.MachineAddedEventType,
user.UserUserNameChangedType,
user.UserDomainClaimedType,
user.UserRemovedType,
user.HumanExternalIDPAddedType,
user.HumanExternalIDPRemovedType,
user.HumanExternalIDPCascadeRemovedType,
usergrant.UserGrantAddedType,
usergrant.UserGrantRemovedType,
usergrant.UserGrantCascadeRemovedType,
iam.MemberAddedEventType,
iam.MemberRemovedEventType,
org.MemberAddedEventType,
org.MemberRemovedEventType,
project.MemberAddedType,
project.MemberRemovedType,
)
}
func (rm *UniqueConstraintReadModel) getUniqueConstraint(aggregateID, objectID, constraintType string) *domain.UniqueConstraintMigration {
for _, uniqueConstraint := range rm.UniqueConstraints {
if uniqueConstraint.AggregateID == aggregateID && uniqueConstraint.ObjectID == objectID && uniqueConstraint.UniqueType == constraintType {
return uniqueConstraint
}
}
return nil
}
func (rm *UniqueConstraintReadModel) addUniqueConstraint(aggregateID, objectID string, constraint *eventstore.EventUniqueConstraint) {
migrateUniqueConstraint := &domain.UniqueConstraintMigration{
AggregateID: aggregateID,
ObjectID: objectID,
UniqueType: constraint.UniqueType,
UniqueField: constraint.UniqueField,
ErrorMessage: constraint.ErrorMessage,
}
rm.UniqueConstraints = append(rm.UniqueConstraints, migrateUniqueConstraint)
}
func (rm *UniqueConstraintReadModel) changeUniqueConstraint(aggregateID, objectID string, constraint *eventstore.EventUniqueConstraint) {
for i, uniqueConstraint := range rm.UniqueConstraints {
if uniqueConstraint.AggregateID == aggregateID && uniqueConstraint.ObjectID == objectID && uniqueConstraint.UniqueType == constraint.UniqueType {
rm.UniqueConstraints[i] = &domain.UniqueConstraintMigration{
AggregateID: aggregateID,
ObjectID: objectID,
UniqueType: constraint.UniqueType,
UniqueField: constraint.UniqueField,
ErrorMessage: constraint.ErrorMessage,
}
return
}
}
}
func (rm *UniqueConstraintReadModel) removeUniqueConstraint(aggregateID, objectID, constraintType string) {
for i, uniqueConstraint := range rm.UniqueConstraints {
if uniqueConstraint.AggregateID == aggregateID && uniqueConstraint.ObjectID == objectID && uniqueConstraint.UniqueType == constraintType {
copy(rm.UniqueConstraints[i:], rm.UniqueConstraints[i+1:])
rm.UniqueConstraints[len(rm.UniqueConstraints)-1] = nil
rm.UniqueConstraints = rm.UniqueConstraints[:len(rm.UniqueConstraints)-1]
return
}
}
}

View File

@ -218,11 +218,16 @@ func (r *CommandSide) userDomainClaimed(ctx context.Context, userID string) (_ *
changedUserGrant := NewUserWriteModel(userID, existingUser.ResourceOwner) changedUserGrant := NewUserWriteModel(userID, existingUser.ResourceOwner)
userAgg := UserAggregateFromWriteModel(&changedUserGrant.WriteModel) userAgg := UserAggregateFromWriteModel(&changedUserGrant.WriteModel)
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, existingUser.ResourceOwner)
if err != nil {
return nil, nil, err
}
id, err := r.idGenerator.Next() id, err := r.idGenerator.Next()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
userAgg.PushEvents(user.NewDomainClaimedEvent(ctx, fmt.Sprintf("%s@temporary.%s", id, r.iamDomain))) userAgg.PushEvents(user.NewDomainClaimedEvent(ctx, fmt.Sprintf("%s@temporary.%s", id, r.iamDomain), existingUser.UserName, orgIAMPolicy.UserLoginMustBeDomain))
return userAgg, changedUserGrant, nil return userAgg, changedUserGrant, nil
} }

View File

@ -251,11 +251,21 @@ func (r *CommandSide) removeUserGrant(ctx context.Context, grantID, resourceOwne
userGrantAgg := UserGrantAggregateFromWriteModel(&removeUserGrant.WriteModel) userGrantAgg := UserGrantAggregateFromWriteModel(&removeUserGrant.WriteModel)
if !cascade { if !cascade {
userGrantAgg.PushEvents( userGrantAgg.PushEvents(
usergrant.NewUserGrantRemovedEvent(ctx, existingUserGrant.ResourceOwner, existingUserGrant.UserID, existingUserGrant.ProjectID), usergrant.NewUserGrantRemovedEvent(
ctx,
existingUserGrant.ResourceOwner,
existingUserGrant.UserID,
existingUserGrant.ProjectID,
existingUserGrant.ProjectGrantID),
) )
} else { } else {
userGrantAgg.PushEvents( userGrantAgg.PushEvents(
usergrant.NewUserGrantCascadeRemovedEvent(ctx, existingUserGrant.ResourceOwner, existingUserGrant.UserID, existingUserGrant.ProjectID), usergrant.NewUserGrantCascadeRemovedEvent(
ctx,
existingUserGrant.ResourceOwner,
existingUserGrant.UserID,
existingUserGrant.ProjectID,
existingUserGrant.ProjectGrantID),
) )
} }

View File

@ -37,7 +37,7 @@ func (wm *HumanExternalIDPWriteModel) Reduce() error {
case *user.HumanExternalIDPAddedEvent: case *user.HumanExternalIDPAddedEvent:
wm.IDPConfigID = e.IDPConfigID wm.IDPConfigID = e.IDPConfigID
wm.DisplayName = e.DisplayName wm.DisplayName = e.DisplayName
wm.ExternalUserID = e.UserID wm.ExternalUserID = e.ExternalUserID
wm.State = domain.ExternalIDPStateActive wm.State = domain.ExternalIDPStateActive
case *user.HumanExternalIDPRemovedEvent: case *user.HumanExternalIDPRemovedEvent:
wm.State = domain.ExternalIDPStateRemoved wm.State = domain.ExternalIDPStateRemoved

View File

@ -13,6 +13,7 @@ const (
Step8 Step8
Step9 Step9
Step10 Step10
Step11
//StepCount marks the the length of possible steps (StepCount-1 == last possible step) //StepCount marks the the length of possible steps (StepCount-1 == last possible step)
StepCount StepCount
) )

View File

@ -0,0 +1,9 @@
package domain
type UniqueConstraintMigration struct {
AggregateID string
ObjectID string
UniqueType string
UniqueField string
ErrorMessage string
}

View File

@ -9,6 +9,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(SetupDoneEventType, SetupStepMapper). RegisterFilterEventMapper(SetupDoneEventType, SetupStepMapper).
RegisterFilterEventMapper(GlobalOrgSetEventType, GlobalOrgSetMapper). RegisterFilterEventMapper(GlobalOrgSetEventType, GlobalOrgSetMapper).
RegisterFilterEventMapper(ProjectSetEventType, ProjectSetMapper). RegisterFilterEventMapper(ProjectSetEventType, ProjectSetMapper).
RegisterFilterEventMapper(UniqueConstraintsMigratedEventType, MigrateUniqueConstraintEventMapper).
RegisterFilterEventMapper(LabelPolicyAddedEventType, LabelPolicyAddedEventMapper). RegisterFilterEventMapper(LabelPolicyAddedEventType, LabelPolicyAddedEventMapper).
RegisterFilterEventMapper(LabelPolicyChangedEventType, LabelPolicyChangedEventMapper). RegisterFilterEventMapper(LabelPolicyChangedEventType, LabelPolicyChangedEventMapper).
RegisterFilterEventMapper(LoginPolicyAddedEventType, LoginPolicyAddedEventMapper). RegisterFilterEventMapper(LoginPolicyAddedEventType, LoginPolicyAddedEventMapper).
@ -33,6 +34,10 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(LoginPolicyIDPProviderAddedEventType, IdentityProviderAddedEventMapper). RegisterFilterEventMapper(LoginPolicyIDPProviderAddedEventType, IdentityProviderAddedEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderRemovedEventType, IdentityProviderRemovedEventMapper). RegisterFilterEventMapper(LoginPolicyIDPProviderRemovedEventType, IdentityProviderRemovedEventMapper).
RegisterFilterEventMapper(LoginPolicyIDPProviderCascadeRemovedEventType, IdentityProviderCascadeRemovedEventMapper). RegisterFilterEventMapper(LoginPolicyIDPProviderCascadeRemovedEventType, IdentityProviderCascadeRemovedEventMapper).
RegisterFilterEventMapper(LoginPolicySecondFactorAddedEventType, SecondFactorAddedEventMapper).
RegisterFilterEventMapper(LoginPolicySecondFactorRemovedEventType, SecondFactorRemovedEventMapper).
RegisterFilterEventMapper(LoginPolicyMultiFactorAddedEventType, MultiFactorAddedEventMapper).
RegisterFilterEventMapper(LoginPolicyMultiFactorRemovedEventType, MultiFactorRemovedEventMapper).
RegisterFilterEventMapper(MailTemplateAddedEventType, MailTemplateAddedEventMapper). RegisterFilterEventMapper(MailTemplateAddedEventType, MailTemplateAddedEventMapper).
RegisterFilterEventMapper(MailTemplateChangedEventType, MailTemplateChangedEventMapper). RegisterFilterEventMapper(MailTemplateChangedEventType, MailTemplateChangedEventMapper).
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper). RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).

View File

@ -59,12 +59,15 @@ type IDPConfigChangedEvent struct {
func NewIDPConfigChangedEvent( func NewIDPConfigChangedEvent(
ctx context.Context, ctx context.Context,
configID string, resourceOwner,
configID,
oldName string,
changes []idpconfig.IDPConfigChanges, changes []idpconfig.IDPConfigChanges,
) (*IDPConfigChangedEvent, error) { ) (*IDPConfigChangedEvent, error) {
changeEvent, err := idpconfig.NewIDPConfigChangedEvent( changeEvent, err := idpconfig.NewIDPConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPConfigChangedEventType), eventstore.NewBaseEventForPushWithResourceOwner(ctx, IDPConfigChangedEventType, resourceOwner),
configID, configID,
oldName,
changes, changes,
) )
if err != nil { if err != nil {

View File

@ -19,6 +19,7 @@ type MemberAddedEvent struct {
func NewMemberAddedEvent( func NewMemberAddedEvent(
ctx context.Context, ctx context.Context,
aggregateID,
userID string, userID string,
roles ...string, roles ...string,
) *MemberAddedEvent { ) *MemberAddedEvent {
@ -29,6 +30,7 @@ func NewMemberAddedEvent(
ctx, ctx,
MemberAddedEventType, MemberAddedEventType,
), ),
aggregateID,
userID, userID,
roles..., roles...,
), ),
@ -80,6 +82,7 @@ type MemberRemovedEvent struct {
func NewMemberRemovedEvent( func NewMemberRemovedEvent(
ctx context.Context, ctx context.Context,
aggregateID,
userID string, userID string,
) *MemberRemovedEvent { ) *MemberRemovedEvent {
@ -89,6 +92,7 @@ func NewMemberRemovedEvent(
ctx, ctx,
MemberRemovedEventType, MemberRemovedEventType,
), ),
aggregateID,
userID, userID,
), ),
} }

View File

@ -0,0 +1,54 @@
package iam
import (
"context"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
)
const (
UniqueConstraintsMigratedEventType eventstore.EventType = "iam.unique.constraints.migrated"
)
type MigrateUniqueConstraintEvent struct {
eventstore.BaseEvent `json:"-"`
uniqueConstraintMigrations []*domain.UniqueConstraintMigration `json:"-"`
}
func NewAddMigrateUniqueConstraint(uniqueMigration *domain.UniqueConstraintMigration) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint(
uniqueMigration.UniqueType,
uniqueMigration.UniqueField,
uniqueMigration.ErrorMessage)
}
func (e *MigrateUniqueConstraintEvent) Data() interface{} {
return nil
}
func (e *MigrateUniqueConstraintEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
constraints := make([]*eventstore.EventUniqueConstraint, len(e.uniqueConstraintMigrations))
for i, uniqueMigration := range e.uniqueConstraintMigrations {
constraints[i] = NewAddMigrateUniqueConstraint(uniqueMigration)
}
return constraints
}
func NewMigrateUniqueConstraintEvent(ctx context.Context, uniqueConstraintMigrations []*domain.UniqueConstraintMigration) *MigrateUniqueConstraintEvent {
return &MigrateUniqueConstraintEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
UniqueConstraintsMigratedEventType,
),
uniqueConstraintMigrations: uniqueConstraintMigrations,
}
}
func MigrateUniqueConstraintEventMapper(event *repository.Event) (eventstore.EventReader, error) {
return &MigrateUniqueConstraintEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}, nil
}

View File

@ -31,7 +31,7 @@ func NewLoginPolicySecondFactorAddedEvent(
} }
} }
func SecondFactorAddedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { func SecondFactorAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := policy.SecondFactorAddedEventMapper(event) e, err := policy.SecondFactorAddedEventMapper(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -58,7 +58,7 @@ func NewLoginPolicySecondFactorRemovedEvent(
} }
} }
func SecondFactorRemovedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { func SecondFactorRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := policy.SecondFactorRemovedEventMapper(event) e, err := policy.SecondFactorRemovedEventMapper(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -84,7 +84,7 @@ func NewLoginPolicyMultiFactorAddedEvent(
} }
} }
func MultiFactorAddedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { func MultiFactorAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := policy.MultiFactorAddedEventMapper(event) e, err := policy.MultiFactorAddedEventMapper(event)
if err != nil { if err != nil {
return nil, err return nil, err
@ -111,7 +111,7 @@ func NewLoginPolicyMultiFactorRemovedEvent(
} }
} }
func MultiFactorRemovedEventEventMapper(event *repository.Event) (eventstore.EventReader, error) { func MultiFactorRemovedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
e, err := policy.MultiFactorRemovedEventMapper(event) e, err := policy.MultiFactorRemovedEventMapper(event)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -10,19 +10,19 @@ import (
) )
const ( const (
uniqueIDPConfigNameType = "idp_config_names" UniqueIDPConfigNameType = "idp_config_names"
) )
func NewAddIDPConfigNameUniqueConstraint(idpConfigName, resourceOwner string) *eventstore.EventUniqueConstraint { func NewAddIDPConfigNameUniqueConstraint(idpConfigName, resourceOwner string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueIDPConfigNameType, UniqueIDPConfigNameType,
idpConfigName+resourceOwner, idpConfigName+resourceOwner,
"Errors.IDPConfig.AlreadyExists") "Errors.IDPConfig.AlreadyExists")
} }
func NewRemoveIDPConfigNameUniqueConstraint(idpConfigName, resourceOwner string) *eventstore.EventUniqueConstraint { func NewRemoveIDPConfigNameUniqueConstraint(idpConfigName, resourceOwner string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueIDPConfigNameType, UniqueIDPConfigNameType,
idpConfigName+resourceOwner) idpConfigName+resourceOwner)
} }
@ -78,6 +78,7 @@ type IDPConfigChangedEvent struct {
ConfigID string `json:"idpConfigId"` ConfigID string `json:"idpConfigId"`
Name *string `json:"name,omitempty"` Name *string `json:"name,omitempty"`
StylingType *domain.IDPConfigStylingType `json:"stylingType,omitempty"` StylingType *domain.IDPConfigStylingType `json:"stylingType,omitempty"`
oldName string `json:"-"`
} }
func (e *IDPConfigChangedEvent) Data() interface{} { func (e *IDPConfigChangedEvent) Data() interface{} {
@ -85,12 +86,19 @@ func (e *IDPConfigChangedEvent) Data() interface{} {
} }
func (e *IDPConfigChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *IDPConfigChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil if e.oldName == "" {
return nil
}
return []*eventstore.EventUniqueConstraint{
NewRemoveIDPConfigNameUniqueConstraint(e.oldName, e.ResourceOwner()),
NewAddIDPConfigNameUniqueConstraint(*e.Name, e.ResourceOwner()),
}
} }
func NewIDPConfigChangedEvent( func NewIDPConfigChangedEvent(
base *eventstore.BaseEvent, base *eventstore.BaseEvent,
configID string, configID,
oldName string,
changes []IDPConfigChanges, changes []IDPConfigChanges,
) (*IDPConfigChangedEvent, error) { ) (*IDPConfigChangedEvent, error) {
if len(changes) == 0 { if len(changes) == 0 {
@ -99,6 +107,7 @@ func NewIDPConfigChangedEvent(
changeEvent := &IDPConfigChangedEvent{ changeEvent := &IDPConfigChangedEvent{
BaseEvent: *base, BaseEvent: *base,
ConfigID: configID, ConfigID: configID,
oldName: oldName,
} }
for _, change := range changes { for _, change := range changes {
change(changeEvent) change(changeEvent)

View File

@ -2,22 +2,39 @@ package member
import ( import (
"encoding/json" "encoding/json"
"fmt"
"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"
"github.com/caos/zitadel/internal/eventstore/v2/repository" "github.com/caos/zitadel/internal/eventstore/v2/repository"
) )
const ( const (
UniqueMember = "member"
AddedEventType = "member.added" AddedEventType = "member.added"
ChangedEventType = "member.changed" ChangedEventType = "member.changed"
RemovedEventType = "member.removed" RemovedEventType = "member.removed"
) )
func NewAddMemberUniqueConstraint(aggregateID, userID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint(
UniqueMember,
fmt.Sprintf("%s:%s", aggregateID, userID),
"Errors.Member.AlreadyExists")
}
func NewRemoveMemberUniqueConstraint(aggregateID, userID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint(
UniqueMember,
fmt.Sprintf("%s:%s", aggregateID, userID),
)
}
type MemberAddedEvent struct { type MemberAddedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
Roles []string `json:"roles"` Roles []string `json:"roles"`
UserID string `json:"userId"` UserID string `json:"userId"`
aggregateID string
} }
func (e *MemberAddedEvent) Data() interface{} { func (e *MemberAddedEvent) Data() interface{} {
@ -25,19 +42,21 @@ func (e *MemberAddedEvent) Data() interface{} {
} }
func (e *MemberAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *MemberAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil return []*eventstore.EventUniqueConstraint{NewAddMemberUniqueConstraint(e.aggregateID, e.UserID)}
} }
func NewMemberAddedEvent( func NewMemberAddedEvent(
base *eventstore.BaseEvent, base *eventstore.BaseEvent,
aggregateID,
userID string, userID string,
roles ...string, roles ...string,
) *MemberAddedEvent { ) *MemberAddedEvent {
return &MemberAddedEvent{ return &MemberAddedEvent{
BaseEvent: *base, BaseEvent: *base,
Roles: roles, aggregateID: aggregateID,
UserID: userID, Roles: roles,
UserID: userID,
} }
} }
@ -97,7 +116,8 @@ func ChangedEventMapper(event *repository.Event) (eventstore.EventReader, error)
type MemberRemovedEvent struct { type MemberRemovedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
UserID string `json:"userId"` UserID string `json:"userId"`
aggregateID string
} }
func (e *MemberRemovedEvent) Data() interface{} { func (e *MemberRemovedEvent) Data() interface{} {
@ -105,17 +125,19 @@ func (e *MemberRemovedEvent) Data() interface{} {
} }
func (e *MemberRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *MemberRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil return []*eventstore.EventUniqueConstraint{NewRemoveMemberUniqueConstraint(e.aggregateID, e.UserID)}
} }
func NewRemovedEvent( func NewRemovedEvent(
base *eventstore.BaseEvent, base *eventstore.BaseEvent,
aggregateID,
userID string, userID string,
) *MemberRemovedEvent { ) *MemberRemovedEvent {
return &MemberRemovedEvent{ return &MemberRemovedEvent{
BaseEvent: *base, BaseEvent: *base,
UserID: userID, aggregateID: aggregateID,
UserID: userID,
} }
} }

View File

@ -12,7 +12,7 @@ import (
) )
const ( const (
uniqueOrgDomain = "org_domain" UniqueOrgDomain = "org_domain"
domainEventPrefix = orgEventTypePrefix + "domain." domainEventPrefix = orgEventTypePrefix + "domain."
OrgDomainAddedEventType = domainEventPrefix + "added" OrgDomainAddedEventType = domainEventPrefix + "added"
OrgDomainVerificationAddedEventType = domainEventPrefix + "verification.added" OrgDomainVerificationAddedEventType = domainEventPrefix + "verification.added"
@ -24,14 +24,14 @@ const (
func NewAddOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint { func NewAddOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueOrgDomain, UniqueOrgDomain,
orgDomain, orgDomain,
"Errors.Org.Domain.AlreadyExists") "Errors.Org.Domain.AlreadyExists")
} }
func NewRemoveOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint { func NewRemoveOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueOrgDomain, UniqueOrgDomain,
orgDomain) orgDomain)
} }
@ -84,7 +84,7 @@ func (e *DomainVerificationAddedEvent) Data() interface{} {
} }
func (e *DomainVerificationAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *DomainVerificationAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewAddOrgDomainUniqueConstraint(e.Domain)} return nil
} }
func NewDomainVerificationAddedEvent( func NewDomainVerificationAddedEvent(
@ -162,7 +162,7 @@ func (e *DomainVerifiedEvent) Data() interface{} {
} }
func (e *DomainVerifiedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *DomainVerifiedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil return []*eventstore.EventUniqueConstraint{NewAddOrgDomainUniqueConstraint(e.Domain)}
} }
func NewDomainVerifiedEvent(ctx context.Context, domain string) *DomainVerifiedEvent { func NewDomainVerifiedEvent(ctx context.Context, domain string) *DomainVerifiedEvent {

View File

@ -49,5 +49,12 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(MailTemplateRemovedEventType, MailTemplateRemovedEventMapper). RegisterFilterEventMapper(MailTemplateRemovedEventType, MailTemplateRemovedEventMapper).
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper). RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).
RegisterFilterEventMapper(MailTextChangedEventType, MailTextChangedEventMapper). RegisterFilterEventMapper(MailTextChangedEventType, MailTextChangedEventMapper).
RegisterFilterEventMapper(MailTextRemovedEventType, MailTextRemovedEventMapper) RegisterFilterEventMapper(MailTextRemovedEventType, MailTextRemovedEventMapper).
RegisterFilterEventMapper(IDPConfigAddedEventType, IDPConfigAddedEventMapper).
RegisterFilterEventMapper(IDPConfigChangedEventType, IDPConfigChangedEventMapper).
RegisterFilterEventMapper(IDPConfigRemovedEventType, IDPConfigRemovedEventMapper).
RegisterFilterEventMapper(IDPConfigDeactivatedEventType, IDPConfigDeactivatedEventMapper).
RegisterFilterEventMapper(IDPConfigReactivatedEventType, IDPConfigReactivatedEventMapper).
RegisterFilterEventMapper(IDPOIDCConfigAddedEventType, IDPOIDCConfigAddedEventMapper).
RegisterFilterEventMapper(IDPOIDCConfigChangedEventType, IDPOIDCConfigChangedEventMapper)
} }

View File

@ -59,12 +59,15 @@ type IDPConfigChangedEvent struct {
func NewIDPConfigChangedEvent( func NewIDPConfigChangedEvent(
ctx context.Context, ctx context.Context,
configID string, resourceOwner,
configID,
oldName string,
changes []idpconfig.IDPConfigChanges, changes []idpconfig.IDPConfigChanges,
) (*IDPConfigChangedEvent, error) { ) (*IDPConfigChangedEvent, error) {
changeEvent, err := idpconfig.NewIDPConfigChangedEvent( changeEvent, err := idpconfig.NewIDPConfigChangedEvent(
eventstore.NewBaseEventForPush(ctx, IDPConfigChangedEventType), eventstore.NewBaseEventForPushWithResourceOwner(ctx, IDPConfigChangedEventType, resourceOwner),
configID, configID,
oldName,
changes, changes,
) )
if err != nil { if err != nil {

View File

@ -19,6 +19,7 @@ type MemberAddedEvent struct {
func NewMemberAddedEvent( func NewMemberAddedEvent(
ctx context.Context, ctx context.Context,
aggregateID,
userID string, userID string,
roles ...string, roles ...string,
) *MemberAddedEvent { ) *MemberAddedEvent {
@ -28,6 +29,7 @@ func NewMemberAddedEvent(
ctx, ctx,
MemberAddedEventType, MemberAddedEventType,
), ),
aggregateID,
userID, userID,
roles..., roles...,
), ),
@ -80,6 +82,7 @@ type MemberRemovedEvent struct {
func NewMemberRemovedEvent( func NewMemberRemovedEvent(
ctx context.Context, ctx context.Context,
aggregateID,
userID string, userID string,
) *MemberRemovedEvent { ) *MemberRemovedEvent {
@ -89,6 +92,7 @@ func NewMemberRemovedEvent(
ctx, ctx,
MemberRemovedEventType, MemberRemovedEventType,
), ),
aggregateID,
userID, userID,
), ),
} }

View File

@ -70,7 +70,8 @@ func OrgAddedEventMapper(event *repository.Event) (eventstore.EventReader, error
type OrgChangedEvent struct { type OrgChangedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
oldName string `json:"-"`
} }
func (e *OrgChangedEvent) Data() interface{} { func (e *OrgChangedEvent) Data() interface{} {
@ -78,16 +79,20 @@ func (e *OrgChangedEvent) Data() interface{} {
} }
func (e *OrgChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *OrgChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil return []*eventstore.EventUniqueConstraint{
NewRemoveOrgDomainUniqueConstraint(e.oldName),
NewAddOrgNameUniqueConstraint(e.Name),
}
} }
func NewOrgChangedEvent(ctx context.Context, name string) *OrgChangedEvent { func NewOrgChangedEvent(ctx context.Context, oldName, newName string) *OrgChangedEvent {
return &OrgChangedEvent{ return &OrgChangedEvent{
BaseEvent: *eventstore.NewBaseEventForPush( BaseEvent: *eventstore.NewBaseEventForPush(
ctx, ctx,
OrgChangedEventType, OrgChangedEventType,
), ),
Name: name, Name: newName,
oldName: oldName,
} }
} }

View File

@ -9,7 +9,7 @@ import (
) )
const ( const (
uniqueMailText = "mail_text" UniqueMailText = "mail_text"
mailTextPolicyPrefix = mailPolicyPrefix + "text." mailTextPolicyPrefix = mailPolicyPrefix + "text."
MailTextPolicyAddedEventType = mailTextPolicyPrefix + "added" MailTextPolicyAddedEventType = mailTextPolicyPrefix + "added"
MailTextPolicyChangedEventType = mailTextPolicyPrefix + "changed" MailTextPolicyChangedEventType = mailTextPolicyPrefix + "changed"
@ -18,14 +18,14 @@ const (
func NewAddMailTextUniqueConstraint(aggregateID, mailTextType, langugage string) *eventstore.EventUniqueConstraint { func NewAddMailTextUniqueConstraint(aggregateID, mailTextType, langugage string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueMailText, UniqueMailText,
fmt.Sprintf("%v:%v:%v", aggregateID, mailTextType, langugage), fmt.Sprintf("%v:%v:%v", aggregateID, mailTextType, langugage),
"Errors.Org.AlreadyExists") "Errors.Org.AlreadyExists")
} }
func NewRemoveMailTextUniqueConstraint(aggregateID, mailTextType, langugage string) *eventstore.EventUniqueConstraint { func NewRemoveMailTextUniqueConstraint(aggregateID, mailTextType, langugage string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueMailText, UniqueMailText,
fmt.Sprintf("%v:%v:%v", aggregateID, mailTextType, langugage)) fmt.Sprintf("%v:%v:%v", aggregateID, mailTextType, langugage))
} }

View File

@ -11,7 +11,7 @@ import (
) )
const ( const (
uniqueAppNameType = "appname" UniqueAppNameType = "appname"
applicationEventTypePrefix = projectEventTypePrefix + "application." applicationEventTypePrefix = projectEventTypePrefix + "application."
ApplicationAddedType = applicationEventTypePrefix + "added" ApplicationAddedType = applicationEventTypePrefix + "added"
ApplicationChangedType = applicationEventTypePrefix + "changed" ApplicationChangedType = applicationEventTypePrefix + "changed"
@ -22,14 +22,14 @@ const (
func NewAddApplicationUniqueConstraint(name, projectID string) *eventstore.EventUniqueConstraint { func NewAddApplicationUniqueConstraint(name, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueAppNameType, UniqueAppNameType,
fmt.Sprintf("%s:%s", name, projectID), fmt.Sprintf("%s:%s", name, projectID),
"Errors.Project.App.AlreadyExists") "Errors.Project.App.AlreadyExists")
} }
func NewRemoveApplicationUniqueConstraint(name, projectID string) *eventstore.EventUniqueConstraint { func NewRemoveApplicationUniqueConstraint(name, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueAppNameType, UniqueAppNameType,
fmt.Sprintf("%s:%s", name, projectID)) fmt.Sprintf("%s:%s", name, projectID))
} }

View File

@ -18,7 +18,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(RoleRemovedType, RoleRemovedEventMapper). RegisterFilterEventMapper(RoleRemovedType, RoleRemovedEventMapper).
RegisterFilterEventMapper(GrantAddedType, GrantAddedEventMapper). RegisterFilterEventMapper(GrantAddedType, GrantAddedEventMapper).
RegisterFilterEventMapper(GrantChangedType, GrantChangedEventMapper). RegisterFilterEventMapper(GrantChangedType, GrantChangedEventMapper).
RegisterFilterEventMapper(GrantCascadeChangedType, GrantChangedEventMapper). RegisterFilterEventMapper(GrantCascadeChangedType, GrantCascadeChangedEventMapper).
RegisterFilterEventMapper(GrantDeactivatedType, GrantDeactivateEventMapper). RegisterFilterEventMapper(GrantDeactivatedType, GrantDeactivateEventMapper).
RegisterFilterEventMapper(GrantReactivatedType, GrantReactivatedEventMapper). RegisterFilterEventMapper(GrantReactivatedType, GrantReactivatedEventMapper).
RegisterFilterEventMapper(GrantRemovedType, GrantRemovedEventMapper). RegisterFilterEventMapper(GrantRemovedType, GrantRemovedEventMapper).
@ -26,7 +26,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(GrantMemberChangedType, GrantMemberChangedEventMapper). RegisterFilterEventMapper(GrantMemberChangedType, GrantMemberChangedEventMapper).
RegisterFilterEventMapper(GrantMemberRemovedType, GrantMemberRemovedEventMapper). RegisterFilterEventMapper(GrantMemberRemovedType, GrantMemberRemovedEventMapper).
RegisterFilterEventMapper(ApplicationAddedType, ApplicationAddedEventMapper). RegisterFilterEventMapper(ApplicationAddedType, ApplicationAddedEventMapper).
RegisterFilterEventMapper(ApplicationChangedType, ApplicationAddedEventMapper). RegisterFilterEventMapper(ApplicationChangedType, ApplicationChangedEventMapper).
RegisterFilterEventMapper(ApplicationRemovedType, ApplicationRemovedEventMapper). RegisterFilterEventMapper(ApplicationRemovedType, ApplicationRemovedEventMapper).
RegisterFilterEventMapper(ApplicationDeactivatedType, ApplicationDeactivatedEventMapper). RegisterFilterEventMapper(ApplicationDeactivatedType, ApplicationDeactivatedEventMapper).
RegisterFilterEventMapper(ApplicationReactivatedType, ApplicationReactivatedEventMapper). RegisterFilterEventMapper(ApplicationReactivatedType, ApplicationReactivatedEventMapper).

View File

@ -10,7 +10,7 @@ import (
) )
var ( var (
uniqueGrantType = "project_Grant" UniqueGrantType = "project_grant"
grantEventTypePrefix = projectEventTypePrefix + "grant." grantEventTypePrefix = projectEventTypePrefix + "grant."
GrantAddedType = grantEventTypePrefix + "added" GrantAddedType = grantEventTypePrefix + "added"
GrantChangedType = grantEventTypePrefix + "changed" GrantChangedType = grantEventTypePrefix + "changed"
@ -22,14 +22,14 @@ var (
func NewAddProjectGrantUniqueConstraint(grantedOrgID, projectID string) *eventstore.EventUniqueConstraint { func NewAddProjectGrantUniqueConstraint(grantedOrgID, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueRoleType, UniqueRoleType,
fmt.Sprintf("%s:%s", grantedOrgID, projectID), fmt.Sprintf("%s:%s", grantedOrgID, projectID),
"Errors.Project.Grant.AlreadyExists") "Errors.Project.Grant.AlreadyExists")
} }
func NewRemoveProjectGrantUniqueConstraint(grantedOrgID, projectID string) *eventstore.EventUniqueConstraint { func NewRemoveProjectGrantUniqueConstraint(grantedOrgID, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueRoleType, UniqueRoleType,
fmt.Sprintf("%s:%s", grantedOrgID, projectID)) fmt.Sprintf("%s:%s", grantedOrgID, projectID))
} }

View File

@ -11,22 +11,22 @@ import (
) )
var ( var (
uniqueProjectGrantType = "project_grant" UniqueProjectGrantMemberType = "project_grant_member"
GrantMemberAddedType = grantEventTypePrefix + member.AddedEventType GrantMemberAddedType = grantEventTypePrefix + member.AddedEventType
GrantMemberChangedType = grantEventTypePrefix + member.ChangedEventType GrantMemberChangedType = grantEventTypePrefix + member.ChangedEventType
GrantMemberRemovedType = grantEventTypePrefix + member.RemovedEventType GrantMemberRemovedType = grantEventTypePrefix + member.RemovedEventType
) )
func NewAddProjectGrantMemberUniqueConstraint(projectID, userID, grantID string) *eventstore.EventUniqueConstraint { func NewAddProjectGrantMemberUniqueConstraint(projectID, userID, grantID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueProjectGrantType, UniqueProjectGrantMemberType,
fmt.Sprintf("%s:%s:%s", projectID, userID, grantID), fmt.Sprintf("%s:%s:%s", projectID, userID, grantID),
"Errors.Project.Member.AlreadyExists") "Errors.Project.Member.AlreadyExists")
} }
func NewRemoveProjectGrantMemberUniqueConstraint(projectID, userID, grantID string) *eventstore.EventUniqueConstraint { func NewRemoveProjectGrantMemberUniqueConstraint(projectID, userID, grantID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueProjectGrantType, UniqueProjectGrantMemberType,
fmt.Sprintf("%s:%s:%s", projectID, userID, grantID), fmt.Sprintf("%s:%s:%s", projectID, userID, grantID),
) )
} }

View File

@ -19,6 +19,7 @@ type MemberAddedEvent struct {
func NewProjectMemberAddedEvent( func NewProjectMemberAddedEvent(
ctx context.Context, ctx context.Context,
aggregateID,
userID string, userID string,
roles ...string, roles ...string,
) *MemberAddedEvent { ) *MemberAddedEvent {
@ -28,6 +29,7 @@ func NewProjectMemberAddedEvent(
ctx, ctx,
MemberAddedType, MemberAddedType,
), ),
aggregateID,
userID, userID,
roles..., roles...,
), ),
@ -80,6 +82,7 @@ type MemberRemovedEvent struct {
func NewProjectMemberRemovedEvent( func NewProjectMemberRemovedEvent(
ctx context.Context, ctx context.Context,
aggregateID,
userID string, userID string,
) *MemberRemovedEvent { ) *MemberRemovedEvent {
@ -89,6 +92,7 @@ func NewProjectMemberRemovedEvent(
ctx, ctx,
MemberRemovedType, MemberRemovedType,
), ),
aggregateID,
userID, userID,
), ),
} }

View File

@ -10,7 +10,7 @@ import (
) )
const ( const (
uniqueProjectnameType = "project_names" UniqueProjectnameType = "project_names"
projectEventTypePrefix = eventstore.EventType("project.") projectEventTypePrefix = eventstore.EventType("project.")
ProjectAddedType = projectEventTypePrefix + "added" ProjectAddedType = projectEventTypePrefix + "added"
ProjectChangedType = projectEventTypePrefix + "changed" ProjectChangedType = projectEventTypePrefix + "changed"
@ -21,14 +21,14 @@ const (
func NewAddProjectNameUniqueConstraint(projectName, resourceOwner string) *eventstore.EventUniqueConstraint { func NewAddProjectNameUniqueConstraint(projectName, resourceOwner string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueProjectnameType, UniqueProjectnameType,
projectName+resourceOwner, projectName+resourceOwner,
"Errors.Project.AlreadyExists") "Errors.Project.AlreadyExists")
} }
func NewRemoveProjectNameUniqueConstraint(projectName, resourceOwner string) *eventstore.EventUniqueConstraint { func NewRemoveProjectNameUniqueConstraint(projectName, resourceOwner string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueProjectnameType, UniqueProjectnameType,
projectName+resourceOwner) projectName+resourceOwner)
} }
@ -78,6 +78,7 @@ type ProjectChangeEvent struct {
Name *string `json:"name,omitempty"` Name *string `json:"name,omitempty"`
ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"` ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"`
ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"` ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"`
oldName string
} }
func (e *ProjectChangeEvent) Data() interface{} { func (e *ProjectChangeEvent) Data() interface{} {
@ -85,19 +86,27 @@ func (e *ProjectChangeEvent) Data() interface{} {
} }
func (e *ProjectChangeEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *ProjectChangeEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
if e.oldName != "" {
return []*eventstore.EventUniqueConstraint{
NewRemoveProjectNameUniqueConstraint(e.oldName, e.ResourceOwner()),
NewAddProjectNameUniqueConstraint(*e.Name, e.ResourceOwner()),
}
}
return nil return nil
} }
func NewProjectChangeEvent( func NewProjectChangeEvent(
ctx context.Context, ctx context.Context,
resourceOwner, oldName string,
changes []ProjectChanges) (*ProjectChangeEvent, error) { changes []ProjectChanges) (*ProjectChangeEvent, error) {
if len(changes) == 0 { if len(changes) == 0 {
return nil, errors.ThrowPreconditionFailed(nil, "PROJECT-mV9xc", "Errors.NoChangesFound") return nil, errors.ThrowPreconditionFailed(nil, "PROJECT-mV9xc", "Errors.NoChangesFound")
} }
changeEvent := &ProjectChangeEvent{ changeEvent := &ProjectChangeEvent{
BaseEvent: *eventstore.NewBaseEventForPush( BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
ctx, ctx,
ProjectChangedType, ProjectChangedType,
resourceOwner,
), ),
} }
for _, change := range changes { for _, change := range changes {

View File

@ -10,24 +10,24 @@ import (
) )
var ( var (
uniqueRoleType = "project_role" UniqueRoleType = "project_role"
roleEventTypePrefix = projectEventTypePrefix + "role." roleEventTypePrefix = projectEventTypePrefix + "role."
RoleAddedType = roleEventTypePrefix + "added" RoleAddedType = roleEventTypePrefix + "added"
RoleChangedType = roleEventTypePrefix + "changed" RoleChangedType = roleEventTypePrefix + "changed"
RoleRemovedType = roleEventTypePrefix + "removed" RoleRemovedType = roleEventTypePrefix + "removed"
) )
func NewAddProjectRoleUniqueConstraint(roleKey, projectID, resourceOwner string) *eventstore.EventUniqueConstraint { func NewAddProjectRoleUniqueConstraint(roleKey, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueRoleType, UniqueRoleType,
fmt.Sprintf("%s:%s:%s", roleKey, projectID, resourceOwner), fmt.Sprintf("%s:%s", roleKey, projectID),
"Errors.Project.Role.AlreadyExists") "Errors.Project.Role.AlreadyExists")
} }
func NewRemoveProjectRoleUniqueConstraint(roleKey, projectID, resourceOwner string) *eventstore.EventUniqueConstraint { func NewRemoveProjectRoleUniqueConstraint(roleKey, projectID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueRoleType, UniqueRoleType,
fmt.Sprintf("%s:%s:%s", roleKey, projectID, resourceOwner)) fmt.Sprintf("%s:%s", roleKey, projectID))
} }
type RoleAddedEvent struct { type RoleAddedEvent struct {
@ -44,15 +44,14 @@ func (e *RoleAddedEvent) Data() interface{} {
} }
func (e *RoleAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *RoleAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewAddProjectRoleUniqueConstraint(e.Key, e.projectID, e.ResourceOwner())} return []*eventstore.EventUniqueConstraint{NewAddProjectRoleUniqueConstraint(e.Key, e.projectID)}
} }
func NewRoleAddedEvent(ctx context.Context, key, displayName, group, projectID, resourceOwner string) *RoleAddedEvent { func NewRoleAddedEvent(ctx context.Context, key, displayName, group, projectID string) *RoleAddedEvent {
return &RoleAddedEvent{ return &RoleAddedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner( BaseEvent: *eventstore.NewBaseEventForPush(
ctx, ctx,
RoleAddedType, RoleAddedType,
resourceOwner,
), ),
Key: key, Key: key,
DisplayName: displayName, DisplayName: displayName,
@ -144,7 +143,7 @@ type RoleRemovedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
Key string `json:"key,omitempty"` Key string `json:"key,omitempty"`
projectID string projectID string `json:"-"`
} }
func (e *RoleRemovedEvent) Data() interface{} { func (e *RoleRemovedEvent) Data() interface{} {
@ -152,15 +151,14 @@ func (e *RoleRemovedEvent) Data() interface{} {
} }
func (e *RoleRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *RoleRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewRemoveProjectRoleUniqueConstraint(e.Key, e.projectID, e.ResourceOwner())} return []*eventstore.EventUniqueConstraint{NewRemoveProjectRoleUniqueConstraint(e.Key, e.projectID)}
} }
func NewRoleRemovedEvent(ctx context.Context, key, projectID, resourceOwner string) *RoleRemovedEvent { func NewRoleRemovedEvent(ctx context.Context, key, projectID string) *RoleRemovedEvent {
return &RoleRemovedEvent{ return &RoleRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner( BaseEvent: *eventstore.NewBaseEventForPush(
ctx, ctx,
RoleRemovedType, RoleRemovedType,
resourceOwner,
), ),
Key: key, Key: key,
projectID: projectID, projectID: projectID,

View File

@ -43,7 +43,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(UserRemovedType, UserRemovedEventMapper). RegisterFilterEventMapper(UserRemovedType, UserRemovedEventMapper).
RegisterFilterEventMapper(UserTokenAddedType, UserTokenAddedEventMapper). RegisterFilterEventMapper(UserTokenAddedType, UserTokenAddedEventMapper).
RegisterFilterEventMapper(UserDomainClaimedType, DomainClaimedEventMapper). RegisterFilterEventMapper(UserDomainClaimedType, DomainClaimedEventMapper).
RegisterFilterEventMapper(UserDomainClaimedSentType, DomainClaimedEventMapper). RegisterFilterEventMapper(UserDomainClaimedSentType, DomainClaimedSentEventMapper).
RegisterFilterEventMapper(UserUserNameChangedType, UsernameChangedEventMapper). RegisterFilterEventMapper(UserUserNameChangedType, UsernameChangedEventMapper).
RegisterFilterEventMapper(HumanAddedType, HumanAddedEventMapper). RegisterFilterEventMapper(HumanAddedType, HumanAddedEventMapper).
RegisterFilterEventMapper(HumanRegisteredType, HumanRegisteredEventMapper). RegisterFilterEventMapper(HumanRegisteredType, HumanRegisteredEventMapper).

View File

@ -9,7 +9,7 @@ import (
) )
const ( const (
uniqueExternalIDPType = "external_idps" UniqueExternalIDPType = "external_idps"
externalIDPEventPrefix = humanEventPrefix + "externalidp." externalIDPEventPrefix = humanEventPrefix + "externalidp."
externalLoginEventPrefix = humanEventPrefix + "externallogin." externalLoginEventPrefix = humanEventPrefix + "externallogin."
@ -22,23 +22,23 @@ const (
func NewAddExternalIDPUniqueConstraint(idpConfigID, externalUserID string) *eventstore.EventUniqueConstraint { func NewAddExternalIDPUniqueConstraint(idpConfigID, externalUserID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueExternalIDPType, UniqueExternalIDPType,
idpConfigID+externalUserID, idpConfigID+externalUserID,
"Errors.User.ExternalIDP.AlreadyExists") "Errors.User.ExternalIDP.AlreadyExists")
} }
func NewRemoveExternalIDPUniqueConstraint(idpConfigID, externalUserID string) *eventstore.EventUniqueConstraint { func NewRemoveExternalIDPUniqueConstraint(idpConfigID, externalUserID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueExternalIDPType, UniqueExternalIDPType,
idpConfigID+externalUserID) idpConfigID+externalUserID)
} }
type HumanExternalIDPAddedEvent struct { type HumanExternalIDPAddedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
IDPConfigID string `json:"idpConfigId,omitempty"` IDPConfigID string `json:"idpConfigId,omitempty"`
UserID string `json:"userId,omitempty"` ExternalUserID string `json:"userId,omitempty"`
DisplayName string `json:"displayName,omitempty"` DisplayName string `json:"displayName,omitempty"`
} }
func (e *HumanExternalIDPAddedEvent) Data() interface{} { func (e *HumanExternalIDPAddedEvent) Data() interface{} {
@ -46,7 +46,7 @@ func (e *HumanExternalIDPAddedEvent) Data() interface{} {
} }
func (e *HumanExternalIDPAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *HumanExternalIDPAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewAddExternalIDPUniqueConstraint(e.IDPConfigID, e.UserID)} return []*eventstore.EventUniqueConstraint{NewAddExternalIDPUniqueConstraint(e.IDPConfigID, e.ExternalUserID)}
} }
func NewHumanExternalIDPAddedEvent(ctx context.Context, idpConfigID, displayName, externalUserID string) *HumanExternalIDPAddedEvent { func NewHumanExternalIDPAddedEvent(ctx context.Context, idpConfigID, displayName, externalUserID string) *HumanExternalIDPAddedEvent {
@ -55,9 +55,9 @@ func NewHumanExternalIDPAddedEvent(ctx context.Context, idpConfigID, displayName
ctx, ctx,
HumanExternalIDPAddedType, HumanExternalIDPAddedType,
), ),
IDPConfigID: idpConfigID, IDPConfigID: idpConfigID,
DisplayName: displayName, DisplayName: displayName,
UserID: externalUserID, ExternalUserID: externalUserID,
} }
} }
@ -77,8 +77,8 @@ func HumanExternalIDPAddedEventMapper(event *repository.Event) (eventstore.Event
type HumanExternalIDPRemovedEvent struct { type HumanExternalIDPRemovedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
IDPConfigID string `json:"idpConfigId"` IDPConfigID string `json:"idpConfigId"`
UserID string `json:"userId,omitempty"` ExternalUserID string `json:"userId,omitempty"`
} }
func (e *HumanExternalIDPRemovedEvent) Data() interface{} { func (e *HumanExternalIDPRemovedEvent) Data() interface{} {
@ -86,7 +86,7 @@ func (e *HumanExternalIDPRemovedEvent) Data() interface{} {
} }
func (e *HumanExternalIDPRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *HumanExternalIDPRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewRemoveExternalIDPUniqueConstraint(e.IDPConfigID, e.UserID)} return []*eventstore.EventUniqueConstraint{NewRemoveExternalIDPUniqueConstraint(e.IDPConfigID, e.ExternalUserID)}
} }
func NewHumanExternalIDPRemovedEvent(ctx context.Context, idpConfigID, externalUserID string) *HumanExternalIDPRemovedEvent { func NewHumanExternalIDPRemovedEvent(ctx context.Context, idpConfigID, externalUserID string) *HumanExternalIDPRemovedEvent {
@ -95,8 +95,8 @@ func NewHumanExternalIDPRemovedEvent(ctx context.Context, idpConfigID, externalU
ctx, ctx,
HumanExternalIDPRemovedType, HumanExternalIDPRemovedType,
), ),
IDPConfigID: idpConfigID, IDPConfigID: idpConfigID,
UserID: externalUserID, ExternalUserID: externalUserID,
} }
} }
@ -116,8 +116,8 @@ func HumanExternalIDPRemovedEventMapper(event *repository.Event) (eventstore.Eve
type HumanExternalIDPCascadeRemovedEvent struct { type HumanExternalIDPCascadeRemovedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
IDPConfigID string `json:"idpConfigId"` IDPConfigID string `json:"idpConfigId"`
UserID string `json:"userId,omitempty"` ExternalUserID string `json:"userId,omitempty"`
} }
func (e *HumanExternalIDPCascadeRemovedEvent) Data() interface{} { func (e *HumanExternalIDPCascadeRemovedEvent) Data() interface{} {
@ -125,7 +125,7 @@ func (e *HumanExternalIDPCascadeRemovedEvent) Data() interface{} {
} }
func (e *HumanExternalIDPCascadeRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *HumanExternalIDPCascadeRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewRemoveExternalIDPUniqueConstraint(e.IDPConfigID, e.UserID)} return []*eventstore.EventUniqueConstraint{NewRemoveExternalIDPUniqueConstraint(e.IDPConfigID, e.ExternalUserID)}
} }
func NewHumanExternalIDPCascadeRemovedEvent(ctx context.Context, idpConfigID, externalUserID string) *HumanExternalIDPCascadeRemovedEvent { func NewHumanExternalIDPCascadeRemovedEvent(ctx context.Context, idpConfigID, externalUserID string) *HumanExternalIDPCascadeRemovedEvent {
@ -134,8 +134,8 @@ func NewHumanExternalIDPCascadeRemovedEvent(ctx context.Context, idpConfigID, ex
ctx, ctx,
HumanExternalIDPCascadeRemovedType, HumanExternalIDPCascadeRemovedType,
), ),
IDPConfigID: idpConfigID, IDPConfigID: idpConfigID,
UserID: externalUserID, ExternalUserID: externalUserID,
} }
} }

View File

@ -10,7 +10,7 @@ import (
) )
const ( const (
uniqueUsername = "usernames" UniqueUsername = "usernames"
userEventTypePrefix = eventstore.EventType("user.") userEventTypePrefix = eventstore.EventType("user.")
UserLockedType = userEventTypePrefix + "locked" UserLockedType = userEventTypePrefix + "locked"
UserUnlockedType = userEventTypePrefix + "unlocked" UserUnlockedType = userEventTypePrefix + "unlocked"
@ -29,7 +29,7 @@ func NewAddUsernameUniqueConstraint(userName, resourceOwner string, userLoginMus
uniqueUserName = userName + resourceOwner uniqueUserName = userName + resourceOwner
} }
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueUsername, UniqueUsername,
uniqueUserName, uniqueUserName,
"Errors.User.AlreadyExists") "Errors.User.AlreadyExists")
} }
@ -40,7 +40,7 @@ func NewRemoveUsernameUniqueConstraint(userName, resourceOwner string, userLogin
uniqueUserName = userName + resourceOwner uniqueUserName = userName + resourceOwner
} }
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueUsername, UniqueUsername,
uniqueUserName) uniqueUserName)
} }
@ -245,7 +245,9 @@ func UserTokenAddedEventMapper(event *repository.Event) (eventstore.EventReader,
type DomainClaimedEvent struct { type DomainClaimedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"` UserName string `json:"userName"`
oldUserName string `json:"-"`
userLoginMustBeDomain bool `json:"-"`
} }
func (e *DomainClaimedEvent) Data() interface{} { func (e *DomainClaimedEvent) Data() interface{} {
@ -253,19 +255,26 @@ func (e *DomainClaimedEvent) Data() interface{} {
} }
func (e *DomainClaimedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *DomainClaimedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil return []*eventstore.EventUniqueConstraint{
NewRemoveUsernameUniqueConstraint(e.oldUserName, e.ResourceOwner(), e.userLoginMustBeDomain),
NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), e.userLoginMustBeDomain),
}
} }
func NewDomainClaimedEvent( func NewDomainClaimedEvent(
ctx context.Context, ctx context.Context,
userName string, userName,
oldUserName string,
userLoginMustBeDomain bool,
) *DomainClaimedEvent { ) *DomainClaimedEvent {
return &DomainClaimedEvent{ return &DomainClaimedEvent{
BaseEvent: *eventstore.NewBaseEventForPush( BaseEvent: *eventstore.NewBaseEventForPush(
ctx, ctx,
UserDomainClaimedType, UserDomainClaimedType,
), ),
UserName: userName, UserName: userName,
oldUserName: oldUserName,
userLoginMustBeDomain: userLoginMustBeDomain,
} }
} }
@ -314,8 +323,8 @@ type UsernameChangedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
UserName string `json:"userName"` UserName string `json:"userName"`
OldUserName string oldUserName string `json:"-"`
UserLoginMustBeDomain bool userLoginMustBeDomain bool `json:"-"`
} }
func (e *UsernameChangedEvent) Data() interface{} { func (e *UsernameChangedEvent) Data() interface{} {
@ -324,8 +333,8 @@ func (e *UsernameChangedEvent) Data() interface{} {
func (e *UsernameChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *UsernameChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{ return []*eventstore.EventUniqueConstraint{
NewRemoveUsernameUniqueConstraint(e.OldUserName, e.ResourceOwner(), e.UserLoginMustBeDomain), NewRemoveUsernameUniqueConstraint(e.oldUserName, e.ResourceOwner(), e.userLoginMustBeDomain),
NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), e.UserLoginMustBeDomain), NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), e.userLoginMustBeDomain),
} }
} }
@ -341,8 +350,8 @@ func NewUsernameChangedEvent(
UserUserNameChangedType, UserUserNameChangedType,
), ),
UserName: newUserName, UserName: newUserName,
OldUserName: oldUserName, oldUserName: oldUserName,
UserLoginMustBeDomain: userLoginMustBeDomain, userLoginMustBeDomain: userLoginMustBeDomain,
} }
} }

View File

@ -10,7 +10,7 @@ import (
) )
const ( const (
uniqueUserGrant = "user_grant" UniqueUserGrant = "user_grant"
userGrantEventTypePrefix = eventstore.EventType("user.grant.") userGrantEventTypePrefix = eventstore.EventType("user.grant.")
UserGrantAddedType = userGrantEventTypePrefix + "added" UserGrantAddedType = userGrantEventTypePrefix + "added"
UserGrantChangedType = userGrantEventTypePrefix + "changed" UserGrantChangedType = userGrantEventTypePrefix + "changed"
@ -21,17 +21,17 @@ const (
UserGrantReactivatedType = userGrantEventTypePrefix + "reactivated" UserGrantReactivatedType = userGrantEventTypePrefix + "reactivated"
) )
func NewAddUserGrantUniqueConstraint(resourceOwner, userID, projectID string) *eventstore.EventUniqueConstraint { func NewAddUserGrantUniqueConstraint(resourceOwner, userID, projectID, projectGrantID string) *eventstore.EventUniqueConstraint {
return eventstore.NewAddEventUniqueConstraint( return eventstore.NewAddEventUniqueConstraint(
uniqueUserGrant, UniqueUserGrant,
fmt.Sprintf("%s:%s:%s", resourceOwner, userID, projectID), fmt.Sprintf("%s:%s:%s:%v", resourceOwner, userID, projectID, projectGrantID),
"Errors.UserGrant.AlreadyExists") "Errors.UserGrant.AlreadyExists")
} }
func NewRemoveUserGrantUniqueConstraint(resourceOwner, userID, projectID string) *eventstore.EventUniqueConstraint { func NewRemoveUserGrantUniqueConstraint(resourceOwner, userID, projectID, projectGrantID string) *eventstore.EventUniqueConstraint {
return eventstore.NewRemoveEventUniqueConstraint( return eventstore.NewRemoveEventUniqueConstraint(
uniqueUserGrant, UniqueUserGrant,
fmt.Sprintf("%s:%s:%s", resourceOwner, userID, projectID)) fmt.Sprintf("%s:%s:%s:%S", resourceOwner, userID, projectID, projectGrantID))
} }
type UserGrantAddedEvent struct { type UserGrantAddedEvent struct {
@ -48,7 +48,7 @@ func (e *UserGrantAddedEvent) Data() interface{} {
} }
func (e *UserGrantAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *UserGrantAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewAddUserGrantUniqueConstraint(e.ResourceOwner(), e.UserID, e.ProjectID)} return []*eventstore.EventUniqueConstraint{NewAddUserGrantUniqueConstraint(e.ResourceOwner(), e.UserID, e.ProjectID, e.ProjectGrantID)}
} }
func NewUserGrantAddedEvent( func NewUserGrantAddedEvent(
@ -162,8 +162,9 @@ func UserGrantCascadeChangedEventMapper(event *repository.Event) (eventstore.Eve
type UserGrantRemovedEvent struct { type UserGrantRemovedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
userID string userID string `json:"-"`
projectID string projectID string `json:"-"`
projectGrantID string `json:"-"`
} }
func (e *UserGrantRemovedEvent) Data() interface{} { func (e *UserGrantRemovedEvent) Data() interface{} {
@ -171,18 +172,19 @@ func (e *UserGrantRemovedEvent) Data() interface{} {
} }
func (e *UserGrantRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *UserGrantRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewRemoveUserGrantUniqueConstraint(e.ResourceOwner(), e.userID, e.projectID)} return []*eventstore.EventUniqueConstraint{NewRemoveUserGrantUniqueConstraint(e.ResourceOwner(), e.userID, e.projectID, e.projectGrantID)}
} }
func NewUserGrantRemovedEvent(ctx context.Context, resourceOwner, userID, projectID string) *UserGrantRemovedEvent { func NewUserGrantRemovedEvent(ctx context.Context, resourceOwner, userID, projectID, projectGrantID string) *UserGrantRemovedEvent {
return &UserGrantRemovedEvent{ return &UserGrantRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner( BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
ctx, ctx,
UserGrantRemovedType, UserGrantRemovedType,
resourceOwner, resourceOwner,
), ),
userID: userID, userID: userID,
projectID: projectID, projectID: projectID,
projectGrantID: projectGrantID,
} }
} }
@ -194,8 +196,9 @@ func UserGrantRemovedEventMapper(event *repository.Event) (eventstore.EventReade
type UserGrantCascadeRemovedEvent struct { type UserGrantCascadeRemovedEvent struct {
eventstore.BaseEvent `json:"-"` eventstore.BaseEvent `json:"-"`
userID string userID string `json:"-"`
projectID string projectID string `json:"-"`
projectGrantID string `json:"-"`
} }
func (e *UserGrantCascadeRemovedEvent) Data() interface{} { func (e *UserGrantCascadeRemovedEvent) Data() interface{} {
@ -203,18 +206,19 @@ func (e *UserGrantCascadeRemovedEvent) Data() interface{} {
} }
func (e *UserGrantCascadeRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint { func (e *UserGrantCascadeRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return []*eventstore.EventUniqueConstraint{NewRemoveUserGrantUniqueConstraint(e.ResourceOwner(), e.userID, e.projectID)} return []*eventstore.EventUniqueConstraint{NewRemoveUserGrantUniqueConstraint(e.ResourceOwner(), e.userID, e.projectID, e.projectGrantID)}
} }
func NewUserGrantCascadeRemovedEvent(ctx context.Context, resourceOwner, userID, projectID string) *UserGrantCascadeRemovedEvent { func NewUserGrantCascadeRemovedEvent(ctx context.Context, resourceOwner, userID, projectID, projectGrantID string) *UserGrantCascadeRemovedEvent {
return &UserGrantCascadeRemovedEvent{ return &UserGrantCascadeRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner( BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
ctx, ctx,
UserGrantCascadeRemovedType, UserGrantCascadeRemovedType,
resourceOwner, resourceOwner,
), ),
userID: userID, userID: userID,
projectID: projectID, projectID: projectID,
projectGrantID: projectGrantID,
} }
} }