refactor(10.2-01): nest framework packages under modules
- Move remaining beach packages and embedded admin assets\n- Rewrite framework, example, build, and gate paths
This commit is contained in:
106
modules/cabana/security_test.go
Normal file
106
modules/cabana/security_test.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package cabana
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/bouncer"
|
||||
"git.golem15.com/golem15/summercms/modules/pact"
|
||||
)
|
||||
|
||||
type orderController struct {
|
||||
perms []string
|
||||
}
|
||||
|
||||
func (orderController) ID() string { return "acme.demo.widgets" }
|
||||
func (orderController) ModelName() string { return "Widget" }
|
||||
func (orderController) ConfigDir() string { return "controllers/widgets" }
|
||||
func (c orderController) RequiredPermissions() []string {
|
||||
return c.perms
|
||||
}
|
||||
|
||||
func TestAuthorizationOrder(t *testing.T) {
|
||||
svc := &service{reg: &Registry{byID: map[string]*CompiledController{
|
||||
"acme.demo.widgets": {
|
||||
Controller: orderController{perms: []string{"acme.demo.access"}},
|
||||
List: &ListSchema{RecordsPerPage: 20, Columns: []ListColumn{}},
|
||||
},
|
||||
}}}
|
||||
t.Run("permission before schema", func(t *testing.T) {
|
||||
called := 0
|
||||
rec := httptest.NewRecorder()
|
||||
req := controllerRequest(&bouncer.Principal{ID: 4})
|
||||
svc.protect(rec, req, func(*CompiledController) { called++ })
|
||||
if rec.Code != http.StatusForbidden {
|
||||
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
if called != 0 {
|
||||
t.Fatal("schema or database callback ran before permission denial")
|
||||
}
|
||||
assertErrorCode(t, rec.Body.Bytes(), "forbidden")
|
||||
})
|
||||
t.Run("superuser reaches handler", func(t *testing.T) {
|
||||
called := 0
|
||||
rec := httptest.NewRecorder()
|
||||
req := controllerRequest(&bouncer.Principal{ID: 1, IsSuperuser: true})
|
||||
svc.protect(rec, req, func(*CompiledController) { called++ })
|
||||
if called != 1 {
|
||||
t.Fatalf("superuser callback count=%d, want 1", called)
|
||||
}
|
||||
})
|
||||
t.Run("unknown controller is not queried", func(t *testing.T) {
|
||||
called := 0
|
||||
rec := httptest.NewRecorder()
|
||||
req := controllerRequest(&bouncer.Principal{ID: 1, IsSuperuser: true})
|
||||
req.SetPathValue("controller", "missing")
|
||||
svc.protect(rec, req, func(*CompiledController) { called++ })
|
||||
if rec.Code != http.StatusNotFound || called != 0 {
|
||||
t.Fatalf("status=%d called=%d", rec.Code, called)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSecretRedaction(t *testing.T) {
|
||||
const secret = "summercms-test-only-admin-hs256-secret"
|
||||
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIn0.signature"
|
||||
rec := httptest.NewRecorder()
|
||||
writeUnauthenticated(rec, errors.New(secret+" "+token))
|
||||
body := rec.Body.String()
|
||||
if strings.Contains(body, secret) || strings.Contains(body, token) || strings.Contains(body, "eyJ") {
|
||||
t.Fatalf("unauthorized body leaked credential material: %s", body)
|
||||
}
|
||||
assertErrorCode(t, rec.Body.Bytes(), "unauthenticated")
|
||||
}
|
||||
|
||||
func controllerRequest(principal *bouncer.Principal) *http.Request {
|
||||
req := httptest.NewRequest(http.MethodGet, adminAPI("/acme/demo/widgets"), nil)
|
||||
req.SetPathValue("vendor", "acme")
|
||||
req.SetPathValue("plugin", "demo")
|
||||
req.SetPathValue("controller", "widgets")
|
||||
if principal != nil {
|
||||
principal.Backend = true
|
||||
req = req.WithContext(bouncer.WithUser(req.Context(), principal))
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func assertErrorCode(t *testing.T, raw []byte, code string) {
|
||||
t.Helper()
|
||||
var body struct {
|
||||
Error struct {
|
||||
Code string `json:"code"`
|
||||
} `json:"error"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &body); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if body.Error.Code != code {
|
||||
t.Fatalf("error code=%q, want %s; body %s", body.Error.Code, code, raw)
|
||||
}
|
||||
}
|
||||
|
||||
var _ pact.AdminPermissioned = orderController{}
|
||||
Reference in New Issue
Block a user