Migration
This is my new public git source viewer. Source coming soon. Please contact with concerns/bugs.
Contact me
internal/notices/handler_test.go
d658fcc4ea9f3bb562fd00dce8f863934560c56c
· 3.3 KB · 114 lines
raw
| 1 | package notices |
| 2 | |
| 3 | import ( |
| 4 | "log/slog" |
| 5 | "net/http" |
| 6 | "net/http/httptest" |
| 7 | "path/filepath" |
| 8 | "testing" |
| 9 | ) |
| 10 | |
| 11 | func testHandler(t *testing.T, cfg HandlerConfig) http.Handler { |
| 12 | t.Helper() |
| 13 | store, err := Open(filepath.Join(t.TempDir(), "notices.yaml")) |
| 14 | if err != nil { |
| 15 | t.Fatalf("Open: %v", err) |
| 16 | } |
| 17 | t.Cleanup(store.Close) |
| 18 | cfg.Store = store |
| 19 | if cfg.Logger == nil { |
| 20 | cfg.Logger = slog.Default() |
| 21 | } |
| 22 | h, err := NewHandler(cfg) |
| 23 | if err != nil { |
| 24 | t.Fatalf("NewHandler: %v", err) |
| 25 | } |
| 26 | return h |
| 27 | } |
| 28 | |
| 29 | // Without RequiredGroup, the handler behaves exactly as it always did: |
| 30 | // reaching it at all is enough, regardless of any group header. |
| 31 | func TestHandlerNoGroupGateByDefault(t *testing.T) { |
| 32 | h := testHandler(t, HandlerConfig{}) |
| 33 | |
| 34 | req := httptest.NewRequest("GET", "/admin/notices", nil) |
| 35 | rec := httptest.NewRecorder() |
| 36 | h.ServeHTTP(rec, req) |
| 37 | if rec.Code != http.StatusOK { |
| 38 | t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | // With RequiredGroup set, a caller whose GroupHeader doesn't list it is |
| 43 | // refused before the handler does anything else -- no CSRF cookie, no page. |
| 44 | func TestHandlerRejectsMissingGroup(t *testing.T) { |
| 45 | h := testHandler(t, HandlerConfig{RequiredGroup: "gsg-admins"}) |
| 46 | |
| 47 | cases := []struct { |
| 48 | name string |
| 49 | groups string |
| 50 | }{ |
| 51 | {"no header", ""}, |
| 52 | {"different group", "some-other-group"}, |
| 53 | {"prefix collision", "gsg-admins-extra"}, |
| 54 | } |
| 55 | for _, tc := range cases { |
| 56 | t.Run(tc.name, func(t *testing.T) { |
| 57 | req := httptest.NewRequest("GET", "/admin/notices", nil) |
| 58 | if tc.groups != "" { |
| 59 | req.Header.Set("X-Authentik-Groups", tc.groups) |
| 60 | } |
| 61 | rec := httptest.NewRecorder() |
| 62 | h.ServeHTTP(rec, req) |
| 63 | if rec.Code != http.StatusForbidden { |
| 64 | t.Fatalf("status = %d, want %d", rec.Code, http.StatusForbidden) |
| 65 | } |
| 66 | if rec.Result().Cookies() != nil && len(rec.Result().Cookies()) != 0 { |
| 67 | t.Errorf("rejected request set cookies: %v", rec.Result().Cookies()) |
| 68 | } |
| 69 | }) |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | // A member -- anywhere in the "|"-delimited list, with incidental |
| 74 | // whitespace -- is let through. |
| 75 | func TestHandlerAllowsMemberGroup(t *testing.T) { |
| 76 | h := testHandler(t, HandlerConfig{RequiredGroup: "gsg-admins"}) |
| 77 | |
| 78 | cases := []string{ |
| 79 | "gsg-admins", |
| 80 | "other-group|gsg-admins", |
| 81 | "gsg-admins|other-group", |
| 82 | "other-group| gsg-admins |another", |
| 83 | } |
| 84 | for _, groups := range cases { |
| 85 | req := httptest.NewRequest("GET", "/admin/notices", nil) |
| 86 | req.Header.Set("X-Authentik-Groups", groups) |
| 87 | rec := httptest.NewRecorder() |
| 88 | h.ServeHTTP(rec, req) |
| 89 | if rec.Code != http.StatusOK { |
| 90 | t.Errorf("groups=%q: status = %d, want %d", groups, rec.Code, http.StatusOK) |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | // A custom GroupHeader is honored instead of the Authentik default. |
| 96 | func TestHandlerCustomGroupHeader(t *testing.T) { |
| 97 | h := testHandler(t, HandlerConfig{RequiredGroup: "gsg-admins", GroupHeader: "X-Custom-Groups"}) |
| 98 | |
| 99 | req := httptest.NewRequest("GET", "/admin/notices", nil) |
| 100 | req.Header.Set("X-Authentik-Groups", "gsg-admins") // wrong header, should not count |
| 101 | rec := httptest.NewRecorder() |
| 102 | h.ServeHTTP(rec, req) |
| 103 | if rec.Code != http.StatusForbidden { |
| 104 | t.Fatalf("status = %d, want %d (wrong header should not authorize)", rec.Code, http.StatusForbidden) |
| 105 | } |
| 106 | |
| 107 | req = httptest.NewRequest("GET", "/admin/notices", nil) |
| 108 | req.Header.Set("X-Custom-Groups", "gsg-admins") |
| 109 | rec = httptest.NewRecorder() |
| 110 | h.ServeHTTP(rec, req) |
| 111 | if rec.Code != http.StatusOK { |
| 112 | t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK) |
| 113 | } |
| 114 | } |