Files
ClusterCanvas/service/internal/api/security_handlers_test.go
T

158 lines
3.9 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) {
t.Parallel()
configDir := t.TempDir()
router := NewRouter(configDir)
request := httptest.NewRequest(http.MethodGet, "/api/v1/security", nil)
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) {
t.Parallel()
configDir := t.TempDir()
router := NewRouter(configDir)
body := []byte(`{
"security": {
"idle_timeout_minutes": 0,
"session_lifetime_hours": 24,
"reauth_sensitive_actions": false,
"reauth_grace_minutes": 15
}
}`)
request := httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body))
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) {
t.Parallel()
configDir := t.TempDir()
router := NewRouter(configDir)
body := []byte(`{
"security": {
"idle_timeout_minutes": 241,
"session_lifetime_hours": 24,
"reauth_sensitive_actions": false,
"reauth_grace_minutes": 15
}
}`)
request := httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body))
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) {
t.Parallel()
configDir := t.TempDir()
router := NewRouter(configDir)
body := []byte(`{
"security": {
"idle_timeout_minutes": 30,
"session_lifetime_hours": 0,
"reauth_sensitive_actions": false,
"reauth_grace_minutes": 15
}
}`)
request := httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body))
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) {
t.Parallel()
configDir := t.TempDir()
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 := httptest.NewRequest(http.MethodPut, "/api/v1/security", bytes.NewReader(body))
putRec := httptest.NewRecorder()
router.ServeHTTP(putRec, putReq)
if putRec.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, putRec.Code)
}
getReq := httptest.NewRequest(http.MethodGet, "/api/v1/security", nil)
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)
}
}