mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PublicDashboards: Add RBAC to secured endpoints (#54544)
This commit is contained in:
parent
295c36e4ec
commit
bfa35ff8d8
@ -419,6 +419,19 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
|||||||
Grants: []string{"Admin"},
|
Grants: []string{"Admin"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publicDashboardsWriterRole := ac.RoleRegistration{
|
||||||
|
Role: ac.RoleDTO{
|
||||||
|
Name: "fixed:dashboards.public:writer",
|
||||||
|
DisplayName: "Public Dashboard writer",
|
||||||
|
Description: "Create, write or disable a public dashboard.",
|
||||||
|
Group: "Dashboards",
|
||||||
|
Permissions: []ac.Permission{
|
||||||
|
{Action: dashboards.ActionDashboardPublicWrite, Scope: dashboards.ScopeDashboardsAll},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Grants: []string{"Admin"},
|
||||||
|
}
|
||||||
|
|
||||||
return hs.accesscontrolService.DeclareFixedRoles(
|
return hs.accesscontrolService.DeclareFixedRoles(
|
||||||
provisioningWriterRole, datasourcesReaderRole, builtInDatasourceReader, datasourcesWriterRole,
|
provisioningWriterRole, datasourcesReaderRole, builtInDatasourceReader, datasourcesWriterRole,
|
||||||
datasourcesIdReaderRole, orgReaderRole, orgWriterRole,
|
datasourcesIdReaderRole, orgReaderRole, orgWriterRole,
|
||||||
@ -426,6 +439,7 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
|||||||
annotationsReaderRole, dashboardAnnotationsWriterRole, annotationsWriterRole,
|
annotationsReaderRole, dashboardAnnotationsWriterRole, annotationsWriterRole,
|
||||||
dashboardsCreatorRole, dashboardsReaderRole, dashboardsWriterRole,
|
dashboardsCreatorRole, dashboardsReaderRole, dashboardsWriterRole,
|
||||||
foldersCreatorRole, foldersReaderRole, foldersWriterRole, apikeyReaderRole, apikeyWriterRole,
|
foldersCreatorRole, foldersReaderRole, foldersWriterRole, apikeyReaderRole, apikeyWriterRole,
|
||||||
|
publicDashboardsWriterRole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ const (
|
|||||||
ActionDashboardsDelete = "dashboards:delete"
|
ActionDashboardsDelete = "dashboards:delete"
|
||||||
ActionDashboardsPermissionsRead = "dashboards.permissions:read"
|
ActionDashboardsPermissionsRead = "dashboards.permissions:read"
|
||||||
ActionDashboardsPermissionsWrite = "dashboards.permissions:write"
|
ActionDashboardsPermissionsWrite = "dashboards.permissions:write"
|
||||||
|
|
||||||
|
ActionDashboardPublicWrite = "dashboards.public:write"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -51,18 +51,25 @@ func ProvideApi(
|
|||||||
//Registers Endpoints on Grafana Router
|
//Registers Endpoints on Grafana Router
|
||||||
func (api *Api) RegisterAPIEndpoints() {
|
func (api *Api) RegisterAPIEndpoints() {
|
||||||
auth := accesscontrol.Middleware(api.AccessControl)
|
auth := accesscontrol.Middleware(api.AccessControl)
|
||||||
reqSignedIn := middleware.ReqSignedIn
|
|
||||||
|
|
||||||
// Anonymous access to public dashboard route is configured in pkg/api/api.go
|
// 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
|
// because it is deeply dependent on the HTTPServer.Index() method and would result in a
|
||||||
// circular dependency
|
// circular dependency
|
||||||
|
|
||||||
|
// public endpoints
|
||||||
api.RouteRegister.Get("/api/public/dashboards/:accessToken", routing.Wrap(api.GetPublicDashboard))
|
api.RouteRegister.Get("/api/public/dashboards/:accessToken", routing.Wrap(api.GetPublicDashboard))
|
||||||
api.RouteRegister.Post("/api/public/dashboards/:accessToken/panels/:panelId/query", routing.Wrap(api.QueryPublicDashboard))
|
api.RouteRegister.Post("/api/public/dashboards/:accessToken/panels/:panelId/query", routing.Wrap(api.QueryPublicDashboard))
|
||||||
|
|
||||||
// Create/Update Public Dashboard
|
// Create/Update Public Dashboard
|
||||||
api.RouteRegister.Get("/api/dashboards/uid/:uid/public-config", auth(reqSignedIn, accesscontrol.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(api.GetPublicDashboardConfig))
|
uidScope := dashboards.ScopeDashboardsProvider.GetResourceScopeUID(accesscontrol.Parameter(":uid"))
|
||||||
api.RouteRegister.Post("/api/dashboards/uid/:uid/public-config", auth(reqSignedIn, accesscontrol.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(api.SavePublicDashboardConfig))
|
|
||||||
|
api.RouteRegister.Get("/api/dashboards/uid/:uid/public-config",
|
||||||
|
auth(middleware.ReqSignedIn, accesscontrol.EvalPermission(dashboards.ActionDashboardsRead, uidScope)),
|
||||||
|
routing.Wrap(api.GetPublicDashboardConfig))
|
||||||
|
|
||||||
|
api.RouteRegister.Post("/api/dashboards/uid/:uid/public-config",
|
||||||
|
auth(middleware.ReqOrgAdmin, accesscontrol.EvalPermission(dashboards.ActionDashboardPublicWrite, uidScope)),
|
||||||
|
routing.Wrap(api.SavePublicDashboardConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets public dashboard
|
// Gets public dashboard
|
||||||
@ -72,7 +79,7 @@ func (api *Api) GetPublicDashboard(c *models.ReqContext) response.Response {
|
|||||||
|
|
||||||
pubdash, dash, err := api.PublicDashboardService.GetPublicDashboard(
|
pubdash, dash, err := api.PublicDashboardService.GetPublicDashboard(
|
||||||
c.Req.Context(),
|
c.Req.Context(),
|
||||||
web.Params(c.Req)[":accessToken"],
|
accessToken,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -92,7 +99,7 @@ func (api *Api) GetPublicDashboard(c *models.ReqContext) response.Response {
|
|||||||
Version: dash.Version,
|
Version: dash.Version,
|
||||||
IsFolder: false,
|
IsFolder: false,
|
||||||
FolderId: dash.FolderId,
|
FolderId: dash.FolderId,
|
||||||
PublicDashboardAccessToken: accessToken,
|
PublicDashboardAccessToken: pubdash.AccessToken,
|
||||||
PublicDashboardUID: pubdash.Uid,
|
PublicDashboardUID: pubdash.Uid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,9 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
dashboardStore "github.com/grafana/grafana/pkg/services/dashboards/database"
|
dashboardStore "github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||||
"github.com/grafana/grafana/pkg/services/datasources"
|
"github.com/grafana/grafana/pkg/services/datasources"
|
||||||
|
datasourcesService "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||||
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/datasources/service"
|
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||||
publicdashboardsStore "github.com/grafana/grafana/pkg/services/publicdashboards/database"
|
publicdashboardsStore "github.com/grafana/grafana/pkg/services/publicdashboards/database"
|
||||||
@ -37,6 +38,12 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/web"
|
"github.com/grafana/grafana/pkg/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var userAdmin = &user.SignedInUser{UserID: 1, OrgID: 1, OrgRole: org.RoleAdmin, Login: "testAdminUser"}
|
||||||
|
var userAdminRBAC = &user.SignedInUser{UserID: 2, OrgID: 1, OrgRole: org.RoleAdmin, Login: "testAdminUserRBAC", Permissions: map[int64]map[string][]string{1: {dashboards.ActionDashboardPublicWrite: {dashboards.ScopeDashboardsAll}}}}
|
||||||
|
var userViewer = &user.SignedInUser{UserID: 3, OrgID: 1, OrgRole: org.RoleViewer, Login: "testViewerUser"}
|
||||||
|
var userViewerRBAC = &user.SignedInUser{UserID: 4, OrgID: 1, OrgRole: org.RoleViewer, Login: "testViewerUserRBAC", Permissions: map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}}}}
|
||||||
|
var anonymousUser *user.SignedInUser
|
||||||
|
|
||||||
func TestAPIGetPublicDashboard(t *testing.T) {
|
func TestAPIGetPublicDashboard(t *testing.T) {
|
||||||
t.Run("It should 404 if featureflag is not enabled", func(t *testing.T) {
|
t.Run("It should 404 if featureflag is not enabled", func(t *testing.T) {
|
||||||
cfg := setting.NewCfg()
|
cfg := setting.NewCfg()
|
||||||
@ -47,7 +54,7 @@ func TestAPIGetPublicDashboard(t *testing.T) {
|
|||||||
service.On("GetPublicDashboardConfig", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).
|
service.On("GetPublicDashboardConfig", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).
|
||||||
Return(&PublicDashboard{}, nil).Maybe()
|
Return(&PublicDashboard{}, nil).Maybe()
|
||||||
|
|
||||||
testServer := setupTestServer(t, cfg, featuremgmt.WithFeatures(), service, nil)
|
testServer := setupTestServer(t, cfg, featuremgmt.WithFeatures(), service, nil, anonymousUser)
|
||||||
|
|
||||||
response := callAPI(testServer, http.MethodGet, "/api/public/dashboards", nil, t)
|
response := callAPI(testServer, http.MethodGet, "/api/public/dashboards", nil, t)
|
||||||
assert.Equal(t, http.StatusNotFound, response.Code)
|
assert.Equal(t, http.StatusNotFound, response.Code)
|
||||||
@ -56,7 +63,7 @@ func TestAPIGetPublicDashboard(t *testing.T) {
|
|||||||
assert.Equal(t, http.StatusNotFound, response.Code)
|
assert.Equal(t, http.StatusNotFound, response.Code)
|
||||||
|
|
||||||
// control set. make sure routes are mounted
|
// control set. make sure routes are mounted
|
||||||
testServer = setupTestServer(t, cfg, featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards), service, nil)
|
testServer = setupTestServer(t, cfg, featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards), service, nil, userAdmin)
|
||||||
response = callAPI(testServer, http.MethodGet, "/api/public/dashboards/asdf", nil, t)
|
response = callAPI(testServer, http.MethodGet, "/api/public/dashboards/asdf", nil, t)
|
||||||
assert.NotEqual(t, http.StatusNotFound, response.Code)
|
assert.NotEqual(t, http.StatusNotFound, response.Code)
|
||||||
})
|
})
|
||||||
@ -108,6 +115,7 @@ func TestAPIGetPublicDashboard(t *testing.T) {
|
|||||||
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
||||||
service,
|
service,
|
||||||
nil,
|
nil,
|
||||||
|
anonymousUser,
|
||||||
)
|
)
|
||||||
|
|
||||||
response := callAPI(testServer, http.MethodGet,
|
response := callAPI(testServer, http.MethodGet,
|
||||||
@ -148,6 +156,9 @@ func TestAPIGetPublicDashboardConfig(t *testing.T) {
|
|||||||
ExpectedHttpResponse int
|
ExpectedHttpResponse int
|
||||||
PublicDashboardResult *PublicDashboard
|
PublicDashboardResult *PublicDashboard
|
||||||
PublicDashboardErr error
|
PublicDashboardErr error
|
||||||
|
User *user.SignedInUser
|
||||||
|
AccessControlEnabled bool
|
||||||
|
ShouldCallService bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Name: "retrieves public dashboard config when dashboard is found",
|
Name: "retrieves public dashboard config when dashboard is found",
|
||||||
@ -155,6 +166,9 @@ func TestAPIGetPublicDashboardConfig(t *testing.T) {
|
|||||||
ExpectedHttpResponse: http.StatusOK,
|
ExpectedHttpResponse: http.StatusOK,
|
||||||
PublicDashboardResult: pubdash,
|
PublicDashboardResult: pubdash,
|
||||||
PublicDashboardErr: nil,
|
PublicDashboardErr: nil,
|
||||||
|
User: userViewer,
|
||||||
|
AccessControlEnabled: false,
|
||||||
|
ShouldCallService: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "returns 404 when dashboard not found",
|
Name: "returns 404 when dashboard not found",
|
||||||
@ -162,6 +176,9 @@ func TestAPIGetPublicDashboardConfig(t *testing.T) {
|
|||||||
ExpectedHttpResponse: http.StatusNotFound,
|
ExpectedHttpResponse: http.StatusNotFound,
|
||||||
PublicDashboardResult: nil,
|
PublicDashboardResult: nil,
|
||||||
PublicDashboardErr: dashboards.ErrDashboardNotFound,
|
PublicDashboardErr: dashboards.ErrDashboardNotFound,
|
||||||
|
User: userViewer,
|
||||||
|
AccessControlEnabled: false,
|
||||||
|
ShouldCallService: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "returns 500 when internal server error",
|
Name: "returns 500 when internal server error",
|
||||||
@ -169,17 +186,42 @@ func TestAPIGetPublicDashboardConfig(t *testing.T) {
|
|||||||
ExpectedHttpResponse: http.StatusInternalServerError,
|
ExpectedHttpResponse: http.StatusInternalServerError,
|
||||||
PublicDashboardResult: nil,
|
PublicDashboardResult: nil,
|
||||||
PublicDashboardErr: errors.New("database broken"),
|
PublicDashboardErr: errors.New("database broken"),
|
||||||
|
User: userViewer,
|
||||||
|
AccessControlEnabled: false,
|
||||||
|
ShouldCallService: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "retrieves public dashboard config when dashboard is found RBAC on",
|
||||||
|
DashboardUid: "1",
|
||||||
|
ExpectedHttpResponse: http.StatusOK,
|
||||||
|
PublicDashboardResult: pubdash,
|
||||||
|
PublicDashboardErr: nil,
|
||||||
|
User: userViewerRBAC,
|
||||||
|
AccessControlEnabled: true,
|
||||||
|
ShouldCallService: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "returns 403 when no permissions RBAC on",
|
||||||
|
ExpectedHttpResponse: http.StatusForbidden,
|
||||||
|
PublicDashboardResult: pubdash,
|
||||||
|
PublicDashboardErr: nil,
|
||||||
|
User: userViewer,
|
||||||
|
AccessControlEnabled: true,
|
||||||
|
ShouldCallService: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.Name, func(t *testing.T) {
|
t.Run(test.Name, func(t *testing.T) {
|
||||||
service := publicdashboards.NewFakePublicDashboardService(t)
|
service := publicdashboards.NewFakePublicDashboardService(t)
|
||||||
|
|
||||||
|
if test.ShouldCallService {
|
||||||
service.On("GetPublicDashboardConfig", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).
|
service.On("GetPublicDashboardConfig", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).
|
||||||
Return(test.PublicDashboardResult, test.PublicDashboardErr)
|
Return(test.PublicDashboardResult, test.PublicDashboardErr)
|
||||||
|
}
|
||||||
|
|
||||||
cfg := setting.NewCfg()
|
cfg := setting.NewCfg()
|
||||||
cfg.RBACEnabled = false
|
cfg.RBACEnabled = test.AccessControlEnabled
|
||||||
|
|
||||||
testServer := setupTestServer(
|
testServer := setupTestServer(
|
||||||
t,
|
t,
|
||||||
@ -187,6 +229,7 @@ func TestAPIGetPublicDashboardConfig(t *testing.T) {
|
|||||||
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
||||||
service,
|
service,
|
||||||
nil,
|
nil,
|
||||||
|
test.User,
|
||||||
)
|
)
|
||||||
|
|
||||||
response := callAPI(
|
response := callAPI(
|
||||||
@ -216,6 +259,9 @@ func TestApiSavePublicDashboardConfig(t *testing.T) {
|
|||||||
publicDashboardConfig *PublicDashboard
|
publicDashboardConfig *PublicDashboard
|
||||||
ExpectedHttpResponse int
|
ExpectedHttpResponse int
|
||||||
SaveDashboardErr error
|
SaveDashboardErr error
|
||||||
|
User *user.SignedInUser
|
||||||
|
AccessControlEnabled bool
|
||||||
|
ShouldCallService bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Name: "returns 200 when update persists",
|
Name: "returns 200 when update persists",
|
||||||
@ -223,29 +269,70 @@ func TestApiSavePublicDashboardConfig(t *testing.T) {
|
|||||||
publicDashboardConfig: &PublicDashboard{IsEnabled: true},
|
publicDashboardConfig: &PublicDashboard{IsEnabled: true},
|
||||||
ExpectedHttpResponse: http.StatusOK,
|
ExpectedHttpResponse: http.StatusOK,
|
||||||
SaveDashboardErr: nil,
|
SaveDashboardErr: nil,
|
||||||
|
User: userAdmin,
|
||||||
|
AccessControlEnabled: false,
|
||||||
|
ShouldCallService: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "returns 500 when not persisted",
|
Name: "returns 500 when not persisted",
|
||||||
ExpectedHttpResponse: http.StatusInternalServerError,
|
ExpectedHttpResponse: http.StatusInternalServerError,
|
||||||
publicDashboardConfig: &PublicDashboard{},
|
publicDashboardConfig: &PublicDashboard{},
|
||||||
SaveDashboardErr: errors.New("backend failed to save"),
|
SaveDashboardErr: errors.New("backend failed to save"),
|
||||||
|
User: userAdmin,
|
||||||
|
AccessControlEnabled: false,
|
||||||
|
ShouldCallService: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "returns 404 when dashboard not found",
|
Name: "returns 404 when dashboard not found",
|
||||||
ExpectedHttpResponse: http.StatusNotFound,
|
ExpectedHttpResponse: http.StatusNotFound,
|
||||||
publicDashboardConfig: &PublicDashboard{},
|
publicDashboardConfig: &PublicDashboard{},
|
||||||
SaveDashboardErr: dashboards.ErrDashboardNotFound,
|
SaveDashboardErr: dashboards.ErrDashboardNotFound,
|
||||||
|
User: userAdmin,
|
||||||
|
AccessControlEnabled: false,
|
||||||
|
ShouldCallService: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "returns 200 when update persists RBAC on",
|
||||||
|
DashboardUid: "1",
|
||||||
|
publicDashboardConfig: &PublicDashboard{IsEnabled: true},
|
||||||
|
ExpectedHttpResponse: http.StatusOK,
|
||||||
|
SaveDashboardErr: nil,
|
||||||
|
User: userAdminRBAC,
|
||||||
|
AccessControlEnabled: true,
|
||||||
|
ShouldCallService: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "returns 403 when no permissions",
|
||||||
|
ExpectedHttpResponse: http.StatusForbidden,
|
||||||
|
publicDashboardConfig: &PublicDashboard{IsEnabled: true},
|
||||||
|
SaveDashboardErr: nil,
|
||||||
|
User: userViewer,
|
||||||
|
AccessControlEnabled: false,
|
||||||
|
ShouldCallService: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "returns 403 when no permissions RBAC on",
|
||||||
|
ExpectedHttpResponse: http.StatusForbidden,
|
||||||
|
publicDashboardConfig: &PublicDashboard{IsEnabled: true},
|
||||||
|
SaveDashboardErr: nil,
|
||||||
|
User: userAdmin,
|
||||||
|
AccessControlEnabled: true,
|
||||||
|
ShouldCallService: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.Name, func(t *testing.T) {
|
t.Run(test.Name, func(t *testing.T) {
|
||||||
service := publicdashboards.NewFakePublicDashboardService(t)
|
service := publicdashboards.NewFakePublicDashboardService(t)
|
||||||
|
|
||||||
|
// this is to avoid AssertExpectations fail at t.Cleanup when the middleware returns before calling the service
|
||||||
|
if test.ShouldCallService {
|
||||||
service.On("SavePublicDashboardConfig", mock.Anything, mock.Anything, mock.AnythingOfType("*models.SavePublicDashboardConfigDTO")).
|
service.On("SavePublicDashboardConfig", mock.Anything, mock.Anything, mock.AnythingOfType("*models.SavePublicDashboardConfigDTO")).
|
||||||
Return(&PublicDashboard{IsEnabled: true}, test.SaveDashboardErr)
|
Return(&PublicDashboard{IsEnabled: true}, test.SaveDashboardErr)
|
||||||
|
}
|
||||||
|
|
||||||
cfg := setting.NewCfg()
|
cfg := setting.NewCfg()
|
||||||
cfg.RBACEnabled = false
|
cfg.RBACEnabled = test.AccessControlEnabled
|
||||||
|
|
||||||
testServer := setupTestServer(
|
testServer := setupTestServer(
|
||||||
t,
|
t,
|
||||||
@ -253,6 +340,7 @@ func TestApiSavePublicDashboardConfig(t *testing.T) {
|
|||||||
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
||||||
service,
|
service,
|
||||||
nil,
|
nil,
|
||||||
|
test.User,
|
||||||
)
|
)
|
||||||
|
|
||||||
response := callAPI(
|
response := callAPI(
|
||||||
@ -339,6 +427,7 @@ func TestAPIQueryPublicDashboard(t *testing.T) {
|
|||||||
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards, enabled),
|
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards, enabled),
|
||||||
service,
|
service,
|
||||||
nil,
|
nil,
|
||||||
|
anonymousUser,
|
||||||
)
|
)
|
||||||
|
|
||||||
return testServer, service
|
return testServer, service
|
||||||
@ -396,7 +485,7 @@ func TestAPIQueryPublicDashboard(t *testing.T) {
|
|||||||
func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T) {
|
func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T) {
|
||||||
db := sqlstore.InitTestDB(t)
|
db := sqlstore.InitTestDB(t)
|
||||||
|
|
||||||
cacheService := service.ProvideCacheService(localcache.ProvideService(), db)
|
cacheService := datasourcesService.ProvideCacheService(localcache.ProvideService(), db)
|
||||||
qds := buildQueryDataService(t, cacheService, nil, db)
|
qds := buildQueryDataService(t, cacheService, nil, db)
|
||||||
|
|
||||||
_ = db.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
_ = db.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||||
@ -436,8 +525,8 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create dashboard
|
// create dashboard
|
||||||
dashboardStore := dashboardStore.ProvideDashboardStore(db, featuremgmt.WithFeatures())
|
dashboardStoreService := dashboardStore.ProvideDashboardStore(db, featuremgmt.WithFeatures())
|
||||||
dashboard, err := dashboardStore.SaveDashboard(saveDashboardCmd)
|
dashboard, err := dashboardStoreService.SaveDashboard(saveDashboardCmd)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Create public dashboard
|
// Create public dashboard
|
||||||
@ -463,6 +552,7 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T)
|
|||||||
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
featuremgmt.WithFeatures(featuremgmt.FlagPublicDashboards),
|
||||||
service,
|
service,
|
||||||
db,
|
db,
|
||||||
|
anonymousUser,
|
||||||
)
|
)
|
||||||
|
|
||||||
resp := callAPI(server, http.MethodPost,
|
resp := callAPI(server, http.MethodPost,
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||||
"github.com/grafana/grafana/pkg/services/datasources"
|
"github.com/grafana/grafana/pkg/services/datasources"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
|
||||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
@ -34,18 +33,13 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
|
||||||
Mux *web.Mux
|
|
||||||
RouteRegister routing.RouteRegister
|
|
||||||
TestServer *httptest.Server
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupTestServer(
|
func setupTestServer(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
cfg *setting.Cfg,
|
cfg *setting.Cfg,
|
||||||
features *featuremgmt.FeatureManager,
|
features *featuremgmt.FeatureManager,
|
||||||
service publicdashboards.Service,
|
service publicdashboards.Service,
|
||||||
db *sqlstore.SQLStore,
|
db *sqlstore.SQLStore,
|
||||||
|
user *user.SignedInUser,
|
||||||
) *web.Mux {
|
) *web.Mux {
|
||||||
// build router to register routes
|
// build router to register routes
|
||||||
rr := routing.NewRouteRegister()
|
rr := routing.NewRouteRegister()
|
||||||
@ -69,18 +63,7 @@ func setupTestServer(
|
|||||||
m := web.New()
|
m := web.New()
|
||||||
|
|
||||||
// set initial context
|
// set initial context
|
||||||
m.Use(func(c *web.Context) {
|
m.Use(contextProvider(&testContext{user}))
|
||||||
ctx := &models.ReqContext{
|
|
||||||
Context: c,
|
|
||||||
IsSignedIn: true, // FIXME need to be able to change this for tests
|
|
||||||
SkipCache: true, // hardcoded to make sure query service doesnt hit the cache
|
|
||||||
Logger: log.New("publicdashboards-test"),
|
|
||||||
|
|
||||||
// Set signed in user. We might not actually need to do this.
|
|
||||||
SignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, OrgRole: org.RoleAdmin, Login: "testUser"},
|
|
||||||
}
|
|
||||||
c.Req = c.Req.WithContext(ctxkey.Set(c.Req.Context(), ctx))
|
|
||||||
})
|
|
||||||
|
|
||||||
// build api, this will mount the routes at the same time if
|
// build api, this will mount the routes at the same time if
|
||||||
// featuremgmt.FlagPublicDashboard is enabled
|
// featuremgmt.FlagPublicDashboard is enabled
|
||||||
@ -92,6 +75,24 @@ func setupTestServer(
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testContext struct {
|
||||||
|
user *user.SignedInUser
|
||||||
|
}
|
||||||
|
|
||||||
|
func contextProvider(tc *testContext) web.Handler {
|
||||||
|
return func(c *web.Context) {
|
||||||
|
signedIn := tc.user != nil
|
||||||
|
reqCtx := &models.ReqContext{
|
||||||
|
Context: c,
|
||||||
|
SignedInUser: tc.user,
|
||||||
|
IsSignedIn: signedIn,
|
||||||
|
SkipCache: true,
|
||||||
|
Logger: log.New("publicdashboards-test"),
|
||||||
|
}
|
||||||
|
c.Req = c.Req.WithContext(ctxkey.Set(c.Req.Context(), reqCtx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func callAPI(server *web.Mux, method, path string, body io.Reader, t *testing.T) *httptest.ResponseRecorder {
|
func callAPI(server *web.Mux, method, path string, body io.Reader, t *testing.T) *httptest.ResponseRecorder {
|
||||||
req, err := http.NewRequest(method, path, body)
|
req, err := http.NewRequest(method, path, body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user