Files
ClusterCanvas/service/internal/api/security_handlers_test.go
T
Squid 2605c3b346 Add users and network settings tabs with admin protections.
List and delete accounts with last-admin and Administrators-group guards, and expose editable network settings via the configuration UI.
2026-07-18 15:18:01 +02:00

153 lines
4.2 KiB
Go

package api
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"codeberg.org/SquidSE/ClusterCanvas/service/internal/settings"
)
type securityResponseTest struct {
Security settings.SecuritySettings `json:"security"`
}
func TestSecurityGetReturnsDefaultsWhenMissing(t *testing.T) {
configDir := t.TempDir()
cookie := seedCompletedSetup(t, configDir)
router := NewRouter(configDir)
request := withSession(httptest.NewRequest(http.MethodGet, "/api/v1/security", nil), cookie)
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, request)
if recorder.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
}
var payload securityResponseTest
if err := json.NewDecoder(recorder.Body).Decode(&payload); err != nil {
t.Fatalf("decode response: %v", err)
}
want := settings.DefaultSecuritySettings()
if payload.Security != want {
t.Fatalf("got %#v, want %#v", payload.Security, want)
}
}
func TestSecurityPutRejectsIdleTimeoutZero(t *testing.T) {
configDir := t.TempDir()
cookie := seedCompletedSetup(t, configDir)
router := NewRouter(configDir)
body := []byte(`{
"security": {
"idle_timeout_minutes": 0,
"session_lifetime_hours": 24,
"reauth_sensitive_actions": false,
"reauth_grace_minutes": 15
}
}`)
request := withSession(httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body)), cookie)
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, request)
if recorder.Code != http.StatusBadRequest {
t.Fatalf("expected status %d, got %d", http.StatusBadRequest, recorder.Code)
}
}
func TestSecurityPutRejectsIdleTimeoutAboveMax(t *testing.T) {
configDir := t.TempDir()
cookie := seedCompletedSetup(t, configDir)
router := NewRouter(configDir)
body := []byte(`{
"security": {
"idle_timeout_minutes": 241,
"session_lifetime_hours": 24,
"reauth_sensitive_actions": false,
"reauth_grace_minutes": 15
}
}`)
request := withSession(httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body)), cookie)
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, request)
if recorder.Code != http.StatusBadRequest {
t.Fatalf("expected status %d, got %d", http.StatusBadRequest, recorder.Code)
}
}
func TestSecurityPutRejectsSessionLifetimeZero(t *testing.T) {
configDir := t.TempDir()
cookie := seedCompletedSetup(t, configDir)
router := NewRouter(configDir)
body := []byte(`{
"security": {
"idle_timeout_minutes": 30,
"session_lifetime_hours": 0,
"reauth_sensitive_actions": false,
"reauth_grace_minutes": 15
}
}`)
request := withSession(httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body)), cookie)
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, request)
if recorder.Code != http.StatusBadRequest {
t.Fatalf("expected status %d, got %d", http.StatusBadRequest, recorder.Code)
}
}
func TestSecurityPutRoundTrip(t *testing.T) {
configDir := t.TempDir()
cookie := seedCompletedSetup(t, configDir)
router := NewRouter(configDir)
body := []byte(`{
"security": {
"idle_timeout_minutes": 45,
"session_lifetime_hours": 12,
"reauth_sensitive_actions": true,
"reauth_grace_minutes": 0,
"totp_enabled": true
}
}`)
putReq := withSession(httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body)), cookie)
putRec := httptest.NewRecorder()
router.ServeHTTP(putRec, putReq)
if putRec.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d body %s", http.StatusOK, putRec.Code, putRec.Body.String())
}
getReq := withSession(httptest.NewRequest(http.MethodGet, "/api/v1/security", nil), cookie)
getRec := httptest.NewRecorder()
router.ServeHTTP(getRec, getReq)
if getRec.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, getRec.Code)
}
var payload securityResponseTest
if err := json.NewDecoder(getRec.Body).Decode(&payload); err != nil {
t.Fatalf("decode response: %v", err)
}
want := settings.SecuritySettings{
IdleTimeoutMinutes: 45,
SessionLifetimeHours: 12,
ReauthSensitiveActions: true,
ReauthGraceMinutes: 0,
TotpEnabled: true,
}
if payload.Security != want {
t.Fatalf("got %#v, want %#v", payload.Security, want)
}
}