PublicDashboards: add recipients to the public dashboards retrieval (#63149)

This commit is contained in:
Ezequiel Victorero 2023-02-10 15:01:26 -03:00 committed by GitHub
parent 91dd5b0e0d
commit 8520a8614c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 134 additions and 23 deletions

View File

@ -385,7 +385,6 @@ var wireTestSet = wire.NewSet(
ProvideTestEnv,
sqlstore.ProvideServiceForTests,
ngmetrics.ProvideServiceForTest,
notifications.MockNotificationService,
wire.Bind(new(notifications.Service), new(*notifications.NotificationServiceMock)),
wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationServiceMock)),

View File

@ -28,6 +28,8 @@ import (
"github.com/grafana/grafana/pkg/services/login/authinfoservice"
"github.com/grafana/grafana/pkg/services/pluginsintegration"
"github.com/grafana/grafana/pkg/services/provisioning"
"github.com/grafana/grafana/pkg/services/publicdashboards"
publicdashboardsService "github.com/grafana/grafana/pkg/services/publicdashboards/service"
"github.com/grafana/grafana/pkg/services/searchusers"
"github.com/grafana/grafana/pkg/services/searchusers/filters"
"github.com/grafana/grafana/pkg/services/sqlstore/migrations"
@ -80,6 +82,8 @@ var wireExtsBasicSet = wire.NewSet(
ossaccesscontrol.ProvideDatasourcePermissionsService,
wire.Bind(new(accesscontrol.DatasourcePermissionsService), new(*ossaccesscontrol.DatasourcePermissionsService)),
pluginsintegration.WireExtensionSet,
publicdashboardsService.ProvideServiceWrapper,
wire.Bind(new(publicdashboards.ServiceWrapper), new(*publicdashboardsService.PublicDashboardServiceWrapperImpl)),
)
var wireExtsSet = wire.NewSet(

View File

@ -324,8 +324,9 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T)
store := publicdashboardsStore.ProvideStore(db)
cfg := setting.NewCfg()
ac := acmock.New()
ws := &publicdashboards.FakePublicDashboardServiceWrapper{}
cfg.RBACEnabled = false
service := publicdashboardsService.ProvideService(cfg, store, qds, annotationsService, ac)
service := publicdashboardsService.ProvideService(cfg, store, qds, annotationsService, ac, ws)
pubdash, err := service.Create(context.Background(), &user.SignedInUser{}, savePubDashboardCmd)
require.NoError(t, err)

View File

@ -49,6 +49,7 @@ type PublicDashboard struct {
AnnotationsEnabled bool `json:"annotationsEnabled" xorm:"annotations_enabled"`
TimeSelectionEnabled bool `json:"timeSelectionEnabled" xorm:"time_selection_enabled"`
Share ShareType `json:"share" xorm:"share"`
Recipients []string `json:"recipients,omitempty" xorm:"-"`
CreatedBy int64 `json:"createdBy" xorm:"created_by"`
UpdatedBy int64 `json:"updatedBy" xorm:"updated_by"`
CreatedAt time.Time `json:"createdAt" xorm:"created_at"`

View File

@ -0,0 +1,53 @@
// Code generated by mockery v2.14.0. DO NOT EDIT.
package publicdashboards
import (
context "context"
models "github.com/grafana/grafana/pkg/services/publicdashboards/models"
mock "github.com/stretchr/testify/mock"
)
// FakePublicDashboardServiceWrapper is an autogenerated mock type for the ServiceWrapper type
type FakePublicDashboardServiceWrapper struct {
mock.Mock
}
// FindByDashboardUid provides a mock function with given fields: ctx, orgId, dashboardUid
func (_m *FakePublicDashboardServiceWrapper) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboard, error) {
ret := _m.Called(ctx, orgId, dashboardUid)
var r0 *models.PublicDashboard
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *models.PublicDashboard); ok {
r0 = rf(ctx, orgId, dashboardUid)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*models.PublicDashboard)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
r1 = rf(ctx, orgId, dashboardUid)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
type mockConstructorTestingTNewFakePublicDashboardServiceWrapper interface {
mock.TestingT
Cleanup(func())
}
// NewFakePublicDashboardServiceWrapper creates a new instance of FakePublicDashboardServiceWrapper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewFakePublicDashboardServiceWrapper(t mockConstructorTestingTNewFakePublicDashboardServiceWrapper) *FakePublicDashboardServiceWrapper {
mock := &FakePublicDashboardServiceWrapper{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@ -1,4 +1,4 @@
// Code generated by mockery v2.16.0. DO NOT EDIT.
// Code generated by mockery v2.14.0. DO NOT EDIT.
package publicdashboards

View File

@ -36,6 +36,13 @@ type Service interface {
ExistsEnabledByDashboardUid(ctx context.Context, dashboardUid string) (bool, error)
}
// ServiceWrapper these methods have different behavior between OSS and Enterprise. The latter would call the OSS service first
//
//go:generate mockery --name ServiceWrapper --structname FakePublicDashboardServiceWrapper --inpackage --filename public_dashboard_service_wrapper_mock.go
type ServiceWrapper interface {
FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
}
//go:generate mockery --name Store --structname FakePublicDashboardStore --inpackage --filename public_dashboard_store_mock.go
type Store interface {
Find(ctx context.Context, uid string) (*PublicDashboard, error)

View File

@ -33,6 +33,7 @@ type PublicDashboardServiceImpl struct {
QueryDataService *query.Service
AnnotationsRepo annotations.Repository
ac accesscontrol.AccessControl
serviceWrapper publicdashboards.ServiceWrapper
}
var LogPrefix = "publicdashboards.service"
@ -49,6 +50,7 @@ func ProvideService(
qds *query.Service,
anno annotations.Repository,
ac accesscontrol.AccessControl,
serviceWrapper publicdashboards.ServiceWrapper,
) *PublicDashboardServiceImpl {
return &PublicDashboardServiceImpl{
log: log.New(LogPrefix),
@ -58,9 +60,15 @@ func ProvideService(
QueryDataService: qds,
AnnotationsRepo: anno,
ac: ac,
serviceWrapper: serviceWrapper,
}
}
// FindByDashboardUid this method would be replaced by another implementation for Enterprise version
func (pd *PublicDashboardServiceImpl) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error) {
return pd.serviceWrapper.FindByDashboardUid(ctx, orgId, dashboardUid)
}
func (pd *PublicDashboardServiceImpl) Find(ctx context.Context, uid string) (*PublicDashboard, error) {
pubdash, err := pd.store.Find(ctx, uid)
if err != nil {
@ -120,20 +128,6 @@ func (pd *PublicDashboardServiceImpl) FindPublicDashboardAndDashboardByAccessTok
return pubdash, dash, nil
}
// FindByDashboardUid is a helper method to retrieve the public dashboard configuration for a given dashboard from the database
func (pd *PublicDashboardServiceImpl) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error) {
pubdash, err := pd.store.FindByDashboardUid(ctx, orgId, dashboardUid)
if err != nil {
return nil, ErrInternalServerError.Errorf("FindByDashboardUid: failed to find a public dashboard by orgId: %d and dashboardUid: %s: %w", orgId, dashboardUid, err)
}
if pubdash == nil {
return nil, ErrPublicDashboardNotFound.Errorf("FindByDashboardUid: Public dashboard not found by orgId: %d and dashboardUid: %s", orgId, dashboardUid)
}
return pubdash, nil
}
// Creates and validates the public dashboard and saves it to the database
func (pd *PublicDashboardServiceImpl) Create(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardDTO) (*PublicDashboard, error) {
// ensure dashboard exists

View File

@ -131,10 +131,12 @@ func TestCreatePublicDashboard(t *testing.T) {
require.NoError(t, err)
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
serviceWrapper := ProvideServiceWrapper(publicdashboardStore)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
store: publicdashboardStore,
log: log.New("test.logger"),
store: publicdashboardStore,
serviceWrapper: serviceWrapper,
}
dto := &SavePublicDashboardDTO{
@ -183,10 +185,12 @@ func TestCreatePublicDashboard(t *testing.T) {
require.NoError(t, err)
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
serviceWrapper := ProvideServiceWrapper(publicdashboardStore)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
store: publicdashboardStore,
log: log.New("test.logger"),
store: publicdashboardStore,
serviceWrapper: serviceWrapper,
}
dto := &SavePublicDashboardDTO{
@ -331,10 +335,12 @@ func TestCreatePublicDashboard(t *testing.T) {
require.NoError(t, err)
publicdashboardStore := database.ProvideStore(sqlStore)
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
serviceWrapper := ProvideServiceWrapper(publicdashboardStore)
service := &PublicDashboardServiceImpl{
log: log.New("test.logger"),
store: publicdashboardStore,
log: log.New("test.logger"),
store: publicdashboardStore,
serviceWrapper: serviceWrapper,
}
dto := &SavePublicDashboardDTO{

View File

@ -0,0 +1,45 @@
package service
import (
"context"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/publicdashboards"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
)
// PublicDashboardServiceWrapperImpl Define the Service Implementation. We're generating mock implementation
// automatically
type PublicDashboardServiceWrapperImpl struct {
log log.Logger
store publicdashboards.Store
}
// Gives us compile time error if the service does not adhere to the contract of
// the interface
var _ publicdashboards.ServiceWrapper = (*PublicDashboardServiceWrapperImpl)(nil)
// ProvideServiceWrapper Factory for method used by wire to inject dependencies.
// builds the service, and api, and configures routes
func ProvideServiceWrapper(
store publicdashboards.Store,
) *PublicDashboardServiceWrapperImpl {
return &PublicDashboardServiceWrapperImpl{
log: log.New(LogPrefix),
store: store,
}
}
// FindByDashboardUid is a helper method to retrieve the public dashboard configuration for a given dashboard from the database
func (pd *PublicDashboardServiceWrapperImpl) FindByDashboardUid(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error) {
pubdash, err := pd.store.FindByDashboardUid(ctx, orgId, dashboardUid)
if err != nil {
return nil, ErrInternalServerError.Errorf("FindByDashboardUid: failed to find a public dashboard by orgId: %d and dashboardUid: %s: %w", orgId, dashboardUid, err)
}
if pubdash == nil {
return nil, ErrPublicDashboardNotFound.Errorf("FindByDashboardUid: Public dashboard not found by orgId: %d and dashboardUid: %s", orgId, dashboardUid)
}
return pubdash, nil
}

View File

@ -51,6 +51,7 @@ export const supportedDatasources = new Set<string>([
'marcusolsson-ynab-datasource',
'mssql',
'mysql',
'nagasudhirpulla-api-datasource',
'opentsdb',
'postgres',
'prometheus',