diff --git a/config/config.go b/config/config.go index 5dad9ac3..bc91d33c 100644 --- a/config/config.go +++ b/config/config.go @@ -62,6 +62,7 @@ type SourcesApiConfig struct { SecretStore string TenantTranslatorUrl string Env string + HandleTenantRefresh bool SecretsManagerAccessKey string SecretsManagerSecretKey string @@ -97,6 +98,7 @@ func (s SourcesApiConfig) String() string { fmt.Fprintf(&b, "%s=%v ", "SecretStore", parsedConfig.SecretStore) fmt.Fprintf(&b, "%s=%v ", "TenantTranslatorUrl", parsedConfig.TenantTranslatorUrl) fmt.Fprintf(&b, "%s=%v ", "Env", parsedConfig.Env) + fmt.Fprintf(&b, "%s=%v ", "HandleTenantRefresh", parsedConfig.HandleTenantRefresh) fmt.Fprintf(&b, "%s=%v ", "SecretsManagerPrefix", parsedConfig.SecretsManagerPrefix) fmt.Fprintf(&b, "%s=%v ", "LocalStackURL", parsedConfig.LocalStackURL) return b.String() @@ -217,6 +219,9 @@ func Get() *SourcesApiConfig { options.SetDefault("Env", os.Getenv("SOURCES_ENV")) + handleTenantRefresh, _ := strconv.ParseBool(os.Getenv("HANDLE_TENANT_REFRESH")) + options.SetDefault("HandleTenantRefresh", handleTenantRefresh) + options.SetDefault("FeatureFlagsService", os.Getenv("FEATURE_FLAGS_SERVICE")) if os.Getenv("SOURCES_ENV") == "prod" { @@ -327,6 +332,7 @@ func Get() *SourcesApiConfig { SecretStore: options.GetString("SecretStore"), TenantTranslatorUrl: options.GetString("TenantTranslatorUrl"), Env: options.GetString("Env"), + HandleTenantRefresh: options.GetBool("HandleTenantRefresh"), SecretsManagerAccessKey: options.GetString("SecretsManagerAccessKey"), SecretsManagerSecretKey: options.GetString("SecretsManagerSecretKey"), SecretsManagerPrefix: options.GetString("SecretsManagerPrefix"), diff --git a/dao/user_dao.go b/dao/user_dao.go index 959ba5ba..0df84c63 100644 --- a/dao/user_dao.go +++ b/dao/user_dao.go @@ -3,7 +3,9 @@ package dao import ( "fmt" + "github.com/RedHatInsights/sources-api-go/config" m "github.com/RedHatInsights/sources-api-go/model" + "gorm.io/gorm/clause" ) var GetUserDao func(*int64) UserDao @@ -40,7 +42,18 @@ func (u *userDaoImpl) FindOrCreate(userID string) (*m.User, error) { if err != nil { user.TenantID = *u.TenantID user.UserID = userID - err = DB.Debug().Create(&user).Error + + stmt := DB.Debug() + + if config.Get().HandleTenantRefresh { + // tenant refresh = we run into conflicts where one user_id is tied to another tenant (since the org_id changes), therefore we tack an `ON CONFLICT UPDATE` if we're in an environment where this can happen + stmt = stmt.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "user_id"}}, + DoUpdates: clause.AssignmentColumns([]string{"tenant_id"}), + }) + } + + err = stmt.Create(&user).Error if err != nil { return nil, err } diff --git a/deploy/clowdapp.yaml b/deploy/clowdapp.yaml index 97eb72ca..5aa9a9a8 100644 --- a/deploy/clowdapp.yaml +++ b/deploy/clowdapp.yaml @@ -261,6 +261,8 @@ objects: name: sources-secrets-manager key: localstack_url optional: true + - name: HANDLE_TENANT_REFRESH + value: ${HANDLE_TENANT_REFRESH} readinessProbe: tcpSocket: port: 8000 @@ -451,3 +453,6 @@ parameters: - description: Which secret-store should sources use for authentications name: SECRET_STORE value: "database" +- description: Whether to handle conflicts on user_ids during a tenant refresh + name: HANDLE_TENANT_REFRESH + value: "false"