aboutsummaryrefslogtreecommitdiffhomepage
path: root/backend/api/auth_middleware_test.go
blob: 9fc20af76d892c1fa4cd7dd76de2abc2ea6f67b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package api

import (
	"context"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/labstack/echo/v4"

	"albatross-2026-backend/db"
	"albatross-2026-backend/session"
)

// mockSessionQuerier implements the subset of db.Querier needed by SessionCookieMiddleware.
type mockSessionQuerier struct {
	db.Querier
	getUserBySessionFunc func(ctx context.Context, sessionID string) (db.User, error)
}

func (m *mockSessionQuerier) GetUserBySession(ctx context.Context, sessionID string) (db.User, error) {
	if m.getUserBySessionFunc != nil {
		return m.getUserBySessionFunc(ctx, sessionID)
	}
	return db.User{}, nil
}

func TestSessionCookieMiddleware_NoCookie(t *testing.T) {
	e := echo.New()
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)

	mw := SessionCookieMiddleware(&mockSessionQuerier{})
	var called bool
	handler := mw(func(c echo.Context) error {
		called = true
		// User should not be set
		_, ok := session.GetUserFromContext(c.Request().Context())
		if ok {
			t.Error("expected no user in context when no cookie is present")
		}
		return nil
	})

	if err := handler(c); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !called {
		t.Error("next handler was not called")
	}
}

func TestSessionCookieMiddleware_ValidSession(t *testing.T) {
	expectedUser := db.User{UserID: 10, Username: "sessionuser"}
	mq := &mockSessionQuerier{
		getUserBySessionFunc: func(_ context.Context, _ string) (db.User, error) {
			return expectedUser, nil
		},
	}

	e := echo.New()
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	req.AddCookie(&http.Cookie{Name: "albatross_session", Value: "raw-session-id"})
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)

	mw := SessionCookieMiddleware(mq)
	var called bool
	handler := mw(func(c echo.Context) error {
		called = true
		user, ok := session.GetUserFromContext(c.Request().Context())
		if !ok {
			t.Fatal("expected user in context")
		}
		if user.UserID != 10 {
			t.Errorf("expected user ID 10, got %d", user.UserID)
		}
		sid, ok := session.GetSessionIDFromContext(c.Request().Context())
		if !ok {
			t.Fatal("expected session ID in context")
		}
		if sid == "" {
			t.Error("expected non-empty hashed session ID")
		}
		return nil
	})

	if err := handler(c); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !called {
		t.Error("next handler was not called")
	}
}

func TestSessionCookieMiddleware_InvalidSession(t *testing.T) {
	mq := &mockSessionQuerier{
		getUserBySessionFunc: func(_ context.Context, _ string) (db.User, error) {
			return db.User{}, echo.ErrNotFound
		},
	}

	e := echo.New()
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	req.AddCookie(&http.Cookie{Name: "albatross_session", Value: "invalid-session"})
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)

	mw := SessionCookieMiddleware(mq)
	var called bool
	handler := mw(func(c echo.Context) error {
		called = true
		_, ok := session.GetUserFromContext(c.Request().Context())
		if ok {
			t.Error("expected no user in context for invalid session")
		}
		return nil
	})

	if err := handler(c); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !called {
		t.Error("next handler was not called")
	}
}