mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-27 01:32:15 +00:00
feat: Feature flag for relational tables (#10599)
# Which Problems Are Solved This PR introduces a new feature flag `EnableRelationalTables` that will be used in following implementations to decide whether Zitadel should use the relational model or the event sourcing one. # TODO - [x] Implement flag at system level - [x] Display the flag on console: https://github.com/zitadel/zitadel/pull/10615 # How the Problems Are Solved - Implement loading the flag from config - Add persistence of the flag through gRPC endpoint (SetInstanceFeatures) - Implement reading of the flag through gRPC endpoint (GetInstanceFeatures) # Additional Changes Some minor refactoring to remove un-needed generics annotations # Additional Context - Closes #10574 --------- Co-authored-by: Silvan <[email protected]>
This commit is contained in:
@@ -26,6 +26,7 @@ func systemFeaturesToCommand(req *feature_pb.SetSystemFeaturesRequest) (*command
|
||||
EnableBackChannelLogout: req.EnableBackChannelLogout,
|
||||
LoginV2: loginV2,
|
||||
PermissionCheckV2: req.PermissionCheckV2,
|
||||
EnableRelationalTables: req.EnableRelationalTables,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -40,6 +41,7 @@ func systemFeaturesToPb(f *query.SystemFeatures) *feature_pb.GetSystemFeaturesRe
|
||||
EnableBackChannelLogout: featureSourceToFlagPb(&f.EnableBackChannelLogout),
|
||||
LoginV2: loginV2ToLoginV2FlagPb(f.LoginV2),
|
||||
PermissionCheckV2: featureSourceToFlagPb(&f.PermissionCheckV2),
|
||||
EnableRelationalTables: featureSourceToFlagPb(&f.EnableRelationalTables),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +61,7 @@ func instanceFeaturesToCommand(req *feature_pb.SetInstanceFeaturesRequest) (*com
|
||||
LoginV2: loginV2,
|
||||
PermissionCheckV2: req.PermissionCheckV2,
|
||||
ConsoleUseV2UserApi: req.ConsoleUseV2UserApi,
|
||||
EnableRelationalTables: req.EnableRelationalTables,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -75,6 +78,7 @@ func instanceFeaturesToPb(f *query.InstanceFeatures) *feature_pb.GetInstanceFeat
|
||||
LoginV2: loginV2ToLoginV2FlagPb(f.LoginV2),
|
||||
PermissionCheckV2: featureSourceToFlagPb(&f.PermissionCheckV2),
|
||||
ConsoleUseV2UserApi: featureSourceToFlagPb(&f.ConsoleUseV2UserApi),
|
||||
EnableRelationalTables: featureSourceToFlagPb(&f.EnableRelationalTables),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
)
|
||||
|
||||
func Test_systemFeaturesToCommand(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
arg := &feature_pb.SetSystemFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(true),
|
||||
@@ -28,6 +30,9 @@ func Test_systemFeaturesToCommand(t *testing.T) {
|
||||
Required: true,
|
||||
BaseUri: gu.Ptr("https://login.com"),
|
||||
},
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
EnableBackChannelLogout: gu.Ptr(true),
|
||||
PermissionCheckV2: gu.Ptr(true),
|
||||
}
|
||||
want := &command.SystemFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
@@ -39,13 +44,23 @@ func Test_systemFeaturesToCommand(t *testing.T) {
|
||||
Required: true,
|
||||
BaseURI: &url.URL{Scheme: "https", Host: "login.com"},
|
||||
},
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
EnableBackChannelLogout: gu.Ptr(true),
|
||||
PermissionCheckV2: gu.Ptr(true),
|
||||
}
|
||||
|
||||
// Test
|
||||
got, err := systemFeaturesToCommand(arg)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, want, got)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_systemFeaturesToPb(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Given
|
||||
arg := &query.SystemFeatures{
|
||||
Details: &domain.ObjectDetails{
|
||||
Sequence: 22,
|
||||
@@ -87,6 +102,10 @@ func Test_systemFeaturesToPb(t *testing.T) {
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
},
|
||||
EnableRelationalTables: query.FeatureSource[bool]{
|
||||
Level: feature.LevelSystem,
|
||||
Value: true,
|
||||
},
|
||||
}
|
||||
want := &feature_pb.GetSystemFeaturesResponse{
|
||||
Details: &object.Details{
|
||||
@@ -127,12 +146,22 @@ func Test_systemFeaturesToPb(t *testing.T) {
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
EnableRelationalTables: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
}
|
||||
|
||||
// Test
|
||||
got := systemFeaturesToPb(arg)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func Test_instanceFeaturesToCommand(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Given
|
||||
arg := &feature_pb.SetInstanceFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(true),
|
||||
@@ -145,7 +174,9 @@ func Test_instanceFeaturesToCommand(t *testing.T) {
|
||||
Required: true,
|
||||
BaseUri: gu.Ptr("https://login.com"),
|
||||
},
|
||||
ConsoleUseV2UserApi: gu.Ptr(true),
|
||||
ConsoleUseV2UserApi: gu.Ptr(true),
|
||||
PermissionCheckV2: gu.Ptr(false),
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
}
|
||||
want := &command.InstanceFeatures{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
@@ -159,14 +190,22 @@ func Test_instanceFeaturesToCommand(t *testing.T) {
|
||||
Required: true,
|
||||
BaseURI: &url.URL{Scheme: "https", Host: "login.com"},
|
||||
},
|
||||
ConsoleUseV2UserApi: gu.Ptr(true),
|
||||
ConsoleUseV2UserApi: gu.Ptr(true),
|
||||
PermissionCheckV2: gu.Ptr(false),
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
}
|
||||
|
||||
// Test
|
||||
got, err := instanceFeaturesToCommand(arg)
|
||||
|
||||
// Verify
|
||||
assert.Equal(t, want, got)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func Test_instanceFeaturesToPb(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
arg := &query.InstanceFeatures{
|
||||
Details: &domain.ObjectDetails{
|
||||
Sequence: 22,
|
||||
@@ -212,6 +251,10 @@ func Test_instanceFeaturesToPb(t *testing.T) {
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
},
|
||||
EnableRelationalTables: query.FeatureSource[bool]{
|
||||
Level: feature.LevelInstance,
|
||||
Value: true,
|
||||
},
|
||||
}
|
||||
want := &feature_pb.GetInstanceFeaturesResponse{
|
||||
Details: &object.Details{
|
||||
@@ -260,6 +303,10 @@ func Test_instanceFeaturesToPb(t *testing.T) {
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_INSTANCE,
|
||||
},
|
||||
EnableRelationalTables: &feature_pb.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature_pb.Source_SOURCE_INSTANCE,
|
||||
},
|
||||
}
|
||||
got := instanceFeaturesToPb(arg)
|
||||
assert.Equal(t, want, got)
|
||||
|
||||
@@ -76,7 +76,8 @@ func TestServer_SetSystemFeatures(t *testing.T) {
|
||||
args: args{
|
||||
ctx: SystemCTX,
|
||||
req: &feature.SetSystemFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
want: &feature.SetSystemFeaturesResponse{
|
||||
@@ -170,8 +171,9 @@ func TestServer_GetSystemFeatures(t *testing.T) {
|
||||
name: "some features",
|
||||
prepare: func(t *testing.T) {
|
||||
_, err := Client.SetSystemFeatures(SystemCTX, &feature.SetSystemFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(false),
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(false),
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
@@ -188,6 +190,10 @@ func TestServer_GetSystemFeatures(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
EnableRelationalTables: &feature.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature.Source_SOURCE_SYSTEM,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -209,6 +215,7 @@ func TestServer_GetSystemFeatures(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assertFeatureFlag(t, tt.want.LoginDefaultOrg, got.LoginDefaultOrg)
|
||||
assertFeatureFlag(t, tt.want.UserSchema, got.UserSchema)
|
||||
assertFeatureFlag(t, tt.want.EnableRelationalTables, got.EnableRelationalTables)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -247,7 +254,8 @@ func TestServer_SetInstanceFeatures(t *testing.T) {
|
||||
args: args{
|
||||
ctx: IamCTX,
|
||||
req: &feature.SetInstanceFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
},
|
||||
},
|
||||
want: &feature.SetInstanceFeaturesResponse{
|
||||
@@ -363,14 +371,19 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
EnableRelationalTables: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "some features, no inheritance",
|
||||
prepare: func(t *testing.T) {
|
||||
_, err := Client.SetInstanceFeatures(IamCTX, &feature.SetInstanceFeaturesRequest{
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(true),
|
||||
LoginDefaultOrg: gu.Ptr(true),
|
||||
UserSchema: gu.Ptr(true),
|
||||
EnableRelationalTables: gu.Ptr(true),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
@@ -387,6 +400,10 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
Enabled: true,
|
||||
Source: feature.Source_SOURCE_INSTANCE,
|
||||
},
|
||||
EnableRelationalTables: &feature.FeatureFlag{
|
||||
Enabled: true,
|
||||
Source: feature.Source_SOURCE_INSTANCE,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -412,6 +429,10 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
EnableRelationalTables: &feature.FeatureFlag{
|
||||
Enabled: false,
|
||||
Source: feature.Source_SOURCE_UNSPECIFIED,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -433,6 +454,7 @@ func TestServer_GetInstanceFeatures(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assertFeatureFlag(t, tt.want.LoginDefaultOrg, got.LoginDefaultOrg)
|
||||
assertFeatureFlag(t, tt.want.UserSchema, got.UserSchema)
|
||||
assertFeatureFlag(t, tt.want.EnableRelationalTables, got.EnableRelationalTables)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user