package spindle import ( "log/slog" "net/http" "net/http/httptest" "testing" "tangled.org/core/idresolver" "tangled.org/core/spindle/config" ) func TestAdminRouterMountedOnlyWhenConfigured(t *testing.T) { tests := []struct { name string password string want int }{ // mounted: rejects the unauthenticated request instead of 404ing {"configured", "s3cret", http.StatusUnauthorized}, {"unset password", "", http.StatusNotFound}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := &Spindle{ l: slog.Default(), res: idresolver.DefaultResolver("https://plc.test"), cfg: &config.Config{Server: config.Server{ AdminPassword: tt.password, Hostname: "spindle.test", }}, } req := httptest.NewRequest(http.MethodPost, "/admin/member/allow", nil) w := httptest.NewRecorder() s.Router().ServeHTTP(w, req) if w.Code != tt.want { t.Errorf("status = %d, want %d", w.Code, tt.want) } }) } } func TestAdminMiddleware(t *testing.T) { tests := []struct { name string configured string user, pass string basicAuth bool want int }{ {"correct password", "s3cret", "admin", "s3cret", true, http.StatusOK}, {"wrong password", "s3cret", "admin", "nope", true, http.StatusUnauthorized}, {"wrong user", "s3cret", "root", "s3cret", true, http.StatusUnauthorized}, {"no credentials", "s3cret", "", "", false, http.StatusUnauthorized}, // Router() skips the mount when the password is unset, but keep the middleware // fail-closed too - an empty password must not authenticate anyone. {"unset password", "", "admin", "", true, http.StatusUnauthorized}, {"unset password, no credentials", "", "", "", false, http.StatusUnauthorized}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := &Spindle{cfg: &config.Config{ Server: config.Server{AdminPassword: tt.configured}, }} req := httptest.NewRequest(http.MethodPost, "/admin/member/allow", nil) if tt.basicAuth { req.SetBasicAuth(tt.user, tt.pass) } w := httptest.NewRecorder() s.adminMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })).ServeHTTP(w, req) if w.Code != tt.want { t.Errorf("status = %d, want %d", w.Code, tt.want) } }) } }