feat(settings): add secret generator type to settings RT implementation (#11152)

# Which Problems Are Solved

The `SecretGenerators` setting is missing among the instance settings in
the new relational model.

# How the Problems Are Solved

This PR adds:
* `SettingTypeSecretGenerator` type to the settings model
* `SecretGeneratorSettingsRepository` and
`secretGeneratorSettingsJSONChanges` interfaces to set, retrieve, and
delete `secret_generator` settings, and corresponding unit tests.
* projection reducers to reduce the following events:
  * `SecretGeneratorAddedEvent`
  * `SecretGeneratorChangedEvent`
  * `SecretGeneratorRemovedEvent`
* integration tests to test that the events get reduced correctly 

# Additional Changes
N/A

# Additional Context
- Part of https://github.com/zitadel/zitadel/issues/10207

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
This commit is contained in:
Gayathri Vijayan
2025-12-11 12:33:19 +01:00
committed by GitHub
co-authored by Copilot Marco A.
parent 826039c620
commit 3903355d18
9 changed files with 2209 additions and 49 deletions
File diff suppressed because it is too large Load Diff
+87
View File
@@ -23,6 +23,7 @@ const (
SettingTypeOrganization
SettingTypeNotification
SettingTypeLegalAndSupport
SettingTypeSecretGenerator
)
//go:generate enumer -type SettingState -transform snake -trimprefix SettingState -sql
@@ -428,3 +429,89 @@ type LegalAndSupportSettingsRepository interface {
settingsRepository[LegalAndSupportSettings]
legalAndSupportSettingsJSONChanges
}
type SecretGeneratorSettings struct {
Settings
SecretGeneratorSettingsAttributes
}
//go:generate mockgen -typed -package domainmock -destination ./mock/secret_generator_settings.mock.go . SecretGeneratorSettingsRepository
type SecretGeneratorSettingsRepository interface {
settingsRepository[SecretGeneratorSettings]
secretGeneratorSettingsJSONChanges
}
type secretGeneratorSettingsJSONChanges interface {
SetSettingFields(value SecretGeneratorSettingsAttributes) database.Change
SetClientSecret(value ClientSecretAttributes) db_json.JsonUpdate
SetInitializeUserCode(value InitializeUserCodeAttributes) db_json.JsonUpdate
SetEmailVerificationCode(value EmailVerificationCodeAttributes) db_json.JsonUpdate
SetPhoneVerificationCode(value PhoneVerificationCodeAttributes) db_json.JsonUpdate
SetPasswordVerificationCode(value PasswordVerificationCodeAttributes) db_json.JsonUpdate
SetPasswordlessInitCode(value PasswordlessInitCodeAttributes) db_json.JsonUpdate
SetDomainVerification(value DomainVerificationAttributes) db_json.JsonUpdate
SetOTPSMS(value OTPSMSAttributes) db_json.JsonUpdate
SetOTPEmail(value OTPEmailAttributes) db_json.JsonUpdate
}
type SecretGeneratorSettingsAttributes struct {
ClientSecret *ClientSecretAttributes `json:"clientSecret,omitempty"`
InitializeUserCode *InitializeUserCodeAttributes `json:"initializeUserCode,omitempty"`
EmailVerificationCode *EmailVerificationCodeAttributes `json:"emailVerificationCode,omitempty"`
PhoneVerificationCode *PhoneVerificationCodeAttributes `json:"phoneVerificationCode,omitempty"`
PasswordVerificationCode *PasswordVerificationCodeAttributes `json:"passwordVerificationCode,omitempty"`
PasswordlessInitCode *PasswordlessInitCodeAttributes `json:"passwordlessInitCode,omitempty"`
DomainVerification *DomainVerificationAttributes `json:"domainVerification,omitempty"`
OTPSMS *OTPSMSAttributes `json:"otpSms,omitempty"`
OTPEmail *OTPEmailAttributes `json:"otpEmail,omitempty"`
}
type ClientSecretAttributes struct {
SecretGeneratorAttrs
}
type InitializeUserCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type EmailVerificationCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type PhoneVerificationCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type PasswordVerificationCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type PasswordlessInitCodeAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type DomainVerificationAttributes struct {
SecretGeneratorAttrs
}
type OTPSMSAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type OTPEmailAttributes struct {
SecretGeneratorAttrsWithExpiry
}
type SecretGeneratorAttrs struct {
Length *uint `json:"length,omitempty"`
IncludeLowerLetters *bool `json:"includeLowerLetters,omitempty"`
IncludeUpperLetters *bool `json:"includeUpperLetters,omitempty"`
IncludeDigits *bool `json:"includeDigits,omitempty"`
IncludeSymbols *bool `json:"includeSymbols,omitempty"`
}
type SecretGeneratorAttrsWithExpiry struct {
Expiry *time.Duration `json:"expiry,omitempty"`
SecretGeneratorAttrs
}
+28 -24
View File
@@ -8,11 +8,11 @@ import (
"strings"
)
const _SettingTypeName = "loginbrandingpassword_complexitypassword_expirydomainlockoutsecurityorganizationnotificationlegal_and_support"
const _SettingTypeName = "loginbrandingpassword_complexitypassword_expirydomainlockoutsecurityorganizationnotificationlegal_and_supportsecret_generator"
var _SettingTypeIndex = [...]uint8{0, 5, 13, 32, 47, 53, 60, 68, 80, 92, 109}
var _SettingTypeIndex = [...]uint8{0, 5, 13, 32, 47, 53, 60, 68, 80, 92, 109, 125}
const _SettingTypeLowerName = "loginbrandingpassword_complexitypassword_expirydomainlockoutsecurityorganizationnotificationlegal_and_support"
const _SettingTypeLowerName = "loginbrandingpassword_complexitypassword_expirydomainlockoutsecurityorganizationnotificationlegal_and_supportsecret_generator"
func (i SettingType) String() string {
if i >= SettingType(len(_SettingTypeIndex)-1) {
@@ -35,31 +35,34 @@ func _SettingTypeNoOp() {
_ = x[SettingTypeOrganization-(7)]
_ = x[SettingTypeNotification-(8)]
_ = x[SettingTypeLegalAndSupport-(9)]
_ = x[SettingTypeSecretGenerator-(10)]
}
var _SettingTypeValues = []SettingType{SettingTypeLogin, SettingTypeBranding, SettingTypePasswordComplexity, SettingTypePasswordExpiry, SettingTypeDomain, SettingTypeLockout, SettingTypeSecurity, SettingTypeOrganization, SettingTypeNotification, SettingTypeLegalAndSupport}
var _SettingTypeValues = []SettingType{SettingTypeLogin, SettingTypeBranding, SettingTypePasswordComplexity, SettingTypePasswordExpiry, SettingTypeDomain, SettingTypeLockout, SettingTypeSecurity, SettingTypeOrganization, SettingTypeNotification, SettingTypeLegalAndSupport, SettingTypeSecretGenerator}
var _SettingTypeNameToValueMap = map[string]SettingType{
_SettingTypeName[0:5]: SettingTypeLogin,
_SettingTypeLowerName[0:5]: SettingTypeLogin,
_SettingTypeName[5:13]: SettingTypeBranding,
_SettingTypeLowerName[5:13]: SettingTypeBranding,
_SettingTypeName[13:32]: SettingTypePasswordComplexity,
_SettingTypeLowerName[13:32]: SettingTypePasswordComplexity,
_SettingTypeName[32:47]: SettingTypePasswordExpiry,
_SettingTypeLowerName[32:47]: SettingTypePasswordExpiry,
_SettingTypeName[47:53]: SettingTypeDomain,
_SettingTypeLowerName[47:53]: SettingTypeDomain,
_SettingTypeName[53:60]: SettingTypeLockout,
_SettingTypeLowerName[53:60]: SettingTypeLockout,
_SettingTypeName[60:68]: SettingTypeSecurity,
_SettingTypeLowerName[60:68]: SettingTypeSecurity,
_SettingTypeName[68:80]: SettingTypeOrganization,
_SettingTypeLowerName[68:80]: SettingTypeOrganization,
_SettingTypeName[80:92]: SettingTypeNotification,
_SettingTypeLowerName[80:92]: SettingTypeNotification,
_SettingTypeName[92:109]: SettingTypeLegalAndSupport,
_SettingTypeLowerName[92:109]: SettingTypeLegalAndSupport,
_SettingTypeName[0:5]: SettingTypeLogin,
_SettingTypeLowerName[0:5]: SettingTypeLogin,
_SettingTypeName[5:13]: SettingTypeBranding,
_SettingTypeLowerName[5:13]: SettingTypeBranding,
_SettingTypeName[13:32]: SettingTypePasswordComplexity,
_SettingTypeLowerName[13:32]: SettingTypePasswordComplexity,
_SettingTypeName[32:47]: SettingTypePasswordExpiry,
_SettingTypeLowerName[32:47]: SettingTypePasswordExpiry,
_SettingTypeName[47:53]: SettingTypeDomain,
_SettingTypeLowerName[47:53]: SettingTypeDomain,
_SettingTypeName[53:60]: SettingTypeLockout,
_SettingTypeLowerName[53:60]: SettingTypeLockout,
_SettingTypeName[60:68]: SettingTypeSecurity,
_SettingTypeLowerName[60:68]: SettingTypeSecurity,
_SettingTypeName[68:80]: SettingTypeOrganization,
_SettingTypeLowerName[68:80]: SettingTypeOrganization,
_SettingTypeName[80:92]: SettingTypeNotification,
_SettingTypeLowerName[80:92]: SettingTypeNotification,
_SettingTypeName[92:109]: SettingTypeLegalAndSupport,
_SettingTypeLowerName[92:109]: SettingTypeLegalAndSupport,
_SettingTypeName[109:125]: SettingTypeSecretGenerator,
_SettingTypeLowerName[109:125]: SettingTypeSecretGenerator,
}
var _SettingTypeNames = []string{
@@ -73,6 +76,7 @@ var _SettingTypeNames = []string{
_SettingTypeName[68:80],
_SettingTypeName[80:92],
_SettingTypeName[92:109],
_SettingTypeName[109:125],
}
// SettingTypeString retrieves an enum value from the enum constants string name.
@@ -8,7 +8,8 @@ CREATE TYPE zitadel.settings_type AS ENUM (
'security',
'organization',
'notification',
'legal_and_support'
'legal_and_support',
'secret_generator'
);
CREATE TYPE zitadel.settings_state AS ENUM (
+2 -1
View File
@@ -6,7 +6,8 @@ import (
)
var (
ErrNoChanges = errors.New("update must contain a change")
ErrNoChanges = errors.New("update must contain a change")
ErrInvalidChangeTarget = errors.New("change target must not be nil")
)
type MissingConditionError struct {
@@ -26,6 +26,7 @@ import (
"github.com/zitadel/zitadel/pkg/grpc/admin"
instance "github.com/zitadel/zitadel/pkg/grpc/instance/v2beta"
"github.com/zitadel/zitadel/pkg/grpc/policy"
settings_pb "github.com/zitadel/zitadel/pkg/grpc/settings"
)
//go:embed picture.png
@@ -1387,3 +1388,150 @@ func TestServer_TestInstanceLegalAndSupportSettingsReduces(t *testing.T) {
}, retryDuration, tick)
})
}
func TestServer_TestInstanceSecretGeneratorSettingsReduces(t *testing.T) {
t.Parallel()
settingsRepo := repository.SecretGeneratorSettingsRepository()
newInstance := integration.NewInstance(t.Context())
IAMCTX := newInstance.WithAuthorizationToken(t.Context(), integration.UserTypeIAMOwner)
t.Run("test secret generator settings set", func(t *testing.T) {
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(IAMCTX, time.Second*20)
assert.EventuallyWithT(t, func(collect *assert.CollectT) {
setting, err := settingsRepo.Get(
IAMCTX, pool,
database.WithCondition(
settingsRepo.UniqueCondition(newInstance.ID(), nil, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
),
)
require.NoError(collect, err)
// ClientSecret
assert.Equal(collect, uint(64), *setting.ClientSecret.Length)
assert.Equal(collect, true, *setting.ClientSecret.IncludeLowerLetters)
assert.Equal(collect, true, *setting.ClientSecret.IncludeUpperLetters)
assert.Equal(collect, true, *setting.ClientSecret.IncludeDigits)
assert.Equal(collect, false, *setting.ClientSecret.IncludeSymbols)
// InitializeUserCode
assert.Equal(collect, uint(6), *setting.InitializeUserCode.Length)
assert.Equal(collect, 72*time.Hour, *setting.InitializeUserCode.Expiry)
assert.Equal(collect, false, *setting.InitializeUserCode.IncludeLowerLetters)
assert.Equal(collect, true, *setting.InitializeUserCode.IncludeUpperLetters)
assert.Equal(collect, true, *setting.InitializeUserCode.IncludeDigits)
assert.Equal(collect, false, *setting.InitializeUserCode.IncludeSymbols)
// EmailVerificationCode
assert.Equal(collect, uint(6), *setting.EmailVerificationCode.Length)
assert.Equal(collect, 1*time.Hour, *setting.EmailVerificationCode.Expiry)
assert.Equal(collect, false, *setting.EmailVerificationCode.IncludeLowerLetters)
assert.Equal(collect, true, *setting.EmailVerificationCode.IncludeUpperLetters)
assert.Equal(collect, true, *setting.EmailVerificationCode.IncludeDigits)
assert.Equal(collect, false, *setting.EmailVerificationCode.IncludeSymbols)
// PhoneVerificationCode
assert.Equal(collect, uint(6), *setting.PhoneVerificationCode.Length)
assert.Equal(collect, 1*time.Hour, *setting.PhoneVerificationCode.Expiry)
assert.Equal(collect, false, *setting.PhoneVerificationCode.IncludeLowerLetters)
assert.Equal(collect, true, *setting.PhoneVerificationCode.IncludeUpperLetters)
assert.Equal(collect, true, *setting.PhoneVerificationCode.IncludeDigits)
assert.Equal(collect, false, *setting.PhoneVerificationCode.IncludeSymbols)
// PasswordVerificationCode
assert.Equal(collect, uint(6), *setting.PasswordVerificationCode.Length)
assert.Equal(collect, 1*time.Hour, *setting.PasswordVerificationCode.Expiry)
assert.Equal(collect, false, *setting.PasswordVerificationCode.IncludeLowerLetters)
assert.Equal(collect, true, *setting.PasswordVerificationCode.IncludeUpperLetters)
assert.Equal(collect, true, *setting.PasswordVerificationCode.IncludeDigits)
assert.Equal(collect, false, *setting.PasswordVerificationCode.IncludeSymbols)
// PasswordlessInitCode
assert.Equal(collect, uint(12), *setting.PasswordlessInitCode.Length)
assert.Equal(collect, 1*time.Hour, *setting.PasswordlessInitCode.Expiry)
assert.Equal(collect, true, *setting.PasswordlessInitCode.IncludeLowerLetters)
assert.Equal(collect, true, *setting.PasswordlessInitCode.IncludeUpperLetters)
assert.Equal(collect, true, *setting.PasswordlessInitCode.IncludeDigits)
assert.Equal(collect, false, *setting.PasswordlessInitCode.IncludeSymbols)
// DomainVerification
assert.Equal(collect, uint(32), *setting.DomainVerification.Length)
assert.Equal(collect, true, *setting.DomainVerification.IncludeLowerLetters)
assert.Equal(collect, true, *setting.DomainVerification.IncludeUpperLetters)
assert.Equal(collect, true, *setting.DomainVerification.IncludeDigits)
assert.Equal(collect, false, *setting.DomainVerification.IncludeSymbols)
// OTPSMS
assert.Equal(collect, uint(8), *setting.OTPSMS.Length)
assert.Equal(collect, 5*time.Minute, *setting.OTPSMS.Expiry)
assert.Equal(collect, false, *setting.OTPSMS.IncludeLowerLetters)
assert.Equal(collect, false, *setting.OTPSMS.IncludeUpperLetters)
assert.Equal(collect, true, *setting.OTPSMS.IncludeDigits)
assert.Equal(collect, false, *setting.OTPSMS.IncludeSymbols)
// OTPEmail
assert.Equal(collect, uint(8), *setting.OTPEmail.Length)
assert.Equal(collect, 5*time.Minute, *setting.OTPEmail.Expiry)
assert.Equal(collect, false, *setting.OTPEmail.IncludeLowerLetters)
assert.Equal(collect, false, *setting.OTPEmail.IncludeUpperLetters)
assert.Equal(collect, true, *setting.OTPEmail.IncludeDigits)
assert.Equal(collect, false, *setting.OTPEmail.IncludeSymbols)
}, retryDuration, tick)
})
t.Run("test secret generator settings update", func(t *testing.T) {
before := time.Now()
_, err := newInstance.Client.Admin.UpdateSecretGenerator(IAMCTX, &admin.UpdateSecretGeneratorRequest{
GeneratorType: settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_INIT_CODE,
IncludeLowerLetters: true,
Expiry: durationpb.New(24 * time.Hour),
Length: uint32(8),
})
require.NoError(t, err)
after := time.Now()
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(IAMCTX, time.Second*20)
assert.EventuallyWithT(t, func(collect *assert.CollectT) {
setting, err := settingsRepo.Get(
IAMCTX, pool,
database.WithCondition(
settingsRepo.UniqueCondition(newInstance.ID(), nil, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
),
)
require.NoError(t, err)
assert.Equal(collect, uint(8), *setting.InitializeUserCode.Length)
assert.Equal(collect, 24*time.Hour, *setting.InitializeUserCode.Expiry)
assert.Equal(collect, true, *setting.InitializeUserCode.IncludeLowerLetters)
assert.WithinRange(collect, setting.UpdatedAt, before, after)
}, retryDuration, tick)
})
t.Run("test delete instance reduces", func(t *testing.T) {
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(IAMCTX, time.Second*20)
assert.EventuallyWithT(t, func(collect *assert.CollectT) {
setting, err := settingsRepo.Get(
IAMCTX, pool,
database.WithCondition(
settingsRepo.UniqueCondition(newInstance.ID(), nil, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
),
)
require.NoError(collect, err)
require.NotNil(collect, setting)
}, retryDuration, tick)
_, err := newInstance.Client.InstanceV2Beta.DeleteInstance(CTX, &instance.DeleteInstanceRequest{
InstanceId: newInstance.ID(),
})
require.NoError(t, err)
retryDuration, tick = integration.WaitForAndTickWithMaxDuration(IAMCTX, time.Second*20)
assert.EventuallyWithT(t, func(collect *assert.CollectT) {
_, err := settingsRepo.Get(
IAMCTX, pool,
database.WithCondition(
settingsRepo.UniqueCondition(newInstance.ID(), nil, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
),
)
require.ErrorIs(collect, err, new(database.NoRowFoundError))
}, retryDuration, tick)
})
}
@@ -149,6 +149,10 @@ func (s settings) list(ctx context.Context, client database.QueryExecutor, opts
}
func (s settings) set(ctx context.Context, client database.QueryExecutor, settings *domain.Settings, changes ...database.Change) error {
if settings == nil {
return database.ErrInvalidChangeTarget
}
var (
id, createdAt, updatedAt any = database.DefaultInstruction, database.DefaultInstruction, database.DefaultInstruction
)
@@ -378,6 +382,10 @@ func LoginSettingsRepository() domain.LoginSettingsRepository {
var _ domain.LoginSettingsRepository = (*loginSettings)(nil)
func (s loginSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.LoginSettings) error {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeLogin
settings.State = domain.SettingStateActive
@@ -572,6 +580,10 @@ func BrandingSettingsRepository() domain.BrandingSettingsRepository {
var _ domain.BrandingSettingsRepository = (*brandingSettings)(nil)
func (s brandingSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.BrandingSettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeBranding
settings.State = domain.SettingStatePreview
@@ -719,6 +731,10 @@ func PasswordComplexitySettingsRepository() domain.PasswordComplexitySettingsRep
var _ domain.PasswordComplexitySettingsRepository = (*passwordComplexitySettings)(nil)
func (s passwordComplexitySettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.PasswordComplexitySettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypePasswordComplexity
settings.State = domain.SettingStateActive
@@ -801,6 +817,10 @@ func PasswordExpirySettingsRepository() domain.PasswordExpirySettingsRepository
}
func (s passwordExpirySettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.PasswordExpirySettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypePasswordExpiry
settings.State = domain.SettingStateActive
@@ -889,6 +909,10 @@ func LockoutSettingsRepository() domain.LockoutSettingsRepository {
var _ domain.LockoutSettingsRepository = (*lockoutSettings)(nil)
func (s lockoutSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.LockoutSettings) error {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeLockout
settings.State = domain.SettingStateActive
@@ -977,6 +1001,10 @@ func SecuritySettingsRepository() domain.SecuritySettingsRepository {
var _ domain.SecuritySettingsRepository = (*securitySettings)(nil)
func (s securitySettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.SecuritySettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeSecurity
settings.State = domain.SettingStateActive
@@ -1065,6 +1093,10 @@ func DomainSettingsRepository() domain.DomainSettingsRepository {
var _ domain.DomainSettingsRepository = (*domainSettings)(nil)
func (s domainSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.DomainSettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeDomain
settings.State = domain.SettingStateActive
@@ -1139,6 +1171,10 @@ func OrganizationSettingsRepository() domain.OrganizationSettingsRepository {
var _ domain.OrganizationSettingsRepository = (*organizationSettings)(nil)
func (s organizationSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.OrganizationSettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeOrganization
settings.State = domain.SettingStateActive
@@ -1213,6 +1249,10 @@ func NotificationSettingsRepository() domain.NotificationSettingsRepository {
var _ domain.NotificationSettingsRepository = (*notificationSettings)(nil)
func (s notificationSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.NotificationSettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeNotification
settings.State = domain.SettingStateActive
@@ -1329,6 +1369,10 @@ func LegalAndSupportSettingsRepository() domain.LegalAndSupportSettingsRepositor
var _ domain.LegalAndSupportSettingsRepository = (*legalAndSupportSettings)(nil)
func (s legalAndSupportSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.LegalAndSupportSettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeLegalAndSupport
settings.State = domain.SettingStateActive
@@ -1375,6 +1419,141 @@ func (s legalAndSupportSettings) Get(ctx context.Context, client database.QueryE
return item, nil
}
// -------------------------------------------------------------
// secret generators
// -------------------------------------------------------------
type secretGeneratorSettings struct {
settings
}
func (s secretGeneratorSettings) SetSettingFields(value domain.SecretGeneratorSettingsAttributes) database.Change {
changes := make([]db_json.JsonUpdate, 0, 11)
if value.ClientSecret != nil {
changes = append(changes, s.SetClientSecret(*value.ClientSecret))
}
if value.InitializeUserCode != nil {
changes = append(changes, s.SetInitializeUserCode(*value.InitializeUserCode))
}
if value.EmailVerificationCode != nil {
changes = append(changes, s.SetEmailVerificationCode(*value.EmailVerificationCode))
}
if value.PhoneVerificationCode != nil {
changes = append(changes, s.SetPhoneVerificationCode(*value.PhoneVerificationCode))
}
if value.PasswordVerificationCode != nil {
changes = append(changes, s.SetPasswordVerificationCode(*value.PasswordVerificationCode))
}
if value.PasswordlessInitCode != nil {
changes = append(changes, s.SetPasswordlessInitCode(*value.PasswordlessInitCode))
}
if value.DomainVerification != nil {
changes = append(changes, s.SetDomainVerification(*value.DomainVerification))
}
if value.OTPSMS != nil {
changes = append(changes, s.SetOTPSMS(*value.OTPSMS))
}
if value.OTPEmail != nil {
changes = append(changes, s.SetOTPEmail(*value.OTPEmail))
}
return db_json.NewJsonChanges(s.SettingsColumn(), changes...)
}
func (s secretGeneratorSettings) SetClientSecret(value domain.ClientSecretAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"clientSecret"}, value)
}
func (s secretGeneratorSettings) SetInitializeUserCode(value domain.InitializeUserCodeAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"initializeUserCode"}, value)
}
func (s secretGeneratorSettings) SetEmailVerificationCode(value domain.EmailVerificationCodeAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"emailVerificationCode"}, value)
}
func (s secretGeneratorSettings) SetPhoneVerificationCode(value domain.PhoneVerificationCodeAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"phoneVerificationCode"}, value)
}
func (s secretGeneratorSettings) SetPasswordVerificationCode(value domain.PasswordVerificationCodeAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"passwordVerificationCode"}, value)
}
func (s secretGeneratorSettings) SetPasswordlessInitCode(value domain.PasswordlessInitCodeAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"passwordlessInitCode"}, value)
}
func (s secretGeneratorSettings) SetDomainVerification(value domain.DomainVerificationAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"domainVerification"}, value)
}
func (s secretGeneratorSettings) SetOTPSMS(value domain.OTPSMSAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"otpSms"}, value)
}
func (s secretGeneratorSettings) SetOTPEmail(value domain.OTPEmailAttributes) db_json.JsonUpdate {
return db_json.NewFieldChange([]string{"otpEmail"}, value)
}
func SecretGeneratorSettingsRepository() domain.SecretGeneratorSettingsRepository {
return &secretGeneratorSettings{
settings{},
}
}
var _ domain.SecretGeneratorSettingsRepository = (*secretGeneratorSettings)(nil)
func (s secretGeneratorSettings) Set(ctx context.Context, client database.QueryExecutor, settings *domain.SecretGeneratorSettings) (err error) {
if settings == nil {
return database.ErrInvalidChangeTarget
}
settings.Type = domain.SettingTypeSecretGenerator
settings.State = domain.SettingStateActive
settingsJSON, err := json.Marshal(settings.SecretGeneratorSettingsAttributes)
if err != nil {
return err
}
settings.Settings.Settings = settingsJSON
if err := s.set(ctx, client, &settings.Settings, s.SetSettingFields(settings.SecretGeneratorSettingsAttributes)); err != nil {
return err
}
settings.Settings.Settings = nil
return nil
}
func (s secretGeneratorSettings) List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*domain.SecretGeneratorSettings, error) {
settings, err := s.list(ctx, client, opts...)
if err != nil {
return nil, err
}
list := make([]*domain.SecretGeneratorSettings, len(settings))
for i := range settings {
list[i] = &domain.SecretGeneratorSettings{Settings: *settings[i]}
if err := json.Unmarshal(list[i].Settings.Settings, &list[i].SecretGeneratorSettingsAttributes); err != nil {
return nil, err
}
list[i].Settings.Settings = nil
}
return list, nil
}
func (s secretGeneratorSettings) Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.SecretGeneratorSettings, error) {
settings, err := s.get(ctx, client, opts...)
if err != nil {
return nil, err
}
item := &domain.SecretGeneratorSettings{Settings: *settings}
if err = json.Unmarshal(item.Settings.Settings, &item.SecretGeneratorSettingsAttributes); err != nil {
return nil, err
}
item.Settings.Settings = nil
return item, nil
}
// -------------------------------------------------------------
// helpers
// -------------------------------------------------------------
@@ -498,6 +498,11 @@ func TestSetLoginSettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -1167,6 +1172,11 @@ func TestSetBrandingSettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -1912,6 +1922,11 @@ func TestSetPasswordComplexitySettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -2300,6 +2315,11 @@ func TestSetPasswordExpirySettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -2695,6 +2715,11 @@ func TestSetLockoutSettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -3092,6 +3117,11 @@ func TestSetSecuritySettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -3489,6 +3519,11 @@ func TestSetDomainSettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -3860,6 +3895,11 @@ func TestSetOrganizationSettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -4227,6 +4267,11 @@ func TestSetNotificationSettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -4672,6 +4717,11 @@ func TestSetLegalAndSupportSettings(t *testing.T) {
},
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -4774,3 +4824,325 @@ func TestDeleteLegalAndSupportSettings(t *testing.T) {
})
}
}
func TestGetSecretGeneratorSettings(t *testing.T) {
tx, rollback := transactionForRollback(t)
defer rollback()
firstInstanceID := createInstance(t, tx)
secondInstanceID := createInstance(t, tx)
firstOrgID := createOrganization(t, tx, firstInstanceID)
secondOrgID := createOrganization(t, tx, secondInstanceID)
repo := repository.SecretGeneratorSettingsRepository()
settings := []*domain.SecretGeneratorSettings{
createSecretGeneratorSettings(firstInstanceID, nil),
createSecretGeneratorSettings(secondInstanceID, nil),
createSecretGeneratorSettings(firstInstanceID, gu.Ptr(firstOrgID)),
createSecretGeneratorSettings(secondInstanceID, gu.Ptr(secondOrgID)),
}
for _, setting := range settings {
err := repo.Set(t.Context(), tx, setting)
require.NoError(t, err)
}
tests := []struct {
name string
condition database.Condition
want *domain.SecretGeneratorSettings
wantErr error
}{
{
name: "incomplete condition",
condition: repo.IDCondition(settings[0].ID),
wantErr: database.NewMissingConditionError(repo.IDColumn()),
},
{
name: "not found",
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
wantErr: database.NewNoRowFoundError(nil),
},
{
name: "too many",
condition: repo.InstanceIDCondition(firstInstanceID),
wantErr: database.NewMultipleRowsFoundError(nil),
},
{
name: "ok, instance",
condition: repo.PrimaryKeyCondition(firstInstanceID, settings[0].ID),
want: settings[0],
},
{
name: "ok, organization",
condition: repo.PrimaryKeyCondition(secondInstanceID, settings[3].ID),
want: settings[3],
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := repo.Get(t.Context(), tx, database.WithCondition(tt.condition))
require.ErrorIs(t, err, tt.wantErr)
assert.EqualExportedValues(t, tt.want, got)
})
}
}
func TestListSecretGeneratorSettings(t *testing.T) {
tx, rollback := transactionForRollback(t)
defer rollback()
firstInstanceID := createInstance(t, tx)
secondInstanceID := createInstance(t, tx)
firstOrgID := createOrganization(t, tx, firstInstanceID)
secondOrgID := createOrganization(t, tx, secondInstanceID)
repo := repository.SecretGeneratorSettingsRepository()
settings := []*domain.SecretGeneratorSettings{
createSecretGeneratorSettings(firstInstanceID, nil),
createSecretGeneratorSettings(secondInstanceID, nil),
createSecretGeneratorSettings(firstInstanceID, gu.Ptr(firstOrgID)),
createSecretGeneratorSettings(secondInstanceID, gu.Ptr(secondOrgID)),
}
for _, setting := range settings {
err := repo.Set(t.Context(), tx, setting)
require.NoError(t, err)
}
tests := []struct {
name string
condition database.Condition
want []*domain.SecretGeneratorSettings
wantErr error
}{
{
name: "incomplete condition",
condition: repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
wantErr: database.NewMissingConditionError(repo.IDColumn()),
},
{
name: "no results, ok",
condition: repo.PrimaryKeyCondition(firstInstanceID, "nix"),
want: []*domain.SecretGeneratorSettings{},
},
{
name: "all from instance",
condition: repo.InstanceIDCondition(firstInstanceID),
want: []*domain.SecretGeneratorSettings{settings[2], settings[0]},
},
{
name: "only from instance",
condition: database.And(
repo.InstanceIDCondition(firstInstanceID),
repo.OrganizationIDCondition(nil),
),
want: []*domain.SecretGeneratorSettings{settings[0]},
},
{
name: "all from first org",
condition: database.And(
repo.InstanceIDCondition(firstInstanceID),
repo.OrganizationIDCondition(gu.Ptr(firstOrgID)),
),
want: []*domain.SecretGeneratorSettings{settings[2]},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := repo.List(t.Context(), tx,
database.WithCondition(tt.condition),
database.WithOrderByAscending(repo.InstanceIDColumn(), repo.OrganizationIDColumn()),
)
require.ErrorIs(t, err, tt.wantErr)
assert.EqualExportedValues(t, tt.want, got)
})
}
}
func TestSetSecretGeneratorSettings(t *testing.T) {
tx, rollback := transactionForRollback(t)
defer rollback()
instanceID := createInstance(t, tx)
orgID := createOrganization(t, tx, instanceID)
repo := repository.SecretGeneratorSettingsRepository()
existingSettings := createSecretGeneratorSettings(instanceID, gu.Ptr(orgID))
err := repo.Set(t.Context(), tx, existingSettings)
require.NoError(t, err)
tests := []struct {
name string
settings *domain.SecretGeneratorSettings
wantErr error
}{
{
name: "create instance",
settings: createSecretGeneratorSettings(instanceID, nil),
},
{
name: "update organization",
settings: createSecretGeneratorSettings(instanceID, gu.Ptr(orgID)),
},
{
name: "non-existing instance",
settings: createSecretGeneratorSettings("foo", nil),
wantErr: new(database.ForeignKeyError),
},
{
name: "non-existing org",
settings: createSecretGeneratorSettings(instanceID, gu.Ptr("foo")),
wantErr: new(database.ForeignKeyError),
},
{
name: "nil settings",
settings: nil,
wantErr: database.ErrInvalidChangeTarget,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
savepoint, rollback := savepointForRollback(t, tx)
defer rollback()
err := repo.Set(t.Context(), savepoint, tt.settings)
require.ErrorIs(t, err, tt.wantErr)
})
}
}
func TestDeleteSecretGeneratorSettings(t *testing.T) {
tx, rollback := transactionForRollback(t)
defer rollback()
instanceID := createInstance(t, tx)
orgID := createOrganization(t, tx, instanceID)
repo := repository.SecretGeneratorSettingsRepository()
existingInstanceSettings := createSecretGeneratorSettings(instanceID, nil)
err := repo.Set(t.Context(), tx, existingInstanceSettings)
require.NoError(t, err)
existingOrganizationSettings := createSecretGeneratorSettings(instanceID, gu.Ptr(orgID))
err = repo.Set(t.Context(), tx, existingOrganizationSettings)
require.NoError(t, err)
tests := []struct {
name string
condition database.Condition
wantRowsAffected int64
wantErr error
}{
{
name: "incomplete condition",
condition: repo.InstanceIDCondition(instanceID),
wantRowsAffected: 0,
wantErr: database.NewMissingConditionError(repo.IDColumn()),
},
{
name: "not found",
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, gu.Ptr("foo"), domain.SettingTypeSecretGenerator, domain.SettingStateActive),
wantRowsAffected: 0,
},
{
name: "delete instance",
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
wantRowsAffected: 1,
},
{
name: "delete instance twice",
condition: repo.UniqueCondition(existingInstanceSettings.InstanceID, existingInstanceSettings.OrganizationID, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
wantRowsAffected: 0,
},
{
name: "delete organization",
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
wantRowsAffected: 1,
},
{
name: "delete organization twice",
condition: repo.UniqueCondition(existingOrganizationSettings.InstanceID, existingOrganizationSettings.OrganizationID, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
wantRowsAffected: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rowsAffected, err := repo.Delete(t.Context(), tx, tt.condition)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, tt.wantRowsAffected, rowsAffected)
})
}
}
func createDefaultSecretGeneratorAttrs() domain.SecretGeneratorAttrs {
return domain.SecretGeneratorAttrs{
Length: gu.Ptr(uint(32)),
IncludeUpperLetters: gu.Ptr(true),
IncludeLowerLetters: gu.Ptr(true),
IncludeDigits: gu.Ptr(true),
IncludeSymbols: gu.Ptr(false),
}
}
func createDefaultSecretGeneratorAttrsWithExpiry(expiry time.Duration) domain.SecretGeneratorAttrsWithExpiry {
return domain.SecretGeneratorAttrsWithExpiry{
Expiry: gu.Ptr(expiry),
SecretGeneratorAttrs: domain.SecretGeneratorAttrs{
Length: gu.Ptr(uint(32)),
IncludeUpperLetters: gu.Ptr(true),
IncludeLowerLetters: gu.Ptr(true),
IncludeDigits: gu.Ptr(true),
IncludeSymbols: gu.Ptr(false),
},
}
}
func createDefaultSecretGeneratorSettingsAttributes() domain.SecretGeneratorSettingsAttributes {
attrs := createDefaultSecretGeneratorAttrs()
oneDay := 24 * time.Hour
thirtyMinutes := 30 * time.Minute
tenMinutes := 10 * time.Minute
return domain.SecretGeneratorSettingsAttributes{
ClientSecret: &domain.ClientSecretAttributes{
SecretGeneratorAttrs: attrs,
},
InitializeUserCode: &domain.InitializeUserCodeAttributes{
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(oneDay),
},
EmailVerificationCode: &domain.EmailVerificationCodeAttributes{
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
},
PhoneVerificationCode: &domain.PhoneVerificationCodeAttributes{
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
},
PasswordVerificationCode: &domain.PasswordVerificationCodeAttributes{
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
},
PasswordlessInitCode: &domain.PasswordlessInitCodeAttributes{
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(tenMinutes),
},
DomainVerification: &domain.DomainVerificationAttributes{
SecretGeneratorAttrs: attrs,
},
OTPSMS: &domain.OTPSMSAttributes{
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
},
OTPEmail: &domain.OTPEmailAttributes{
SecretGeneratorAttrsWithExpiry: createDefaultSecretGeneratorAttrsWithExpiry(thirtyMinutes),
},
}
}
func createSecretGeneratorSettings(instanceID string, organizationID *string) *domain.SecretGeneratorSettings {
return &domain.SecretGeneratorSettings{
Settings: domain.Settings{
InstanceID: instanceID,
OrganizationID: organizationID,
},
SecretGeneratorSettingsAttributes: createDefaultSecretGeneratorSettingsAttributes(),
}
}
+193 -23
View File
@@ -4,12 +4,14 @@ import (
"context"
"database/sql"
"net/url"
"time"
"github.com/muhlemmer/gu"
"github.com/zitadel/zitadel/backend/v3/domain"
v3_sql "github.com/zitadel/zitadel/backend/v3/storage/database/dialect/sql"
"github.com/zitadel/zitadel/backend/v3/storage/database/repository"
legacy_domain "github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
"github.com/zitadel/zitadel/internal/repository/instance"
@@ -358,6 +360,19 @@ func (s *settingsRelationalProjection) Reducers() []handler.AggregateReducer {
Event: instance.PrivacyPolicyChangedEventType,
Reduce: s.reducePrivacyPolicyChanged,
},
// Secret Generator
{
Event: instance.SecretGeneratorAddedEventType,
Reduce: s.reduceSecretGeneratorAdded,
},
{
Event: instance.SecretGeneratorChangedEventType,
Reduce: s.reduceSecretGeneratorChanged,
},
{
Event: instance.SecretGeneratorRemovedEventType,
Reduce: s.reduceSecretGeneratorRemoved,
},
},
},
}
@@ -772,7 +787,7 @@ func (s *settingsRelationalProjection) reduceLabelActivated(event eventstore.Eve
}), nil
}
func (p *settingsRelationalProjection) reduceLogoAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceLogoAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyLogoAddedEvent
switch e := event.(type) {
@@ -810,7 +825,7 @@ func (p *settingsRelationalProjection) reduceLogoAdded(event eventstore.Event) (
}), nil
}
func (p *settingsRelationalProjection) reduceLogoDarkAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceLogoDarkAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyLogoDarkAddedEvent
switch e := event.(type) {
@@ -849,7 +864,7 @@ func (p *settingsRelationalProjection) reduceLogoDarkAdded(event eventstore.Even
}), nil
}
func (p *settingsRelationalProjection) reduceLogoRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceLogoRemoved(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyLogoRemovedEvent
switch e := event.(type) {
@@ -883,7 +898,7 @@ func (p *settingsRelationalProjection) reduceLogoRemoved(event eventstore.Event)
}), nil
}
func (p *settingsRelationalProjection) reduceLogoDarkRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceLogoDarkRemoved(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyLogoDarkRemovedEvent
switch e := event.(type) {
@@ -916,7 +931,7 @@ func (p *settingsRelationalProjection) reduceLogoDarkRemoved(event eventstore.Ev
}), nil
}
func (p *settingsRelationalProjection) reduceIconAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceIconAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyIconAddedEvent
switch e := event.(type) {
@@ -955,7 +970,7 @@ func (p *settingsRelationalProjection) reduceIconAdded(event eventstore.Event) (
}), nil
}
func (p *settingsRelationalProjection) reduceIconDarkAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceIconDarkAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyIconDarkAddedEvent
switch e := event.(type) {
@@ -994,7 +1009,7 @@ func (p *settingsRelationalProjection) reduceIconDarkAdded(event eventstore.Even
}), nil
}
func (p *settingsRelationalProjection) reduceIconRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceIconRemoved(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyIconRemovedEvent
switch e := event.(type) {
@@ -1028,7 +1043,7 @@ func (p *settingsRelationalProjection) reduceIconRemoved(event eventstore.Event)
}), nil
}
func (p *settingsRelationalProjection) reduceIconDarkRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceIconDarkRemoved(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyIconDarkRemovedEvent
switch e := event.(type) {
@@ -1062,7 +1077,7 @@ func (p *settingsRelationalProjection) reduceIconDarkRemoved(event eventstore.Ev
}), nil
}
func (p *settingsRelationalProjection) reduceFontAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceFontAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyFontAddedEvent
switch e := event.(type) {
@@ -1101,7 +1116,7 @@ func (p *settingsRelationalProjection) reduceFontAdded(event eventstore.Event) (
}), nil
}
func (p *settingsRelationalProjection) reduceFontRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceFontRemoved(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LabelPolicyFontRemovedEvent
switch e := event.(type) {
@@ -1135,7 +1150,7 @@ func (p *settingsRelationalProjection) reduceFontRemoved(event eventstore.Event)
}), nil
}
func (p *settingsRelationalProjection) reducePasswordComplexityAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reducePasswordComplexityAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.PasswordComplexityPolicyAddedEvent
switch e := event.(type) {
@@ -1232,7 +1247,7 @@ func (s *settingsRelationalProjection) reducePasswordComplexityRemoved(event eve
}), nil
}
func (p *settingsRelationalProjection) reducePasswordPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reducePasswordPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.PasswordAgePolicyAddedEvent
switch e := event.(type) {
@@ -1268,7 +1283,7 @@ func (p *settingsRelationalProjection) reducePasswordPolicyAdded(event eventstor
}), nil
}
func (p *settingsRelationalProjection) reducePasswordPolicyChanged(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reducePasswordPolicyChanged(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.PasswordAgePolicyChangedEvent
switch e := event.(type) {
@@ -1302,7 +1317,7 @@ func (p *settingsRelationalProjection) reducePasswordPolicyChanged(event eventst
}), nil
}
func (p *settingsRelationalProjection) reducePasswordPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reducePasswordPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
policyEvent, ok := event.(*org.PasswordAgePolicyRemovedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "PROJE-EtHWB", "reduce.wrong.event.type %s", org.PasswordAgePolicyRemovedEventType)
@@ -1321,7 +1336,7 @@ func (p *settingsRelationalProjection) reducePasswordPolicyRemoved(event eventst
}), nil
}
func (p *settingsRelationalProjection) reduceOrgLockoutPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceOrgLockoutPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
policyEvent, ok := event.(*org.LockoutPolicyRemovedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "PROJE-Bqut9", "reduce.wrong.event.type %s", org.LockoutPolicyRemovedEventType)
@@ -1340,7 +1355,7 @@ func (p *settingsRelationalProjection) reduceOrgLockoutPolicyRemoved(event event
}), nil
}
func (p *settingsRelationalProjection) reduceLockoutPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceLockoutPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LockoutPolicyAddedEvent
switch e := event.(type) {
@@ -1376,7 +1391,7 @@ func (p *settingsRelationalProjection) reduceLockoutPolicyAdded(event eventstore
}), nil
}
func (p *settingsRelationalProjection) reduceLockoutPolicyChanged(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceLockoutPolicyChanged(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.LockoutPolicyChangedEvent
switch e := event.(type) {
@@ -1413,7 +1428,7 @@ func (p *settingsRelationalProjection) reduceLockoutPolicyChanged(event eventsto
}), nil
}
func (p *settingsRelationalProjection) reduceDomainPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceDomainPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.DomainPolicyAddedEvent
switch e := event.(type) {
@@ -1486,7 +1501,7 @@ func (s *settingsRelationalProjection) reduceDomainPolicyChanged(event eventstor
}), nil
}
func (p *settingsRelationalProjection) reduceOrgDomainPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceOrgDomainPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
policyEvent, ok := event.(*org.DomainPolicyRemovedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "PROJE-Bqut9", "reduce.wrong.event.type %s", org.LockoutPolicyRemovedEventType)
@@ -1505,7 +1520,7 @@ func (p *settingsRelationalProjection) reduceOrgDomainPolicyRemoved(event events
}), nil
}
func (p *settingsRelationalProjection) reduceNotificationPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceNotificationPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.NotificationPolicyAddedEvent
switch e := event.(type) {
@@ -1575,7 +1590,7 @@ func (s *settingsRelationalProjection) reduceNotificationPolicyChanged(event eve
}), nil
}
func (p *settingsRelationalProjection) reduceOrgNotificationPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceOrgNotificationPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
policyEvent, ok := event.(*org.NotificationPolicyRemovedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "PROJE-Bqut9", "reduce.wrong.event.type %s", org.NotificationPolicyRemovedEventType)
@@ -1594,7 +1609,7 @@ func (p *settingsRelationalProjection) reduceOrgNotificationPolicyRemoved(event
}), nil
}
func (p *settingsRelationalProjection) reducePrivacyPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reducePrivacyPolicyAdded(event eventstore.Event) (*handler.Statement, error) {
var orgId *string
var policyEvent policy.PrivacyPolicyAddedEvent
switch e := event.(type) {
@@ -1680,7 +1695,7 @@ func (s *settingsRelationalProjection) reducePrivacyPolicyChanged(event eventsto
}), nil
}
func (p *settingsRelationalProjection) reduceOrgPrivacyPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
func (s *settingsRelationalProjection) reduceOrgPrivacyPolicyRemoved(event eventstore.Event) (*handler.Statement, error) {
policyEvent, ok := event.(*org.PrivacyPolicyRemovedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "PROJE-Bqut9", "reduce.wrong.event.type %s", org.PrivacyPolicyRemovedEventType)
@@ -1781,3 +1796,158 @@ func (s *settingsRelationalProjection) reduceOrganizationSettingsRemoved(event e
return err
}), nil
}
func (s *settingsRelationalProjection) reduceSecretGeneratorAdded(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SecretGeneratorAddedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-yTuWKA", "reduce.wrong.event.type %s", instance.SecretGeneratorAddedEventType)
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-jNhP6P", "reduce.wrong.db.pool %T", ex)
}
settingsRepo := repository.SecretGeneratorSettingsRepository()
secretGeneratorAttrs, err := setSecretGeneratorSettingsAttrs(
e.GeneratorType,
&e.Length,
&e.IncludeLowerLetters,
&e.IncludeUpperLetters,
&e.IncludeDigits,
&e.IncludeSymbols,
&e.Expiry,
)
if err != nil {
return err
}
settings := domain.SecretGeneratorSettings{
Settings: domain.Settings{
InstanceID: event.Aggregate().InstanceID,
OrganizationID: nil,
CreatedAt: e.Creation,
UpdatedAt: e.Creation,
},
SecretGeneratorSettingsAttributes: secretGeneratorAttrs,
}
return settingsRepo.Set(ctx, v3_sql.SQLTx(tx), &settings)
}), nil
}
func (s *settingsRelationalProjection) reduceSecretGeneratorChanged(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SecretGeneratorChangedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-HhaZbQ", "reduce.wrong.event.type %s", instance.SecretGeneratorChangedEventType)
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-3SidEv", "reduce.wrong.db.pool %T", ex)
}
settingsRepo := repository.SecretGeneratorSettingsRepository()
secretGeneratorAttrs, err := setSecretGeneratorSettingsAttrs(
e.GeneratorType,
e.Length,
e.IncludeLowerLetters,
e.IncludeUpperLetters,
e.IncludeDigits,
e.IncludeSymbols,
e.Expiry,
)
if err != nil {
return err
}
settings := domain.SecretGeneratorSettings{
Settings: domain.Settings{
InstanceID: event.Aggregate().InstanceID,
OrganizationID: nil,
UpdatedAt: e.Creation,
},
SecretGeneratorSettingsAttributes: secretGeneratorAttrs,
}
return settingsRepo.Set(ctx, v3_sql.SQLTx(tx), &settings)
}), nil
}
func (s *settingsRelationalProjection) reduceSecretGeneratorRemoved(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*instance.SecretGeneratorRemovedEvent)
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-fmiIf", "reduce.wrong.event.type %s", instance.SecretGeneratorRemovedEventType)
}
return handler.NewStatement(e, func(ctx context.Context, ex handler.Executer, projectionName string) error {
tx, ok := ex.(*sql.Tx)
if !ok {
return zerrors.ThrowInvalidArgumentf(nil, "HANDL-xOUC9O", "reduce.wrong.db.pool %T", ex)
}
settingsRepo := repository.SecretGeneratorSettingsRepository()
_, err := settingsRepo.Delete(ctx, v3_sql.SQLTx(tx),
settingsRepo.UniqueCondition(e.Aggregate().InstanceID, nil, domain.SettingTypeSecretGenerator, domain.SettingStateActive),
)
return err
}), nil
}
func setSecretGeneratorSettingsAttrs(generatorType legacy_domain.SecretGeneratorType, length *uint, includeLowerLetters, includeUpperLetters, includeDigits, includeSymbols *bool, expiry *time.Duration) (domain.SecretGeneratorSettingsAttributes, error) {
var secretGeneratorSettingsAttrs domain.SecretGeneratorSettingsAttributes
attrs := domain.SecretGeneratorAttrs{
Length: length,
IncludeLowerLetters: includeLowerLetters,
IncludeUpperLetters: includeUpperLetters,
IncludeDigits: includeDigits,
IncludeSymbols: includeSymbols,
}
attrsWithExpiry := domain.SecretGeneratorAttrsWithExpiry{
SecretGeneratorAttrs: attrs,
Expiry: expiry,
}
switch generatorType {
case legacy_domain.SecretGeneratorTypeAppSecret:
secretGeneratorSettingsAttrs.ClientSecret = &domain.ClientSecretAttributes{
SecretGeneratorAttrs: attrs,
}
case legacy_domain.SecretGeneratorTypeInitCode:
secretGeneratorSettingsAttrs.InitializeUserCode = &domain.InitializeUserCodeAttributes{
SecretGeneratorAttrsWithExpiry: attrsWithExpiry,
}
case legacy_domain.SecretGeneratorTypeVerifyEmailCode:
secretGeneratorSettingsAttrs.EmailVerificationCode = &domain.EmailVerificationCodeAttributes{
SecretGeneratorAttrsWithExpiry: attrsWithExpiry,
}
case legacy_domain.SecretGeneratorTypeVerifyPhoneCode:
secretGeneratorSettingsAttrs.PhoneVerificationCode = &domain.PhoneVerificationCodeAttributes{
SecretGeneratorAttrsWithExpiry: attrsWithExpiry,
}
case legacy_domain.SecretGeneratorTypePasswordlessInitCode:
secretGeneratorSettingsAttrs.PasswordlessInitCode = &domain.PasswordlessInitCodeAttributes{
SecretGeneratorAttrsWithExpiry: attrsWithExpiry,
}
case legacy_domain.SecretGeneratorTypePasswordResetCode:
secretGeneratorSettingsAttrs.PasswordVerificationCode = &domain.PasswordVerificationCodeAttributes{
SecretGeneratorAttrsWithExpiry: attrsWithExpiry,
}
case legacy_domain.SecretGeneratorTypeVerifyDomain:
secretGeneratorSettingsAttrs.DomainVerification = &domain.DomainVerificationAttributes{
SecretGeneratorAttrs: attrs,
}
case legacy_domain.SecretGeneratorTypeOTPSMS:
secretGeneratorSettingsAttrs.OTPSMS = &domain.OTPSMSAttributes{
SecretGeneratorAttrsWithExpiry: attrsWithExpiry,
}
case legacy_domain.SecretGeneratorTypeOTPEmail:
secretGeneratorSettingsAttrs.OTPEmail = &domain.OTPEmailAttributes{
SecretGeneratorAttrsWithExpiry: attrsWithExpiry,
}
case legacy_domain.SecretGeneratorTypeInviteCode, legacy_domain.SecretGeneratorTypeSigningKey:
// do nothing as these secret generators are not persisted in the settings
case legacy_domain.SecretGeneratorTypeUnspecified:
return domain.SecretGeneratorSettingsAttributes{}, zerrors.ThrowInvalidArgumentf(nil, "HANDL-2n3fK", "unspecified secret generator type")
default:
return domain.SecretGeneratorSettingsAttributes{}, zerrors.ThrowInvalidArgumentf(nil, "HANDL-9mG7f", "unknown secret generator type %s", generatorType)
}
return secretGeneratorSettingsAttrs, nil
}