From 8c9b6571326ddf63b328d381df4761a1e564c6b1 Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Sat, 26 Nov 2022 14:42:45 +0200 Subject: [PATCH] moved settings under models and added settings dao helpers --- apis/settings_test.go | 2 +- core/app.go | 11 +- core/base.go | 97 ++++++--------- ..._refresh_test.go => base_settings_test.go} | 19 +-- core/events.go | 11 +- daos/settings.go | 63 ++++++++++ daos/settings_test.go | 50 ++++++++ forms/settings_upsert.go | 20 ++- mails/record.go | 33 ++--- mails/templates/admin_password_reset.go | 3 - {core => models/settings}/settings.go | 12 +- .../settings}/settings_templates.go | 2 +- {core => models/settings}/settings_test.go | 116 +++++++++--------- tests/data/data.db | Bin 237568 -> 237568 bytes 14 files changed, 257 insertions(+), 182 deletions(-) rename core/{settings_refresh_test.go => base_settings_test.go} (75%) create mode 100644 daos/settings.go create mode 100644 daos/settings_test.go rename {core => models/settings}/settings.go (98%) rename {core => models/settings}/settings_templates.go (99%) rename {core => models/settings}/settings_test.go (90%) diff --git a/apis/settings_test.go b/apis/settings_test.go index ad70513e..6f7af921 100644 --- a/apis/settings_test.go +++ b/apis/settings_test.go @@ -127,7 +127,7 @@ func TestSettingsSet(t *testing.T) { `"twitchAuth":{`, `"secret":"******"`, `"clientSecret":"******"`, - `"appName":"Acme"`, + `"appName":"acme_test"`, }, ExpectedEvents: map[string]int{ "OnModelBeforeUpdate": 1, diff --git a/core/app.go b/core/app.go index f51c4ec9..77d7fdf3 100644 --- a/core/app.go +++ b/core/app.go @@ -6,6 +6,7 @@ package core import ( "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase/daos" + "github.com/pocketbase/pocketbase/models/settings" "github.com/pocketbase/pocketbase/tools/filesystem" "github.com/pocketbase/pocketbase/tools/hook" "github.com/pocketbase/pocketbase/tools/mailer" @@ -47,7 +48,7 @@ type App interface { IsDebug() bool // Settings returns the loaded app settings. - Settings() *Settings + Settings() *settings.Settings // Cache returns the app internal cache store. Cache() *store.Store[any] @@ -79,6 +80,14 @@ type App interface { // App event hooks // --------------------------------------------------------------- + // OnBeforeBootstrap hook is triggered before initializing the base + // application resources (eg. before db open and initial settings load). + OnBeforeBootstrap() *hook.Hook[*BootstrapEvent] + + // OnAfterBootstrap hook is triggered after initializing the base + // application resources (eg. after db open and initial settings load). + OnAfterBootstrap() *hook.Hook[*BootstrapEvent] + // OnBeforeServe hook is triggered before serving the internal router (echo), // allowing you to adjust its options and attach new routes. OnBeforeServe() *hook.Hook[*ServeEvent] diff --git a/core/base.go b/core/base.go index 4169eb5c..af49e36d 100644 --- a/core/base.go +++ b/core/base.go @@ -1,10 +1,8 @@ package core import ( - "bytes" "context" "database/sql" - "encoding/json" "errors" "log" "os" @@ -15,10 +13,10 @@ import ( "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase/daos" "github.com/pocketbase/pocketbase/models" + "github.com/pocketbase/pocketbase/models/settings" "github.com/pocketbase/pocketbase/tools/filesystem" "github.com/pocketbase/pocketbase/tools/hook" "github.com/pocketbase/pocketbase/tools/mailer" - "github.com/pocketbase/pocketbase/tools/security" "github.com/pocketbase/pocketbase/tools/store" "github.com/pocketbase/pocketbase/tools/subscriptions" ) @@ -34,15 +32,17 @@ type BaseApp struct { // internals cache *store.Store[any] - settings *Settings + settings *settings.Settings db *dbx.DB dao *daos.Dao logsDB *dbx.DB logsDao *daos.Dao subscriptionsBroker *subscriptions.Broker - // serve event hooks - onBeforeServe *hook.Hook[*ServeEvent] + // app event hooks + onBeforeBootstrap *hook.Hook[*BootstrapEvent] + onAfterBootstrap *hook.Hook[*BootstrapEvent] + onBeforeServe *hook.Hook[*ServeEvent] // dao event hooks onModelBeforeCreate *hook.Hook[*ModelEvent] @@ -125,11 +125,13 @@ func NewBaseApp(dataDir string, encryptionEnv string, isDebug bool) *BaseApp { isDebug: isDebug, encryptionEnv: encryptionEnv, cache: store.New[any](nil), - settings: NewSettings(), + settings: settings.New(), subscriptionsBroker: subscriptions.NewBroker(), - // serve event hooks - onBeforeServe: &hook.Hook[*ServeEvent]{}, + // app event hooks + onBeforeBootstrap: &hook.Hook[*BootstrapEvent]{}, + onAfterBootstrap: &hook.Hook[*BootstrapEvent]{}, + onBeforeServe: &hook.Hook[*ServeEvent]{}, // dao event hooks onModelBeforeCreate: &hook.Hook[*ModelEvent]{}, @@ -210,6 +212,12 @@ func NewBaseApp(dataDir string, encryptionEnv string, isDebug bool) *BaseApp { // Bootstrap initializes the application // (aka. create data dir, open db connections, load settings, etc.) func (app *BaseApp) Bootstrap() error { + event := &BootstrapEvent{app} + + if err := app.OnBeforeBootstrap().Trigger(event); err != nil { + return err + } + // clear resources of previous core state (if any) if err := app.ResetBootstrapState(); err != nil { return err @@ -228,10 +236,13 @@ func (app *BaseApp) Bootstrap() error { return err } - // we don't check for an error because the db migrations may - // have not been executed yet. + // we don't check for an error because the db migrations may have not been executed yet app.RefreshSettings() + if err := app.OnAfterBootstrap().Trigger(event); err != nil && app.IsDebug() { + log.Println(err) + } + return nil } @@ -295,7 +306,7 @@ func (app *BaseApp) IsDebug() bool { } // Settings returns the loaded app settings. -func (app *BaseApp) Settings() *Settings { +func (app *BaseApp) Settings() *settings.Settings { return app.settings } @@ -349,75 +360,41 @@ func (app *BaseApp) NewFilesystem() (*filesystem.System, error) { // RefreshSettings reinitializes and reloads the stored application settings. func (app *BaseApp) RefreshSettings() error { if app.settings == nil { - app.settings = NewSettings() + app.settings = settings.New() } encryptionKey := os.Getenv(app.EncryptionEnv()) - param, err := app.Dao().FindParamByKey(models.ParamAppSettings) + storedSettings, err := app.Dao().FindSettings(encryptionKey) if err != nil && err != sql.ErrNoRows { return err } // no settings were previously stored - if param == nil { - return app.Dao().SaveParam(models.ParamAppSettings, app.settings, encryptionKey) + if storedSettings == nil { + return app.Dao().SaveSettings(app.settings, encryptionKey) } // load the settings from the stored param into the app ones - // --- - newSettings := NewSettings() - - // try first without decryption - plainDecodeErr := json.Unmarshal(param.Value, newSettings) - - // failed, try to decrypt - if plainDecodeErr != nil { - // load without decrypt has failed and there is no encryption key to use for decrypt - if encryptionKey == "" { - return errors.New("Failed to load the stored app settings (missing or invalid encryption key).") - } - - // decrypt - decrypted, decryptErr := security.Decrypt(string(param.Value), encryptionKey) - if decryptErr != nil { - return decryptErr - } - - // decode again - decryptedDecodeErr := json.Unmarshal(decrypted, newSettings) - if decryptedDecodeErr != nil { - return decryptedDecodeErr - } - } - - if err := app.settings.Merge(newSettings); err != nil { + if err := app.settings.Merge(storedSettings); err != nil { return err } - afterMergeRaw, err := json.Marshal(app.settings) - if err != nil { - return err - } - - if - // save because previously the settings weren't stored encrypted - (plainDecodeErr == nil && encryptionKey != "") || - // or save because there are new fields after the merge - !bytes.Equal(param.Value, afterMergeRaw) { - saveErr := app.Dao().SaveParam(models.ParamAppSettings, app.settings, encryptionKey) - if saveErr != nil { - return saveErr - } - } - return nil } // ------------------------------------------------------------------- -// Serve event hooks +// App event hooks // ------------------------------------------------------------------- +func (app *BaseApp) OnBeforeBootstrap() *hook.Hook[*BootstrapEvent] { + return app.onBeforeBootstrap +} + +func (app *BaseApp) OnAfterBootstrap() *hook.Hook[*BootstrapEvent] { + return app.onAfterBootstrap +} + func (app *BaseApp) OnBeforeServe() *hook.Hook[*ServeEvent] { return app.onBeforeServe } diff --git a/core/settings_refresh_test.go b/core/base_settings_test.go similarity index 75% rename from core/settings_refresh_test.go rename to core/base_settings_test.go index 8a5519c1..08c51584 100644 --- a/core/settings_refresh_test.go +++ b/core/base_settings_test.go @@ -1,7 +1,6 @@ package core_test import ( - "bytes" "testing" "github.com/pocketbase/pocketbase/models" @@ -32,7 +31,7 @@ func TestBaseAppRefreshSettings(t *testing.T) { t.Fatalf("Expected new settings to be persisted, got %v", err) } - // change the db entry and refresh the app settings + // change the db entry and refresh the app settings (ensure that there was no db update) param.Value = types.JsonRaw([]byte(`{"example": 123}`)) if err := app.Dao().SaveParam(param.Key, param.Value); err != nil { t.Fatalf("Failed to update the test settings: %v", err) @@ -41,21 +40,9 @@ func TestBaseAppRefreshSettings(t *testing.T) { if err := app.RefreshSettings(); err != nil { t.Fatalf("Failed to refresh the app settings: %v", err) } - testEventCalls(t, app, map[string]int{ - "OnModelBeforeUpdate": 1, - "OnModelAfterUpdate": 1, - }) + testEventCalls(t, app, nil) - // make sure that the newly merged settings were actually saved - newParam, err := app.Dao().FindParamByKey(models.ParamAppSettings) - if err != nil { - t.Fatalf("Failed to fetch new settings param: %v", err) - } - if bytes.Equal(param.Value, newParam.Value) { - t.Fatalf("Expected the new refreshed settings to be different, got: \n%v", string(newParam.Value)) - } - - // try to refresh again and ensure that there was no db update + // try to refresh again without doing any changes app.ResetEventCalls() if err := app.RefreshSettings(); err != nil { t.Fatalf("Failed to refresh the app settings without change: %v", err) diff --git a/core/events.go b/core/events.go index 24eab5cf..c88d80f8 100644 --- a/core/events.go +++ b/core/events.go @@ -4,6 +4,7 @@ import ( "github.com/pocketbase/pocketbase/daos" "github.com/pocketbase/pocketbase/models" "github.com/pocketbase/pocketbase/models/schema" + "github.com/pocketbase/pocketbase/models/settings" "github.com/pocketbase/pocketbase/tools/mailer" "github.com/pocketbase/pocketbase/tools/search" "github.com/pocketbase/pocketbase/tools/subscriptions" @@ -15,6 +16,10 @@ import ( // Serve events data // ------------------------------------------------------------------- +type BootstrapEvent struct { + App App +} + type ServeEvent struct { App App Router *echo.Echo @@ -68,13 +73,13 @@ type RealtimeSubscribeEvent struct { type SettingsListEvent struct { HttpContext echo.Context - RedactedSettings *Settings + RedactedSettings *settings.Settings } type SettingsUpdateEvent struct { HttpContext echo.Context - OldSettings *Settings - NewSettings *Settings + OldSettings *settings.Settings + NewSettings *settings.Settings } // ------------------------------------------------------------------- diff --git a/daos/settings.go b/daos/settings.go new file mode 100644 index 00000000..f4830e7b --- /dev/null +++ b/daos/settings.go @@ -0,0 +1,63 @@ +package daos + +import ( + "encoding/json" + "errors" + + "github.com/pocketbase/pocketbase/models" + "github.com/pocketbase/pocketbase/models/settings" + "github.com/pocketbase/pocketbase/tools/security" +) + +// FindSettings returns and decode the serialized app settings param value. +// +// The method will first try to decode the param value without decryption. +// If it fails and optEncryptionKey is set, it will try again by first +// decrypting the value and then decode it again. +// +// Returns an error if it fails to decode the stored serialized param value. +func (dao *Dao) FindSettings(optEncryptionKey ...string) (*settings.Settings, error) { + param, err := dao.FindParamByKey(models.ParamAppSettings) + if err != nil { + return nil, err + } + + result := settings.New() + + // try first without decryption + plainDecodeErr := json.Unmarshal(param.Value, result) + + // failed, try to decrypt + if plainDecodeErr != nil { + var encryptionKey string + if len(optEncryptionKey) > 0 && optEncryptionKey[0] != "" { + encryptionKey = optEncryptionKey[0] + } + + // load without decrypt has failed and there is no encryption key to use for decrypt + if encryptionKey == "" { + return nil, errors.New("failed to load the stored app settings - missing or invalid encryption key") + } + + // decrypt + decrypted, decryptErr := security.Decrypt(string(param.Value), encryptionKey) + if decryptErr != nil { + return nil, decryptErr + } + + // decode again + decryptedDecodeErr := json.Unmarshal(decrypted, result) + if decryptedDecodeErr != nil { + return nil, decryptedDecodeErr + } + } + + return result, nil +} + +// SaveSettings persists the specified settings configuration. +// +// If optEncryptionKey is set, then the stored serialized value will be encrypted with it. +func (dao *Dao) SaveSettings(newSettings *settings.Settings, optEncryptionKey ...string) error { + return dao.SaveParam(models.ParamAppSettings, newSettings, optEncryptionKey...) +} diff --git a/daos/settings_test.go b/daos/settings_test.go new file mode 100644 index 00000000..3791f42b --- /dev/null +++ b/daos/settings_test.go @@ -0,0 +1,50 @@ +package daos_test + +import ( + "testing" + + "github.com/pocketbase/pocketbase/tests" + "github.com/pocketbase/pocketbase/tools/security" +) + +func TestSaveAndFindSettings(t *testing.T) { + app, _ := tests.NewTestApp() + defer app.Cleanup() + + encryptionKey := security.PseudorandomString(32) + + // change unencrypted app settings + app.Settings().Meta.AppName = "save_unencrypted" + if err := app.Dao().SaveSettings(app.Settings()); err != nil { + t.Fatal(err) + } + + // check if the change was persisted + s1, err := app.Dao().FindSettings() + if err != nil { + t.Fatalf("Failed to fetch settings: %v", err) + } + if s1.Meta.AppName != "save_unencrypted" { + t.Fatalf("Expected settings to be changed with app name %q, got \n%v", "save_unencrypted", s1) + } + + // make another change but this time provide an encryption key + app.Settings().Meta.AppName = "save_encrypted" + if err := app.Dao().SaveSettings(app.Settings(), encryptionKey); err != nil { + t.Fatal(err) + } + + // try to fetch the settings without encryption key (should fail) + if s2, err := app.Dao().FindSettings(); err == nil { + t.Fatalf("Expected FindSettings to fail without an encryption key, got \n%v", s2) + } + + // try again but this time with an encryption key + s3, err := app.Dao().FindSettings(encryptionKey) + if err != nil { + t.Fatalf("Failed to fetch settings with an encryption key %s: %v", encryptionKey, err) + } + if s3.Meta.AppName != "save_encrypted" { + t.Fatalf("Expected settings to be changed with app name %q, got \n%v", "save_encrypted", s3) + } +} diff --git a/forms/settings_upsert.go b/forms/settings_upsert.go index 9d966de9..6864d1c8 100644 --- a/forms/settings_upsert.go +++ b/forms/settings_upsert.go @@ -6,12 +6,12 @@ import ( "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/daos" - "github.com/pocketbase/pocketbase/models" + "github.com/pocketbase/pocketbase/models/settings" ) -// SettingsUpsert is a [core.Settings] upsert (create/update) form. +// SettingsUpsert is a [settings.Settings] upsert (create/update) form. type SettingsUpsert struct { - *core.Settings + *settings.Settings app core.App dao *daos.Dao @@ -55,16 +55,10 @@ func (form *SettingsUpsert) Submit(interceptors ...InterceptorFunc) error { return err } - encryptionKey := os.Getenv(form.app.EncryptionEnv()) - return runInterceptors(func() error { - saveErr := form.dao.SaveParam( - models.ParamAppSettings, - form.Settings, - encryptionKey, - ) - if saveErr != nil { - return saveErr + encryptionKey := os.Getenv(form.app.EncryptionEnv()) + if err := form.dao.SaveSettings(form.Settings, encryptionKey); err != nil { + return err } // explicitly trigger old logs deletion @@ -73,7 +67,7 @@ func (form *SettingsUpsert) Submit(interceptors ...InterceptorFunc) error { ) if form.Settings.Logs.MaxDays == 0 { - // reclaim deleted logs disk space + // no logs are allowed -> reclaim preserved disk space after the previous delete operation form.app.LogsDao().Vacuum() } diff --git a/mails/record.go b/mails/record.go index daac3344..a15ecbc6 100644 --- a/mails/record.go +++ b/mails/record.go @@ -7,6 +7,7 @@ import ( "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/mails/templates" "github.com/pocketbase/pocketbase/models" + "github.com/pocketbase/pocketbase/models/settings" "github.com/pocketbase/pocketbase/tokens" "github.com/pocketbase/pocketbase/tools/mailer" ) @@ -20,17 +21,15 @@ func SendRecordPasswordReset(app core.App, authRecord *models.Record) error { mailClient := app.NewMailClient() - settings := app.Settings() - - subject, body, err := resolveEmailTemplate(app, token, settings.Meta.ResetPasswordTemplate) + subject, body, err := resolveEmailTemplate(app, token, app.Settings().Meta.ResetPasswordTemplate) if err != nil { return err } message := &mailer.Message{ From: mail.Address{ - Name: settings.Meta.SenderName, - Address: settings.Meta.SenderAddress, + Name: app.Settings().Meta.SenderName, + Address: app.Settings().Meta.SenderAddress, }, To: mail.Address{Address: authRecord.Email()}, Subject: subject, @@ -64,17 +63,15 @@ func SendRecordVerification(app core.App, authRecord *models.Record) error { mailClient := app.NewMailClient() - settings := app.Settings() - - subject, body, err := resolveEmailTemplate(app, token, settings.Meta.VerificationTemplate) + subject, body, err := resolveEmailTemplate(app, token, app.Settings().Meta.VerificationTemplate) if err != nil { return err } message := &mailer.Message{ From: mail.Address{ - Name: settings.Meta.SenderName, - Address: settings.Meta.SenderAddress, + Name: app.Settings().Meta.SenderName, + Address: app.Settings().Meta.SenderAddress, }, To: mail.Address{Address: authRecord.Email()}, Subject: subject, @@ -108,17 +105,15 @@ func SendRecordChangeEmail(app core.App, record *models.Record, newEmail string) mailClient := app.NewMailClient() - settings := app.Settings() - - subject, body, err := resolveEmailTemplate(app, token, settings.Meta.ConfirmEmailChangeTemplate) + subject, body, err := resolveEmailTemplate(app, token, app.Settings().Meta.ConfirmEmailChangeTemplate) if err != nil { return err } message := &mailer.Message{ From: mail.Address{ - Name: settings.Meta.SenderName, - Address: settings.Meta.SenderAddress, + Name: app.Settings().Meta.SenderName, + Address: app.Settings().Meta.SenderAddress, }, To: mail.Address{Address: newEmail}, Subject: subject, @@ -149,13 +144,11 @@ func SendRecordChangeEmail(app core.App, record *models.Record, newEmail string) func resolveEmailTemplate( app core.App, token string, - emailTemplate core.EmailTemplate, + emailTemplate settings.EmailTemplate, ) (subject string, body string, err error) { - settings := app.Settings() - subject, rawBody, _ := emailTemplate.Resolve( - settings.Meta.AppName, - settings.Meta.AppUrl, + app.Settings().Meta.AppName, + app.Settings().Meta.AppUrl, token, ) diff --git a/mails/templates/admin_password_reset.go b/mails/templates/admin_password_reset.go index 1a38d8d3..f6207c3f 100644 --- a/mails/templates/admin_password_reset.go +++ b/mails/templates/admin_password_reset.go @@ -12,13 +12,10 @@ package templates const AdminPasswordResetBody = ` {{define "content"}}

Hello,

-

Follow this link to reset your admin password for {{.AppName}}.

-

Reset password

-

If you did not request to reset your password, please ignore this email and the link will expire on its own.

{{end}} ` diff --git a/core/settings.go b/models/settings/settings.go similarity index 98% rename from core/settings.go rename to models/settings/settings.go index 8793a25b..91742ad6 100644 --- a/core/settings.go +++ b/models/settings/settings.go @@ -1,4 +1,4 @@ -package core +package settings import ( "encoding/json" @@ -45,8 +45,8 @@ type Settings struct { TwitchAuth AuthProviderConfig `form:"twitchAuth" json:"twitchAuth"` } -// NewSettings creates and returns a new default Settings instance. -func NewSettings() *Settings { +// New creates and returns a new default Settings instance. +func New() *Settings { return &Settings{ Meta: MetaConfig{ AppName: "Acme", @@ -170,11 +170,11 @@ func (s *Settings) Merge(other *Settings) error { // Clone creates a new deep copy of the current settings. func (s *Settings) Clone() (*Settings, error) { - settings := &Settings{} - if err := settings.Merge(s); err != nil { + clone := &Settings{} + if err := clone.Merge(s); err != nil { return nil, err } - return settings, nil + return clone, nil } // RedactClone creates a new deep copy of the current settings, diff --git a/core/settings_templates.go b/models/settings/settings_templates.go similarity index 99% rename from core/settings_templates.go rename to models/settings/settings_templates.go index 006e56e0..a0f913a3 100644 --- a/core/settings_templates.go +++ b/models/settings/settings_templates.go @@ -1,4 +1,4 @@ -package core +package settings // Common settings placeholder tokens const ( diff --git a/core/settings_test.go b/models/settings/settings_test.go similarity index 90% rename from core/settings_test.go rename to models/settings/settings_test.go index 5da92177..044b39fe 100644 --- a/core/settings_test.go +++ b/models/settings/settings_test.go @@ -1,4 +1,4 @@ -package core_test +package settings_test import ( "encoding/json" @@ -7,12 +7,12 @@ import ( "testing" validation "github.com/go-ozzo/ozzo-validation/v4" - "github.com/pocketbase/pocketbase/core" + "github.com/pocketbase/pocketbase/models/settings" "github.com/pocketbase/pocketbase/tools/auth" ) func TestSettingsValidate(t *testing.T) { - s := core.NewSettings() + s := settings.New() // set invalid settings data s.Meta.AppName = "" @@ -87,10 +87,10 @@ func TestSettingsValidate(t *testing.T) { } func TestSettingsMerge(t *testing.T) { - s1 := core.NewSettings() + s1 := settings.New() s1.Meta.AppUrl = "old_app_url" - s2 := core.NewSettings() + s2 := settings.New() s2.Meta.AppName = "test" s2.Logs.MaxDays = 123 s2.Smtp.Host = "test" @@ -144,7 +144,7 @@ func TestSettingsMerge(t *testing.T) { } func TestSettingsClone(t *testing.T) { - s1 := core.NewSettings() + s1 := settings.New() s2, err := s1.Clone() if err != nil { @@ -173,7 +173,7 @@ func TestSettingsClone(t *testing.T) { } func TestSettingsRedactClone(t *testing.T) { - s1 := core.NewSettings() + s1 := settings.New() s1.Meta.AppName = "test123" // control field s1.Smtp.Password = "test123" s1.Smtp.Tls = true @@ -213,7 +213,7 @@ func TestSettingsRedactClone(t *testing.T) { } func TestNamedAuthProviderConfigs(t *testing.T) { - s := core.NewSettings() + s := settings.New() s.GoogleAuth.ClientId = "google_test" s.FacebookAuth.ClientId = "facebook_test" @@ -256,17 +256,17 @@ func TestNamedAuthProviderConfigs(t *testing.T) { func TestTokenConfigValidate(t *testing.T) { scenarios := []struct { - config core.TokenConfig + config settings.TokenConfig expectError bool }{ // zero values { - core.TokenConfig{}, + settings.TokenConfig{}, true, }, // invalid data { - core.TokenConfig{ + settings.TokenConfig{ Secret: strings.Repeat("a", 5), Duration: 4, }, @@ -274,7 +274,7 @@ func TestTokenConfigValidate(t *testing.T) { }, // valid secret but invalid duration { - core.TokenConfig{ + settings.TokenConfig{ Secret: strings.Repeat("a", 30), Duration: 63072000 + 1, }, @@ -282,7 +282,7 @@ func TestTokenConfigValidate(t *testing.T) { }, // valid data { - core.TokenConfig{ + settings.TokenConfig{ Secret: strings.Repeat("a", 30), Duration: 100, }, @@ -305,22 +305,22 @@ func TestTokenConfigValidate(t *testing.T) { func TestSmtpConfigValidate(t *testing.T) { scenarios := []struct { - config core.SmtpConfig + config settings.SmtpConfig expectError bool }{ // zero values (disabled) { - core.SmtpConfig{}, + settings.SmtpConfig{}, false, }, // zero values (enabled) { - core.SmtpConfig{Enabled: true}, + settings.SmtpConfig{Enabled: true}, true, }, // invalid data { - core.SmtpConfig{ + settings.SmtpConfig{ Enabled: true, Host: "test:test:test", Port: -10, @@ -329,7 +329,7 @@ func TestSmtpConfigValidate(t *testing.T) { }, // valid data { - core.SmtpConfig{ + settings.SmtpConfig{ Enabled: true, Host: "example.com", Port: 100, @@ -354,22 +354,22 @@ func TestSmtpConfigValidate(t *testing.T) { func TestS3ConfigValidate(t *testing.T) { scenarios := []struct { - config core.S3Config + config settings.S3Config expectError bool }{ // zero values (disabled) { - core.S3Config{}, + settings.S3Config{}, false, }, // zero values (enabled) { - core.S3Config{Enabled: true}, + settings.S3Config{Enabled: true}, true, }, // invalid data { - core.S3Config{ + settings.S3Config{ Enabled: true, Endpoint: "test:test:test", }, @@ -377,7 +377,7 @@ func TestS3ConfigValidate(t *testing.T) { }, // valid data (url endpoint) { - core.S3Config{ + settings.S3Config{ Enabled: true, Endpoint: "https://localhost:8090", Bucket: "test", @@ -389,7 +389,7 @@ func TestS3ConfigValidate(t *testing.T) { }, // valid data (hostname endpoint) { - core.S3Config{ + settings.S3Config{ Enabled: true, Endpoint: "example.com", Bucket: "test", @@ -415,36 +415,36 @@ func TestS3ConfigValidate(t *testing.T) { } func TestMetaConfigValidate(t *testing.T) { - invalidTemplate := core.EmailTemplate{ + invalidTemplate := settings.EmailTemplate{ Subject: "test", ActionUrl: "test", Body: "test", } - noPlaceholdersTemplate := core.EmailTemplate{ + noPlaceholdersTemplate := settings.EmailTemplate{ Subject: "test", ActionUrl: "http://example.com", Body: "test", } - withPlaceholdersTemplate := core.EmailTemplate{ + withPlaceholdersTemplate := settings.EmailTemplate{ Subject: "test", - ActionUrl: "http://example.com" + core.EmailPlaceholderToken, - Body: "test" + core.EmailPlaceholderActionUrl, + ActionUrl: "http://example.com" + settings.EmailPlaceholderToken, + Body: "test" + settings.EmailPlaceholderActionUrl, } scenarios := []struct { - config core.MetaConfig + config settings.MetaConfig expectError bool }{ // zero values { - core.MetaConfig{}, + settings.MetaConfig{}, true, }, // invalid data { - core.MetaConfig{ + settings.MetaConfig{ AppName: strings.Repeat("a", 300), AppUrl: "test", SenderName: strings.Repeat("a", 300), @@ -457,7 +457,7 @@ func TestMetaConfigValidate(t *testing.T) { }, // invalid data (missing required placeholders) { - core.MetaConfig{ + settings.MetaConfig{ AppName: "test", AppUrl: "https://example.com", SenderName: "test", @@ -470,7 +470,7 @@ func TestMetaConfigValidate(t *testing.T) { }, // valid data { - core.MetaConfig{ + settings.MetaConfig{ AppName: "test", AppUrl: "https://example.com", SenderName: "test", @@ -498,17 +498,17 @@ func TestMetaConfigValidate(t *testing.T) { func TestEmailTemplateValidate(t *testing.T) { scenarios := []struct { - emailTemplate core.EmailTemplate + emailTemplate settings.EmailTemplate expectedErrors []string }{ // require values { - core.EmailTemplate{}, + settings.EmailTemplate{}, []string{"subject", "actionUrl", "body"}, }, // missing placeholders { - core.EmailTemplate{ + settings.EmailTemplate{ Subject: "test", ActionUrl: "test", Body: "test", @@ -517,10 +517,10 @@ func TestEmailTemplateValidate(t *testing.T) { }, // valid data { - core.EmailTemplate{ + settings.EmailTemplate{ Subject: "test", - ActionUrl: "test" + core.EmailPlaceholderToken, - Body: "test" + core.EmailPlaceholderActionUrl, + ActionUrl: "test" + settings.EmailPlaceholderToken, + Body: "test" + settings.EmailPlaceholderActionUrl, }, []string{}, }, @@ -549,17 +549,17 @@ func TestEmailTemplateValidate(t *testing.T) { } func TestEmailTemplateResolve(t *testing.T) { - allPlaceholders := core.EmailPlaceholderActionUrl + core.EmailPlaceholderToken + core.EmailPlaceholderAppName + core.EmailPlaceholderAppUrl + allPlaceholders := settings.EmailPlaceholderActionUrl + settings.EmailPlaceholderToken + settings.EmailPlaceholderAppName + settings.EmailPlaceholderAppUrl scenarios := []struct { - emailTemplate core.EmailTemplate + emailTemplate settings.EmailTemplate expectedSubject string expectedBody string expectedActionUrl string }{ // no placeholders { - emailTemplate: core.EmailTemplate{ + emailTemplate: settings.EmailTemplate{ Subject: "subject:", Body: "body:", ActionUrl: "/actionUrl////", @@ -570,7 +570,7 @@ func TestEmailTemplateResolve(t *testing.T) { }, // with placeholders { - emailTemplate: core.EmailTemplate{ + emailTemplate: settings.EmailTemplate{ ActionUrl: "/actionUrl////" + allPlaceholders, Subject: "subject:" + allPlaceholders, Body: "body:" + allPlaceholders, @@ -583,8 +583,8 @@ func TestEmailTemplateResolve(t *testing.T) { ), expectedSubject: fmt.Sprintf( "subject:%s%s%s%s", - core.EmailPlaceholderActionUrl, - core.EmailPlaceholderToken, + settings.EmailPlaceholderActionUrl, + settings.EmailPlaceholderToken, "name_test", "url_test", ), @@ -622,22 +622,22 @@ func TestEmailTemplateResolve(t *testing.T) { func TestLogsConfigValidate(t *testing.T) { scenarios := []struct { - config core.LogsConfig + config settings.LogsConfig expectError bool }{ // zero values { - core.LogsConfig{}, + settings.LogsConfig{}, false, }, // invalid data { - core.LogsConfig{MaxDays: -10}, + settings.LogsConfig{MaxDays: -10}, true, }, // valid data { - core.LogsConfig{MaxDays: 1}, + settings.LogsConfig{MaxDays: 1}, false, }, } @@ -657,22 +657,22 @@ func TestLogsConfigValidate(t *testing.T) { func TestAuthProviderConfigValidate(t *testing.T) { scenarios := []struct { - config core.AuthProviderConfig + config settings.AuthProviderConfig expectError bool }{ // zero values (disabled) { - core.AuthProviderConfig{}, + settings.AuthProviderConfig{}, false, }, // zero values (enabled) { - core.AuthProviderConfig{Enabled: true}, + settings.AuthProviderConfig{Enabled: true}, true, }, // invalid data { - core.AuthProviderConfig{ + settings.AuthProviderConfig{ Enabled: true, ClientId: "", ClientSecret: "", @@ -684,7 +684,7 @@ func TestAuthProviderConfigValidate(t *testing.T) { }, // valid data (only the required) { - core.AuthProviderConfig{ + settings.AuthProviderConfig{ Enabled: true, ClientId: "test", ClientSecret: "test", @@ -693,7 +693,7 @@ func TestAuthProviderConfigValidate(t *testing.T) { }, // valid data (fill all fields) { - core.AuthProviderConfig{ + settings.AuthProviderConfig{ Enabled: true, ClientId: "test", ClientSecret: "test", @@ -722,12 +722,12 @@ func TestAuthProviderConfigSetupProvider(t *testing.T) { provider := auth.NewGithubProvider() // disabled config - c1 := core.AuthProviderConfig{Enabled: false} + c1 := settings.AuthProviderConfig{Enabled: false} if err := c1.SetupProvider(provider); err == nil { t.Errorf("Expected error, got nil") } - c2 := core.AuthProviderConfig{ + c2 := settings.AuthProviderConfig{ Enabled: true, ClientId: "test_ClientId", ClientSecret: "test_ClientSecret", diff --git a/tests/data/data.db b/tests/data/data.db index 0e56937a23873fa906405dacc1e2e066c4a8a356..4ff0718b9e9c4fba9ec710aa0da8166c4aabdb2f 100644 GIT binary patch delta 75 zcmZoTz}IkqZv)!`mgfvi&o>JS+-2gJCC13EExTEE@|Q)roQcV~sqrPL#U-0n7oX!G_nFBQxiQ4!{&eM+yAX+-2QJp6VnF(2Y(zz delta 70 zcmV-M0J;Bwzz%@G4zLEG1nd9;?6VON;sOYo5djA)9kUaY@1iXPL1S%Yvn8X;3=T0i cATlyKGB`RgHZC?egZ{6F{;vVI{;vW8@N@JU1poj5