mirror of https://github.com/grafana/grafana
Plugins: Forbid loading Angular plugins when Angular is disabled (#69225)
* Plugins: Forbid loading Angular plugins when Angular is disabled * Plugins: Made angulardetector a service, add tests for angular loader cases * Fix missing importpull/69657/head
parent
067bbcbe56
commit
ff34279ff4
@ -0,0 +1,29 @@ |
||||
package angulardetector |
||||
|
||||
import "github.com/grafana/grafana/pkg/plugins" |
||||
|
||||
// FakeInspector is an inspector whose Inspect function can be set to any function.
|
||||
type FakeInspector struct { |
||||
// InspectFunc is the function called when calling Inspect()
|
||||
InspectFunc func(p *plugins.Plugin) (bool, error) |
||||
} |
||||
|
||||
func (i *FakeInspector) Inspect(p *plugins.Plugin) (bool, error) { |
||||
return i.InspectFunc(p) |
||||
} |
||||
|
||||
var ( |
||||
// AlwaysAngularFakeInspector is an inspector that always returns `true, nil`
|
||||
AlwaysAngularFakeInspector = &FakeInspector{ |
||||
InspectFunc: func(p *plugins.Plugin) (bool, error) { |
||||
return true, nil |
||||
}, |
||||
} |
||||
|
||||
// NeverAngularFakeInspector is an inspector that always returns `false, nil`
|
||||
NeverAngularFakeInspector = &FakeInspector{ |
||||
InspectFunc: func(p *plugins.Plugin) (bool, error) { |
||||
return false, nil |
||||
}, |
||||
} |
||||
) |
||||
@ -0,0 +1,62 @@ |
||||
package angulardetector |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io" |
||||
"regexp" |
||||
|
||||
"github.com/grafana/grafana/pkg/plugins" |
||||
) |
||||
|
||||
// defaultDetectors contains all the detectors to detect Angular plugins.
|
||||
// They are executed in the specified order.
|
||||
var defaultDetectors = []detector{ |
||||
&containsBytesDetector{pattern: []byte("PanelCtrl")}, |
||||
&containsBytesDetector{pattern: []byte("QueryCtrl")}, |
||||
&containsBytesDetector{pattern: []byte("app/plugins/sdk")}, |
||||
&containsBytesDetector{pattern: []byte("angular.isNumber(")}, |
||||
&containsBytesDetector{pattern: []byte("editor.html")}, |
||||
&containsBytesDetector{pattern: []byte("ctrl.annotation")}, |
||||
&containsBytesDetector{pattern: []byte("getLegacyAngularInjector")}, |
||||
|
||||
®exDetector{regex: regexp.MustCompile(`['"](app/core/utils/promiseToDigest)|(app/plugins/.*?)|(app/core/core_module)['"]`)}, |
||||
®exDetector{regex: regexp.MustCompile(`from\s+['"]grafana\/app\/`)}, |
||||
®exDetector{regex: regexp.MustCompile(`System\.register\(`)}, |
||||
} |
||||
|
||||
// PatternsListInspector matches module.js against all the specified patterns, in sequence.
|
||||
type PatternsListInspector struct { |
||||
detectors []detector |
||||
} |
||||
|
||||
// NewDefaultPatternsListInspector returns a new *PatternsListInspector using defaultDetectors as detectors.
|
||||
func NewDefaultPatternsListInspector() *PatternsListInspector { |
||||
return &PatternsListInspector{detectors: defaultDetectors} |
||||
} |
||||
|
||||
func ProvideService() Inspector { |
||||
return NewDefaultPatternsListInspector() |
||||
} |
||||
|
||||
func (i *PatternsListInspector) Inspect(p *plugins.Plugin) (isAngular bool, err error) { |
||||
f, err := p.FS.Open("module.js") |
||||
if err != nil { |
||||
return false, fmt.Errorf("open module.js: %w", err) |
||||
} |
||||
defer func() { |
||||
if closeErr := f.Close(); closeErr != nil && err == nil { |
||||
err = fmt.Errorf("close module.js: %w", closeErr) |
||||
} |
||||
}() |
||||
b, err := io.ReadAll(f) |
||||
if err != nil { |
||||
return false, fmt.Errorf("module.js readall: %w", err) |
||||
} |
||||
for _, d := range i.detectors { |
||||
if d.Detect(b) { |
||||
isAngular = true |
||||
break |
||||
} |
||||
} |
||||
return |
||||
} |
||||
Loading…
Reference in new issue