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 b46c41e4bf50af7f3873c6d0deb62206d77ec6e9)
This commit is contained in:
Iraq 2025-06-02 10:40:19 +02:00 committed by Livio Spring
parent f065257e4f
commit dedb923f43
No known key found for this signature in database
3 changed files with 52 additions and 39 deletions

View File

@ -9,9 +9,7 @@ import (
"github.com/zitadel/zitadel/internal/feature"
)
var (
emptyInstance = &instance{}
)
var emptyInstance = &instance{}
type Instance interface {
InstanceID() string
@ -33,13 +31,13 @@ type InstanceVerifier interface {
}
type instance struct {
id string
domain string
projectID string
appID string
clientID string
orgID string
features feature.Features
id string
projectID string
appID string
clientID string
orgID string
defaultLanguage language.Tag
features feature.Features
}
func (i *instance) Block() *bool {
@ -67,7 +65,7 @@ func (i *instance) ConsoleApplicationID() string {
}
func (i *instance) DefaultLanguage() language.Tag {
return language.Und
return i.defaultLanguage
}
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})
}
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 {
i, ok := ctx.Value(instanceKey).(*instance)
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 {
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)
if err != nil {
@ -254,19 +254,22 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
return setup.zitadel.instanceID, token, machineKey, details, nil
}
func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, consoleAppID, externalDomain string) context.Context {
return authz.WithConsole(
authz.SetCtxData(
http.WithRequestedHost(
authz.WithInstanceID(
ctx,
instanceID),
externalDomain,
func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, consoleAppID, externalDomain string, defaultLanguage language.Tag) context.Context {
return authz.WithDefaultLanguage(
authz.WithConsole(
authz.SetCtxData(
http.WithRequestedHost(
authz.WithInstanceID(
ctx,
instanceID),
externalDomain,
),
authz.CtxData{ResourceOwner: instanceID},
),
authz.CtxData{ResourceOwner: instanceID},
projectID,
consoleAppID,
),
projectID,
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),
}
}
func instanceElementsConfig() *SecretGenerators {
return &SecretGenerators{
ClientSecret: &crypto.GeneratorConfig{Length: 64, IncludeLowerLetters: true, IncludeUpperLetters: true, IncludeDigits: true},
@ -668,22 +669,23 @@ func TestCommandSide_setupMinimalInterfaces(t *testing.T) {
eventstore: expectEventstore(
slices.Concat(
projectFilters(),
[]expect{expectPush(
projectAddedEvents(context.Background(),
"INSTANCE",
"ORG",
"PROJECT",
"owner",
false,
)...,
),
[]expect{
expectPush(
projectAddedEvents(context.Background(),
"INSTANCE",
"ORG",
"PROJECT",
"owner",
false,
)...,
),
},
)...,
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, projectClientIDs()...),
},
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"),
orgAgg: org.NewAggregate("ORG"),
owner: "owner",
@ -767,7 +769,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
},
},
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"),
orgAgg: org.NewAggregate("ORG"),
human: instanceSetupHumanConfig(),
@ -806,7 +808,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
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"),
orgAgg: org.NewAggregate("ORG"),
machine: instanceSetupMachineConfig(),
@ -855,7 +857,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
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"),
orgAgg: org.NewAggregate("ORG"),
machine: instanceSetupMachineConfig(),
@ -972,7 +974,7 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
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"),
orgName: "ZITADEL",
machine: &AddMachine{
@ -1097,7 +1099,7 @@ func TestCommandSide_setupInstanceElements(t *testing.T) {
),
},
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"),
setup: setupInstanceElementsConfig(),
},
@ -1183,7 +1185,7 @@ func TestCommandSide_setUpInstance(t *testing.T) {
},
},
args: args{
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN"),
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
setup: setupInstanceConfig(),
},
res: res{