package api import ( "bytes" "net/http" "net/http/httptest" "strings" "testing" "gardomatic.kleiax.de/internal/storage" ) type demoAccountTokenUserModel struct { sessionTestUserModel } func (m demoAccountTokenUserModel) GetForToken(string, string) (storage.User, error) { return m.user, nil } func TestRequireMutableAccountProtectsConfiguredDemoUser(t *testing.T) { app := &application{config: Config{DemoAccountEmail: "demo@example.com"}} called := false handler := app.requireMutableAccount(func(w http.ResponseWriter, _ *http.Request) { called = true w.WriteHeader(http.StatusNoContent) }) request := httptest.NewRequest(http.MethodPatch, "/v1/account", nil) request = app.contextSetAuthenticatedUser(request, storage.User{Email: "Demo@Example.com"}) response := httptest.NewRecorder() handler.ServeHTTP(response, request) if response.Code != http.StatusForbidden || called { t.Fatalf("protected account: got status %d and called=%t, want 403 and called=false", response.Code, called) } } func TestRequireMutableAccountAllowsOtherUsers(t *testing.T) { app := &application{config: Config{DemoAccountEmail: "demo@example.com"}} handler := app.requireMutableAccount(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNoContent) }) request := httptest.NewRequest(http.MethodPatch, "/v1/account", nil) request = app.contextSetAuthenticatedUser(request, storage.User{Email: "alice@example.com"}) response := httptest.NewRecorder() handler.ServeHTTP(response, request) if response.Code != http.StatusNoContent { t.Fatalf("ordinary account: got status %d, want %d", response.Code, http.StatusNoContent) } } func TestPasswordResetCannotChangeProtectedDemoAccount(t *testing.T) { app := &application{ config: Config{DemoAccountEmail: "demo@example.com"}, models: storage.Models{Users: demoAccountTokenUserModel{sessionTestUserModel: sessionTestUserModel{ user: storage.User{ID: 42, Email: "demo@example.com", Activated: true}, }}}, } t.Run("request token", func(t *testing.T) { request := httptest.NewRequest(http.MethodPost, "/v1/tokens/password-reset", bytes.NewBufferString(`{"email":"DEMO@example.com"}`)) response := httptest.NewRecorder() app.createPasswordResetTokenHandler(response, request) if response.Code != http.StatusForbidden || !strings.Contains(response.Body.String(), "shared demo account") { t.Fatalf("got status %d and body %q, want protected-account response", response.Code, response.Body.String()) } }) t.Run("use existing token", func(t *testing.T) { request := httptest.NewRequest(http.MethodPut, "/v1/users/password", bytes.NewBufferString(`{"password":"a-new-demo-password","token":"abcdefghijklmnopqrstuvwxyz"}`)) response := httptest.NewRecorder() app.updateUserPasswordHandler(response, request) if response.Code != http.StatusForbidden || !strings.Contains(response.Body.String(), "shared demo account") { t.Fatalf("got status %d and body %q, want protected-account response", response.Code, response.Body.String()) } }) }