fix: define base uri for login v2 feature as string to make it config… (#10533)

…urable

# Which Problems Are Solved

BaseURI defined in environment variables or configuration files was
ignored for Login v2 feature flag.

# How the Problems Are Solved

Define BaseURI as string so that the environment variables and
configuration files can be parsed into it.

# Additional Changes

None

# Additional Context

Closes #10405

(cherry picked from commit 2a78fdfe1f)
This commit is contained in:
Stefan Benz
2025-08-26 14:18:13 +02:00
committed by Livio Spring
parent 1625e5f7bc
commit ce00cf22db
4 changed files with 74 additions and 6 deletions

View File

@@ -37,6 +37,9 @@ DefaultInstance:
Features: Features:
LoginDefaultOrg: true LoginDefaultOrg: true
UserSchema: true UserSchema: true
LoginV2:
Required: true
BaseURI: 'http://zitadel:8080'
Log: Log:
Level: info Level: info
Actions: Actions:
@@ -44,9 +47,13 @@ Actions:
DenyList: [] DenyList: []
`}, `},
want: func(t *testing.T, config *Config) { want: func(t *testing.T, config *Config) {
assert.Equal(t, config.DefaultInstance.Features, &command.InstanceFeatures{ assert.Equal(t, config.DefaultInstance.Features, &command.InstanceSetupFeatures{
LoginDefaultOrg: gu.Ptr(true), LoginDefaultOrg: gu.Ptr(true),
UserSchema: gu.Ptr(true), UserSchema: gu.Ptr(true),
LoginV2: &command.InstanceSetupFeatureLoginV2{
Required: true,
BaseURI: gu.Ptr("http://zitadel:8080"),
},
}) })
}, },
}, { }, {

View File

@@ -74,6 +74,9 @@ DefaultInstance:
Features: Features:
LoginDefaultOrg: true LoginDefaultOrg: true
UserSchema: true UserSchema: true
LoginV2:
Required: true
BaseURI: 'http://zitadel:8080'
Log: Log:
Level: info Level: info
Actions: Actions:
@@ -81,9 +84,13 @@ Actions:
DenyList: [] DenyList: []
`}, `},
want: func(t *testing.T, config *Config) { want: func(t *testing.T, config *Config) {
assert.Equal(t, config.DefaultInstance.Features, &command.InstanceFeatures{ assert.Equal(t, config.DefaultInstance.Features, &command.InstanceSetupFeatures{
LoginDefaultOrg: gu.Ptr(true), LoginDefaultOrg: gu.Ptr(true),
UserSchema: gu.Ptr(true), UserSchema: gu.Ptr(true),
LoginV2: &command.InstanceSetupFeatureLoginV2{
Required: true,
BaseURI: gu.Ptr("http://zitadel:8080"),
},
}) })
}, },
}, { }, {

View File

@@ -2,6 +2,7 @@ package command
import ( import (
"context" "context"
"net/url"
"strings" "strings"
"time" "time"
@@ -14,6 +15,7 @@ import (
"github.com/zitadel/zitadel/internal/crypto" "github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore" "github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/feature"
"github.com/zitadel/zitadel/internal/i18n" "github.com/zitadel/zitadel/internal/i18n"
"github.com/zitadel/zitadel/internal/id" "github.com/zitadel/zitadel/internal/id"
"github.com/zitadel/zitadel/internal/notification/channels/smtp" "github.com/zitadel/zitadel/internal/notification/channels/smtp"
@@ -122,12 +124,59 @@ type InstanceSetup struct {
SMTPConfiguration *SMTPConfiguration SMTPConfiguration *SMTPConfiguration
OIDCSettings *OIDCSettings OIDCSettings *OIDCSettings
Quotas *SetQuotas Quotas *SetQuotas
Features *InstanceFeatures Features *InstanceSetupFeatures
Limits *SetLimits Limits *SetLimits
Restrictions *SetRestrictions Restrictions *SetRestrictions
RolePermissionMappings []authz.RoleMapping RolePermissionMappings []authz.RoleMapping
} }
type InstanceSetupFeatures struct {
LoginDefaultOrg *bool
UserSchema *bool
TokenExchange *bool
ImprovedPerformance []feature.ImprovedPerformanceType
DebugOIDCParentError *bool
OIDCSingleV1SessionTermination *bool
EnableBackChannelLogout *bool
LoginV2 *InstanceSetupFeatureLoginV2
PermissionCheckV2 *bool
ConsoleUseV2UserApi *bool
}
type InstanceSetupFeatureLoginV2 struct {
Required bool `json:"required,omitempty"`
BaseURI *string `json:"base_uri,omitempty"`
}
func (f *InstanceSetupFeatures) ToInstanceFeatures() (_ *InstanceFeatures, err error) {
if f == nil {
return nil, nil
}
var loginV2 *feature.LoginV2
if f.LoginV2 != nil {
loginV2 = &feature.LoginV2{Required: f.LoginV2.Required}
if f.LoginV2.BaseURI != nil {
loginV2.BaseURI, err = url.Parse(*f.LoginV2.BaseURI)
if err != nil {
return nil, err
}
}
}
return &InstanceFeatures{
LoginDefaultOrg: f.LoginDefaultOrg,
UserSchema: f.UserSchema,
TokenExchange: f.TokenExchange,
ImprovedPerformance: f.ImprovedPerformance,
DebugOIDCParentError: f.DebugOIDCParentError,
OIDCSingleV1SessionTermination: f.OIDCSingleV1SessionTermination,
EnableBackChannelLogout: f.EnableBackChannelLogout,
LoginV2: loginV2,
PermissionCheckV2: f.PermissionCheckV2,
ConsoleUseV2UserApi: f.ConsoleUseV2UserApi,
}, nil
}
type SMTPConfiguration struct { type SMTPConfiguration struct {
Description string Description string
SMTP smtp.SMTP SMTP smtp.SMTP
@@ -421,7 +470,7 @@ func setupQuotas(commands *Commands, validations *[]preparation.Validation, setQ
return nil return nil
} }
func setupFeatures(validations *[]preparation.Validation, features *InstanceFeatures, instanceID string) { func setupFeatures(validations *[]preparation.Validation, features *InstanceSetupFeatures, instanceID string) {
if features != nil { if features != nil {
*validations = append(*validations, prepareSetFeatures(instanceID, features)) *validations = append(*validations, prepareSetFeatures(instanceID, features))
} }

View File

@@ -57,11 +57,16 @@ func (c *Commands) SetInstanceFeatures(ctx context.Context, f *InstanceFeatures)
return pushedEventsToObjectDetails(events), nil return pushedEventsToObjectDetails(events), nil
} }
func prepareSetFeatures(instanceID string, f *InstanceFeatures) preparation.Validation { func prepareSetFeatures(instanceID string, f *InstanceSetupFeatures) preparation.Validation {
return func() (preparation.CreateCommands, error) { return func() (preparation.CreateCommands, error) {
features, err := f.ToInstanceFeatures()
if err != nil {
return nil, err
}
return func(ctx context.Context, _ preparation.FilterToQueryReducer) ([]eventstore.Command, error) { return func(ctx context.Context, _ preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
wm := NewInstanceFeaturesWriteModel(instanceID) wm := NewInstanceFeaturesWriteModel(instanceID)
return wm.setCommands(ctx, f), nil return wm.setCommands(ctx, features), nil
}, nil }, nil
} }
} }