fix: ensure uniqueness (#6956)

* fix: ensure uniqueness

* only update wrong ones

* Update cmd/setup/16.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

---------

Co-authored-by: Silvan <silvan.reusser@gmail.com>
(cherry picked from commit b563041103)
This commit is contained in:
Livio Spring 2023-11-22 14:05:14 +02:00
parent 7786b09444
commit 3a0f7ef193
No known key found for this signature in database
GPG Key ID: 26BB1C2FA5952CF0
5 changed files with 63 additions and 12 deletions

33
cmd/setup/16.go Normal file
View File

@ -0,0 +1,33 @@
package setup
import (
"context"
_ "embed"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/database"
)
var (
//go:embed 16.sql
uniqueConstraintLower string
)
type UniqueConstraintToLower struct {
dbClient *database.DB
}
func (mig *UniqueConstraintToLower) Execute(ctx context.Context) error {
res, err := mig.dbClient.ExecContext(ctx, uniqueConstraintLower)
if err != nil {
return err
}
count, err := res.RowsAffected()
logging.WithFields("count", count).Info("unique constraints updated")
return err
}
func (mig *UniqueConstraintToLower) String() string {
return "16_unique_constraint_lower"
}

13
cmd/setup/16.sql Normal file
View File

@ -0,0 +1,13 @@
WITH casesensitive as (
SELECT instance_id, unique_type, lower(unique_field)
FROM eventstore.unique_constraints
GROUP BY instance_id, unique_type, lower(unique_field)
HAVING count(unique_field) < 2
)
UPDATE eventstore.unique_constraints c
SET unique_field = casesensitive.lower
FROM casesensitive
WHERE c.instance_id = casesensitive.instance_id
AND c.unique_type = casesensitive.unique_type
AND lower(c.unique_field) = casesensitive.lower
AND c.unique_field <> casesensitive.lower;

View File

@ -61,18 +61,19 @@ func MustNewConfig(v *viper.Viper) *Config {
} }
type Steps struct { type Steps struct {
s1ProjectionTable *ProjectionTable s1ProjectionTable *ProjectionTable
s2AssetsTable *AssetTable s2AssetsTable *AssetTable
FirstInstance *FirstInstance FirstInstance *FirstInstance
s5LastFailed *LastFailed s5LastFailed *LastFailed
s6OwnerRemoveColumns *OwnerRemoveColumns s6OwnerRemoveColumns *OwnerRemoveColumns
s7LogstoreTables *LogstoreTables s7LogstoreTables *LogstoreTables
s8AuthTokens *AuthTokenIndexes s8AuthTokens *AuthTokenIndexes
CorrectCreationDate *CorrectCreationDate CorrectCreationDate *CorrectCreationDate
s12AddOTPColumns *AddOTPColumns s12AddOTPColumns *AddOTPColumns
s13FixQuotaProjection *FixQuotaConstraints s13FixQuotaProjection *FixQuotaConstraints
s14NewEventsTable *NewEventsTable s14NewEventsTable *NewEventsTable
s15CurrentStates *CurrentProjectionState s15CurrentStates *CurrentProjectionState
s16UniqueConstraintsLower *UniqueConstraintToLower
} }
type encryptionKeyConfig struct { type encryptionKeyConfig struct {

View File

@ -100,6 +100,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
steps.s13FixQuotaProjection = &FixQuotaConstraints{dbClient: zitadelDBClient} steps.s13FixQuotaProjection = &FixQuotaConstraints{dbClient: zitadelDBClient}
steps.s14NewEventsTable = &NewEventsTable{dbClient: esPusherDBClient} steps.s14NewEventsTable = &NewEventsTable{dbClient: esPusherDBClient}
steps.s15CurrentStates = &CurrentProjectionState{dbClient: zitadelDBClient} steps.s15CurrentStates = &CurrentProjectionState{dbClient: zitadelDBClient}
steps.s16UniqueConstraintsLower = &UniqueConstraintToLower{dbClient: zitadelDBClient}
err = projection.Create(ctx, zitadelDBClient, eventstoreClient, config.Projections, nil, nil, nil) err = projection.Create(ctx, zitadelDBClient, eventstoreClient, config.Projections, nil, nil, nil)
logging.OnError(err).Fatal("unable to start projections") logging.OnError(err).Fatal("unable to start projections")
@ -140,6 +141,8 @@ func Setup(config *Config, steps *Steps, masterKey string) {
logging.WithFields("name", steps.s13FixQuotaProjection.String()).OnError(err).Fatal("migration failed") logging.WithFields("name", steps.s13FixQuotaProjection.String()).OnError(err).Fatal("migration failed")
err = migration.Migrate(ctx, eventstoreClient, steps.s15CurrentStates) err = migration.Migrate(ctx, eventstoreClient, steps.s15CurrentStates)
logging.WithFields("name", steps.s15CurrentStates.String()).OnError(err).Fatal("migration failed") logging.WithFields("name", steps.s15CurrentStates.String()).OnError(err).Fatal("migration failed")
err = migration.Migrate(ctx, eventstoreClient, steps.s16UniqueConstraintsLower)
logging.WithFields("name", steps.s16UniqueConstraintsLower.String()).OnError(err).Fatal("migration failed")
for _, repeatableStep := range repeatableSteps { for _, repeatableStep := range repeatableSteps {
err = migration.Migrate(ctx, eventstoreClient, repeatableStep) err = migration.Migrate(ctx, eventstoreClient, repeatableStep)

View File

@ -33,6 +33,7 @@ func handleUniqueConstraints(ctx context.Context, tx *sql.Tx, commands []eventst
for _, command := range commands { for _, command := range commands {
for _, constraint := range command.UniqueConstraints() { for _, constraint := range command.UniqueConstraints() {
constraint.UniqueField = strings.ToLower(constraint.UniqueField)
switch constraint.Action { switch constraint.Action {
case eventstore.UniqueConstraintAdd: case eventstore.UniqueConstraintAdd:
addPlaceholders = append(addPlaceholders, fmt.Sprintf("($%d, $%d, $%d)", len(addArgs)+1, len(addArgs)+2, len(addArgs)+3)) addPlaceholders = append(addPlaceholders, fmt.Sprintf("($%d, $%d, $%d)", len(addArgs)+1, len(addArgs)+2, len(addArgs)+3))