From 9c5daed33635a33cc30ef5e4a1b7f8afed24a968 Mon Sep 17 00:00:00 2001 From: Juan Cabanas Date: Tue, 21 Nov 2023 17:56:36 -0300 Subject: [PATCH] PublicDashboards: Middleware creation (#77941) --- pkg/api/api.go | 1 + pkg/api/dashboard_test.go | 3 +- pkg/server/wireexts_oss.go | 3 ++ pkg/services/publicdashboards/api/api.go | 14 ++++--- .../publicdashboards/api/common_test.go | 2 +- .../publicdashboards/api/middleware.go | 16 +++++++ .../public_dashboard_middleware_mock.go | 42 +++++++++++++++++++ .../publicdashboards/publicdashboard.go | 8 ++++ 8 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 pkg/services/publicdashboards/public_dashboard_middleware_mock.go diff --git a/pkg/api/api.go b/pkg/api/api.go index 0196f234820..b3137dc198d 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -166,6 +166,7 @@ func (hs *HTTPServer) registerRoutes() { // anonymous view public dashboard r.Get("/public-dashboards/:accessToken", + hs.PublicDashboardsApi.Middleware.HandleView, publicdashboardsapi.SetPublicDashboardAccessToken, publicdashboardsapi.SetPublicDashboardOrgIdOnContext(hs.PublicDashboardsApi.PublicDashboardService), publicdashboardsapi.CountPublicDashboardRequest(), diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index 17bd61af4b1..0363884e060 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -273,7 +273,8 @@ func TestHTTPServer_DeleteDashboardByUID_AccessControl(t *testing.T) { pubDashService := publicdashboards.NewFakePublicDashboardService(t) pubDashService.On("DeleteByDashboard", mock.Anything, mock.Anything).Return(nil).Maybe() - hs.PublicDashboardsApi = api.ProvideApi(pubDashService, nil, hs.AccessControl, featuremgmt.WithFeatures()) + middleware := publicdashboards.NewFakePublicDashboardMiddleware(t) + hs.PublicDashboardsApi = api.ProvideApi(pubDashService, nil, hs.AccessControl, featuremgmt.WithFeatures(), middleware) guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService) }) diff --git a/pkg/server/wireexts_oss.go b/pkg/server/wireexts_oss.go index 70fb6d45ac7..366cc425646 100644 --- a/pkg/server/wireexts_oss.go +++ b/pkg/server/wireexts_oss.go @@ -35,6 +35,7 @@ import ( "github.com/grafana/grafana/pkg/services/pluginsintegration" "github.com/grafana/grafana/pkg/services/provisioning" "github.com/grafana/grafana/pkg/services/publicdashboards" + publicdashboardsApi "github.com/grafana/grafana/pkg/services/publicdashboards/api" publicdashboardsService "github.com/grafana/grafana/pkg/services/publicdashboards/service" "github.com/grafana/grafana/pkg/services/searchusers" "github.com/grafana/grafana/pkg/services/searchusers/filters" @@ -87,6 +88,8 @@ var wireExtsBasicSet = wire.NewSet( ossaccesscontrol.ProvideDatasourcePermissionsService, wire.Bind(new(accesscontrol.DatasourcePermissionsService), new(*ossaccesscontrol.DatasourcePermissionsService)), pluginsintegration.WireExtensionSet, + publicdashboardsApi.ProvideMiddleware, + wire.Bind(new(publicdashboards.Middleware), new(*publicdashboardsApi.Middleware)), publicdashboardsService.ProvideServiceWrapper, wire.Bind(new(publicdashboards.ServiceWrapper), new(*publicdashboardsService.PublicDashboardServiceWrapperImpl)), caching.ProvideCachingService, diff --git a/pkg/services/publicdashboards/api/api.go b/pkg/services/publicdashboards/api/api.go index 6dfaf7babeb..3713e7d8c59 100644 --- a/pkg/services/publicdashboards/api/api.go +++ b/pkg/services/publicdashboards/api/api.go @@ -26,6 +26,7 @@ type Api struct { AccessControl accesscontrol.AccessControl Features *featuremgmt.FeatureManager Log log.Logger + Middleware publicdashboards.Middleware } func ProvideApi( @@ -33,6 +34,7 @@ func ProvideApi( rr routing.RouteRegister, ac accesscontrol.AccessControl, features *featuremgmt.FeatureManager, + md publicdashboards.Middleware, ) *Api { api := &Api{ PublicDashboardService: pd, @@ -40,6 +42,7 @@ func ProvideApi( AccessControl: ac, Features: features, Log: log.New("publicdashboards.api"), + Middleware: md, } // attach api if PublicDashboards feature flag is enabled @@ -56,11 +59,11 @@ func (api *Api) RegisterAPIEndpoints() { // Anonymous access to public dashboard route is configured in pkg/api/api.go // because it is deeply dependent on the HTTPServer.Index() method and would result in a // circular dependency - - api.RouteRegister.Get("/api/public/dashboards/:accessToken", routing.Wrap(api.ViewPublicDashboard)) - api.RouteRegister.Get("/api/public/dashboards/:accessToken/annotations", routing.Wrap(api.GetPublicAnnotations)) - - api.RouteRegister.Post("/api/public/dashboards/:accessToken/panels/:panelId/query", routing.Wrap(api.QueryPublicDashboard)) + api.RouteRegister.Group("/api/public/dashboards/:accessToken", func(apiRoute routing.RouteRegister) { + apiRoute.Get("/", routing.Wrap(api.ViewPublicDashboard)) + apiRoute.Get("/annotations", routing.Wrap(api.GetPublicAnnotations)) + apiRoute.Post("/panels/:panelId/query", routing.Wrap(api.QueryPublicDashboard)) + }, api.Middleware.HandleApi) // Auth endpoints auth := accesscontrol.Middleware(api.AccessControl) @@ -68,7 +71,6 @@ func (api *Api) RegisterAPIEndpoints() { // List public dashboards for org api.RouteRegister.Get("/api/dashboards/public-dashboards", middleware.ReqSignedIn, routing.Wrap(api.ListPublicDashboards)) - // Get public dashboard api.RouteRegister.Get("/api/dashboards/uid/:dashboardUid/public-dashboards", auth(accesscontrol.EvalPermission(dashboards.ActionDashboardsRead, uidScope)), diff --git a/pkg/services/publicdashboards/api/common_test.go b/pkg/services/publicdashboards/api/common_test.go index 5a7993d9be3..3be29466b68 100644 --- a/pkg/services/publicdashboards/api/common_test.go +++ b/pkg/services/publicdashboards/api/common_test.go @@ -58,7 +58,7 @@ func setupTestServer( // build api, this will mount the routes at the same time if // featuremgmt.FlagPublicDashboard is enabled - ProvideApi(service, rr, ac, features) + ProvideApi(service, rr, ac, features, &Middleware{}) // connect routes to mux rr.Register(m.Router) diff --git a/pkg/services/publicdashboards/api/middleware.go b/pkg/services/publicdashboards/api/middleware.go index cac27ffbc79..dfca53d2313 100644 --- a/pkg/services/publicdashboards/api/middleware.go +++ b/pkg/services/publicdashboards/api/middleware.go @@ -67,3 +67,19 @@ func CountPublicDashboardRequest() func(c *contextmodel.ReqContext) { metrics.MPublicDashboardRequestCount.Inc() } } + +// Empty middleware created in order to bind the enterprise one +type Middleware struct { +} + +var _ publicdashboards.Middleware = (*Middleware)(nil) + +func ProvideMiddleware() *Middleware { + return &Middleware{} +} +func (m *Middleware) HandleApi(c *contextmodel.ReqContext) { +} +func (m *Middleware) HandleView(c *contextmodel.ReqContext) { +} +func (m *Middleware) HandleAccessView(c *contextmodel.ReqContext) { +} diff --git a/pkg/services/publicdashboards/public_dashboard_middleware_mock.go b/pkg/services/publicdashboards/public_dashboard_middleware_mock.go new file mode 100644 index 00000000000..67361df812e --- /dev/null +++ b/pkg/services/publicdashboards/public_dashboard_middleware_mock.go @@ -0,0 +1,42 @@ +// Code generated by mockery v2.36.1. DO NOT EDIT. + +package publicdashboards + +import ( + contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" + mock "github.com/stretchr/testify/mock" +) + +// FakePublicDashboardMiddleware is an autogenerated mock type for the Middleware type +type FakePublicDashboardMiddleware struct { + mock.Mock +} + +// HandleApi provides a mock function with given fields: c +func (_m *FakePublicDashboardMiddleware) HandleApi(c *contextmodel.ReqContext) { + _m.Called(c) +} + +// HandleGet provides a mock function with given fields: c +func (_m *FakePublicDashboardMiddleware) HandleView(c *contextmodel.ReqContext) { + _m.Called(c) +} + +// HandleRequestOrConfirmAccess provides a mock function with given fields: c +func (_m *FakePublicDashboardMiddleware) HandleAccessView(c *contextmodel.ReqContext) { + _m.Called(c) +} + +// NewFakePublicDashboardMiddleware creates a new instance of FakePublicDashboardMiddleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFakePublicDashboardMiddleware(t interface { + mock.TestingT + Cleanup(func()) +}) *FakePublicDashboardMiddleware { + mock := &FakePublicDashboardMiddleware{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/publicdashboards/publicdashboard.go b/pkg/services/publicdashboards/publicdashboard.go index d6fe478c87b..943fd810b55 100644 --- a/pkg/services/publicdashboards/publicdashboard.go +++ b/pkg/services/publicdashboards/publicdashboard.go @@ -5,6 +5,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana/pkg/api/dtos" + contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/dashboards" . "github.com/grafana/grafana/pkg/services/publicdashboards/models" "github.com/grafana/grafana/pkg/services/user" @@ -64,3 +65,10 @@ type Store interface { ExistsEnabledByDashboardUid(ctx context.Context, dashboardUid string) (bool, error) GetMetrics(ctx context.Context) (*Metrics, error) } + +//go:generate mockery --name Middleware --structname FakePublicDashboardMiddleware --inpackage --filename public_dashboard_middleware_mock.go +type Middleware interface { + HandleApi(c *contextmodel.ReqContext) + HandleView(c *contextmodel.ReqContext) + HandleAccessView(c *contextmodel.ReqContext) +}