package auth import ( "errors" "net/http" "net/http/httptest" "testing" "time" "codeberg.org/SquidSE/ClusterCanvas/service/internal/settings" ) func TestLookupValidSessionReturnsIdle(t *testing.T) { configDir := t.TempDir() key := testSessionKey() manager := NewSessionManager(configDir, key) security := settings.DefaultSecuritySettings() security.IdleTimeoutMinutes = 5 createRec := httptest.NewRecorder() record, err := manager.CreateSession(createRec, "user-1", security) if err != nil { t.Fatalf("CreateSession: %v", err) } store, err := settings.LoadSessions(configDir, key) if err != nil { t.Fatalf("LoadSessions: %v", err) } if len(store.Sessions) != 1 { t.Fatalf("expected 1 session, got %d", len(store.Sessions)) } store.Sessions[0].LastSeenAt = time.Now().UTC().Add(-6 * time.Minute) if err := settings.SaveSessions(configDir, store, key); err != nil { t.Fatalf("SaveSessions: %v", err) } request := httptest.NewRequest(http.MethodGet, "/api/v1/status", nil) request.AddCookie(&http.Cookie{Name: SessionCookieName, Value: record.ID}) lookupRec := httptest.NewRecorder() _, err = manager.LookupValidSession(lookupRec, request, security, true) if !errors.Is(err, ErrSessionIdle) { t.Fatalf("expected ErrSessionIdle, got %v", err) } store, err = settings.LoadSessionsOrEmpty(configDir, key) if err != nil { t.Fatalf("LoadSessionsOrEmpty: %v", err) } if len(store.Sessions) != 0 { t.Fatalf("expected idle session removed, got %#v", store.Sessions) } } func TestLookupValidSessionMissingCookie(t *testing.T) { configDir := t.TempDir() manager := NewSessionManager(configDir, testSessionKey()) security := settings.DefaultSecuritySettings() request := httptest.NewRequest(http.MethodGet, "/api/v1/status", nil) lookupRec := httptest.NewRecorder() _, err := manager.LookupValidSession(lookupRec, request, security, true) if !errors.Is(err, ErrSessionNotFound) { t.Fatalf("expected ErrSessionNotFound, got %v", err) } } func TestLookupValidSessionUnknownCookie(t *testing.T) { configDir := t.TempDir() manager := NewSessionManager(configDir, testSessionKey()) security := settings.DefaultSecuritySettings() request := httptest.NewRequest(http.MethodGet, "/api/v1/status", nil) request.AddCookie(&http.Cookie{Name: SessionCookieName, Value: "unknown-session"}) lookupRec := httptest.NewRecorder() _, err := manager.LookupValidSession(lookupRec, request, security, true) if !errors.Is(err, ErrSessionNotFound) { t.Fatalf("expected ErrSessionNotFound, got %v", err) } } func TestLookupValidSessionWithoutTouchLeavesLastSeenAt(t *testing.T) { configDir := t.TempDir() key := testSessionKey() manager := NewSessionManager(configDir, key) security := settings.DefaultSecuritySettings() security.IdleTimeoutMinutes = 30 createRec := httptest.NewRecorder() record, err := manager.CreateSession(createRec, "user-1", security) if err != nil { t.Fatalf("CreateSession: %v", err) } store, err := settings.LoadSessions(configDir, key) if err != nil { t.Fatalf("LoadSessions: %v", err) } originalLastSeen := time.Now().UTC().Add(-10 * time.Minute).Truncate(time.Second) store.Sessions[0].LastSeenAt = originalLastSeen if err := settings.SaveSessions(configDir, store, key); err != nil { t.Fatalf("SaveSessions: %v", err) } request := httptest.NewRequest(http.MethodGet, "/api/v1/status", nil) request.AddCookie(&http.Cookie{Name: SessionCookieName, Value: record.ID}) lookupRec := httptest.NewRecorder() got, err := manager.LookupValidSession(lookupRec, request, security, false) if err != nil { t.Fatalf("LookupValidSession: %v", err) } if got.ID != record.ID { t.Fatalf("expected session id %q, got %q", record.ID, got.ID) } store, err = settings.LoadSessions(configDir, key) if err != nil { t.Fatalf("LoadSessions after lookup: %v", err) } if len(store.Sessions) != 1 { t.Fatalf("expected 1 session, got %d", len(store.Sessions)) } if !store.Sessions[0].LastSeenAt.Equal(originalLastSeen) { t.Fatalf( "expected LastSeenAt %v unchanged, got %v", originalLastSeen, store.Sessions[0].LastSeenAt, ) } } func TestLookupValidSessionIdleWithoutTouchStillIdle(t *testing.T) { configDir := t.TempDir() key := testSessionKey() manager := NewSessionManager(configDir, key) security := settings.DefaultSecuritySettings() security.IdleTimeoutMinutes = 5 createRec := httptest.NewRecorder() record, err := manager.CreateSession(createRec, "user-1", security) if err != nil { t.Fatalf("CreateSession: %v", err) } store, err := settings.LoadSessions(configDir, key) if err != nil { t.Fatalf("LoadSessions: %v", err) } store.Sessions[0].LastSeenAt = time.Now().UTC().Add(-6 * time.Minute) if err := settings.SaveSessions(configDir, store, key); err != nil { t.Fatalf("SaveSessions: %v", err) } request := httptest.NewRequest(http.MethodGet, "/api/v1/status", nil) request.AddCookie(&http.Cookie{Name: SessionCookieName, Value: record.ID}) lookupRec := httptest.NewRecorder() _, err = manager.LookupValidSession(lookupRec, request, security, false) if !errors.Is(err, ErrSessionIdle) { t.Fatalf("expected ErrSessionIdle, got %v", err) } } func testSessionKey() []byte { key := make([]byte, 32) for index := range key { key[index] = byte(index + 3) } return key }