package middleware import ( "context" "errors" "net/http" "net/http/httptest" "testing" "github.com/google/uuid" "github.com/stretchr/testify/require" ) // fakeAuth is a stub SessionResolver used by the auth middleware tests. // It returns either the configured user (ok=true) or the configured error, // so each test can target a specific branch in Auth without spinning up // the real user.Service (which lives in a later phase). type fakeAuth struct { user uuid.UUID err error } func (f fakeAuth) ResolveSession(_ context.Context, _ string) (uuid.UUID, bool, error) { if f.err != nil { return uuid.Nil, false, f.err } return f.user, true, nil } func TestAuth_NoTokenAllowedWhenOptional(t *testing.T) { called := false mw := Auth(fakeAuth{}, AuthOptions{Optional: true}) h := mw(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { called = true _, ok := UserIDFromContext(r.Context()) require.False(t, ok) })) rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest("GET", "/", nil)) require.True(t, called) require.Equal(t, http.StatusOK, rec.Code) } func TestAuth_NoTokenRejectedWhenRequired(t *testing.T) { mw := Auth(fakeAuth{}, AuthOptions{}) h := mw(http.HandlerFunc(func(http.ResponseWriter, *http.Request) { t.Fatal("handler should not be called") })) rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest("GET", "/", nil)) require.Equal(t, http.StatusUnauthorized, rec.Code) } func TestAuth_ValidTokenPopulatesContext(t *testing.T) { uid := uuid.New() mw := Auth(fakeAuth{user: uid}, AuthOptions{}) h := mw(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { got, ok := UserIDFromContext(r.Context()) require.True(t, ok) require.Equal(t, uid, got) })) req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Authorization", "Bearer tok") rec := httptest.NewRecorder() h.ServeHTTP(rec, req) require.Equal(t, http.StatusOK, rec.Code) } func TestAuth_BadTokenReturns401(t *testing.T) { mw := Auth(fakeAuth{err: errors.New("invalid")}, AuthOptions{}) h := mw(http.HandlerFunc(func(http.ResponseWriter, *http.Request) { t.Fatal("handler should not be called") })) req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Authorization", "Bearer x") rec := httptest.NewRecorder() h.ServeHTTP(rec, req) require.Equal(t, http.StatusUnauthorized, rec.Code) } func TestAuth_WebSocketTokenFromSubprotocol(t *testing.T) { uid := uuid.New() mw := Auth(fakeAuth{user: uid}, AuthOptions{}) h := mw(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { got, ok := UserIDFromContext(r.Context()) require.True(t, ok) require.Equal(t, uid, got) })) req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Sec-WebSocket-Protocol", "acp-v1, acw-token.ws-tok") rec := httptest.NewRecorder() h.ServeHTTP(rec, req) require.Equal(t, http.StatusOK, rec.Code) }