Files
zitadel/internal/query/instance_features_model.go
Livio SpringandGitHub 855bac2731 fix: revert renaming of (management) console feature flag (#11706)
# Which Problems Are Solved

#11390 renamed "Console" to "Management Console". This included a rename
of the feature key to enable the management console to use the V2 API
for user creation. Due to the rename generated events would also be
changed, resp. existing events would be ignored, which leads to
inconsistency in the data model.

# How the Problems Are Solved

Renamed the key back to `KeyConsoleUseV2UserApi`.
And added a comment to prevent future issues.

# Additional Changes

None

# Additional Context

- relates to #11390 
- backport to v4
2026-02-27 09:43:11 +01:00

128 lines
3.9 KiB
Go

package query
import (
"context"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/feature"
feature_v1 "github.com/zitadel/zitadel/internal/repository/feature"
"github.com/zitadel/zitadel/internal/repository/feature/feature_v2"
)
type InstanceFeaturesReadModel struct {
*eventstore.ReadModel
system *SystemFeatures
instance *InstanceFeatures
}
func NewInstanceFeaturesReadModel(ctx context.Context, system *SystemFeatures) *InstanceFeaturesReadModel {
instanceID := authz.GetInstance(ctx).InstanceID()
m := &InstanceFeaturesReadModel{
ReadModel: &eventstore.ReadModel{
AggregateID: instanceID,
ResourceOwner: instanceID,
},
instance: new(InstanceFeatures),
system: system,
}
m.populateFromSystem()
return m
}
func (m *InstanceFeaturesReadModel) Reduce() (err error) {
for _, event := range m.Events {
switch e := event.(type) {
case *feature_v2.ResetEvent:
m.reduceReset()
case *feature_v1.SetEvent[feature_v1.Boolean]:
err = reduceInstanceFeatureSet(
m.instance,
feature_v1.DefaultLoginInstanceEventToV2(e),
)
case *feature_v2.SetEvent[bool]:
err = reduceInstanceFeatureSet(m.instance, e)
case *feature_v2.SetEvent[*feature.LoginV2]:
err = reduceInstanceFeatureSet(m.instance, e)
case *feature_v2.SetEvent[[]feature.ImprovedPerformanceType]:
err = reduceInstanceFeatureSet(m.instance, e)
}
if err != nil {
return err
}
}
return m.ReadModel.Reduce()
}
func (m *InstanceFeaturesReadModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
AwaitOpenTransactions().
AddQuery().
AggregateTypes(feature_v2.AggregateType).
EventTypes(
feature_v1.DefaultLoginInstanceEventType,
feature_v2.InstanceResetEventType,
feature_v2.InstanceLoginDefaultOrgEventType,
feature_v2.InstanceUserSchemaEventType,
feature_v2.InstanceImprovedPerformanceEventType,
feature_v2.InstanceDebugOIDCParentErrorEventType,
feature_v2.InstanceOIDCSingleV1SessionTerminationEventType,
feature_v2.InstanceLoginVersion,
feature_v2.InstancePermissionCheckV2,
feature_v2.InstanceManagementConsoleUseV2UserApi,
feature_v2.InstanceEnableRelationalTables,
).
Builder().ResourceOwner(m.ResourceOwner)
}
func (m *InstanceFeaturesReadModel) reduceReset() {
m.instance.EnableRelationalTables = FeatureSource[bool]{}
if m.populateFromSystem() {
return
}
m.instance = nil
m.instance = new(InstanceFeatures)
}
func (m *InstanceFeaturesReadModel) populateFromSystem() bool {
if m.system == nil {
return false
}
m.instance.LoginDefaultOrg = m.system.LoginDefaultOrg
m.instance.UserSchema = m.system.UserSchema
m.instance.ImprovedPerformance = m.system.ImprovedPerformance
m.instance.OIDCSingleV1SessionTermination = m.system.OIDCSingleV1SessionTermination
m.instance.LoginV2 = m.system.LoginV2
return true
}
func reduceInstanceFeatureSet[T any](features *InstanceFeatures, event *feature_v2.SetEvent[T]) error {
level, key, err := event.FeatureInfo()
if err != nil {
return err
}
switch key {
case feature.KeyUnspecified:
return nil
case feature.KeyLoginDefaultOrg:
features.LoginDefaultOrg.set(level, event.Value)
case feature.KeyUserSchema:
features.UserSchema.set(level, event.Value)
case feature.KeyImprovedPerformance:
features.ImprovedPerformance.set(level, event.Value)
case feature.KeyDebugOIDCParentError:
features.DebugOIDCParentError.set(level, event.Value)
case feature.KeyOIDCSingleV1SessionTermination:
features.OIDCSingleV1SessionTermination.set(level, event.Value)
case feature.KeyLoginV2:
features.LoginV2.set(level, event.Value)
case feature.KeyPermissionCheckV2:
features.PermissionCheckV2.set(level, event.Value)
case feature.KeyConsoleUseV2UserApi:
features.ManagementConsoleUseV2UserApi.set(level, event.Value)
case feature.KeyEnableRelationalTables:
features.EnableRelationalTables.set(level, event.Value)
}
return nil
}