94 lines
2.3 KiB
Go
94 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
type toolbarViolation struct {
|
|
file string
|
|
line int
|
|
funcName string
|
|
}
|
|
|
|
// Functions that render full public pages but legitimately skip toolbar injection.
|
|
var toolbarExemptFuncs = map[string]bool{
|
|
// Auto-generated SEO listing pages — not block-editable.
|
|
"renderListingPage": true,
|
|
// Historical version preview — has its own preview banner; toolbar edit/publish
|
|
// buttons would be misleading in that context.
|
|
"renderVersionPreview": true,
|
|
}
|
|
|
|
// checkToolbarInjection scans handler Go files for public page render functions
|
|
// (identified by containing both getSiteSettings and doc["site_settings"]) and
|
|
// verifies each one also injects siteSettings["toolbar"] for the admin toolbar.
|
|
func checkToolbarInjection(root string) []toolbarViolation {
|
|
var violations []toolbarViolation
|
|
|
|
handlersDir := filepath.Join(root, "internal", "handlers")
|
|
if _, err := os.Stat(handlersDir); err != nil {
|
|
return nil
|
|
}
|
|
|
|
_ = filepath.Walk(handlersDir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil || info.IsDir() || !strings.HasSuffix(path, ".go") {
|
|
return nil
|
|
}
|
|
if strings.HasSuffix(path, "_test.go") {
|
|
return nil
|
|
}
|
|
|
|
src, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
srcText := string(src)
|
|
|
|
fset := token.NewFileSet()
|
|
f, err := parser.ParseFile(fset, path, src, 0)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
relPath, _ := filepath.Rel(root, path)
|
|
|
|
for _, decl := range f.Decls {
|
|
fn, ok := decl.(*ast.FuncDecl)
|
|
if !ok || fn.Body == nil {
|
|
continue
|
|
}
|
|
|
|
if toolbarExemptFuncs[fn.Name.Name] {
|
|
continue
|
|
}
|
|
|
|
bodyStart := fset.Position(fn.Body.Pos()).Offset
|
|
bodyEnd := min(fset.Position(fn.Body.End()).Offset, len(srcText))
|
|
body := srcText[bodyStart:bodyEnd]
|
|
|
|
hasSiteSettings := strings.Contains(body, "getSiteSettings")
|
|
hasDocAssign := strings.Contains(body, `doc["site_settings"]`)
|
|
|
|
if hasSiteSettings && hasDocAssign {
|
|
hasToolbar := strings.Contains(body, `siteSettings["toolbar"]`)
|
|
if !hasToolbar {
|
|
violations = append(violations, toolbarViolation{
|
|
file: relPath,
|
|
line: fset.Position(fn.Pos()).Line,
|
|
funcName: fn.Name.Name,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return violations
|
|
}
|