package test import ( "RenewCMS/internal/domain/role" "go/ast" "go/parser" "go/token" "io/fs" "path/filepath" "reflect" "strconv" "strings" "testing" ) func nonTestGoFiles(t *testing.T, roots ...string) []string { t.Helper() files := []string{} for _, root := range roots { err := filepath.WalkDir(root, func(path string, entry fs.DirEntry, walkErr error) error { if walkErr != nil { return walkErr } if !entry.IsDir() && strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, "_test.go") { files = append(files, path) } return nil }) if err != nil { t.Fatal(err) } } if len(files) == 0 { t.Fatalf("no Go files under %v", roots) } return files } func parsedGoFile(t *testing.T, path string) *ast.File { t.Helper() file, err := parser.ParseFile(token.NewFileSet(), path, nil, 0) if err != nil { t.Fatalf("cannot parse %s: %v", path, err) } return file } func isCreatedBySelector(expression ast.Expr) bool { selector, ok := expression.(*ast.SelectorExpr) return ok && selector.Sel.Name == "CreatedBy" } func TestOwnAndAllHasOneImplementation(t *testing.T) { t.Run("No use case, handler or middleware compares CreatedBy for an authorization decision", func(t *testing.T) { for _, path := range nonTestGoFiles(t, "../api", "../internal/infrastructure/useCases") { ast.Inspect(parsedGoFile(t, path), func(node ast.Node) bool { comparison, ok := node.(*ast.BinaryExpr) if ok && (comparison.Op == token.EQL || comparison.Op == token.NEQ) && (isCreatedBySelector(comparison.X) || isCreatedBySelector(comparison.Y)) { t.Errorf("%s compares CreatedBy directly", path) } return true }) } }) t.Run("A GrantSet is opaque outside the role domain", func(t *testing.T) { if reflect.TypeOf(role.GrantSet{}).Kind() != reflect.Struct { t.Errorf("GrantSet must be a struct so no caller can index it") } }) t.Run("The router and the middleware hold no catalogue key literal", func(t *testing.T) { keys := map[string]bool{} for _, permission := range role.Catalogue() { keys[permission.Key] = true } for _, path := range nonTestGoFiles(t, "../api/middleware", "../api/router.go") { ast.Inspect(parsedGoFile(t, path), func(node ast.Node) bool { literal, ok := node.(*ast.BasicLit) if !ok || literal.Kind != token.STRING { return true } if value, err := strconv.Unquote(literal.Value); err == nil && keys[value] { t.Errorf("%s holds the literal %q, use the role.Key constant", path, value) } return true }) } }) }