This reverts commit ff34279ff4.
This commit is contained in:
@@ -2,6 +2,8 @@ package angulardetector
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
@@ -38,9 +40,43 @@ func (d *regexDetector) Detect(moduleJs []byte) bool {
|
||||
return d.regex.Match(moduleJs)
|
||||
}
|
||||
|
||||
// Inspector can inspect a module.js and determine if it's an Angular plugin or not.
|
||||
type Inspector interface {
|
||||
// Inspect open module.js and checks if the plugin is using Angular by matching against its source code.
|
||||
// It returns true if module.js matches against any of the detectors in angularDetectors.
|
||||
Inspect(p *plugins.Plugin) (bool, error)
|
||||
// angularDetectors contains all the detectors to detect Angular plugins.
|
||||
// They are executed in the specified order.
|
||||
var angularDetectors = []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\(`)},
|
||||
}
|
||||
|
||||
// Inspect open module.js and checks if the plugin is using Angular by matching against its source code.
|
||||
// It returns true if module.js matches against any of the detectors in angularDetectors.
|
||||
func 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 angularDetectors {
|
||||
if d.Detect(b) {
|
||||
isAngular = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -44,10 +44,9 @@ func TestAngularDetector_Inspect(t *testing.T) {
|
||||
},
|
||||
exp: false,
|
||||
})
|
||||
inspector := NewDefaultPatternsListInspector()
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
isAngular, err := inspector.Inspect(tc.plugin)
|
||||
isAngular, err := Inspect(tc.plugin)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.exp, isAngular)
|
||||
})
|
||||
@@ -55,33 +54,7 @@ func TestAngularDetector_Inspect(t *testing.T) {
|
||||
|
||||
t.Run("no module.js", func(t *testing.T) {
|
||||
p := &plugins.Plugin{FS: plugins.NewInMemoryFS(map[string][]byte{})}
|
||||
_, err := inspector.Inspect(p)
|
||||
_, err := Inspect(p)
|
||||
require.ErrorIs(t, err, plugins.ErrFileNotExist)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFakeInspector(t *testing.T) {
|
||||
t.Run("FakeInspector", func(t *testing.T) {
|
||||
var called bool
|
||||
inspector := FakeInspector{InspectFunc: func(p *plugins.Plugin) (bool, error) {
|
||||
called = true
|
||||
return false, nil
|
||||
}}
|
||||
r, err := inspector.Inspect(&plugins.Plugin{})
|
||||
require.True(t, called)
|
||||
require.NoError(t, err)
|
||||
require.False(t, r)
|
||||
})
|
||||
|
||||
t.Run("AlwaysAngularFakeInspector", func(t *testing.T) {
|
||||
r, err := AlwaysAngularFakeInspector.Inspect(&plugins.Plugin{})
|
||||
require.NoError(t, err)
|
||||
require.True(t, r)
|
||||
})
|
||||
|
||||
t.Run("NeverAngularFakeInspector", func(t *testing.T) {
|
||||
r, err := NeverAngularFakeInspector.Inspect(&plugins.Plugin{})
|
||||
require.NoError(t, err)
|
||||
require.False(t, r)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
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
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -1,62 +0,0 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user