mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 17:17:23 +00:00
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:
parent
3bc3ef1f2c
commit
ee86eb4399
@ -179,3 +179,5 @@ SetUp:
|
||||
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.
|
||||
ButtonText: Login
|
||||
Step11:
|
||||
MigrateV1EventstoreToV2: true
|
||||
|
@ -16,6 +16,7 @@ type IAMSetUp struct {
|
||||
Step8 *command.Step8
|
||||
Step9 *command.Step9
|
||||
Step10 *command.Step10
|
||||
Step11 *command.Step11
|
||||
}
|
||||
|
||||
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.Step9,
|
||||
setup.Step10,
|
||||
setup.Step11,
|
||||
} {
|
||||
if step.Step() <= currentDone {
|
||||
continue
|
||||
|
@ -290,6 +290,8 @@ Errors:
|
||||
NotInactive: Benutzer Berechtigung ist nicht deaktiviert
|
||||
NoPermissionForProject: Benutzer hat keine Rechte auf diesem Projekt
|
||||
RoleKeyNotFound: Rolle konnte nicht gefunden werden
|
||||
Member:
|
||||
AlreadyExists: Member existiert bereits
|
||||
IDPConfig:
|
||||
AlreadyExists: IDP Konfiguration mit diesem Name existiert bereits
|
||||
Changes:
|
||||
|
@ -286,6 +286,8 @@ Errors:
|
||||
NotInactive: User grant is not deactivated
|
||||
NoPermissionForProject: User has no permissions on this project
|
||||
RoleKeyNotFound: Role not found
|
||||
Member:
|
||||
AlreadyExists: Member already exists
|
||||
IDPConfig:
|
||||
AlreadyExists: IDP Configuration with this name already exists
|
||||
Changes:
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
@ -84,13 +84,16 @@ func (wm *IAMIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventRead
|
||||
|
||||
func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
resourceOwner,
|
||||
configID,
|
||||
name string,
|
||||
stylingType domain.IDPConfigStylingType,
|
||||
) (*iam.IDPConfigChangedEvent, bool) {
|
||||
|
||||
changes := make([]idpconfig.IDPConfigChanges, 0)
|
||||
oldName := ""
|
||||
if wm.Name != name {
|
||||
oldName = wm.Name
|
||||
changes = append(changes, idpconfig.ChangeName(name))
|
||||
}
|
||||
if stylingType.Valid() && wm.StylingType != stylingType {
|
||||
@ -99,7 +102,7 @@ func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changeEvent, err := iam.NewIDPConfigChangedEvent(ctx, configID, changes)
|
||||
changeEvent, err := iam.NewIDPConfigChangedEvent(ctx, resourceOwner, configID, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
iamAgg.PushEvents(iam_repo.NewMemberAddedEvent(ctx, member.UserID, member.Roles...))
|
||||
iamAgg.PushEvents(iam_repo.NewMemberAddedEvent(ctx, iamAgg.ID(), member.UserID, member.Roles...))
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -89,7 +89,7 @@ func (r *CommandSide) RemoveIAMMember(ctx context.Context, userID string) error
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -27,14 +27,6 @@ func NewIAMWriteModel() *IAMWriteModel {
|
||||
|
||||
func (wm *IAMWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
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 {
|
||||
@ -61,17 +53,6 @@ func (wm *IAMWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
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 {
|
||||
return &iam.Aggregate{
|
||||
Aggregate: *eventstore.AggregateFromWriteModel(wm, iam.AggregateType, iam.AggregateVersion),
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-4M9vs", "Errors.Org.LabelPolicy.NotChanged")
|
||||
}
|
||||
|
@ -84,13 +84,16 @@ func (wm *OrgIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventRead
|
||||
|
||||
func (wm *OrgIDPConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
resourceOwner,
|
||||
configID,
|
||||
name string,
|
||||
stylingType domain.IDPConfigStylingType,
|
||||
) (*org.IDPConfigChangedEvent, bool) {
|
||||
|
||||
changes := make([]idpconfig.IDPConfigChanges, 0)
|
||||
oldName := ""
|
||||
if wm.Name != name {
|
||||
oldName = wm.Name
|
||||
changes = append(changes, idpconfig.ChangeName(name))
|
||||
}
|
||||
if stylingType.Valid() && wm.StylingType != stylingType {
|
||||
@ -99,7 +102,7 @@ func (wm *OrgIDPConfigWriteModel) NewChangedEvent(
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
changeEvent, err := org.NewIDPConfigChangedEvent(ctx, configID, changes)
|
||||
changeEvent, err := org.NewIDPConfigChangedEvent(ctx, resourceOwner, configID, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
orgAgg.PushEvents(org.NewMemberAddedEvent(ctx, member.UserID, member.Roles...))
|
||||
orgAgg.PushEvents(org.NewMemberAddedEvent(ctx, orgAgg.ID(), member.UserID, member.Roles...))
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -89,7 +89,7 @@ func (r *CommandSide) RemoveOrgMember(ctx context.Context, orgID, userID string)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@ -141,7 +141,7 @@ func (r *CommandSide) ReactivateProject(ctx context.Context, projectID string, r
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingProject.WriteModel)
|
||||
projectAgg.PushEvents(project.NewProjectDeactivatedEvent(ctx))
|
||||
projectAgg.PushEvents(project.NewProjectReactivatedEvent(ctx))
|
||||
|
||||
return r.eventstore.PushAggregate(ctx, existingProject, projectAgg)
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
"github.com/caos/zitadel/internal/v2/repository/usergrant"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
@ -123,7 +122,7 @@ func (r *CommandSide) removeRoleFromProjectGrant(ctx context.Context, projectAgg
|
||||
)
|
||||
} else {
|
||||
projectAgg.PushEvents(
|
||||
usergrant.NewUserGrantCascadeChangedEvent(ctx, existingProjectGrant.RoleKeys),
|
||||
project.NewGrantCascadeChangedEvent(ctx, projectGrantID, existingProjectGrant.RoleKeys),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ func (r *CommandSide) addProjectMember(ctx context.Context, projectAgg *project.
|
||||
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
|
||||
}
|
||||
@ -93,7 +93,7 @@ func (r *CommandSide) RemoveProjectMember(ctx context.Context, projectID, userID
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ func (wm *ProjectWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
|
||||
func (wm *ProjectWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
resourceOwner,
|
||||
name string,
|
||||
projectRoleAssertion,
|
||||
projectRoleCheck bool,
|
||||
@ -79,7 +80,9 @@ func (wm *ProjectWriteModel) NewChangedEvent(
|
||||
changes := make([]project.ProjectChanges, 0)
|
||||
var err error
|
||||
|
||||
oldName := ""
|
||||
if wm.Name != name {
|
||||
oldName = wm.Name
|
||||
changes = append(changes, project.ChangeName(name))
|
||||
}
|
||||
if wm.ProjectRoleAssertion != projectRoleAssertion {
|
||||
@ -91,7 +94,7 @@ func (wm *ProjectWriteModel) NewChangedEvent(
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := project.NewProjectChangeEvent(ctx, changes)
|
||||
changeEvent, err := project.NewProjectChangeEvent(ctx, resourceOwner, oldName, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ func (r *CommandSide) addProjectRoles(ctx context.Context, projectAgg *project.A
|
||||
projectRole.DisplayName,
|
||||
projectRole.Group,
|
||||
projectID,
|
||||
resourceOwner,
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -107,7 +106,7 @@ func (r *CommandSide) RemoveProjectRole(ctx context.Context, projectID, key, res
|
||||
}
|
||||
aggregates := make([]eventstore.Aggregater, 0)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&existingRole.WriteModel)
|
||||
projectAgg.PushEvents(project.NewRoleRemovedEvent(ctx, key, projectID, existingRole.ResourceOwner))
|
||||
projectAgg.PushEvents(project.NewRoleRemovedEvent(ctx, key, projectID))
|
||||
for _, projectGrantID := range cascadingProjectGrantIds {
|
||||
_, err = r.removeRoleFromProjectGrant(ctx, projectAgg, projectID, projectGrantID, key, true)
|
||||
if err != nil {
|
||||
|
35
internal/v2/command/setup_step11.go
Normal file
35
internal/v2/command/setup_step11.go
Normal 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)
|
||||
}
|
255
internal/v2/command/unique_constraints_model.go
Normal file
255
internal/v2/command/unique_constraints_model.go
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -218,11 +218,16 @@ func (r *CommandSide) userDomainClaimed(ctx context.Context, userID string) (_ *
|
||||
changedUserGrant := NewUserWriteModel(userID, existingUser.ResourceOwner)
|
||||
userAgg := UserAggregateFromWriteModel(&changedUserGrant.WriteModel)
|
||||
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, existingUser.ResourceOwner)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
id, err := r.idGenerator.Next()
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -251,11 +251,21 @@ func (r *CommandSide) removeUserGrant(ctx context.Context, grantID, resourceOwne
|
||||
userGrantAgg := UserGrantAggregateFromWriteModel(&removeUserGrant.WriteModel)
|
||||
if !cascade {
|
||||
userGrantAgg.PushEvents(
|
||||
usergrant.NewUserGrantRemovedEvent(ctx, existingUserGrant.ResourceOwner, existingUserGrant.UserID, existingUserGrant.ProjectID),
|
||||
usergrant.NewUserGrantRemovedEvent(
|
||||
ctx,
|
||||
existingUserGrant.ResourceOwner,
|
||||
existingUserGrant.UserID,
|
||||
existingUserGrant.ProjectID,
|
||||
existingUserGrant.ProjectGrantID),
|
||||
)
|
||||
} else {
|
||||
userGrantAgg.PushEvents(
|
||||
usergrant.NewUserGrantCascadeRemovedEvent(ctx, existingUserGrant.ResourceOwner, existingUserGrant.UserID, existingUserGrant.ProjectID),
|
||||
usergrant.NewUserGrantCascadeRemovedEvent(
|
||||
ctx,
|
||||
existingUserGrant.ResourceOwner,
|
||||
existingUserGrant.UserID,
|
||||
existingUserGrant.ProjectID,
|
||||
existingUserGrant.ProjectGrantID),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ func (wm *HumanExternalIDPWriteModel) Reduce() error {
|
||||
case *user.HumanExternalIDPAddedEvent:
|
||||
wm.IDPConfigID = e.IDPConfigID
|
||||
wm.DisplayName = e.DisplayName
|
||||
wm.ExternalUserID = e.UserID
|
||||
wm.ExternalUserID = e.ExternalUserID
|
||||
wm.State = domain.ExternalIDPStateActive
|
||||
case *user.HumanExternalIDPRemovedEvent:
|
||||
wm.State = domain.ExternalIDPStateRemoved
|
||||
|
@ -13,6 +13,7 @@ const (
|
||||
Step8
|
||||
Step9
|
||||
Step10
|
||||
Step11
|
||||
//StepCount marks the the length of possible steps (StepCount-1 == last possible step)
|
||||
StepCount
|
||||
)
|
||||
|
9
internal/v2/domain/unique_constraint_migration.go
Normal file
9
internal/v2/domain/unique_constraint_migration.go
Normal file
@ -0,0 +1,9 @@
|
||||
package domain
|
||||
|
||||
type UniqueConstraintMigration struct {
|
||||
AggregateID string
|
||||
ObjectID string
|
||||
UniqueType string
|
||||
UniqueField string
|
||||
ErrorMessage string
|
||||
}
|
@ -9,6 +9,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(SetupDoneEventType, SetupStepMapper).
|
||||
RegisterFilterEventMapper(GlobalOrgSetEventType, GlobalOrgSetMapper).
|
||||
RegisterFilterEventMapper(ProjectSetEventType, ProjectSetMapper).
|
||||
RegisterFilterEventMapper(UniqueConstraintsMigratedEventType, MigrateUniqueConstraintEventMapper).
|
||||
RegisterFilterEventMapper(LabelPolicyAddedEventType, LabelPolicyAddedEventMapper).
|
||||
RegisterFilterEventMapper(LabelPolicyChangedEventType, LabelPolicyChangedEventMapper).
|
||||
RegisterFilterEventMapper(LoginPolicyAddedEventType, LoginPolicyAddedEventMapper).
|
||||
@ -33,6 +34,10 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(LoginPolicyIDPProviderAddedEventType, IdentityProviderAddedEventMapper).
|
||||
RegisterFilterEventMapper(LoginPolicyIDPProviderRemovedEventType, IdentityProviderRemovedEventMapper).
|
||||
RegisterFilterEventMapper(LoginPolicyIDPProviderCascadeRemovedEventType, IdentityProviderCascadeRemovedEventMapper).
|
||||
RegisterFilterEventMapper(LoginPolicySecondFactorAddedEventType, SecondFactorAddedEventMapper).
|
||||
RegisterFilterEventMapper(LoginPolicySecondFactorRemovedEventType, SecondFactorRemovedEventMapper).
|
||||
RegisterFilterEventMapper(LoginPolicyMultiFactorAddedEventType, MultiFactorAddedEventMapper).
|
||||
RegisterFilterEventMapper(LoginPolicyMultiFactorRemovedEventType, MultiFactorRemovedEventMapper).
|
||||
RegisterFilterEventMapper(MailTemplateAddedEventType, MailTemplateAddedEventMapper).
|
||||
RegisterFilterEventMapper(MailTemplateChangedEventType, MailTemplateChangedEventMapper).
|
||||
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).
|
||||
|
@ -59,12 +59,15 @@ type IDPConfigChangedEvent struct {
|
||||
|
||||
func NewIDPConfigChangedEvent(
|
||||
ctx context.Context,
|
||||
configID string,
|
||||
resourceOwner,
|
||||
configID,
|
||||
oldName string,
|
||||
changes []idpconfig.IDPConfigChanges,
|
||||
) (*IDPConfigChangedEvent, error) {
|
||||
changeEvent, err := idpconfig.NewIDPConfigChangedEvent(
|
||||
eventstore.NewBaseEventForPush(ctx, IDPConfigChangedEventType),
|
||||
eventstore.NewBaseEventForPushWithResourceOwner(ctx, IDPConfigChangedEventType, resourceOwner),
|
||||
configID,
|
||||
oldName,
|
||||
changes,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -19,6 +19,7 @@ type MemberAddedEvent struct {
|
||||
|
||||
func NewMemberAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregateID,
|
||||
userID string,
|
||||
roles ...string,
|
||||
) *MemberAddedEvent {
|
||||
@ -29,6 +30,7 @@ func NewMemberAddedEvent(
|
||||
ctx,
|
||||
MemberAddedEventType,
|
||||
),
|
||||
aggregateID,
|
||||
userID,
|
||||
roles...,
|
||||
),
|
||||
@ -80,6 +82,7 @@ type MemberRemovedEvent struct {
|
||||
|
||||
func NewMemberRemovedEvent(
|
||||
ctx context.Context,
|
||||
aggregateID,
|
||||
userID string,
|
||||
) *MemberRemovedEvent {
|
||||
|
||||
@ -89,6 +92,7 @@ func NewMemberRemovedEvent(
|
||||
ctx,
|
||||
MemberRemovedEventType,
|
||||
),
|
||||
aggregateID,
|
||||
userID,
|
||||
),
|
||||
}
|
||||
|
54
internal/v2/repository/iam/migrate_unique_constraints.go
Normal file
54
internal/v2/repository/iam/migrate_unique_constraints.go
Normal 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
|
||||
}
|
@ -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)
|
||||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -10,19 +10,19 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueIDPConfigNameType = "idp_config_names"
|
||||
UniqueIDPConfigNameType = "idp_config_names"
|
||||
)
|
||||
|
||||
func NewAddIDPConfigNameUniqueConstraint(idpConfigName, resourceOwner string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueIDPConfigNameType,
|
||||
UniqueIDPConfigNameType,
|
||||
idpConfigName+resourceOwner,
|
||||
"Errors.IDPConfig.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveIDPConfigNameUniqueConstraint(idpConfigName, resourceOwner string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueIDPConfigNameType,
|
||||
UniqueIDPConfigNameType,
|
||||
idpConfigName+resourceOwner)
|
||||
}
|
||||
|
||||
@ -78,6 +78,7 @@ type IDPConfigChangedEvent struct {
|
||||
ConfigID string `json:"idpConfigId"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
StylingType *domain.IDPConfigStylingType `json:"stylingType,omitempty"`
|
||||
oldName string `json:"-"`
|
||||
}
|
||||
|
||||
func (e *IDPConfigChangedEvent) Data() interface{} {
|
||||
@ -85,12 +86,19 @@ func (e *IDPConfigChangedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
func (e *IDPConfigChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
if e.oldName == "" {
|
||||
return nil
|
||||
}
|
||||
return []*eventstore.EventUniqueConstraint{
|
||||
NewRemoveIDPConfigNameUniqueConstraint(e.oldName, e.ResourceOwner()),
|
||||
NewAddIDPConfigNameUniqueConstraint(*e.Name, e.ResourceOwner()),
|
||||
}
|
||||
}
|
||||
|
||||
func NewIDPConfigChangedEvent(
|
||||
base *eventstore.BaseEvent,
|
||||
configID string,
|
||||
configID,
|
||||
oldName string,
|
||||
changes []IDPConfigChanges,
|
||||
) (*IDPConfigChangedEvent, error) {
|
||||
if len(changes) == 0 {
|
||||
@ -99,6 +107,7 @@ func NewIDPConfigChangedEvent(
|
||||
changeEvent := &IDPConfigChangedEvent{
|
||||
BaseEvent: *base,
|
||||
ConfigID: configID,
|
||||
oldName: oldName,
|
||||
}
|
||||
for _, change := range changes {
|
||||
change(changeEvent)
|
||||
|
@ -2,22 +2,39 @@ package member
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
UniqueMember = "member"
|
||||
AddedEventType = "member.added"
|
||||
ChangedEventType = "member.changed"
|
||||
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 {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Roles []string `json:"roles"`
|
||||
UserID string `json:"userId"`
|
||||
aggregateID string
|
||||
}
|
||||
|
||||
func (e *MemberAddedEvent) Data() interface{} {
|
||||
@ -25,17 +42,19 @@ func (e *MemberAddedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
func (e *MemberAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
return []*eventstore.EventUniqueConstraint{NewAddMemberUniqueConstraint(e.aggregateID, e.UserID)}
|
||||
}
|
||||
|
||||
func NewMemberAddedEvent(
|
||||
base *eventstore.BaseEvent,
|
||||
aggregateID,
|
||||
userID string,
|
||||
roles ...string,
|
||||
) *MemberAddedEvent {
|
||||
|
||||
return &MemberAddedEvent{
|
||||
BaseEvent: *base,
|
||||
aggregateID: aggregateID,
|
||||
Roles: roles,
|
||||
UserID: userID,
|
||||
}
|
||||
@ -98,6 +117,7 @@ type MemberRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserID string `json:"userId"`
|
||||
aggregateID string
|
||||
}
|
||||
|
||||
func (e *MemberRemovedEvent) Data() interface{} {
|
||||
@ -105,16 +125,18 @@ func (e *MemberRemovedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
func (e *MemberRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
return []*eventstore.EventUniqueConstraint{NewRemoveMemberUniqueConstraint(e.aggregateID, e.UserID)}
|
||||
}
|
||||
|
||||
func NewRemovedEvent(
|
||||
base *eventstore.BaseEvent,
|
||||
aggregateID,
|
||||
userID string,
|
||||
) *MemberRemovedEvent {
|
||||
|
||||
return &MemberRemovedEvent{
|
||||
BaseEvent: *base,
|
||||
aggregateID: aggregateID,
|
||||
UserID: userID,
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueOrgDomain = "org_domain"
|
||||
UniqueOrgDomain = "org_domain"
|
||||
domainEventPrefix = orgEventTypePrefix + "domain."
|
||||
OrgDomainAddedEventType = domainEventPrefix + "added"
|
||||
OrgDomainVerificationAddedEventType = domainEventPrefix + "verification.added"
|
||||
@ -24,14 +24,14 @@ const (
|
||||
|
||||
func NewAddOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueOrgDomain,
|
||||
UniqueOrgDomain,
|
||||
orgDomain,
|
||||
"Errors.Org.Domain.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveOrgDomainUniqueConstraint(orgDomain string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueOrgDomain,
|
||||
UniqueOrgDomain,
|
||||
orgDomain)
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ func (e *DomainVerificationAddedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
func (e *DomainVerificationAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return []*eventstore.EventUniqueConstraint{NewAddOrgDomainUniqueConstraint(e.Domain)}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewDomainVerificationAddedEvent(
|
||||
@ -162,7 +162,7 @@ func (e *DomainVerifiedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
func (e *DomainVerifiedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
return []*eventstore.EventUniqueConstraint{NewAddOrgDomainUniqueConstraint(e.Domain)}
|
||||
}
|
||||
|
||||
func NewDomainVerifiedEvent(ctx context.Context, domain string) *DomainVerifiedEvent {
|
||||
|
@ -49,5 +49,12 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(MailTemplateRemovedEventType, MailTemplateRemovedEventMapper).
|
||||
RegisterFilterEventMapper(MailTextAddedEventType, MailTextAddedEventMapper).
|
||||
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)
|
||||
}
|
||||
|
@ -59,12 +59,15 @@ type IDPConfigChangedEvent struct {
|
||||
|
||||
func NewIDPConfigChangedEvent(
|
||||
ctx context.Context,
|
||||
configID string,
|
||||
resourceOwner,
|
||||
configID,
|
||||
oldName string,
|
||||
changes []idpconfig.IDPConfigChanges,
|
||||
) (*IDPConfigChangedEvent, error) {
|
||||
changeEvent, err := idpconfig.NewIDPConfigChangedEvent(
|
||||
eventstore.NewBaseEventForPush(ctx, IDPConfigChangedEventType),
|
||||
eventstore.NewBaseEventForPushWithResourceOwner(ctx, IDPConfigChangedEventType, resourceOwner),
|
||||
configID,
|
||||
oldName,
|
||||
changes,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -19,6 +19,7 @@ type MemberAddedEvent struct {
|
||||
|
||||
func NewMemberAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregateID,
|
||||
userID string,
|
||||
roles ...string,
|
||||
) *MemberAddedEvent {
|
||||
@ -28,6 +29,7 @@ func NewMemberAddedEvent(
|
||||
ctx,
|
||||
MemberAddedEventType,
|
||||
),
|
||||
aggregateID,
|
||||
userID,
|
||||
roles...,
|
||||
),
|
||||
@ -80,6 +82,7 @@ type MemberRemovedEvent struct {
|
||||
|
||||
func NewMemberRemovedEvent(
|
||||
ctx context.Context,
|
||||
aggregateID,
|
||||
userID string,
|
||||
) *MemberRemovedEvent {
|
||||
|
||||
@ -89,6 +92,7 @@ func NewMemberRemovedEvent(
|
||||
ctx,
|
||||
MemberRemovedEventType,
|
||||
),
|
||||
aggregateID,
|
||||
userID,
|
||||
),
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ type OrgChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
oldName string `json:"-"`
|
||||
}
|
||||
|
||||
func (e *OrgChangedEvent) Data() interface{} {
|
||||
@ -78,16 +79,20 @@ func (e *OrgChangedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
OrgChangedEventType,
|
||||
),
|
||||
Name: name,
|
||||
Name: newName,
|
||||
oldName: oldName,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueMailText = "mail_text"
|
||||
UniqueMailText = "mail_text"
|
||||
mailTextPolicyPrefix = mailPolicyPrefix + "text."
|
||||
MailTextPolicyAddedEventType = mailTextPolicyPrefix + "added"
|
||||
MailTextPolicyChangedEventType = mailTextPolicyPrefix + "changed"
|
||||
@ -18,14 +18,14 @@ const (
|
||||
|
||||
func NewAddMailTextUniqueConstraint(aggregateID, mailTextType, langugage string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueMailText,
|
||||
UniqueMailText,
|
||||
fmt.Sprintf("%v:%v:%v", aggregateID, mailTextType, langugage),
|
||||
"Errors.Org.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveMailTextUniqueConstraint(aggregateID, mailTextType, langugage string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueMailText,
|
||||
UniqueMailText,
|
||||
fmt.Sprintf("%v:%v:%v", aggregateID, mailTextType, langugage))
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueAppNameType = "appname"
|
||||
UniqueAppNameType = "appname"
|
||||
applicationEventTypePrefix = projectEventTypePrefix + "application."
|
||||
ApplicationAddedType = applicationEventTypePrefix + "added"
|
||||
ApplicationChangedType = applicationEventTypePrefix + "changed"
|
||||
@ -22,14 +22,14 @@ const (
|
||||
|
||||
func NewAddApplicationUniqueConstraint(name, projectID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueAppNameType,
|
||||
UniqueAppNameType,
|
||||
fmt.Sprintf("%s:%s", name, projectID),
|
||||
"Errors.Project.App.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveApplicationUniqueConstraint(name, projectID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueAppNameType,
|
||||
UniqueAppNameType,
|
||||
fmt.Sprintf("%s:%s", name, projectID))
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(RoleRemovedType, RoleRemovedEventMapper).
|
||||
RegisterFilterEventMapper(GrantAddedType, GrantAddedEventMapper).
|
||||
RegisterFilterEventMapper(GrantChangedType, GrantChangedEventMapper).
|
||||
RegisterFilterEventMapper(GrantCascadeChangedType, GrantChangedEventMapper).
|
||||
RegisterFilterEventMapper(GrantCascadeChangedType, GrantCascadeChangedEventMapper).
|
||||
RegisterFilterEventMapper(GrantDeactivatedType, GrantDeactivateEventMapper).
|
||||
RegisterFilterEventMapper(GrantReactivatedType, GrantReactivatedEventMapper).
|
||||
RegisterFilterEventMapper(GrantRemovedType, GrantRemovedEventMapper).
|
||||
@ -26,7 +26,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(GrantMemberChangedType, GrantMemberChangedEventMapper).
|
||||
RegisterFilterEventMapper(GrantMemberRemovedType, GrantMemberRemovedEventMapper).
|
||||
RegisterFilterEventMapper(ApplicationAddedType, ApplicationAddedEventMapper).
|
||||
RegisterFilterEventMapper(ApplicationChangedType, ApplicationAddedEventMapper).
|
||||
RegisterFilterEventMapper(ApplicationChangedType, ApplicationChangedEventMapper).
|
||||
RegisterFilterEventMapper(ApplicationRemovedType, ApplicationRemovedEventMapper).
|
||||
RegisterFilterEventMapper(ApplicationDeactivatedType, ApplicationDeactivatedEventMapper).
|
||||
RegisterFilterEventMapper(ApplicationReactivatedType, ApplicationReactivatedEventMapper).
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
uniqueGrantType = "project_Grant"
|
||||
UniqueGrantType = "project_grant"
|
||||
grantEventTypePrefix = projectEventTypePrefix + "grant."
|
||||
GrantAddedType = grantEventTypePrefix + "added"
|
||||
GrantChangedType = grantEventTypePrefix + "changed"
|
||||
@ -22,14 +22,14 @@ var (
|
||||
|
||||
func NewAddProjectGrantUniqueConstraint(grantedOrgID, projectID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueRoleType,
|
||||
UniqueRoleType,
|
||||
fmt.Sprintf("%s:%s", grantedOrgID, projectID),
|
||||
"Errors.Project.Grant.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveProjectGrantUniqueConstraint(grantedOrgID, projectID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueRoleType,
|
||||
UniqueRoleType,
|
||||
fmt.Sprintf("%s:%s", grantedOrgID, projectID))
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
uniqueProjectGrantType = "project_grant"
|
||||
UniqueProjectGrantMemberType = "project_grant_member"
|
||||
GrantMemberAddedType = grantEventTypePrefix + member.AddedEventType
|
||||
GrantMemberChangedType = grantEventTypePrefix + member.ChangedEventType
|
||||
GrantMemberRemovedType = grantEventTypePrefix + member.RemovedEventType
|
||||
@ -19,14 +19,14 @@ var (
|
||||
|
||||
func NewAddProjectGrantMemberUniqueConstraint(projectID, userID, grantID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueProjectGrantType,
|
||||
UniqueProjectGrantMemberType,
|
||||
fmt.Sprintf("%s:%s:%s", projectID, userID, grantID),
|
||||
"Errors.Project.Member.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveProjectGrantMemberUniqueConstraint(projectID, userID, grantID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueProjectGrantType,
|
||||
UniqueProjectGrantMemberType,
|
||||
fmt.Sprintf("%s:%s:%s", projectID, userID, grantID),
|
||||
)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ type MemberAddedEvent struct {
|
||||
|
||||
func NewProjectMemberAddedEvent(
|
||||
ctx context.Context,
|
||||
aggregateID,
|
||||
userID string,
|
||||
roles ...string,
|
||||
) *MemberAddedEvent {
|
||||
@ -28,6 +29,7 @@ func NewProjectMemberAddedEvent(
|
||||
ctx,
|
||||
MemberAddedType,
|
||||
),
|
||||
aggregateID,
|
||||
userID,
|
||||
roles...,
|
||||
),
|
||||
@ -80,6 +82,7 @@ type MemberRemovedEvent struct {
|
||||
|
||||
func NewProjectMemberRemovedEvent(
|
||||
ctx context.Context,
|
||||
aggregateID,
|
||||
userID string,
|
||||
) *MemberRemovedEvent {
|
||||
|
||||
@ -89,6 +92,7 @@ func NewProjectMemberRemovedEvent(
|
||||
ctx,
|
||||
MemberRemovedType,
|
||||
),
|
||||
aggregateID,
|
||||
userID,
|
||||
),
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueProjectnameType = "project_names"
|
||||
UniqueProjectnameType = "project_names"
|
||||
projectEventTypePrefix = eventstore.EventType("project.")
|
||||
ProjectAddedType = projectEventTypePrefix + "added"
|
||||
ProjectChangedType = projectEventTypePrefix + "changed"
|
||||
@ -21,14 +21,14 @@ const (
|
||||
|
||||
func NewAddProjectNameUniqueConstraint(projectName, resourceOwner string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueProjectnameType,
|
||||
UniqueProjectnameType,
|
||||
projectName+resourceOwner,
|
||||
"Errors.Project.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveProjectNameUniqueConstraint(projectName, resourceOwner string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueProjectnameType,
|
||||
UniqueProjectnameType,
|
||||
projectName+resourceOwner)
|
||||
}
|
||||
|
||||
@ -78,6 +78,7 @@ type ProjectChangeEvent struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
ProjectRoleAssertion *bool `json:"projectRoleAssertion,omitempty"`
|
||||
ProjectRoleCheck *bool `json:"projectRoleCheck,omitempty"`
|
||||
oldName string
|
||||
}
|
||||
|
||||
func (e *ProjectChangeEvent) Data() interface{} {
|
||||
@ -85,19 +86,27 @@ func (e *ProjectChangeEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
func (e *ProjectChangeEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
if e.oldName != "" {
|
||||
return []*eventstore.EventUniqueConstraint{
|
||||
NewRemoveProjectNameUniqueConstraint(e.oldName, e.ResourceOwner()),
|
||||
NewAddProjectNameUniqueConstraint(*e.Name, e.ResourceOwner()),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewProjectChangeEvent(
|
||||
ctx context.Context,
|
||||
resourceOwner, oldName string,
|
||||
changes []ProjectChanges) (*ProjectChangeEvent, error) {
|
||||
if len(changes) == 0 {
|
||||
return nil, errors.ThrowPreconditionFailed(nil, "PROJECT-mV9xc", "Errors.NoChangesFound")
|
||||
}
|
||||
changeEvent := &ProjectChangeEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
|
||||
ctx,
|
||||
ProjectChangedType,
|
||||
resourceOwner,
|
||||
),
|
||||
}
|
||||
for _, change := range changes {
|
||||
|
@ -10,24 +10,24 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
uniqueRoleType = "project_role"
|
||||
UniqueRoleType = "project_role"
|
||||
roleEventTypePrefix = projectEventTypePrefix + "role."
|
||||
RoleAddedType = roleEventTypePrefix + "added"
|
||||
RoleChangedType = roleEventTypePrefix + "changed"
|
||||
RoleRemovedType = roleEventTypePrefix + "removed"
|
||||
)
|
||||
|
||||
func NewAddProjectRoleUniqueConstraint(roleKey, projectID, resourceOwner string) *eventstore.EventUniqueConstraint {
|
||||
func NewAddProjectRoleUniqueConstraint(roleKey, projectID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueRoleType,
|
||||
fmt.Sprintf("%s:%s:%s", roleKey, projectID, resourceOwner),
|
||||
UniqueRoleType,
|
||||
fmt.Sprintf("%s:%s", roleKey, projectID),
|
||||
"Errors.Project.Role.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveProjectRoleUniqueConstraint(roleKey, projectID, resourceOwner string) *eventstore.EventUniqueConstraint {
|
||||
func NewRemoveProjectRoleUniqueConstraint(roleKey, projectID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueRoleType,
|
||||
fmt.Sprintf("%s:%s:%s", roleKey, projectID, resourceOwner))
|
||||
UniqueRoleType,
|
||||
fmt.Sprintf("%s:%s", roleKey, projectID))
|
||||
}
|
||||
|
||||
type RoleAddedEvent struct {
|
||||
@ -44,15 +44,14 @@ func (e *RoleAddedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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{
|
||||
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
RoleAddedType,
|
||||
resourceOwner,
|
||||
),
|
||||
Key: key,
|
||||
DisplayName: displayName,
|
||||
@ -144,7 +143,7 @@ type RoleRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Key string `json:"key,omitempty"`
|
||||
projectID string
|
||||
projectID string `json:"-"`
|
||||
}
|
||||
|
||||
func (e *RoleRemovedEvent) Data() interface{} {
|
||||
@ -152,15 +151,14 @@ func (e *RoleRemovedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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{
|
||||
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
RoleRemovedType,
|
||||
resourceOwner,
|
||||
),
|
||||
Key: key,
|
||||
projectID: projectID,
|
||||
|
@ -43,7 +43,7 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
RegisterFilterEventMapper(UserRemovedType, UserRemovedEventMapper).
|
||||
RegisterFilterEventMapper(UserTokenAddedType, UserTokenAddedEventMapper).
|
||||
RegisterFilterEventMapper(UserDomainClaimedType, DomainClaimedEventMapper).
|
||||
RegisterFilterEventMapper(UserDomainClaimedSentType, DomainClaimedEventMapper).
|
||||
RegisterFilterEventMapper(UserDomainClaimedSentType, DomainClaimedSentEventMapper).
|
||||
RegisterFilterEventMapper(UserUserNameChangedType, UsernameChangedEventMapper).
|
||||
RegisterFilterEventMapper(HumanAddedType, HumanAddedEventMapper).
|
||||
RegisterFilterEventMapper(HumanRegisteredType, HumanRegisteredEventMapper).
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueExternalIDPType = "external_idps"
|
||||
UniqueExternalIDPType = "external_idps"
|
||||
externalIDPEventPrefix = humanEventPrefix + "externalidp."
|
||||
externalLoginEventPrefix = humanEventPrefix + "externallogin."
|
||||
|
||||
@ -22,14 +22,14 @@ const (
|
||||
|
||||
func NewAddExternalIDPUniqueConstraint(idpConfigID, externalUserID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueExternalIDPType,
|
||||
UniqueExternalIDPType,
|
||||
idpConfigID+externalUserID,
|
||||
"Errors.User.ExternalIDP.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveExternalIDPUniqueConstraint(idpConfigID, externalUserID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueExternalIDPType,
|
||||
UniqueExternalIDPType,
|
||||
idpConfigID+externalUserID)
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ type HumanExternalIDPAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
IDPConfigID string `json:"idpConfigId,omitempty"`
|
||||
UserID string `json:"userId,omitempty"`
|
||||
ExternalUserID string `json:"userId,omitempty"`
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ func (e *HumanExternalIDPAddedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -57,7 +57,7 @@ func NewHumanExternalIDPAddedEvent(ctx context.Context, idpConfigID, displayName
|
||||
),
|
||||
IDPConfigID: idpConfigID,
|
||||
DisplayName: displayName,
|
||||
UserID: externalUserID,
|
||||
ExternalUserID: externalUserID,
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ type HumanExternalIDPRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
IDPConfigID string `json:"idpConfigId"`
|
||||
UserID string `json:"userId,omitempty"`
|
||||
ExternalUserID string `json:"userId,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanExternalIDPRemovedEvent) Data() interface{} {
|
||||
@ -86,7 +86,7 @@ func (e *HumanExternalIDPRemovedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -96,7 +96,7 @@ func NewHumanExternalIDPRemovedEvent(ctx context.Context, idpConfigID, externalU
|
||||
HumanExternalIDPRemovedType,
|
||||
),
|
||||
IDPConfigID: idpConfigID,
|
||||
UserID: externalUserID,
|
||||
ExternalUserID: externalUserID,
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ type HumanExternalIDPCascadeRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
IDPConfigID string `json:"idpConfigId"`
|
||||
UserID string `json:"userId,omitempty"`
|
||||
ExternalUserID string `json:"userId,omitempty"`
|
||||
}
|
||||
|
||||
func (e *HumanExternalIDPCascadeRemovedEvent) Data() interface{} {
|
||||
@ -125,7 +125,7 @@ func (e *HumanExternalIDPCascadeRemovedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -135,7 +135,7 @@ func NewHumanExternalIDPCascadeRemovedEvent(ctx context.Context, idpConfigID, ex
|
||||
HumanExternalIDPCascadeRemovedType,
|
||||
),
|
||||
IDPConfigID: idpConfigID,
|
||||
UserID: externalUserID,
|
||||
ExternalUserID: externalUserID,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueUsername = "usernames"
|
||||
UniqueUsername = "usernames"
|
||||
userEventTypePrefix = eventstore.EventType("user.")
|
||||
UserLockedType = userEventTypePrefix + "locked"
|
||||
UserUnlockedType = userEventTypePrefix + "unlocked"
|
||||
@ -29,7 +29,7 @@ func NewAddUsernameUniqueConstraint(userName, resourceOwner string, userLoginMus
|
||||
uniqueUserName = userName + resourceOwner
|
||||
}
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueUsername,
|
||||
UniqueUsername,
|
||||
uniqueUserName,
|
||||
"Errors.User.AlreadyExists")
|
||||
}
|
||||
@ -40,7 +40,7 @@ func NewRemoveUsernameUniqueConstraint(userName, resourceOwner string, userLogin
|
||||
uniqueUserName = userName + resourceOwner
|
||||
}
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueUsername,
|
||||
UniqueUsername,
|
||||
uniqueUserName)
|
||||
}
|
||||
|
||||
@ -246,6 +246,8 @@ type DomainClaimedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
oldUserName string `json:"-"`
|
||||
userLoginMustBeDomain bool `json:"-"`
|
||||
}
|
||||
|
||||
func (e *DomainClaimedEvent) Data() interface{} {
|
||||
@ -253,12 +255,17 @@ func (e *DomainClaimedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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(
|
||||
ctx context.Context,
|
||||
userName string,
|
||||
userName,
|
||||
oldUserName string,
|
||||
userLoginMustBeDomain bool,
|
||||
) *DomainClaimedEvent {
|
||||
return &DomainClaimedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
@ -266,6 +273,8 @@ func NewDomainClaimedEvent(
|
||||
UserDomainClaimedType,
|
||||
),
|
||||
UserName: userName,
|
||||
oldUserName: oldUserName,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,8 +323,8 @@ type UsernameChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
UserName string `json:"userName"`
|
||||
OldUserName string
|
||||
UserLoginMustBeDomain bool
|
||||
oldUserName string `json:"-"`
|
||||
userLoginMustBeDomain bool `json:"-"`
|
||||
}
|
||||
|
||||
func (e *UsernameChangedEvent) Data() interface{} {
|
||||
@ -324,8 +333,8 @@ func (e *UsernameChangedEvent) Data() interface{} {
|
||||
|
||||
func (e *UsernameChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return []*eventstore.EventUniqueConstraint{
|
||||
NewRemoveUsernameUniqueConstraint(e.OldUserName, e.ResourceOwner(), e.UserLoginMustBeDomain),
|
||||
NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), e.UserLoginMustBeDomain),
|
||||
NewRemoveUsernameUniqueConstraint(e.oldUserName, e.ResourceOwner(), e.userLoginMustBeDomain),
|
||||
NewAddUsernameUniqueConstraint(e.UserName, e.ResourceOwner(), e.userLoginMustBeDomain),
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,8 +350,8 @@ func NewUsernameChangedEvent(
|
||||
UserUserNameChangedType,
|
||||
),
|
||||
UserName: newUserName,
|
||||
OldUserName: oldUserName,
|
||||
UserLoginMustBeDomain: userLoginMustBeDomain,
|
||||
oldUserName: oldUserName,
|
||||
userLoginMustBeDomain: userLoginMustBeDomain,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
uniqueUserGrant = "user_grant"
|
||||
UniqueUserGrant = "user_grant"
|
||||
userGrantEventTypePrefix = eventstore.EventType("user.grant.")
|
||||
UserGrantAddedType = userGrantEventTypePrefix + "added"
|
||||
UserGrantChangedType = userGrantEventTypePrefix + "changed"
|
||||
@ -21,17 +21,17 @@ const (
|
||||
UserGrantReactivatedType = userGrantEventTypePrefix + "reactivated"
|
||||
)
|
||||
|
||||
func NewAddUserGrantUniqueConstraint(resourceOwner, userID, projectID string) *eventstore.EventUniqueConstraint {
|
||||
func NewAddUserGrantUniqueConstraint(resourceOwner, userID, projectID, projectGrantID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewAddEventUniqueConstraint(
|
||||
uniqueUserGrant,
|
||||
fmt.Sprintf("%s:%s:%s", resourceOwner, userID, projectID),
|
||||
UniqueUserGrant,
|
||||
fmt.Sprintf("%s:%s:%s:%v", resourceOwner, userID, projectID, projectGrantID),
|
||||
"Errors.UserGrant.AlreadyExists")
|
||||
}
|
||||
|
||||
func NewRemoveUserGrantUniqueConstraint(resourceOwner, userID, projectID string) *eventstore.EventUniqueConstraint {
|
||||
func NewRemoveUserGrantUniqueConstraint(resourceOwner, userID, projectID, projectGrantID string) *eventstore.EventUniqueConstraint {
|
||||
return eventstore.NewRemoveEventUniqueConstraint(
|
||||
uniqueUserGrant,
|
||||
fmt.Sprintf("%s:%s:%s", resourceOwner, userID, projectID))
|
||||
UniqueUserGrant,
|
||||
fmt.Sprintf("%s:%s:%s:%S", resourceOwner, userID, projectID, projectGrantID))
|
||||
}
|
||||
|
||||
type UserGrantAddedEvent struct {
|
||||
@ -48,7 +48,7 @@ func (e *UserGrantAddedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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(
|
||||
@ -162,8 +162,9 @@ func UserGrantCascadeChangedEventMapper(event *repository.Event) (eventstore.Eve
|
||||
|
||||
type UserGrantRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
userID string
|
||||
projectID string
|
||||
userID string `json:"-"`
|
||||
projectID string `json:"-"`
|
||||
projectGrantID string `json:"-"`
|
||||
}
|
||||
|
||||
func (e *UserGrantRemovedEvent) Data() interface{} {
|
||||
@ -171,10 +172,10 @@ func (e *UserGrantRemovedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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{
|
||||
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
|
||||
ctx,
|
||||
@ -183,6 +184,7 @@ func NewUserGrantRemovedEvent(ctx context.Context, resourceOwner, userID, projec
|
||||
),
|
||||
userID: userID,
|
||||
projectID: projectID,
|
||||
projectGrantID: projectGrantID,
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,8 +196,9 @@ func UserGrantRemovedEventMapper(event *repository.Event) (eventstore.EventReade
|
||||
|
||||
type UserGrantCascadeRemovedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
userID string
|
||||
projectID string
|
||||
userID string `json:"-"`
|
||||
projectID string `json:"-"`
|
||||
projectGrantID string `json:"-"`
|
||||
}
|
||||
|
||||
func (e *UserGrantCascadeRemovedEvent) Data() interface{} {
|
||||
@ -203,10 +206,10 @@ func (e *UserGrantCascadeRemovedEvent) Data() interface{} {
|
||||
}
|
||||
|
||||
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{
|
||||
BaseEvent: *eventstore.NewBaseEventForPushWithResourceOwner(
|
||||
ctx,
|
||||
@ -215,6 +218,7 @@ func NewUserGrantCascadeRemovedEvent(ctx context.Context, resourceOwner, userID,
|
||||
),
|
||||
userID: userID,
|
||||
projectID: projectID,
|
||||
projectGrantID: projectGrantID,
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user