Files
CyberStrikeAI/internal/security/route_inventory_test.go
T
2026-07-10 18:58:17 +08:00

61 lines
1.6 KiB
Go

package security
import (
"go/ast"
"go/parser"
"go/token"
"net/http"
"path/filepath"
"strconv"
"testing"
)
func TestEveryProtectedRouteHasCatalogPermission(t *testing.T) {
file, err := parser.ParseFile(token.NewFileSet(), filepath.Join("..", "app", "app.go"), nil, 0)
if err != nil {
t.Fatal(err)
}
methods := map[string]string{
"GET": http.MethodGet, "POST": http.MethodPost, "PUT": http.MethodPut,
"PATCH": http.MethodPatch, "DELETE": http.MethodDelete,
}
prefixes := map[string]string{"protected": "", "c2Routes": "/c2", "knowledgeRoutes": "/knowledge"}
found := 0
ast.Inspect(file, func(node ast.Node) bool {
call, ok := node.(*ast.CallExpr)
if !ok || len(call.Args) == 0 {
return true
}
sel, ok := call.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
ident, ok := sel.X.(*ast.Ident)
if !ok {
return true
}
prefix, protected := prefixes[ident.Name]
method, routeMethod := methods[sel.Sel.Name]
literal, literalPath := call.Args[0].(*ast.BasicLit)
if !protected || !routeMethod || !literalPath || literal.Kind != token.STRING {
return true
}
path, err := strconv.Unquote(literal.Value)
if err != nil {
t.Errorf("invalid route literal %s", literal.Value)
return true
}
found++
permission := permissionForRequest(method, "/api"+prefix+path)
if permission == "" {
t.Errorf("unmapped protected route: %s %s%s", method, prefix, path)
} else if _, ok := PermissionCatalog[permission]; !ok {
t.Errorf("route %s %s%s maps to unknown permission %q", method, prefix, path, permission)
}
return true
})
if found < 100 {
t.Fatalf("route inventory unexpectedly small: %d", found)
}
}