package handlers import ( "net/http" "testing" "time" "edge-infra.dev/pkg/edge/auth-proxy/types" "github.com/gin-contrib/sessions" "github.com/stretchr/testify/assert" ) func setValidSession(session sessions.Session) { session.Set(types.SessionExpirationField, time.Now().Add(time.Minute)) session.Set(types.SessionIDField, "sessionID") } // User details set in the session are expected to be set identically in the incoming request func TestSessionUserDetailsValid(t *testing.T) { tests := map[string]struct { req *http.Request }{ "Empty Header": { req: &http.Request{ Header: http.Header{}, }, }, "Overwrite Pre-Written Header Values": { req: &http.Request{ Header: http.Header{ headerKeyUsername: []string{"overwrite"}, headerKeyEmail: []string{"overwrite"}, headerKeyRoles: []string{"overwrite"}, headerKeyBannerEdgeIDs: []string{"overwrite"}, }, }, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { username := "user" email := "email@domain" roles := []string{"role1", "role2", "role3"} bannerEdgeIDs := []string{"banner1", "banner2", "banner3"} proxyHandler.session.Set(types.SessionUsernameField, username) proxyHandler.session.Set(types.SessionEmailField, email) proxyHandler.session.Set(types.SessionRolesField, roles) proxyHandler.session.Set(types.SessionBannerEdgeIDs, bannerEdgeIDs) setValidSession(proxyHandler.session) res, _, err := proxyHandler.SessionUserDetails(tc.req, nil) assert.NoError(t, err) assert.Equal(t, username, res.Header.Get(headerKeyUsername)) assert.Equal(t, email, res.Header.Get(headerKeyEmail)) assert.Equal(t, roles, res.Header.Values(headerKeyRoles)) assert.Equal(t, bannerEdgeIDs, res.Header.Values(headerKeyBannerEdgeIDs)) }) } } // On any error, no session user details should be set on the incoming request func TestSessionUserDetailsBad(t *testing.T) { tests := map[string]struct { key1 interface{} key2 interface{} key3 interface{} val1 interface{} val2 interface{} val3 interface{} }{ "No Username": { key1: types.SessionBannerEdgeIDs, val1: []string{"banner1", "banner2", "banner3"}, key2: types.SessionRolesField, val2: []string{"role1", "role2", "role3"}, key3: types.SessionEmailField, val3: "email", }, "No Roles": { key1: types.SessionUsernameField, val1: "user", key2: types.SessionBannerEdgeIDs, val2: []string{"banner1", "banner2", "banner3"}, key3: types.SessionEmailField, val3: "email", }, "No Banners": { key1: types.SessionUsernameField, val1: "user", key2: types.SessionRolesField, val2: []string{"role1", "role2", "role3"}, key3: types.SessionEmailField, val3: "email", }, "No Email": { key1: types.SessionUsernameField, val1: "user", key2: types.SessionRolesField, val2: []string{"role1", "role2", "role3"}, key3: types.SessionBannerEdgeIDs, val3: []string{"banner1", "banner2", "banner3"}, }, "No Session Values": {}, } for name, tc := range tests { t.Run(name, func(t *testing.T) { proxyHandler.session.Clear() proxyHandler.session.Set(tc.key1, tc.val1) proxyHandler.session.Set(tc.key2, tc.val2) proxyHandler.session.Set(tc.key3, tc.val3) setValidSession(proxyHandler.session) req, err := http.NewRequest(http.MethodGet, "", nil) assert.NoError(t, err) assert.Empty(t, req.Header) req, _, err = proxyHandler.SessionUserDetails(req, nil) // We must not return non-nil errors assert.NoError(t, err) assert.Empty(t, req.Header) }) } } // Empty arrays are treated as not-nil and will not cause an error func TestSessionUserDetailsEmptyArrays(t *testing.T) { proxyHandler.session.Set(types.SessionUsernameField, "username") proxyHandler.session.Set(types.SessionEmailField, "email@domain") proxyHandler.session.Set(types.SessionRolesField, []string{}) proxyHandler.session.Set(types.SessionBannerEdgeIDs, []string{}) setValidSession(proxyHandler.session) req, err := http.NewRequest(http.MethodGet, "", nil) assert.NoError(t, err) _, _, err = proxyHandler.SessionUserDetails(req, nil) assert.NoError(t, err) } // If the initial valid session check returns false, return with error func TestSessionUserDetailsInvalidSession(t *testing.T) { tests := map[string]struct { req *http.Request }{ "Empty Header": { req: &http.Request{ Header: http.Header{}, }, }, "With Injected Headers": { req: &http.Request{ Header: http.Header{ headerKeyUsername: []string{"overwrite"}, headerKeyEmail: []string{"overwrite"}, headerKeyRoles: []string{"overwrite"}, headerKeyBannerEdgeIDs: []string{"overwrite"}, }, }, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { proxyHandler.session.Clear() req, _, err := proxyHandler.SessionUserDetails(tc.req, nil) // We must not return non-nil errors assert.NoError(t, err) assert.Empty(t, req.Header) }) } }