Public dashboards: move to integration tests (#108735)

This commit is contained in:
Stephanie Hingtgen
2025-07-28 17:14:09 +00:00
committed by GitHub
parent 5ef744aa20
commit caa75b1d94
5 changed files with 634 additions and 798 deletions
@@ -1,7 +1,6 @@
package api
import (
"context"
"io"
"net/http"
"net/http/httptest"
@@ -9,32 +8,15 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/datasources"
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
"github.com/grafana/grafana/pkg/services/datasources/guardian"
datasourceService "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/licensing/licensingtest"
"github.com/grafana/grafana/pkg/services/mtdsclient"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig"
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/services/publicdashboards"
publicdashboardModels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
"github.com/grafana/grafana/pkg/services/query"
fakeSecrets "github.com/grafana/grafana/pkg/services/secrets/fakes"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tests/testsuite"
@@ -108,77 +90,3 @@ func callAPI(server *web.Mux, method, path string, body io.Reader, t *testing.T)
server.ServeHTTP(recorder, req)
return recorder
}
// helper to query.Service
// allows us to stub the cache and plugin clients
func buildQueryDataService(t *testing.T, cs datasources.CacheService, fpc *fakePluginClient, store db.DB) *query.ServiceImpl {
// build database if we need one
if store == nil {
store = db.InitTestDB(t)
}
// default cache service
if cs == nil {
cs = datasourceService.ProvideCacheService(localcache.ProvideService(), store, guardian.ProvideGuardian())
}
// default fakePluginClient
if fpc == nil {
fpc = &fakePluginClient{
QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
resp := backend.Responses{
"A": backend.DataResponse{
Frames: []*data.Frame{{}},
},
}
return &backend.QueryDataResponse{Responses: resp}, nil
},
}
}
ds := &fakeDatasources.FakeDataSourceService{}
pCtxProvider := plugincontext.ProvideService(setting.NewCfg(),
localcache.ProvideService(), &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
JSONData: plugins.JSONData{
ID: "mysql",
},
},
},
}, &fakeDatasources.FakeCacheService{}, ds,
pluginSettings.ProvideService(store, fakeSecrets.NewFakeSecretsService()), pluginconfig.NewFakePluginRequestConfigProvider())
return query.ProvideService(
setting.NewCfg(),
cs,
nil,
&fakeDataSourceRequestValidator{},
fpc,
pCtxProvider,
mtdsclient.NewNullMTDatasourceClientBuilder(),
)
}
// copied from pkg/api/metrics_test.go
type fakeDataSourceRequestValidator struct {
err error
}
func (rv *fakeDataSourceRequestValidator) Validate(ds *datasources.DataSource, req *http.Request) error {
return rv.err
}
// copied from pkg/api/plugins_test.go
type fakePluginClient struct {
plugins.Client
backend.QueryDataHandlerFunc
}
func (c *fakePluginClient) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if c.QueryDataHandlerFunc != nil {
return c.QueryDataHandlerFunc.QueryData(ctx, req)
}
return backend.NewQueryDataResponse(), nil
}
@@ -1,7 +1,6 @@
package api
import (
"context"
"encoding/json"
"errors"
"fmt"
@@ -20,35 +19,9 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/serverlock"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
"github.com/grafana/grafana/pkg/services/apiserver/client"
"github.com/grafana/grafana/pkg/services/dashboards"
dashboardStore "github.com/grafana/grafana/pkg/services/dashboards/database"
"github.com/grafana/grafana/pkg/services/dashboards/service"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/guardian"
datasourcesService "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
"github.com/grafana/grafana/pkg/services/folder/foldertest"
"github.com/grafana/grafana/pkg/services/licensing/licensingtest"
"github.com/grafana/grafana/pkg/services/publicdashboards"
publicdashboardsStore "github.com/grafana/grafana/pkg/services/publicdashboards/database"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
publicdashboardsService "github.com/grafana/grafana/pkg/services/publicdashboards/service"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/search/sort"
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/storage/legacysql/dualwrite"
"github.com/grafana/grafana/pkg/web"
)
@@ -258,126 +231,6 @@ func getValidQueryPath(accessToken string) string {
return fmt.Sprintf("/api/public/dashboards/%s/panels/2/query", accessToken)
}
func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
db, cfg := db.InitTestDBWithCfg(t)
cacheService := datasourcesService.ProvideCacheService(localcache.ProvideService(), db, guardian.ProvideGuardian())
qds := buildQueryDataService(t, cacheService, nil, db)
dsStore := datasourcesService.CreateStore(db, log.New("publicdashboards.test"))
_, _ = dsStore.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
UID: "ds1",
OrgID: 1,
Name: "laban",
Type: datasources.DS_MYSQL,
Access: datasources.DS_ACCESS_DIRECT,
URL: "http://test",
Database: "site",
ReadOnly: true,
})
// Create Dashboard
saveDashboardCmd := dashboards.SaveDashboardCommand{
OrgID: 1,
FolderUID: "",
IsFolder: false,
Dashboard: simplejson.NewFromAny(map[string]any{
"id": nil,
"title": "test",
"panels": []map[string]any{
{
"id": 1,
"targets": []map[string]any{
{
"datasource": map[string]string{
"type": "mysql",
"uid": "ds1",
},
"refId": "A",
},
},
},
},
}),
}
// create dashboard
dashboardStoreService, err := dashboardStore.ProvideDashboardStore(db, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(db))
require.NoError(t, err)
dashboard, err := dashboardStoreService.SaveDashboard(context.Background(), saveDashboardCmd)
require.NoError(t, err)
// Create public dashboard
isEnabled := true
savePubDashboardCmd := &SavePublicDashboardDTO{
DashboardUid: dashboard.UID,
OrgID: dashboard.OrgID,
PublicDashboard: &PublicDashboardDTO{
IsEnabled: &isEnabled,
},
}
annotationsService := annotationstest.NewFakeAnnotationsRepo()
// create public dashboard
store := publicdashboardsStore.ProvideStore(db, cfg, featuremgmt.WithFeatures())
cfg.PublicDashboardsEnabled = true
ac := actest.FakeAccessControl{}
ws := publicdashboardsService.ProvideServiceWrapper(store)
folderStore := folderimpl.ProvideDashboardFolderStore(db)
dashPermissionService := acmock.NewMockedPermissionsService()
dashService, err := service.ProvideDashboardServiceImpl(
cfg, dashboardStoreService, folderStore,
featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), ac, actest.FakeService{},
foldertest.NewFakeService(), nil, client.MockTestRestConfig{}, nil, quotatest.New(false, nil), nil, nil,
nil, dualwrite.ProvideTestService(), sort.ProvideService(),
serverlock.ProvideService(db, tracing.InitializeTracerForTest()),
kvstore.NewFakeKVStore(),
)
require.NoError(t, err)
dashService.RegisterDashboardPermissions(dashPermissionService)
license := licensingtest.NewFakeLicensing()
license.On("FeatureEnabled", FeaturePublicDashboardsEmailSharing).Return(false)
pds := publicdashboardsService.ProvideService(cfg, featuremgmt.WithFeatures(), store, qds, annotationsService, ac, ws, dashService, license)
pubdash, err := pds.Create(context.Background(), &user.SignedInUser{}, savePubDashboardCmd)
require.NoError(t, err)
// setup test server
server := setupTestServer(t, cfg, pds, anonymousUser)
resp := callAPI(server, http.MethodPost,
fmt.Sprintf("/api/public/dashboards/%s/panels/1/query", pubdash.AccessToken),
strings.NewReader(`{}`),
t,
)
require.Equal(t, http.StatusOK, resp.Code)
require.NoError(t, err)
require.JSONEq(
t,
`{
"results": {
"A": {
"status": 200,
"frames": [
{
"data": {
"values": []
},
"schema": {
"fields": []
}
}
]
}
}
}`,
resp.Body.String(),
)
}
func TestAPIGetAnnotations(t *testing.T) {
testCases := []struct {
Name string
@@ -16,33 +16,16 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/serverlock"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/apiserver"
"github.com/grafana/grafana/pkg/services/apiserver/client"
"github.com/grafana/grafana/pkg/services/dashboards"
dashboardsDB "github.com/grafana/grafana/pkg/services/dashboards/database"
dashsvc "github.com/grafana/grafana/pkg/services/dashboards/service"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
"github.com/grafana/grafana/pkg/services/org"
. "github.com/grafana/grafana/pkg/services/publicdashboards"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
"github.com/grafana/grafana/pkg/services/publicdashboards/service/intervalv2"
"github.com/grafana/grafana/pkg/services/publicdashboards/validation"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/search/sort"
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/storage/legacysql/dualwrite"
"github.com/grafana/grafana/pkg/tests/testsuite"
"github.com/grafana/grafana/pkg/util"
)
@@ -1407,548 +1390,6 @@ func TestDashboardEnabledChanged(t *testing.T) {
})
}
func TestIntegrationPublicDashboardServiceImpl_ListPublicDashboards(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test in short mode")
}
features := featuremgmt.WithFeatures()
testDB, cfg := db.InitTestDBWithCfg(t)
dashStore, err := dashboardsDB.ProvideDashboardStore(testDB, cfg, features, tagimpl.ProvideService(testDB))
require.NoError(t, err)
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
fStore := folderimpl.ProvideStore(testDB)
folderPermissions := acmock.NewMockedPermissionsService()
folderStore := folderimpl.ProvideDashboardFolderStore(testDB)
folderSvc := folderimpl.ProvideService(
fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore,
nil, testDB, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig)
dashboardService, err := dashsvc.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuremgmt.WithFeatures(), folderPermissions, ac, actest.FakeService{}, folderSvc, nil, client.MockTestRestConfig{}, nil, quotatest.New(false, nil), nil, nil, nil, dualwrite.ProvideTestService(), sort.ProvideService(),
serverlock.ProvideService(testDB, tracing.InitializeTracerForTest()),
kvstore.NewFakeKVStore())
require.NoError(t, err)
dashboardService.RegisterDashboardPermissions(&actest.FakePermissionsService{})
// insert in test data so we can check that permissions are working properly through the dashboard service
// this will create 4 dashboards and 3 users
// user1 has access to all dashboards ("*")
// user2 has access to solely one dashboard
// user3 has access to all created dashboards through specific permissions
creatingUser := &user.SignedInUser{
UserID: 1,
OrgID: 1,
OrgRole: org.RoleAdmin,
}
dashboardsToSave := []dashboards.SaveDashboardDTO{
{
OrgID: 1,
User: creatingUser,
Dashboard: &dashboards.Dashboard{
OrgID: 1,
UID: "9S6TmO67z",
Title: "test",
Slug: "test",
Data: simplejson.New(),
},
},
{
OrgID: 1,
User: creatingUser,
Dashboard: &dashboards.Dashboard{
OrgID: 1,
UID: "1S6TmO67z",
Title: "my first dashboard",
Slug: "my-first-dashboard",
Data: simplejson.New(),
},
},
{
OrgID: 1,
User: creatingUser,
Dashboard: &dashboards.Dashboard{
OrgID: 1,
UID: "2S6TmO67z",
Title: "my second dashboard",
Slug: "my-second-dashboard",
Data: simplejson.New(),
},
},
{
OrgID: 1,
User: creatingUser,
Dashboard: &dashboards.Dashboard{
OrgID: 1,
UID: "0S6TmO67z",
Title: "my zero dashboard",
Slug: "my-zero-dashboard",
Data: simplejson.New(),
},
},
}
for _, dash := range dashboardsToSave {
_, err = dashboardService.SaveDashboard(context.Background(), &dash, true)
require.NoError(t, err)
}
users := []user.User{
{
ID: 1,
UID: "user1",
Email: "test1@gmail.com",
Login: "user1",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 2,
UID: "user2",
Login: "user2",
Email: "test2@gmail.com",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 3,
UID: "user3",
Login: "user3",
Email: "test3@gmail.com",
Created: time.Now(),
Updated: time.Now(),
},
}
roles := []accesscontrol.Role{
{
ID: 1,
UID: "role1",
Name: "forUser1",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 2,
UID: "role2",
Name: "forUser2",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 3,
UID: "role3",
Name: "forUser3",
Created: time.Now(),
Updated: time.Now(),
},
}
userRoles := []accesscontrol.UserRole{
{
ID: 1,
OrgID: 1,
UserID: 1,
RoleID: 1,
Created: time.Now(),
},
{
ID: 2,
OrgID: 1,
UserID: 2,
RoleID: 2,
Created: time.Now(),
},
{
ID: 3,
OrgID: 1,
UserID: 3,
RoleID: 3,
Created: time.Now(),
},
}
permissions := []accesscontrol.Permission{
{
ID: 1,
RoleID: 1,
Action: dashboards.ActionDashboardsRead,
Scope: "*",
Kind: "dashboards",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 2,
RoleID: 2,
Action: dashboards.ActionDashboardsRead,
Scope: "dashboards:uid:1S6TmO67z",
Attribute: "uid",
Identifier: "1S6TmO67z",
Kind: "dashboards",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 3,
RoleID: 3,
Action: dashboards.ActionDashboardsRead,
Scope: "dashboards:uid:0S6TmO67z",
Identifier: "0S6TmO67z",
Attribute: "uid",
Kind: "dashboards",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 4,
RoleID: 3,
Action: dashboards.ActionDashboardsRead,
Scope: "dashboards:uid:1S6TmO67z",
Identifier: "1S6TmO67z",
Kind: "dashboards",
Attribute: "uid",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 5,
RoleID: 3,
Action: dashboards.ActionDashboardsRead,
Scope: "dashboards:uid:2S6TmO67z",
Identifier: "2S6TmO67z",
Kind: "dashboards",
Attribute: "uid",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 6,
RoleID: 3,
Action: dashboards.ActionDashboardsRead,
Scope: "dashboards:uid:9S6TmO67z",
Identifier: "9S6TmO67z",
Kind: "dashboards",
Attribute: "uid",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 7,
RoleID: 1,
Action: dashboards.ActionFoldersRead,
Scope: "*",
Kind: "folders",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 8,
RoleID: 2,
Action: dashboards.ActionFoldersRead,
Scope: "*",
Kind: "folders",
Created: time.Now(),
Updated: time.Now(),
},
{
ID: 9,
RoleID: 3,
Action: dashboards.ActionFoldersRead,
Scope: "*",
Kind: "folders",
Created: time.Now(),
Updated: time.Now(),
},
}
err = testDB.WithDbSession(context.Background(), func(sess *db.Session) error {
if _, err := sess.Insert(users); err != nil {
return err
}
if _, err := sess.Insert(roles); err != nil {
return err
}
if _, err := sess.Insert(userRoles); err != nil {
return err
}
_, err := sess.Insert(permissions)
return err
})
require.NoError(t, err)
type args struct {
ctx context.Context
query *PublicDashboardListQuery
}
type mockResponse struct {
PublicDashboardListResponseWithPagination *PublicDashboardListResponseWithPagination
Err error
DashboardResponse []dashboards.DashboardSearchProjection
DashboardErr error
}
expectedFinalResponse := []*PublicDashboardListResponse{
{
Uid: "1GwW7mgVk",
AccessToken: "1b458cb7fe7f42c68712078bcacee6e3",
DashboardUid: "1S6TmO67z",
Title: "my first dashboard",
Slug: "my-first-dashboard",
IsEnabled: true,
},
{
Uid: "2GwW7mgVk",
AccessToken: "2b458cb7fe7f42c68712078bcacee6e3",
DashboardUid: "2S6TmO67z",
Title: "my second dashboard",
Slug: "my-second-dashboard",
IsEnabled: false,
},
{
Uid: "0GwW7mgVk",
AccessToken: "0b458cb7fe7f42c68712078bcacee6e3",
DashboardUid: "0S6TmO67z",
Title: "my zero dashboard",
Slug: "my-zero-dashboard",
IsEnabled: true,
},
{
Uid: "9GwW7mgVk",
AccessToken: "deletedashboardaccesstoken",
DashboardUid: "9S6TmO67z",
Title: "test",
Slug: "test",
IsEnabled: true,
},
}
mockedStoreResponse := []*PublicDashboardListResponse{
{
Uid: "0GwW7mgVk",
AccessToken: "0b458cb7fe7f42c68712078bcacee6e3",
DashboardUid: "0S6TmO67z",
IsEnabled: true,
},
{
Uid: "1GwW7mgVk",
AccessToken: "1b458cb7fe7f42c68712078bcacee6e3",
DashboardUid: "1S6TmO67z",
IsEnabled: true,
},
{
Uid: "2GwW7mgVk",
AccessToken: "2b458cb7fe7f42c68712078bcacee6e3",
DashboardUid: "2S6TmO67z",
IsEnabled: false,
},
{
Uid: "9GwW7mgVk",
AccessToken: "deletedashboardaccesstoken",
DashboardUid: "9S6TmO67z",
IsEnabled: true,
},
}
testCases := []struct {
name string
args args
want *PublicDashboardListResponseWithPagination
mockResponse *mockResponse
wantErr assert.ErrorAssertionFunc
}{
{
name: "should return full response when user has access to all dashboards",
args: args{
ctx: context.Background(),
query: &PublicDashboardListQuery{
User: &user.SignedInUser{OrgID: 1, UserID: 1, Permissions: map[int64]map[string][]string{1: {"dashboards:read": {"*"}, "folders:read": {"*"}}}},
OrgID: 1,
Page: 1,
Limit: 50,
},
},
mockResponse: &mockResponse{
PublicDashboardListResponseWithPagination: &PublicDashboardListResponseWithPagination{
TotalCount: int64(len(mockedStoreResponse)),
PublicDashboards: mockedStoreResponse,
},
Err: nil,
},
want: &PublicDashboardListResponseWithPagination{
Page: 1,
PerPage: 50,
TotalCount: int64(len(expectedFinalResponse)),
PublicDashboards: expectedFinalResponse,
},
wantErr: assert.NoError,
},
{
name: "should only return the one dashboard user 2 has access to",
args: args{
ctx: context.Background(),
query: &PublicDashboardListQuery{
User: &user.SignedInUser{OrgID: 1, UserID: 2, Permissions: map[int64]map[string][]string{1: {"dashboards:read": {"dashboards:uid:1S6TmO67z"}, "folders:read": {"*"}}}},
OrgID: 1,
Page: 1,
Limit: 50,
},
},
mockResponse: &mockResponse{
PublicDashboardListResponseWithPagination: &PublicDashboardListResponseWithPagination{
TotalCount: int64(len(mockedStoreResponse)),
PublicDashboards: mockedStoreResponse,
},
Err: nil,
},
want: &PublicDashboardListResponseWithPagination{
Page: 1,
PerPage: 50,
TotalCount: 1,
PublicDashboards: []*PublicDashboardListResponse{expectedFinalResponse[0]},
},
wantErr: assert.NoError,
},
{
name: "should return full response when user 3 has specific access to all dashboards",
args: args{
ctx: context.Background(),
query: &PublicDashboardListQuery{
User: &user.SignedInUser{OrgID: 1, UserID: 3, Permissions: map[int64]map[string][]string{1: {"dashboards:read": {"dashboards:uid:0S6TmO67z", "dashboards:uid:1S6TmO67z", "dashboards:uid:2S6TmO67z", "dashboards:uid:9S6TmO67z"}, "folders:read": {"*"}}}},
OrgID: 1,
Page: 1,
Limit: 50,
},
},
mockResponse: &mockResponse{
PublicDashboardListResponseWithPagination: &PublicDashboardListResponseWithPagination{
TotalCount: int64(len(mockedStoreResponse)),
PublicDashboards: mockedStoreResponse,
},
Err: nil,
},
want: &PublicDashboardListResponseWithPagination{
Page: 1,
PerPage: 50,
TotalCount: int64(len(expectedFinalResponse)),
PublicDashboards: expectedFinalResponse,
},
wantErr: assert.NoError,
},
{
name: "should an empty response for a user with no access",
args: args{
ctx: context.Background(),
query: &PublicDashboardListQuery{
User: &user.SignedInUser{OrgID: 1, UserID: 4, Permissions: map[int64]map[string][]string{}},
OrgID: 1,
Page: 1,
Limit: 50,
},
},
mockResponse: &mockResponse{
PublicDashboardListResponseWithPagination: &PublicDashboardListResponseWithPagination{
TotalCount: int64(len(mockedStoreResponse)),
PublicDashboards: mockedStoreResponse,
},
Err: nil,
},
want: &PublicDashboardListResponseWithPagination{
Page: 1,
PerPage: 50,
TotalCount: 0,
PublicDashboards: []*PublicDashboardListResponse{},
},
wantErr: assert.NoError,
},
{
name: "should return correct pagination response if limited",
args: args{
ctx: context.Background(),
query: &PublicDashboardListQuery{
User: &user.SignedInUser{OrgID: 1, UserID: 1, Permissions: map[int64]map[string][]string{1: {"dashboards:read": {"*"}, "folders:read": {"*"}}}},
OrgID: 1,
Page: 1,
Limit: 2,
},
},
mockResponse: &mockResponse{
PublicDashboardListResponseWithPagination: &PublicDashboardListResponseWithPagination{
TotalCount: int64(len(mockedStoreResponse)),
PublicDashboards: mockedStoreResponse,
},
Err: nil,
},
want: &PublicDashboardListResponseWithPagination{
Page: 1,
PerPage: 2,
TotalCount: 4,
PublicDashboards: expectedFinalResponse[:2],
},
wantErr: assert.NoError,
},
{
name: "should return correct page",
args: args{
ctx: context.Background(),
query: &PublicDashboardListQuery{
User: &user.SignedInUser{OrgID: 1, UserID: 1, Permissions: map[int64]map[string][]string{1: {"dashboards:read": {"*"}, "folders:read": {"*"}}}},
OrgID: 1,
Page: 2,
Limit: 2,
},
},
mockResponse: &mockResponse{
PublicDashboardListResponseWithPagination: &PublicDashboardListResponseWithPagination{
TotalCount: int64(len(mockedStoreResponse)),
PublicDashboards: mockedStoreResponse,
},
Err: nil,
},
want: &PublicDashboardListResponseWithPagination{
Page: 2,
PerPage: 2,
TotalCount: 4,
PublicDashboards: expectedFinalResponse[2:],
},
wantErr: assert.NoError,
},
{
name: "should return error when store returns error",
args: args{
ctx: context.Background(),
query: &PublicDashboardListQuery{
User: &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{
1: {"dashboards:read": {"dashboards:uid:0S6TmO67z"}}},
},
OrgID: 1,
Page: 1,
Limit: 50,
},
},
mockResponse: &mockResponse{
PublicDashboardListResponseWithPagination: nil,
Err: errors.New("an err"),
},
want: nil,
wantErr: assert.Error,
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
store := NewFakePublicDashboardStore(t)
store.On("FindAll", mock.Anything, mock.Anything).
Return(tt.mockResponse.PublicDashboardListResponseWithPagination, tt.mockResponse.Err)
pd, _, _ := newPublicDashboardServiceImpl(t, testDB, cfg, store, dashboardService, nil)
pd.ac = ac
got, err := pd.FindAllWithPagination(tt.args.ctx, tt.args.query)
if !tt.wantErr(t, err, fmt.Sprintf("FindAllWithPagination(%v, %v)", tt.args.ctx, tt.args.query)) {
return
}
assert.Equalf(t, tt.want, got, "FindAllWithPagination(%v, %v)", tt.args.ctx, tt.args.query)
})
}
}
func TestPublicDashboardServiceImpl_NewPublicDashboardUid(t *testing.T) {
mockedDashboard := &PublicDashboard{
IsEnabled: true,