Files
warpbox/lib/server/account_settings_test.go
Daniel Legt 2714907ff4 feat(config): add box owner policy settings
Adds configuration options and environment variables to manage
box owner policies, including settings for refresh counts and expiry.
2026-04-30 19:30:13 +03:00

198 lines
7.2 KiB
Go

package server
import (
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
"warpbox/lib/config"
"warpbox/lib/metastore"
)
func TestAccountSettingsPermissionDenied(t *testing.T) {
app, _ := setupAccountTestApp(t)
user, err := app.store.CreateUserWithPassword("regular", "regular@example.test", "secret", nil)
if err != nil {
t.Fatalf("CreateUserWithPassword returned error: %v", err)
}
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
request := httptest.NewRequest(http.MethodGet, "/account/settings", nil)
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusForbidden {
t.Fatalf("expected permission denied, got %d", response.Code)
}
}
func TestAccountSettingsPageLoadsForAdmin(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
request := httptest.NewRequest(http.MethodGet, "/account/settings", nil)
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusOK {
t.Fatalf("expected settings page, got %d body=%s", response.Code, response.Body.String())
}
for _, text := range []string{"Uploads", "Downloads", "Box policy", "Save Settings"} {
if !strings.Contains(response.Body.String(), text) {
t.Fatalf("expected settings page to contain %q", text)
}
}
}
func TestAccountSettingsValidUpdate(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
form := url.Values{}
form.Set("csrf_token", session.CSRFToken)
form.Set(config.SettingAPIEnabled, "false")
response := postAccountSettingsForm(router, session, form)
if response.Code != http.StatusSeeOther {
t.Fatalf("expected settings redirect, got %d body=%s", response.Code, response.Body.String())
}
if app.config.APIEnabled {
t.Fatal("expected API setting to be disabled")
}
value, ok, err := app.store.GetSetting(config.SettingAPIEnabled)
if err != nil || !ok || value != "false" {
t.Fatalf("expected API setting override false, got value=%q ok=%v err=%v", value, ok, err)
}
}
func TestAccountSettingsInvalidUpdate(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
form := url.Values{}
form.Set("csrf_token", session.CSRFToken)
form.Set(config.SettingSessionTTLSeconds, "1")
response := postAccountSettingsForm(router, session, form)
if response.Code != http.StatusOK {
t.Fatalf("expected settings form render, got %d", response.Code)
}
if !strings.Contains(response.Body.String(), "must be at least 60") {
t.Fatal("expected validation error in response")
}
}
func TestAccountSettingsLockedSettingCannotChange(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
form := url.Values{}
form.Set("csrf_token", session.CSRFToken)
form.Set(config.SettingGlobalMaxFileSizeBytes, "1")
response := postAccountSettingsForm(router, session, form)
if response.Code != http.StatusOK {
t.Fatalf("expected settings form render, got %d", response.Code)
}
if !strings.Contains(response.Body.String(), "locked") {
t.Fatal("expected locked setting error")
}
if value, ok, err := app.store.GetSetting(config.SettingGlobalMaxFileSizeBytes); err != nil || ok || value != "" {
t.Fatalf("expected no locked setting override, got value=%q ok=%v err=%v", value, ok, err)
}
}
func TestAccountSettingsImportRejectsUnknownOrInvalidSettings(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
for _, body := range []string{
`{"version":1,"settings":{"not_real":"true"}}`,
`{"version":1,"settings":{"session_ttl_seconds":"1"}}`,
} {
response := postAccountSettingsJSON(router, session, body)
if response.Code != http.StatusBadRequest {
t.Fatalf("expected bad import for %s, got %d", body, response.Code)
}
}
}
func TestAccountSettingsImportAppliesValidSettings(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
response := postAccountSettingsJSON(router, session, `{"version":1,"settings":{"api_enabled":"false","box_owner_max_refresh_count":"7"}}`)
if response.Code != http.StatusOK {
t.Fatalf("expected import success, got %d body=%s", response.Code, response.Body.String())
}
if app.config.APIEnabled {
t.Fatal("expected imported API setting to be disabled")
}
if app.config.BoxOwnerMaxRefreshCount != 7 {
t.Fatalf("expected imported box owner refresh count 7, got %d", app.config.BoxOwnerMaxRefreshCount)
}
}
func TestAccountSettingsExportShape(t *testing.T) {
app, user := setupAccountTestApp(t)
router := setupAccountTestRouter(t, app)
session := createAccountTestSession(t, app, user)
request := httptest.NewRequest(http.MethodGet, "/account/settings/export.json", nil)
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
if response.Code != http.StatusOK {
t.Fatalf("expected export success, got %d", response.Code)
}
var backup SettingsBackup
if err := json.Unmarshal(response.Body.Bytes(), &backup); err != nil {
t.Fatalf("Unmarshal returned error: %v", err)
}
if backup.Version != 1 {
t.Fatalf("expected version 1, got %d", backup.Version)
}
if _, ok := backup.Settings[config.SettingBoxOwnerMaxRefreshCount]; !ok {
t.Fatal("expected export to include box owner policy setting")
}
if _, ok := backup.Settings[config.SettingDataDir]; ok {
t.Fatal("did not expect locked data dir in export settings")
}
}
func createAccountTestSession(t *testing.T, app *App, user metastore.User) metastore.Session {
t.Helper()
session, err := app.store.CreateSession(user.ID, time.Hour)
if err != nil {
t.Fatalf("CreateSession returned error: %v", err)
}
return session
}
func postAccountSettingsForm(router http.Handler, session metastore.Session, form url.Values) *httptest.ResponseRecorder {
request := httptest.NewRequest(http.MethodPost, "/account/settings", strings.NewReader(form.Encode()))
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
return response
}
func postAccountSettingsJSON(router http.Handler, session metastore.Session, body string) *httptest.ResponseRecorder {
request := httptest.NewRequest(http.MethodPost, "/account/settings/import.json", strings.NewReader(body))
request.Header.Set("Content-Type", "application/json")
request.Header.Set("X-CSRF-Token", session.CSRFToken)
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
return response
}