From 2d78ae423c6d2b81765393ef15a3295311fed50a Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Fri, 6 Aug 2021 13:18:20 +0200 Subject: [PATCH] Remove PROVISION_SETTINGS_ and replace it with importing setting yaml --- pkg/provision/auth.go | 191 ++++--------------------------- pkg/provision/provision.go | 2 +- provision/001_settings/auth.yaml | 14 +++ system/types/settings.go | 8 +- 4 files changed, 44 insertions(+), 171 deletions(-) create mode 100644 provision/001_settings/auth.yaml diff --git a/pkg/provision/auth.go b/pkg/provision/auth.go index b381be54a..f43147635 100644 --- a/pkg/provision/auth.go +++ b/pkg/provision/auth.go @@ -2,191 +2,44 @@ package provision import ( "context" - "fmt" "os" "github.com/cortezaproject/corteza-server/pkg/errors" - "github.com/cortezaproject/corteza-server/pkg/logger" "github.com/cortezaproject/corteza-server/store" "github.com/cortezaproject/corteza-server/system/types" - "github.com/spf13/cast" - "go.uber.org/zap" ) -// Discovers "auth.%" settings from the environment +// Sets email-related settings (if not set) under "auth.internal..." // -// when other kinds of auto-discoverable settings come, lambdas inside will probably need a bit of refactoring -func authSettingsAutoDiscovery(ctx context.Context, log *zap.Logger, s store.Storer) (err error) { - type ( - stringWrapper func() string - boolWrapper func() bool - ) - +// +func emailSettings(ctx context.Context, s store.Storer) error { var ( - // Setter - // - // Finds existing settings, tries with environmental "PROVISION_SETTINGS_AUTH_..." probing - // and falls back to default value - // - // We are extremely verbose here - we want to show all the info available and - // how settings were discovered and set - // - // @todo generalize and move under settings - set = func(name string, env string, def interface{}, maskSensitive bool) error { - - var ( - log = log.With( - zap.String("name", name), - ) - - envExists bool - value interface{} - - v, err = s.LookupSettingByNameOwnedBy(ctx, name, 0) - ) - - if !errors.IsNotFound(err) && err != nil { - return fmt.Errorf("could not load settings value for '%s': %w", name, err) - } - - if v != nil { - // Nothing to discover, already set - log.Debug("already set", logger.MaskIf("value", v, maskSensitive)) - return nil - } - - v = &types.SettingValue{Name: name} - - value, envExists = os.LookupEnv(env) - - switch dfn := def.(type) { - case stringWrapper: - log = log.With(zap.String("type", "string")) - // already a string, no need to do any magic - if envExists { - log = log.With(zap.String("env", env), logger.MaskIf("value", value, maskSensitive)) - } else { - value = dfn() - log = log.With(zap.Any("default", value)) - } - case boolWrapper: - log = log.With(zap.String("type", "bool")) - - if envExists { - value = cast.ToBool(value) - log = log.With(zap.String("env", env), zap.Any("value", value)) - } else { - value = dfn() - log = log.With(zap.Any("default", value)) - } - - default: - return fmt.Errorf("unsupported type %T for '%s'", def, name) - } - - if err := v.SetValue(value); err != nil { - return fmt.Errorf("could not set value to '%q': %w", name, err) - } - - log.Debug("value auto-discovered") - return s.UpsertSetting(ctx, v) - } - - // Assume we have emailing capabilities if SMTP_HOST variable is set - emailCapabilities = func() boolWrapper { - return func() bool { - val, has := os.LookupEnv("SMTP_HOST") - return has && len(val) > 0 - } - } - - wrapBool = func(val bool) boolWrapper { - return func() bool { return val } - } - - wrapString = func(val string) stringWrapper { - return func() string { return val } - } + val, has = os.LookupEnv("SMTP_HOST") + canSendEmails = has && len(val) > 0 ) // List of name-value pairs we need to iterate and set - list := []struct { - // Setting name - nme string - - // provision environmental variable name - // we're using full variable name here so developers - // can find where things are coming from - env string - - // default value - // expects one of the *wrapper() functions - // this also determinate the value type of the setting and casting rules for the env value - def interface{} - - // mask value if sensitive - mask bool - }{ - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // - // External auth - - // Enable federated auth - { - "auth.external.enabled", - "PROVISION_SETTINGS_AUTH_EXTERNAL_ENABLED", - wrapBool(true), - false}, - - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // - - // Auth email - { - "auth.mail.from-address", - "PROVISION_SETTINGS_AUTH_EMAIL_FROM_ADDRESS", - wrapString("info@example.tld"), - false}, - - { - "auth.mail.from-name", - "PROVISION_SETTINGS_AUTH_EMAIL_FROM_NAME", - wrapString("Example Sender"), - false}, - - // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // - // Enable internal login - { - "auth.internal.enabled", - "PROVISION_SETTINGS_AUTH_INTERNAL_ENABLED", - wrapBool(true), - false}, - - // Enable internal signup - { - "auth.internal.signup.enabled", - "PROVISION_SETTINGS_AUTH_INTERNAL_SIGNUP_ENABLED", - wrapBool(true), - false}, - - // Enable email confirmation if we have email capabilities - { + ss := types.SettingValueSet{ + types.MakeSettingValue( "auth.internal.signup.email-confirmation-required", - "PROVISION_SETTINGS_AUTH_INTERNAL_SIGNUP_EMAIL_CONFIRMATION_REQUIRED", - emailCapabilities(), - false}, + canSendEmails, + ), - // Enable password reset if we have email capabilities - { + types.MakeSettingValue( "auth.internal.password-reset.enabled", - "PROVISION_SETTINGS_AUTH_INTERNAL_PASSWORD_RESET_ENABLED", - emailCapabilities(), - false}, + canSendEmails, + ), } - for _, item := range list { - if err = set(item.nme, item.env, item.def, item.mask); err != nil { + return s.Tx(ctx, func(ctx context.Context, s store.Storer) error { + return ss.Walk(func(setting *types.SettingValue) error { + _, err := store.LookupSettingByNameOwnedBy(ctx, s, setting.Name, 0) + if errors.IsNotFound(err) { + setting.UpdatedAt = *now() + return store.CreateSetting(ctx, s, setting) + } + return err - } - } - - return nil + }) + }) } diff --git a/pkg/provision/provision.go b/pkg/provision/provision.go index 6a6ac0544..47a11f7f2 100644 --- a/pkg/provision/provision.go +++ b/pkg/provision/provision.go @@ -36,7 +36,7 @@ func Run(ctx context.Context, log *zap.Logger, s store.Storer, provisionOpt opti func() error { return importConfig(ctx, log.Named("config"), s, provisionOpt.Path) }, // Auto-discoveries and other parts that cannot be imported from static files - func() error { return authSettingsAutoDiscovery(ctx, log.Named("auth.settings-discovery"), s) }, + func() error { return emailSettings(ctx, s) }, func() error { return authAddExternals(ctx, log.Named("auth.externals"), s) }, func() error { return oidcAutoDiscovery(ctx, log.Named("auth.oidc-auto-discovery"), s, authOpt) }, func() error { return defaultAuthClient(ctx, log.Named("auth.clients"), s, authOpt) }, diff --git a/provision/001_settings/auth.yaml b/provision/001_settings/auth.yaml new file mode 100644 index 000000000..988e0be40 --- /dev/null +++ b/provision/001_settings/auth.yaml @@ -0,0 +1,14 @@ +settings: + auth.external.enabled: true + auth.mail.from-address: info@example.tld + auth.mail.from-name: Corteza + auth.internal.enabled: true + auth.internal.signup.enabled: true + + # We add this through provision procedures + # if we detect valid SMTP settings + # auth.internal.signup.email-confirmation-required: true + + # We add this through provision procedures + # if we detect valid SMTP settings + # auth.internal.password-reset.enabled: true diff --git a/system/types/settings.go b/system/types/settings.go index 19e24b338..1ef0ceece 100644 --- a/system/types/settings.go +++ b/system/types/settings.go @@ -41,6 +41,12 @@ const ( settingsFilterPerPageMax = 100 ) +func MakeSettingValue(name string, value interface{}) *SettingValue { + o := &SettingValue{Name: name} + _ = o.SetValue(value) + return o +} + func (v *SettingValue) SetRawValue(str string) error { var dummy interface{} // Test input to be sure we can save it... @@ -60,7 +66,7 @@ func (v *SettingValue) SetValue(value interface{}) (err error) { return err } - v.Value = buf.Bytes() + v.Value = bytes.TrimSpace(buf.Bytes()) return }