mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-09 23:55:12 +00:00
feat: uniqueness (#1190)
* feat: uniqueness on events * fix: some tests * fix: add unique username * fix: nice error message * fix: add unique test * fix: add unique test * fix: add unique constraint to events * fix: correct unique constraint on user events * fix: remove user constraint * fix: add unique constraints * fix: add unique constraints * fix: add unique constraints * fix: unnique constraints without interface * fix: unique idp config * fix: unique constraint comments * fix: unique constraints in one table * fix: unique constraints error * fix: fix unique constraint on create user * fix: fix unique constraint on create project * fix: fix unique constraint on idp configs
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
)
|
||||
|
||||
@@ -110,27 +109,17 @@ func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, idpID stri
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, idpID string) error {
|
||||
_, err := r.pushDefaultIDPWriteModel(ctx, idpID, func(a *iam.Aggregate, _ *IAMIDPConfigWriteModel) *iam.Aggregate {
|
||||
a.Aggregate = *a.PushEvents(iam_repo.NewIDPConfigRemovedEvent(ctx, idpID))
|
||||
return a
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) pushDefaultIDPWriteModel(ctx context.Context, idpID string, eventSetter func(*iam.Aggregate, *IAMIDPConfigWriteModel) *iam.Aggregate) (*IAMIDPConfigWriteModel, error) {
|
||||
writeModel := NewIAMIDPConfigWriteModel(idpID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, idpID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
aggregate := eventSetter(IAMAggregateFromWriteModel(&writeModel.WriteModel), writeModel)
|
||||
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
||||
return caos_errs.ThrowNotFound(nil, "IAM-4M0xy", "Errors.IAM.IDPConfig.NotExisting")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
iamAgg.PushEvents(iam_repo.NewIDPConfigRemovedEvent(ctx, existingIDP.ResourceOwner, idpID, existingIDP.Name))
|
||||
|
||||
return writeModel, nil
|
||||
return r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
|
||||
}
|
||||
|
||||
func (r *CommandSide) iamIDPConfigWriteModelByID(ctx context.Context, idpID string) (policy *IAMIDPConfigWriteModel, err error) {
|
||||
|
||||
@@ -122,7 +122,6 @@ func (r *CommandSide) addOrg(ctx context.Context, organisation *domain.Org) (_ *
|
||||
addedOrg := NewOrgWriteModel(organisation.AggregateID)
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedOrg.WriteModel)
|
||||
//TODO: uniqueness org name
|
||||
orgAgg.PushEvents(org.NewOrgAddedEvent(ctx, organisation.Name))
|
||||
for _, orgDomain := range organisation.Domains {
|
||||
if err := r.addOrgDomain(ctx, orgAgg, NewOrgDomainWriteModel(orgAgg.ID(), orgDomain.Domain), orgDomain); err != nil {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
org_repo "github.com/caos/zitadel/internal/v2/repository/org"
|
||||
)
|
||||
|
||||
@@ -34,6 +33,7 @@ func (r *CommandSide) AddIDPConfig(ctx context.Context, config *domain.IDPConfig
|
||||
orgAgg.PushEvents(
|
||||
org_repo.NewIDPConfigAddedEvent(
|
||||
ctx,
|
||||
orgAgg.ResourceOwner(),
|
||||
idpConfigID,
|
||||
config.Name,
|
||||
config.Type,
|
||||
@@ -110,27 +110,21 @@ func (r *CommandSide) ReactivateIDPConfig(ctx context.Context, idpID, orgID stri
|
||||
}
|
||||
|
||||
func (r *CommandSide) RemoveIDPConfig(ctx context.Context, idpID, orgID string) error {
|
||||
_, err := r.pushIDPWriteModel(ctx, idpID, orgID, func(a *org.Aggregate, _ *OrgIDPConfigWriteModel) *org.Aggregate {
|
||||
a.Aggregate = *a.PushEvents(org_repo.NewIDPConfigRemovedEvent(ctx, idpID))
|
||||
return a
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *CommandSide) pushIDPWriteModel(ctx context.Context, idpID, orgID string, eventSetter func(*org.Aggregate, *OrgIDPConfigWriteModel) *org.Aggregate) (*OrgIDPConfigWriteModel, error) {
|
||||
writeModel := NewOrgIDPConfigWriteModel(idpID, orgID)
|
||||
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
existingIDP, err := r.orgIDPConfigWriteModelByID(ctx, idpID, orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
aggregate := eventSetter(OrgAggregateFromWriteModel(&writeModel.WriteModel), writeModel)
|
||||
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
||||
return caos_errs.ThrowNotFound(nil, "Org-Yx9vd", "Errors.Org.IDPConfig.NotExisting")
|
||||
}
|
||||
if existingIDP.State != domain.IDPConfigStateInactive {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "Org-5Mo0d", "Errors.Org.IDPConfig.NotInactive")
|
||||
}
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||
orgAgg.PushEvents(org_repo.NewIDPConfigRemovedEvent(ctx, existingIDP.ResourceOwner, idpID, existingIDP.Name))
|
||||
|
||||
return writeModel, nil
|
||||
return r.eventstore.PushAggregate(ctx, existingIDP, orgAgg)
|
||||
}
|
||||
|
||||
func (r *CommandSide) orgIDPConfigWriteModelByID(ctx context.Context, idpID, orgID string) (policy *OrgIDPConfigWriteModel, err error) {
|
||||
|
||||
@@ -29,7 +29,6 @@ func (r *CommandSide) addProject(ctx context.Context, projectAdd *domain.Project
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// TODO: Add uniqueness check
|
||||
addedProject := NewProjectWriteModel(projectAdd.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedProject.WriteModel)
|
||||
|
||||
@@ -38,7 +37,7 @@ func (r *CommandSide) addProject(ctx context.Context, projectAdd *domain.Project
|
||||
// projectRole = domain.RoleProjectOwnerGlobal
|
||||
//}
|
||||
projectAgg.PushEvents(
|
||||
project.NewProjectAddedEvent(ctx, projectAdd.Name),
|
||||
project.NewProjectAddedEvent(ctx, projectAdd.Name, resourceOwner),
|
||||
project.NewMemberAddedEvent(ctx, ownerUserID, projectRole),
|
||||
)
|
||||
return projectAgg, addedProject, nil
|
||||
|
||||
@@ -88,7 +88,7 @@ func (r *CommandSide) setup(ctx context.Context, step Step, iamAggregateProvider
|
||||
|
||||
_, err = r.eventstore.PushAggregates(ctx, iamAgg)
|
||||
if err != nil {
|
||||
return caos_errs.ThrowPreconditionFailedf(nil, "EVENT-dbG31", "Setup %s failed", step.Step())
|
||||
return caos_errs.ThrowPreconditionFailedf(nil, "EVENT-dbG31", "Setup %v failed", step.Step())
|
||||
}
|
||||
logging.LogWithFields("SETUP-Sg1t1", "step", step.Step()).Info("setup step done")
|
||||
return nil
|
||||
|
||||
@@ -32,9 +32,7 @@ func (r *CommandSide) ChangeUsername(ctx context.Context, orgID, userID, userNam
|
||||
return err
|
||||
}
|
||||
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
|
||||
userAgg.PushEvents(user.NewUsernameChangedEvent(ctx, userName))
|
||||
//TODO: Check Uniqueness
|
||||
//TODO: release old username, set new unique username
|
||||
userAgg.PushEvents(user.NewUsernameChangedEvent(ctx, existingUser.UserName, userName, orgIAMPolicy.UserLoginMustBeDomain))
|
||||
|
||||
return r.eventstore.PushAggregate(ctx, existingUser, userAgg)
|
||||
}
|
||||
@@ -130,9 +128,12 @@ func (r *CommandSide) RemoveUser(ctx context.Context, userID, resourceOwner stri
|
||||
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
|
||||
return caos_errs.ThrowNotFound(nil, "COMMAND-5M0od", "Errors.User.NotFound")
|
||||
}
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, existingUser.ResourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
|
||||
userAgg.PushEvents(user.NewUserRemovedEvent(ctx))
|
||||
//TODO: release unqie username
|
||||
userAgg.PushEvents(user.NewUserRemovedEvent(ctx, existingUser.ResourceOwner, existingUser.UserName, orgIAMPolicy.UserLoginMustBeDomain))
|
||||
//TODO: remove user grants
|
||||
|
||||
return r.eventstore.PushAggregate(ctx, existingUser, userAgg)
|
||||
|
||||
@@ -27,6 +27,9 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID string, human *domain.
|
||||
}
|
||||
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
||||
if err != nil {
|
||||
if caos_errs.IsErrorAlreadyExists(err) {
|
||||
return nil, caos_errs.ThrowAlreadyExists(err, "COMMAND-4kSff", "Errors.User.AlreadyExists")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -47,6 +50,9 @@ func (r *CommandSide) RegisterHuman(ctx context.Context, orgID string, human *do
|
||||
}
|
||||
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
||||
if err != nil {
|
||||
if caos_errs.IsErrorAlreadyExists(err) {
|
||||
return nil, caos_errs.ThrowAlreadyExists(err, "COMMAND-4kSff", "Errors.User.AlreadyExists")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -76,7 +82,6 @@ func (r *CommandSide) createHuman(ctx context.Context, orgID string, human *doma
|
||||
}
|
||||
|
||||
addedHuman := NewHumanWriteModel(human.AggregateID, orgID)
|
||||
//TODO: Check Unique Username or unique external idp
|
||||
if err := human.CheckOrgIAMPolicy(human.Username, orgIAMPolicy); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -88,9 +93,9 @@ func (r *CommandSide) createHuman(ctx context.Context, orgID string, human *doma
|
||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||
var createEvent eventstore.EventPusher
|
||||
if selfregister {
|
||||
createEvent = createRegisterHumanEvent(ctx, human.Username, human)
|
||||
createEvent = createRegisterHumanEvent(ctx, orgID, human, orgIAMPolicy.UserLoginMustBeDomain)
|
||||
} else {
|
||||
createEvent = createAddHumanEvent(ctx, human.Username, human)
|
||||
createEvent = createAddHumanEvent(ctx, orgID, human, orgIAMPolicy.UserLoginMustBeDomain)
|
||||
}
|
||||
userAgg.PushEvents(createEvent)
|
||||
|
||||
@@ -152,10 +157,11 @@ func (r *CommandSide) ResendInitialMail(ctx context.Context, userID, email, reso
|
||||
return r.eventstore.PushAggregate(ctx, existingEmail, userAgg)
|
||||
}
|
||||
|
||||
func createAddHumanEvent(ctx context.Context, username string, human *domain.Human) *user.HumanAddedEvent {
|
||||
func createAddHumanEvent(ctx context.Context, orgID string, human *domain.Human, userLoginMustBeDomain bool) *user.HumanAddedEvent {
|
||||
addEvent := user.NewHumanAddedEvent(
|
||||
ctx,
|
||||
username,
|
||||
orgID,
|
||||
human.Username,
|
||||
human.FirstName,
|
||||
human.LastName,
|
||||
human.NickName,
|
||||
@@ -163,6 +169,7 @@ func createAddHumanEvent(ctx context.Context, username string, human *domain.Hum
|
||||
human.PreferredLanguage,
|
||||
human.Gender,
|
||||
human.EmailAddress,
|
||||
userLoginMustBeDomain,
|
||||
)
|
||||
if human.Phone != nil {
|
||||
addEvent.AddPhoneData(human.PhoneNumber)
|
||||
@@ -181,10 +188,11 @@ func createAddHumanEvent(ctx context.Context, username string, human *domain.Hum
|
||||
return addEvent
|
||||
}
|
||||
|
||||
func createRegisterHumanEvent(ctx context.Context, username string, human *domain.Human) *user.HumanRegisteredEvent {
|
||||
func createRegisterHumanEvent(ctx context.Context, orgID string, human *domain.Human, userLoginMustBeDomain bool) *user.HumanRegisteredEvent {
|
||||
addEvent := user.NewHumanRegisteredEvent(
|
||||
ctx,
|
||||
username,
|
||||
orgID,
|
||||
human.Username,
|
||||
human.FirstName,
|
||||
human.LastName,
|
||||
human.NickName,
|
||||
@@ -192,6 +200,7 @@ func createRegisterHumanEvent(ctx context.Context, username string, human *domai
|
||||
human.PreferredLanguage,
|
||||
human.Gender,
|
||||
human.EmailAddress,
|
||||
userLoginMustBeDomain,
|
||||
)
|
||||
if human.Phone != nil {
|
||||
addEvent.AddPhoneData(human.PhoneNumber)
|
||||
|
||||
@@ -34,8 +34,6 @@ func (r *CommandSide) removeHumanExternalIDP(ctx context.Context, externalIDP *d
|
||||
user.NewHumanExternalIDPCascadeRemovedEvent(ctx, externalIDP.IDPConfigID, externalIDP.ExternalUserID),
|
||||
)
|
||||
}
|
||||
|
||||
//TODO: Release unique externalidp
|
||||
return r.eventstore.PushAggregate(ctx, existingExternalIDP, userAgg)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ func (r *CommandSide) AddMachine(ctx context.Context, orgID string, machine *dom
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//TODO: Check Unique username
|
||||
machine.AggregateID = userID
|
||||
orgIAMPolicy, err := r.getOrgIAMPolicy(ctx, orgID)
|
||||
if err != nil {
|
||||
@@ -34,6 +33,7 @@ func (r *CommandSide) AddMachine(ctx context.Context, orgID string, machine *dom
|
||||
machine.Username,
|
||||
machine.Name,
|
||||
machine.Description,
|
||||
orgIAMPolicy.UserLoginMustBeDomain,
|
||||
),
|
||||
)
|
||||
err = r.eventstore.PushAggregate(ctx, addedMachine, userAgg)
|
||||
|
||||
Reference in New Issue
Block a user