package user import ( "net/http" "net/http/httptest" "strings" "testing" "git.golem15.com/golem15/sm-user-plugin/classes" "git.golem15.com/golem15/sm-user-plugin/controllers" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/towel" ) const mailFallbackKey = "golem15.user.mail.fallback_locale" // TestMailFallbackLocaleConfig reads golem15.user.mail.fallback_locale from // the plugin's config.yaml default and from overrides. func TestMailFallbackLocaleConfig(t *testing.T) { app := bareApp(t) if err := app.Config.MergePlugin("golem15.user", configFS); err != nil { t.Fatal(err) } if v, ok := app.Config.Lookup(mailFallbackKey); !ok || v != "pl" { t.Fatalf("config.yaml default = %#v (set %v), want pl", v, ok) } if got, err := classes.MailFallbackLocale(app); got != "pl" || err != nil { t.Fatalf("default: %q %v", got, err) } for _, tc := range []struct{ value, want string }{{"en", "en"}, {"EN-gb", "en"}} { if err := app.Config.Set(mailFallbackKey, tc.value); err != nil { t.Fatal(err) } if got, err := classes.MailFallbackLocale(app); got != tc.want || err != nil { t.Errorf("%q: %q %v", tc.value, got, err) } } if err := app.Config.Set(mailFallbackKey, "de"); err != nil { t.Fatal(err) } if _, err := classes.MailFallbackLocale(app); err == nil || !strings.Contains(err.Error(), mailFallbackKey) { t.Errorf("de: %v", err) } } // TestMailFallbackLocaleBoot fails Boot on an unsupported fallback before // anything is started, and leaves an unset key alone. func TestMailFallbackLocaleBoot(t *testing.T) { withSecret := func(t *testing.T) *backpack.App { app := bareApp(t) if err := app.Config.Set("golem15.user.jwt.secret", "mail-locale-boot-secret"); err != nil { t.Fatal(err) } return app } app := withSecret(t) if err := app.Config.Set(mailFallbackKey, "de"); err != nil { t.Fatal(err) } if err := (&Plugin{}).Boot(app); err == nil || !strings.Contains(err.Error(), mailFallbackKey) { t.Fatalf("Boot with fallback de: %v", err) } if err := (&Plugin{}).Boot(withSecret(t)); err != nil && strings.Contains(err.Error(), mailFallbackKey) { t.Fatalf("Boot with the key unset: %v", err) } } // TestMailLocaleFromRequest sends the reset mail through POST // /forgot-password with the request locale the router stores when no // translate plugin is installed: the raw Accept-Language header. func TestMailLocaleFromRequest(t *testing.T) { if testing.Short() { t.Skip("Postgres (testcontainers)") } app, gdb := sessionApp(t, "0s") rec, _ := publishMemoryMail(t, app) forgot := func(t *testing.T, email, locale string) { t.Helper() req := httptest.NewRequest(http.MethodPost, "/_user/api/v1/forgot-password", strings.NewReader(`{"email":"`+email+`"}`)) req.Host = "example.com" req.Header.Set("Content-Type", "application/json") if locale != "" { req = req.WithContext(towel.WithLocale(req.Context(), locale)) } w := httptest.NewRecorder() controllers.ForgotPassword(app)(w, req) if w.Code >= 300 { t.Fatalf("forgot-password %s: %d %s", email, w.Code, w.Body.String()) } } insertUser(t, gdb, "locale-header@example.test", "correct-horse") forgot(t, "locale-header@example.test", "en-GB,en;q=0.9") assertTemplate(t, rec, "golem15.user::mail.restore-en", "locale-header@example.test") insertUser(t, gdb, "locale-none@example.test", "correct-horse") forgot(t, "locale-none@example.test", "") assertTemplate(t, rec, "golem15.user::mail.restore", "locale-none@example.test") if err := app.Config.Set(mailFallbackKey, "en"); err != nil { t.Fatal(err) } insertUser(t, gdb, "locale-fallback@example.test", "correct-horse") forgot(t, "locale-fallback@example.test", "") assertTemplate(t, rec, "golem15.user::mail.restore-en", "locale-fallback@example.test") saved := insertUser(t, gdb, "locale-saved@example.test", "correct-horse") if err := gdb.Model(saved).Update("preferred_locale", "en-GB").Error; err != nil { t.Fatal(err) } forgot(t, "locale-saved@example.test", "pl") assertTemplate(t, rec, "golem15.user::mail.restore-en", "locale-saved@example.test") }