grafana/pkg/services/pluginsintegration/clientmiddleware/user_header_middleware_test.go
Marcus Efraimsson c35c689a96
Plugins: Automatically forward plugin request HTTP headers in outgoing HTTP requests (#60417)
Automatically forward core plugin request HTTP headers in outgoing HTTP requests. 
Core datasource plugin authors don't have to specifically handle forwarding of HTTP 
headers, e.g. do not have to "hardcode" the header-names in the datasource plugin, 
if not having custom needs.

Fixes #57065
2022-12-21 13:25:58 +01:00

205 lines
7.2 KiB
Go

package clientmiddleware
import (
"net/http"
"testing"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/plugins/manager/client/clienttest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util/proxyutil"
"github.com/stretchr/testify/require"
)
func TestUserHeaderMiddleware(t *testing.T) {
t.Run("When anononymous user in reqContext", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, "/some/thing", nil)
require.NoError(t, err)
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
}
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.QueryDataReq)
require.Empty(t, cdt.QueryDataReq.Headers)
})
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
require.NoError(t, err)
require.NotNil(t, cdt.CallResourceReq)
require.Empty(t, cdt.CallResourceReq.Headers)
})
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.CheckHealthReq)
require.Empty(t, cdt.CheckHealthReq.Headers)
})
})
t.Run("And requests are for an app", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
IsAnonymous: true,
Login: "anonymous"},
),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
AppInstanceSettings: &backend.AppInstanceSettings{},
}
t.Run("Should not forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.QueryDataReq)
require.Empty(t, cdt.QueryDataReq.Headers)
})
t.Run("Should not forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
require.NoError(t, err)
require.NotNil(t, cdt.CallResourceReq)
require.Empty(t, cdt.CallResourceReq.Headers)
})
t.Run("Should not forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.CheckHealthReq)
require.Empty(t, cdt.CheckHealthReq.Headers)
})
})
})
t.Run("When real user in reqContext", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, "/some/thing", nil)
require.NoError(t, err)
t.Run("And requests are for a datasource", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
Login: "admin",
}),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
}
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.QueryDataReq)
require.Len(t, cdt.QueryDataReq.Headers, 1)
require.Equal(t, "admin", cdt.QueryDataReq.GetHTTPHeader(proxyutil.UserHeaderName))
})
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
require.NoError(t, err)
require.NotNil(t, cdt.CallResourceReq)
require.Len(t, cdt.CallResourceReq.Headers, 1)
require.Equal(t, "admin", cdt.CallResourceReq.GetHTTPHeader(proxyutil.UserHeaderName))
})
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.CheckHealthReq)
require.Len(t, cdt.CheckHealthReq.Headers, 1)
require.Equal(t, "admin", cdt.CheckHealthReq.GetHTTPHeader(proxyutil.UserHeaderName))
})
})
t.Run("And requests are for an app", func(t *testing.T) {
cdt := clienttest.NewClientDecoratorTest(t,
clienttest.WithReqContext(req, &user.SignedInUser{
Login: "admin",
}),
clienttest.WithMiddlewares(NewUserHeaderMiddleware()),
)
pluginCtx := backend.PluginContext{
AppInstanceSettings: &backend.AppInstanceSettings{},
}
t.Run("Should forward user header when calling QueryData", func(t *testing.T) {
_, err = cdt.Decorator.QueryData(req.Context(), &backend.QueryDataRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.QueryDataReq)
require.Len(t, cdt.QueryDataReq.Headers, 1)
require.Equal(t, "admin", cdt.QueryDataReq.GetHTTPHeader(proxyutil.UserHeaderName))
})
t.Run("Should forward user header when calling CallResource", func(t *testing.T) {
err = cdt.Decorator.CallResource(req.Context(), &backend.CallResourceRequest{
PluginContext: pluginCtx,
Headers: map[string][]string{},
}, nopCallResourceSender)
require.NoError(t, err)
require.NotNil(t, cdt.CallResourceReq)
require.Len(t, cdt.CallResourceReq.Headers, 1)
require.Equal(t, "admin", cdt.CallResourceReq.GetHTTPHeader(proxyutil.UserHeaderName))
})
t.Run("Should forward user header when calling CheckHealth", func(t *testing.T) {
_, err = cdt.Decorator.CheckHealth(req.Context(), &backend.CheckHealthRequest{
PluginContext: pluginCtx,
Headers: map[string]string{},
})
require.NoError(t, err)
require.NotNil(t, cdt.CheckHealthReq)
require.Len(t, cdt.CheckHealthReq.Headers, 1)
require.Equal(t, "admin", cdt.CheckHealthReq.GetHTTPHeader(proxyutil.UserHeaderName))
})
})
})
}