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:
Fabi
2021-01-21 10:49:38 +01:00
committed by GitHub
parent c2e6e782a8
commit 28bfe72930
62 changed files with 1046 additions and 313 deletions
+7 -18
View File
@@ -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) {
-1
View File
@@ -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 {
+11 -17
View File
@@ -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) {
+1 -2
View File
@@ -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
+1 -1
View File
@@ -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
+6 -5
View File
@@ -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)
+16 -7
View File
@@ -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)
}
+1 -1
View File
@@ -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)