fix(settings): fix for setting restricted languages (#9947)

# Which Problems Are Solved

Zitadel encounters a migration error when setting `restricted languages`
and fails to start.

# How the Problems Are Solved

The problem is that there is a check that checks that at least one of
the restricted languages is the same as the `default language`, however,
in the `authz instance` (where the default language is pulled form) is
never set.

I've added code to set the `default language` in the `authz instance`

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/9787

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
(cherry picked from commit b46c41e4bf)
This commit is contained in:
Iraq
2025-06-02 10:40:19 +02:00
committed by Livio Spring
parent 35c9ed187d
commit 2cb0e8b9ab
3 changed files with 52 additions and 39 deletions

View File

@@ -9,9 +9,7 @@ import (
"github.com/zitadel/zitadel/internal/feature" "github.com/zitadel/zitadel/internal/feature"
) )
var ( var emptyInstance = &instance{}
emptyInstance = &instance{}
)
type Instance interface { type Instance interface {
InstanceID() string InstanceID() string
@@ -34,11 +32,11 @@ type InstanceVerifier interface {
type instance struct { type instance struct {
id string id string
domain string
projectID string projectID string
appID string appID string
clientID string clientID string
orgID string orgID string
defaultLanguage language.Tag
features feature.Features features feature.Features
} }
@@ -67,7 +65,7 @@ func (i *instance) ConsoleApplicationID() string {
} }
func (i *instance) DefaultLanguage() language.Tag { func (i *instance) DefaultLanguage() language.Tag {
return language.Und return i.defaultLanguage
} }
func (i *instance) DefaultOrganisationID() string { func (i *instance) DefaultOrganisationID() string {
@@ -106,6 +104,16 @@ func WithInstanceID(ctx context.Context, id string) context.Context {
return context.WithValue(ctx, instanceKey, &instance{id: id}) return context.WithValue(ctx, instanceKey, &instance{id: id})
} }
func WithDefaultLanguage(ctx context.Context, defaultLanguage language.Tag) context.Context {
i, ok := ctx.Value(instanceKey).(*instance)
if !ok {
i = new(instance)
}
i.defaultLanguage = defaultLanguage
return context.WithValue(ctx, instanceKey, i)
}
func WithConsole(ctx context.Context, projectID, appID string) context.Context { func WithConsole(ctx context.Context, projectID, appID string) context.Context {
i, ok := ctx.Value(instanceKey).(*instance) i, ok := ctx.Value(instanceKey).(*instance)
if !ok { if !ok {

View File

@@ -220,7 +220,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
if err := setup.generateIDs(c.idGenerator); err != nil { if err := setup.generateIDs(c.idGenerator); err != nil {
return "", "", nil, nil, err return "", "", nil, nil, err
} }
ctx = contextWithInstanceSetupInfo(ctx, setup.zitadel.instanceID, setup.zitadel.projectID, setup.zitadel.consoleAppID, c.externalDomain) ctx = contextWithInstanceSetupInfo(ctx, setup.zitadel.instanceID, setup.zitadel.projectID, setup.zitadel.consoleAppID, c.externalDomain, setup.DefaultLanguage)
validations, pat, machineKey, err := setUpInstance(ctx, c, setup) validations, pat, machineKey, err := setUpInstance(ctx, c, setup)
if err != nil { if err != nil {
@@ -254,8 +254,9 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
return setup.zitadel.instanceID, token, machineKey, details, nil return setup.zitadel.instanceID, token, machineKey, details, nil
} }
func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, consoleAppID, externalDomain string) context.Context { func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, consoleAppID, externalDomain string, defaultLanguage language.Tag) context.Context {
return authz.WithConsole( return authz.WithDefaultLanguage(
authz.WithConsole(
authz.SetCtxData( authz.SetCtxData(
http.WithRequestedHost( http.WithRequestedHost(
authz.WithInstanceID( authz.WithInstanceID(
@@ -267,6 +268,8 @@ func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, co
), ),
projectID, projectID,
consoleAppID, consoleAppID,
),
defaultLanguage,
) )
} }

View File

@@ -345,6 +345,7 @@ func instanceElementsEvents(ctx context.Context, instanceID, instanceName string
instance.NewSecretGeneratorAddedEvent(ctx, &instanceAgg.Aggregate, domain.SecretGeneratorTypeOTPEmail, 8, 5*time.Minute, false, false, true, false), instance.NewSecretGeneratorAddedEvent(ctx, &instanceAgg.Aggregate, domain.SecretGeneratorTypeOTPEmail, 8, 5*time.Minute, false, false, true, false),
} }
} }
func instanceElementsConfig() *SecretGenerators { func instanceElementsConfig() *SecretGenerators {
return &SecretGenerators{ return &SecretGenerators{
ClientSecret: &crypto.GeneratorConfig{Length: 64, IncludeLowerLetters: true, IncludeUpperLetters: true, IncludeDigits: true}, ClientSecret: &crypto.GeneratorConfig{Length: 64, IncludeLowerLetters: true, IncludeUpperLetters: true, IncludeDigits: true},
@@ -668,7 +669,8 @@ func TestCommandSide_setupMinimalInterfaces(t *testing.T) {
eventstore: expectEventstore( eventstore: expectEventstore(
slices.Concat( slices.Concat(
projectFilters(), projectFilters(),
[]expect{expectPush( []expect{
expectPush(
projectAddedEvents(context.Background(), projectAddedEvents(context.Background(),
"INSTANCE", "INSTANCE",
"ORG", "ORG",
@@ -683,7 +685,7 @@ func TestCommandSide_setupMinimalInterfaces(t *testing.T) {
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, projectClientIDs()...), idGenerator: id_mock.NewIDGeneratorExpectIDs(t, projectClientIDs()...),
}, },
args: args{ args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"), ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
instanceAgg: instance.NewAggregate("INSTANCE"), instanceAgg: instance.NewAggregate("INSTANCE"),
orgAgg: org.NewAggregate("ORG"), orgAgg: org.NewAggregate("ORG"),
owner: "owner", owner: "owner",
@@ -767,7 +769,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
}, },
}, },
args: args{ args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"), ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
instanceAgg: instance.NewAggregate("INSTANCE"), instanceAgg: instance.NewAggregate("INSTANCE"),
orgAgg: org.NewAggregate("ORG"), orgAgg: org.NewAggregate("ORG"),
human: instanceSetupHumanConfig(), human: instanceSetupHumanConfig(),
@@ -806,7 +808,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)), keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
}, },
args: args{ args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"), ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
instanceAgg: instance.NewAggregate("INSTANCE"), instanceAgg: instance.NewAggregate("INSTANCE"),
orgAgg: org.NewAggregate("ORG"), orgAgg: org.NewAggregate("ORG"),
machine: instanceSetupMachineConfig(), machine: instanceSetupMachineConfig(),
@@ -855,7 +857,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)), keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
}, },
args: args{ args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"), ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
instanceAgg: instance.NewAggregate("INSTANCE"), instanceAgg: instance.NewAggregate("INSTANCE"),
orgAgg: org.NewAggregate("ORG"), orgAgg: org.NewAggregate("ORG"),
machine: instanceSetupMachineConfig(), machine: instanceSetupMachineConfig(),
@@ -972,7 +974,7 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)), keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
}, },
args: args{ args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"), ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
instanceAgg: instance.NewAggregate("INSTANCE"), instanceAgg: instance.NewAggregate("INSTANCE"),
orgName: "ZITADEL", orgName: "ZITADEL",
machine: &AddMachine{ machine: &AddMachine{
@@ -1097,7 +1099,7 @@ func TestCommandSide_setupInstanceElements(t *testing.T) {
), ),
}, },
args: args{ args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"), ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
instanceAgg: instance.NewAggregate("INSTANCE"), instanceAgg: instance.NewAggregate("INSTANCE"),
setup: setupInstanceElementsConfig(), setup: setupInstanceElementsConfig(),
}, },
@@ -1183,7 +1185,7 @@ func TestCommandSide_setUpInstance(t *testing.T) {
}, },
}, },
args: args{ args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"), ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
setup: setupInstanceConfig(), setup: setupInstanceConfig(),
}, },
res: res{ res: res{