mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
chore/backend: move dashboard errors to dashboard service (#51593)
* chore/backend: move dashboard errors to dashboard service Dashboard-related models are slowly moving out of the models package and into dashboard services. This commit moves dashboard-related errors; the rest will come in later commits. There are no logical code changes, this is only a structural (package) move. * lint lint lint
This commit is contained in:
parent
a1fb73c503
commit
9de00c8eb2
@ -7,15 +7,15 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
// ToDashboardErrorResponse returns a different response status according to the dashboard error type
|
||||
func ToDashboardErrorResponse(ctx context.Context, pluginStore plugins.Store, err error) response.Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
var dashboardErr dashboards.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
if body := dashboardErr.Body(); body != nil {
|
||||
return response.JSON(dashboardErr.StatusCode, body)
|
||||
@ -26,7 +26,7 @@ func ToDashboardErrorResponse(ctx context.Context, pluginStore plugins.Store, er
|
||||
return response.Error(dashboardErr.StatusCode, dashboardErr.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||
return response.Error(http.StatusBadRequest, err.Error(), nil)
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ func ToDashboardErrorResponse(ctx context.Context, pluginStore plugins.Store, er
|
||||
return response.Error(http.StatusUnprocessableEntity, validationErr.Error(), err)
|
||||
}
|
||||
|
||||
var pluginErr models.UpdatePluginDashboardError
|
||||
var pluginErr dashboards.UpdatePluginDashboardError
|
||||
if ok := errors.As(err, &pluginErr); ok {
|
||||
message := fmt.Sprintf("The dashboard belongs to plugin %s.", pluginErr.PluginId)
|
||||
// look up plugin name
|
||||
|
@ -4,40 +4,40 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
// ToFolderErrorResponse returns a different response status according to the folder error type
|
||||
func ToFolderErrorResponse(err error) response.Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
var dashboardErr dashboards.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
return response.Error(dashboardErr.StatusCode, err.Error(), err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderTitleEmpty) ||
|
||||
errors.Is(err, models.ErrDashboardTypeMismatch) ||
|
||||
errors.Is(err, models.ErrDashboardInvalidUid) ||
|
||||
errors.Is(err, models.ErrDashboardUidTooLong) ||
|
||||
errors.Is(err, models.ErrFolderContainsAlertRules) {
|
||||
if errors.Is(err, dashboards.ErrFolderTitleEmpty) ||
|
||||
errors.Is(err, dashboards.ErrDashboardTypeMismatch) ||
|
||||
errors.Is(err, dashboards.ErrDashboardInvalidUid) ||
|
||||
errors.Is(err, dashboards.ErrDashboardUidTooLong) ||
|
||||
errors.Is(err, dashboards.ErrFolderContainsAlertRules) {
|
||||
return response.Error(400, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderAccessDenied) {
|
||||
if errors.Is(err, dashboards.ErrFolderAccessDenied) {
|
||||
return response.Error(403, "Access denied", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
return response.JSON(404, util.DynMap{"status": "not-found", "message": models.ErrFolderNotFound.Error()})
|
||||
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||
return response.JSON(404, util.DynMap{"status": "not-found", "message": dashboards.ErrFolderNotFound.Error()})
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderSameNameExists) ||
|
||||
errors.Is(err, models.ErrFolderWithSameUIDExists) {
|
||||
if errors.Is(err, dashboards.ErrFolderSameNameExists) ||
|
||||
errors.Is(err, dashboards.ErrFolderWithSameUIDExists) {
|
||||
return response.Error(409, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderVersionMismatch) {
|
||||
return response.JSON(412, util.DynMap{"status": "version-mismatch", "message": models.ErrFolderVersionMismatch.Error()})
|
||||
if errors.Is(err, dashboards.ErrFolderVersionMismatch) {
|
||||
return response.JSON(412, util.DynMap{"status": "version-mismatch", "message": dashboards.ErrFolderVersionMismatch.Error()})
|
||||
}
|
||||
|
||||
return response.Error(500, "Folder API error", err)
|
||||
|
@ -145,7 +145,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response {
|
||||
if dash.FolderId > 0 {
|
||||
query := models.GetDashboardQuery{Id: dash.FolderId, OrgId: c.OrgId}
|
||||
if err := hs.dashboardService.GetDashboard(c.Req.Context(), &query); err != nil {
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||
return response.Error(404, "Folder not found", err)
|
||||
}
|
||||
return response.Error(500, "Dashboard folder could not be read", err)
|
||||
@ -264,9 +264,9 @@ func (hs *HTTPServer) deleteDashboard(c *models.ReqContext) response.Response {
|
||||
|
||||
err = hs.dashboardService.DeleteDashboard(c.Req.Context(), dash.Id, c.OrgId)
|
||||
if err != nil {
|
||||
var dashboardErr models.DashboardErr
|
||||
var dashboardErr dashboards.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
if errors.Is(err, models.ErrDashboardCannotDeleteProvisionedDashboard) {
|
||||
if errors.Is(err, dashboards.ErrDashboardCannotDeleteProvisionedDashboard) {
|
||||
return response.Error(dashboardErr.StatusCode, dashboardErr.Error(), err)
|
||||
}
|
||||
}
|
||||
@ -333,7 +333,7 @@ func (hs *HTTPServer) postDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
||||
if cmd.FolderUid != "" {
|
||||
folder, err := hs.folderService.GetFolderByUID(ctx, c.SignedInUser, c.OrgId, cmd.FolderUid)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||
return response.Error(400, "Folder not found", err)
|
||||
}
|
||||
return response.Error(500, "Error while checking folder ID", err)
|
||||
@ -362,7 +362,7 @@ func (hs *HTTPServer) postDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
||||
provisioningData = data
|
||||
} else if dash.Uid != "" {
|
||||
data, err := hs.dashboardProvisioningService.GetProvisionedDashboardDataByDashboardUID(dash.OrgId, dash.Uid)
|
||||
if err != nil && !errors.Is(err, models.ErrProvisionedDashboardNotFound) && !errors.Is(err, models.ErrDashboardNotFound) {
|
||||
if err != nil && !errors.Is(err, dashboards.ErrProvisionedDashboardNotFound) && !errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return response.Error(500, "Error while checking if dashboard is provisioned", err)
|
||||
}
|
||||
provisioningData = data
|
||||
|
@ -131,7 +131,7 @@ func (hs *HTTPServer) QueryPublicDashboard(c *models.ReqContext) response.Respon
|
||||
|
||||
// util to help us unpack a dashboard err or use default http code and message
|
||||
func handleDashboardErr(defaultCode int, defaultMsg string, err error) response.Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
var dashboardErr dashboards.DashboardErr
|
||||
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
return response.Error(dashboardErr.StatusCode, dashboardErr.Error(), dashboardErr)
|
||||
|
@ -87,7 +87,7 @@ func TestAPIGetPublicDashboard(t *testing.T) {
|
||||
AccessToken: accessToken,
|
||||
ExpectedHttpResponse: http.StatusNotFound,
|
||||
publicDashboardResult: nil,
|
||||
publicDashboardErr: models.ErrPublicDashboardNotFound,
|
||||
publicDashboardErr: dashboards.ErrPublicDashboardNotFound,
|
||||
},
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ func TestAPIGetPublicDashboardConfig(t *testing.T) {
|
||||
DashboardUid: "77777",
|
||||
ExpectedHttpResponse: http.StatusNotFound,
|
||||
PublicDashboardResult: nil,
|
||||
PublicDashboardError: models.ErrDashboardNotFound,
|
||||
PublicDashboardError: dashboards.ErrDashboardNotFound,
|
||||
},
|
||||
{
|
||||
Name: "returns 500 when internal server error",
|
||||
@ -218,7 +218,7 @@ func TestApiSavePublicDashboardConfig(t *testing.T) {
|
||||
Name: "returns 404 when dashboard not found",
|
||||
ExpectedHttpResponse: http.StatusNotFound,
|
||||
publicDashboardConfig: &models.PublicDashboard{},
|
||||
saveDashboardError: models.ErrDashboardNotFound,
|
||||
saveDashboardError: dashboards.ErrDashboardNotFound,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardsnapshots"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -272,11 +273,11 @@ func (hs *HTTPServer) DeleteDashboardSnapshot(c *models.ReqContext) response.Res
|
||||
guardian := guardian.New(c.Req.Context(), dashboardID, c.OrgId, c.SignedInUser)
|
||||
canEdit, err := guardian.CanEdit()
|
||||
// check for permissions only if the dahboard is found
|
||||
if err != nil && !errors.Is(err, models.ErrDashboardNotFound) {
|
||||
if err != nil && !errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return response.Error(500, "Error while checking permissions for snapshot", err)
|
||||
}
|
||||
|
||||
if !canEdit && query.Result.UserId != c.SignedInUser.UserId && !errors.Is(err, models.ErrDashboardNotFound) {
|
||||
if !canEdit && query.Result.UserId != c.SignedInUser.UserId && !errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return response.Error(403, "Access denied to this snapshot", nil)
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/framework/coremodel/registry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -18,6 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/framework/coremodel/registry"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
@ -679,24 +679,24 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
SaveError error
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{SaveError: models.ErrDashboardNotFound, ExpectedStatusCode: 404},
|
||||
{SaveError: models.ErrFolderNotFound, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardWithSameUIDExists, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardWithSameNameInFolderExists, ExpectedStatusCode: 412},
|
||||
{SaveError: models.ErrDashboardVersionMismatch, ExpectedStatusCode: 412},
|
||||
{SaveError: models.ErrDashboardTitleEmpty, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardFolderCannotHaveParent, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardNotFound, ExpectedStatusCode: 404},
|
||||
{SaveError: dashboards.ErrFolderNotFound, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardWithSameUIDExists, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardWithSameNameInFolderExists, ExpectedStatusCode: 412},
|
||||
{SaveError: dashboards.ErrDashboardVersionMismatch, ExpectedStatusCode: 412},
|
||||
{SaveError: dashboards.ErrDashboardTitleEmpty, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardFolderCannotHaveParent, ExpectedStatusCode: 400},
|
||||
{SaveError: alerting.ValidationError{Reason: "Mu"}, ExpectedStatusCode: 422},
|
||||
{SaveError: models.ErrDashboardFailedGenerateUniqueUid, ExpectedStatusCode: 500},
|
||||
{SaveError: models.ErrDashboardTypeMismatch, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardFolderWithSameNameAsDashboard, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardWithSameNameAsFolder, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardFolderNameExists, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardUpdateAccessDenied, ExpectedStatusCode: 403},
|
||||
{SaveError: models.ErrDashboardInvalidUid, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardUidTooLong, ExpectedStatusCode: 400},
|
||||
{SaveError: models.ErrDashboardCannotSaveProvisionedDashboard, ExpectedStatusCode: 400},
|
||||
{SaveError: models.UpdatePluginDashboardError{PluginId: "plug"}, ExpectedStatusCode: 412},
|
||||
{SaveError: dashboards.ErrDashboardFailedGenerateUniqueUid, ExpectedStatusCode: 500},
|
||||
{SaveError: dashboards.ErrDashboardTypeMismatch, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardFolderWithSameNameAsDashboard, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardWithSameNameAsFolder, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardFolderNameExists, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardUpdateAccessDenied, ExpectedStatusCode: 403},
|
||||
{SaveError: dashboards.ErrDashboardInvalidUid, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardUidTooLong, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.ErrDashboardCannotSaveProvisionedDashboard, ExpectedStatusCode: 400},
|
||||
{SaveError: dashboards.UpdatePluginDashboardError{PluginId: "plug"}, ExpectedStatusCode: 412},
|
||||
}
|
||||
|
||||
cmd := models.SaveDashboardCommand{
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@ -24,7 +25,7 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser)
|
||||
|
||||
if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin {
|
||||
return apierrors.ToFolderErrorResponse(models.ErrFolderAccessDenied)
|
||||
return apierrors.ToFolderErrorResponse(dashboards.ErrFolderAccessDenied)
|
||||
}
|
||||
|
||||
acl, err := g.GetAcl()
|
||||
@ -78,7 +79,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
||||
}
|
||||
|
||||
if !canAdmin {
|
||||
return apierrors.ToFolderErrorResponse(models.ErrFolderAccessDenied)
|
||||
return apierrors.ToFolderErrorResponse(dashboards.ErrFolderAccessDenied)
|
||||
}
|
||||
|
||||
var items []*models.DashboardAcl
|
||||
|
@ -49,7 +49,7 @@ func TestFolderPermissionAPIEndpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("Given folder not exists", func(t *testing.T) {
|
||||
folderService.On("GetFolderByUID", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, models.ErrFolderNotFound).Twice()
|
||||
folderService.On("GetFolderByUID", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, dashboards.ErrFolderNotFound).Twice()
|
||||
mockSQLStore := mockstore.NewSQLStoreMock()
|
||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/folders/uid/permissions", "/api/folders/:uid/permissions", models.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
callGetFolderPermissions(sc, hs)
|
||||
@ -81,7 +81,7 @@ func TestFolderPermissionAPIEndpoint(t *testing.T) {
|
||||
})
|
||||
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanAdminValue: false})
|
||||
folderService.On("GetFolderByUID", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, models.ErrFolderAccessDenied).Twice()
|
||||
folderService.On("GetFolderByUID", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, dashboards.ErrFolderAccessDenied).Twice()
|
||||
mockSQLStore := mockstore.NewSQLStoreMock()
|
||||
|
||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/folders/uid/permissions", "/api/folders/:uid/permissions", models.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
|
@ -7,6 +7,10 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
@ -19,9 +23,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web/webtest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFoldersAPIEndpoint(t *testing.T) {
|
||||
@ -55,15 +56,15 @@ func TestFoldersAPIEndpoint(t *testing.T) {
|
||||
Error error
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{Error: models.ErrFolderWithSameUIDExists, ExpectedStatusCode: 409},
|
||||
{Error: models.ErrFolderTitleEmpty, ExpectedStatusCode: 400},
|
||||
{Error: models.ErrFolderSameNameExists, ExpectedStatusCode: 409},
|
||||
{Error: models.ErrDashboardInvalidUid, ExpectedStatusCode: 400},
|
||||
{Error: models.ErrDashboardUidTooLong, ExpectedStatusCode: 400},
|
||||
{Error: models.ErrFolderAccessDenied, ExpectedStatusCode: 403},
|
||||
{Error: models.ErrFolderNotFound, ExpectedStatusCode: 404},
|
||||
{Error: models.ErrFolderVersionMismatch, ExpectedStatusCode: 412},
|
||||
{Error: models.ErrFolderFailedGenerateUniqueUid, ExpectedStatusCode: 500},
|
||||
{Error: dashboards.ErrFolderWithSameUIDExists, ExpectedStatusCode: 409},
|
||||
{Error: dashboards.ErrFolderTitleEmpty, ExpectedStatusCode: 400},
|
||||
{Error: dashboards.ErrFolderSameNameExists, ExpectedStatusCode: 409},
|
||||
{Error: dashboards.ErrDashboardInvalidUid, ExpectedStatusCode: 400},
|
||||
{Error: dashboards.ErrDashboardUidTooLong, ExpectedStatusCode: 400},
|
||||
{Error: dashboards.ErrFolderAccessDenied, ExpectedStatusCode: 403},
|
||||
{Error: dashboards.ErrFolderNotFound, ExpectedStatusCode: 404},
|
||||
{Error: dashboards.ErrFolderVersionMismatch, ExpectedStatusCode: 412},
|
||||
{Error: dashboards.ErrFolderFailedGenerateUniqueUid, ExpectedStatusCode: 500},
|
||||
}
|
||||
|
||||
cmd := models.CreateFolderCommand{
|
||||
@ -110,15 +111,15 @@ func TestFoldersAPIEndpoint(t *testing.T) {
|
||||
Error error
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{Error: models.ErrFolderWithSameUIDExists, ExpectedStatusCode: 409},
|
||||
{Error: models.ErrFolderTitleEmpty, ExpectedStatusCode: 400},
|
||||
{Error: models.ErrFolderSameNameExists, ExpectedStatusCode: 409},
|
||||
{Error: models.ErrDashboardInvalidUid, ExpectedStatusCode: 400},
|
||||
{Error: models.ErrDashboardUidTooLong, ExpectedStatusCode: 400},
|
||||
{Error: models.ErrFolderAccessDenied, ExpectedStatusCode: 403},
|
||||
{Error: models.ErrFolderNotFound, ExpectedStatusCode: 404},
|
||||
{Error: models.ErrFolderVersionMismatch, ExpectedStatusCode: 412},
|
||||
{Error: models.ErrFolderFailedGenerateUniqueUid, ExpectedStatusCode: 500},
|
||||
{Error: dashboards.ErrFolderWithSameUIDExists, ExpectedStatusCode: 409},
|
||||
{Error: dashboards.ErrFolderTitleEmpty, ExpectedStatusCode: 400},
|
||||
{Error: dashboards.ErrFolderSameNameExists, ExpectedStatusCode: 409},
|
||||
{Error: dashboards.ErrDashboardInvalidUid, ExpectedStatusCode: 400},
|
||||
{Error: dashboards.ErrDashboardUidTooLong, ExpectedStatusCode: 400},
|
||||
{Error: dashboards.ErrFolderAccessDenied, ExpectedStatusCode: 403},
|
||||
{Error: dashboards.ErrFolderNotFound, ExpectedStatusCode: 404},
|
||||
{Error: dashboards.ErrFolderVersionMismatch, ExpectedStatusCode: 412},
|
||||
{Error: dashboards.ErrFolderFailedGenerateUniqueUid, ExpectedStatusCode: 500},
|
||||
}
|
||||
|
||||
cmd := models.UpdateFolderCommand{
|
||||
|
@ -10,173 +10,10 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
const RootFolderName = "General"
|
||||
|
||||
// Typed errors
|
||||
var (
|
||||
ErrDashboardNotFound = DashboardErr{
|
||||
Reason: "Dashboard not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardCorrupt = DashboardErr{
|
||||
Reason: "Dashboard data is missing or corrupt",
|
||||
StatusCode: 500,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardPanelNotFound = DashboardErr{
|
||||
Reason: "Dashboard panel not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardFolderNotFound = DashboardErr{
|
||||
Reason: "Folder not found",
|
||||
StatusCode: 404,
|
||||
}
|
||||
ErrDashboardSnapshotNotFound = DashboardErr{
|
||||
Reason: "Dashboard snapshot not found",
|
||||
StatusCode: 404,
|
||||
}
|
||||
ErrDashboardWithSameUIDExists = DashboardErr{
|
||||
Reason: "A dashboard with the same uid already exists",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardWithSameNameInFolderExists = DashboardErr{
|
||||
Reason: "A dashboard with the same name in the folder already exists",
|
||||
StatusCode: 412,
|
||||
Status: "name-exists",
|
||||
}
|
||||
ErrDashboardVersionMismatch = DashboardErr{
|
||||
Reason: "The dashboard has been changed by someone else",
|
||||
StatusCode: 412,
|
||||
Status: "version-mismatch",
|
||||
}
|
||||
ErrDashboardTitleEmpty = DashboardErr{
|
||||
Reason: "Dashboard title cannot be empty",
|
||||
StatusCode: 400,
|
||||
Status: "empty-name",
|
||||
}
|
||||
ErrDashboardFolderCannotHaveParent = DashboardErr{
|
||||
Reason: "A Dashboard Folder cannot be added to another folder",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardsWithSameSlugExists = DashboardErr{
|
||||
Reason: "Multiple dashboards with the same slug exists",
|
||||
StatusCode: 412,
|
||||
}
|
||||
ErrDashboardFailedGenerateUniqueUid = DashboardErr{
|
||||
Reason: "Failed to generate unique dashboard id",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrDashboardTypeMismatch = DashboardErr{
|
||||
Reason: "Dashboard cannot be changed to a folder",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardFolderWithSameNameAsDashboard = DashboardErr{
|
||||
Reason: "Folder name cannot be the same as one of its dashboards",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardWithSameNameAsFolder = DashboardErr{
|
||||
Reason: "Dashboard name cannot be the same as folder",
|
||||
StatusCode: 400,
|
||||
Status: "name-match",
|
||||
}
|
||||
ErrDashboardFolderNameExists = DashboardErr{
|
||||
Reason: "A folder with that name already exists",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardUpdateAccessDenied = DashboardErr{
|
||||
Reason: "Access denied to save dashboard",
|
||||
StatusCode: 403,
|
||||
}
|
||||
ErrDashboardInvalidUid = DashboardErr{
|
||||
Reason: "uid contains illegal characters",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardUidTooLong = DashboardErr{
|
||||
Reason: "uid too long, max 40 characters",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardCannotSaveProvisionedDashboard = DashboardErr{
|
||||
Reason: "Cannot save provisioned dashboard",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardRefreshIntervalTooShort = DashboardErr{
|
||||
Reason: "Dashboard refresh interval is too low",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardCannotDeleteProvisionedDashboard = DashboardErr{
|
||||
Reason: "provisioned dashboard cannot be deleted",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardIdentifierNotSet = DashboardErr{
|
||||
Reason: "Unique identifier needed to be able to get a dashboard",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardIdentifierInvalid = DashboardErr{
|
||||
Reason: "Dashboard ID not a number",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardPanelIdentifierInvalid = DashboardErr{
|
||||
Reason: "Dashboard panel ID not a number",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardOrPanelIdentifierNotSet = DashboardErr{
|
||||
Reason: "Unique identifier needed to be able to get a dashboard panel",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrProvisionedDashboardNotFound = DashboardErr{
|
||||
Reason: "Dashboard is not provisioned",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardThumbnailNotFound = DashboardErr{
|
||||
Reason: "Dashboard thumbnail not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
)
|
||||
|
||||
// DashboardErr represents a dashboard error.
|
||||
type DashboardErr struct {
|
||||
StatusCode int
|
||||
Status string
|
||||
Reason string
|
||||
}
|
||||
|
||||
// Equal returns whether equal to another DashboardErr.
|
||||
func (e DashboardErr) Equal(o DashboardErr) bool {
|
||||
return o.StatusCode == e.StatusCode && o.Status == e.Status && o.Reason == e.Reason
|
||||
}
|
||||
|
||||
// Error returns the error message.
|
||||
func (e DashboardErr) Error() string {
|
||||
if e.Reason != "" {
|
||||
return e.Reason
|
||||
}
|
||||
return "Dashboard Error"
|
||||
}
|
||||
|
||||
// Body returns the error's response body, if applicable.
|
||||
func (e DashboardErr) Body() util.DynMap {
|
||||
if e.Status == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return util.DynMap{"status": e.Status, "message": e.Error()}
|
||||
}
|
||||
|
||||
type UpdatePluginDashboardError struct {
|
||||
PluginId string
|
||||
}
|
||||
|
||||
func (d UpdatePluginDashboardError) Error() string {
|
||||
return "Dashboard belongs to plugin"
|
||||
}
|
||||
|
||||
const (
|
||||
DashTypeDB = "db"
|
||||
DashTypeSnapshot = "snapshot"
|
||||
|
@ -6,31 +6,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrPublicDashboardFailedGenerateUniqueUid = DashboardErr{
|
||||
Reason: "Failed to generate unique public dashboard id",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrPublicDashboardFailedGenerateAccesstoken = DashboardErr{
|
||||
Reason: "Failed to public dashboard access token",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrPublicDashboardNotFound = DashboardErr{
|
||||
Reason: "Public dashboard not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardPanelNotFound = DashboardErr{
|
||||
Reason: "Panel not found in dashboard",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardIdentifierNotSet = DashboardErr{
|
||||
Reason: "No Uid for public dashboard specified",
|
||||
StatusCode: 400,
|
||||
}
|
||||
)
|
||||
|
||||
type PublicDashboard struct {
|
||||
Uid string `json:"uid" xorm:"pk uid"`
|
||||
DashboardUid string `json:"dashboardUid" xorm:"dashboard_uid"`
|
||||
|
@ -1,24 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Typed errors
|
||||
var (
|
||||
ErrFolderNotFound = errors.New("folder not found")
|
||||
ErrFolderVersionMismatch = errors.New("the folder has been changed by someone else")
|
||||
ErrFolderTitleEmpty = errors.New("folder title cannot be empty")
|
||||
ErrFolderWithSameUIDExists = errors.New("a folder/dashboard with the same uid already exists")
|
||||
ErrFolderInvalidUID = errors.New("invalid uid for folder provided")
|
||||
ErrFolderSameNameExists = errors.New("a folder or dashboard in the general folder with the same name already exists")
|
||||
ErrFolderFailedGenerateUniqueUid = errors.New("failed to generate unique folder ID")
|
||||
ErrFolderAccessDenied = errors.New("access denied to folder")
|
||||
ErrFolderContainsAlertRules = errors.New("folder contains alert rules")
|
||||
)
|
||||
|
||||
type Folder struct {
|
||||
Id int64
|
||||
Uid string
|
||||
|
@ -64,12 +64,12 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore)
|
||||
|
||||
orgId := rand.Int63()
|
||||
dashboardStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything).Return(nil, models.ErrDashboardNotFound).Once()
|
||||
dashboardStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
|
||||
scope := "folders:name:" + util.GenerateShortUID()
|
||||
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
require.ErrorIs(t, err, models.ErrDashboardNotFound)
|
||||
require.ErrorIs(t, err, ErrDashboardNotFound)
|
||||
require.Nil(t, resolvedScopes)
|
||||
})
|
||||
}
|
||||
@ -136,11 +136,11 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore)
|
||||
|
||||
orgId := rand.Int63()
|
||||
dashboardStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(nil, models.ErrDashboardNotFound).Once()
|
||||
dashboardStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
|
||||
scope := "folders:id:10"
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
require.ErrorIs(t, err, models.ErrDashboardNotFound)
|
||||
require.ErrorIs(t, err, ErrDashboardNotFound)
|
||||
require.Nil(t, resolvedScopes)
|
||||
})
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func (d *DashboardStore) ValidateDashboardBeforeSave(dashboard *models.Dashboard
|
||||
|
||||
func (d *DashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, title string) (*models.Folder, error) {
|
||||
if title == "" {
|
||||
return nil, models.ErrFolderTitleEmpty
|
||||
return nil, dashboards.ErrFolderTitleEmpty
|
||||
}
|
||||
|
||||
// there is a unique constraint on org_id, folder_id, title
|
||||
@ -72,7 +72,7 @@ func (d *DashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, titl
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
return models.ErrFolderNotFound
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
dashboard.SetId(dashboard.Id)
|
||||
dashboard.SetUid(dashboard.Uid)
|
||||
@ -89,7 +89,7 @@ func (d *DashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int6
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
return models.ErrFolderNotFound
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
dashboard.SetId(dashboard.Id)
|
||||
dashboard.SetUid(dashboard.Uid)
|
||||
@ -103,7 +103,7 @@ func (d *DashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int6
|
||||
|
||||
func (d *DashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*models.Folder, error) {
|
||||
if uid == "" {
|
||||
return nil, models.ErrDashboardIdentifierNotSet
|
||||
return nil, dashboards.ErrDashboardIdentifierNotSet
|
||||
}
|
||||
|
||||
dashboard := models.Dashboard{OrgId: orgID, FolderId: 0, Uid: uid}
|
||||
@ -113,7 +113,7 @@ func (d *DashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid st
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
return models.ErrFolderNotFound
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
dashboard.SetId(dashboard.Id)
|
||||
dashboard.SetUid(dashboard.Uid)
|
||||
@ -147,15 +147,14 @@ func (d *DashboardStore) GetProvisionedDataByDashboardUID(orgID int64, dashboard
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return models.
|
||||
ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
exists, err = sess.Where("dashboard_id = ?", dashboard.Id).Get(&provisionedDashboard)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return models.ErrProvisionedDashboardNotFound
|
||||
return dashboards.ErrProvisionedDashboardNotFound
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@ -267,7 +266,7 @@ func (d *DashboardStore) DeleteOrphanedProvisionedDashboards(ctx context.Context
|
||||
|
||||
for _, deleteDashCommand := range result {
|
||||
err := d.DeleteDashboard(ctx, &models.DeleteDashboardCommand{Id: deleteDashCommand.DashboardId})
|
||||
if err != nil && !errors.Is(err, models.ErrDashboardNotFound) {
|
||||
if err != nil && !errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -289,7 +288,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *sqlstore.DBSession, dash *mode
|
||||
}
|
||||
|
||||
if !dashWithIdExists {
|
||||
return false, models.ErrDashboardNotFound
|
||||
return false, dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
if dash.Uid == "" {
|
||||
@ -317,7 +316,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *sqlstore.DBSession, dash *mode
|
||||
}
|
||||
|
||||
if !folderExists {
|
||||
return false, models.ErrDashboardFolderNotFound
|
||||
return false, dashboards.ErrDashboardFolderNotFound
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,7 +325,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *sqlstore.DBSession, dash *mode
|
||||
}
|
||||
|
||||
if dashWithIdExists && dashWithUidExists && existingById.Id != existingByUid.Id {
|
||||
return false, models.ErrDashboardWithSameUIDExists
|
||||
return false, dashboards.ErrDashboardWithSameUIDExists
|
||||
}
|
||||
|
||||
existing := existingById
|
||||
@ -339,7 +338,7 @@ func getExistingDashboardByIdOrUidForUpdate(sess *sqlstore.DBSession, dash *mode
|
||||
|
||||
if (existing.IsFolder && !dash.IsFolder) ||
|
||||
(!existing.IsFolder && dash.IsFolder) {
|
||||
return isParentFolderChanged, models.ErrDashboardTypeMismatch
|
||||
return isParentFolderChanged, dashboards.ErrDashboardTypeMismatch
|
||||
}
|
||||
|
||||
if !dash.IsFolder && dash.FolderId != existing.FolderId {
|
||||
@ -351,13 +350,13 @@ func getExistingDashboardByIdOrUidForUpdate(sess *sqlstore.DBSession, dash *mode
|
||||
if overwrite {
|
||||
dash.SetVersion(existing.Version)
|
||||
} else {
|
||||
return isParentFolderChanged, models.ErrDashboardVersionMismatch
|
||||
return isParentFolderChanged, dashboards.ErrDashboardVersionMismatch
|
||||
}
|
||||
}
|
||||
|
||||
// do not allow plugin dashboard updates without overwrite flag
|
||||
if existing.PluginId != "" && !overwrite {
|
||||
return isParentFolderChanged, models.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
return isParentFolderChanged, dashboards.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
}
|
||||
|
||||
return isParentFolderChanged, nil
|
||||
@ -374,11 +373,11 @@ func getExistingDashboardByTitleAndFolder(sess *sqlstore.DBSession, dash *models
|
||||
|
||||
if exists && dash.Id != existing.Id {
|
||||
if existing.IsFolder && !dash.IsFolder {
|
||||
return isParentFolderChanged, models.ErrDashboardWithSameNameAsFolder
|
||||
return isParentFolderChanged, dashboards.ErrDashboardWithSameNameAsFolder
|
||||
}
|
||||
|
||||
if !existing.IsFolder && dash.IsFolder {
|
||||
return isParentFolderChanged, models.ErrDashboardFolderWithSameNameAsDashboard
|
||||
return isParentFolderChanged, dashboards.ErrDashboardFolderWithSameNameAsDashboard
|
||||
}
|
||||
|
||||
if !dash.IsFolder && (dash.FolderId != existing.FolderId || dash.Id == 0) {
|
||||
@ -390,7 +389,7 @@ func getExistingDashboardByTitleAndFolder(sess *sqlstore.DBSession, dash *models
|
||||
dash.SetUid(existing.Uid)
|
||||
dash.SetVersion(existing.Version)
|
||||
} else {
|
||||
return isParentFolderChanged, models.ErrDashboardWithSameNameInFolderExists
|
||||
return isParentFolderChanged, dashboards.ErrDashboardWithSameNameInFolderExists
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,7 +412,7 @@ func saveDashboard(sess *sqlstore.DBSession, cmd *models.SaveDashboardCommand) e
|
||||
return err
|
||||
}
|
||||
if !dashWithIdExists {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
// check for is someone else has written in between
|
||||
@ -421,13 +420,13 @@ func saveDashboard(sess *sqlstore.DBSession, cmd *models.SaveDashboardCommand) e
|
||||
if cmd.Overwrite {
|
||||
dash.SetVersion(existing.Version)
|
||||
} else {
|
||||
return models.ErrDashboardVersionMismatch
|
||||
return dashboards.ErrDashboardVersionMismatch
|
||||
}
|
||||
}
|
||||
|
||||
// do not allow plugin dashboard updates without overwrite flag
|
||||
if existing.PluginId != "" && !cmd.Overwrite {
|
||||
return models.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
return dashboards.UpdatePluginDashboardError{PluginId: existing.PluginId}
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,7 +469,7 @@ func saveDashboard(sess *sqlstore.DBSession, cmd *models.SaveDashboardCommand) e
|
||||
}
|
||||
|
||||
if affectedRows == 0 {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
dashVersion := &dashver.DashboardVersion{
|
||||
@ -488,7 +487,7 @@ func saveDashboard(sess *sqlstore.DBSession, cmd *models.SaveDashboardCommand) e
|
||||
if affectedRows, err = sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
// delete existing tags
|
||||
@ -525,7 +524,7 @@ func generateNewDashboardUid(sess *sqlstore.DBSession, orgId int64) (string, err
|
||||
}
|
||||
}
|
||||
|
||||
return "", models.ErrDashboardFailedGenerateUniqueUid
|
||||
return "", dashboards.ErrDashboardFailedGenerateUniqueUid
|
||||
}
|
||||
|
||||
func saveProvisionedData(sess *sqlstore.DBSession, provisioning *models.DashboardProvisioning, dashboard *models.Dashboard) error {
|
||||
@ -709,7 +708,7 @@ func (d *DashboardStore) deleteDashboard(cmd *models.DeleteDashboardCommand, ses
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
deletes := []string{
|
||||
@ -779,7 +778,7 @@ func (d *DashboardStore) deleteDashboard(cmd *models.DeleteDashboardCommand, ses
|
||||
}
|
||||
if exists {
|
||||
if !cmd.ForceDeleteFolderRules {
|
||||
return fmt.Errorf("folder cannot be deleted: %w", models.ErrFolderContainsAlertRules)
|
||||
return fmt.Errorf("folder cannot be deleted: %w", dashboards.ErrFolderContainsAlertRules)
|
||||
}
|
||||
|
||||
// Delete all rules under this folder.
|
||||
@ -836,7 +835,7 @@ func (d *DashboardStore) deleteAlertDefinition(dashboardId int64, sess *sqlstore
|
||||
func (d *DashboardStore) GetDashboard(ctx context.Context, query *models.GetDashboardQuery) (*models.Dashboard, error) {
|
||||
err := d.sqlStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
if query.Id == 0 && len(query.Slug) == 0 && len(query.Uid) == 0 {
|
||||
return models.ErrDashboardIdentifierNotSet
|
||||
return dashboards.ErrDashboardIdentifierNotSet
|
||||
}
|
||||
|
||||
dashboard := models.Dashboard{Slug: query.Slug, OrgId: query.OrgId, Id: query.Id, Uid: query.Uid}
|
||||
@ -845,7 +844,7 @@ func (d *DashboardStore) GetDashboard(ctx context.Context, query *models.GetDash
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
dashboard.SetId(dashboard.Id)
|
||||
@ -865,7 +864,7 @@ func (d *DashboardStore) GetDashboardUIDById(ctx context.Context, query *models.
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !exists {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
query.Result = us
|
||||
return nil
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
@ -11,7 +12,7 @@ import (
|
||||
// retrieves public dashboard configuration
|
||||
func (d *DashboardStore) GetPublicDashboard(ctx context.Context, accessToken string) (*models.PublicDashboard, *models.Dashboard, error) {
|
||||
if accessToken == "" {
|
||||
return nil, nil, models.ErrPublicDashboardIdentifierNotSet
|
||||
return nil, nil, dashboards.ErrPublicDashboardIdentifierNotSet
|
||||
}
|
||||
|
||||
// get public dashboard
|
||||
@ -22,7 +23,7 @@ func (d *DashboardStore) GetPublicDashboard(ctx context.Context, accessToken str
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
return models.ErrPublicDashboardNotFound
|
||||
return dashboards.ErrPublicDashboardNotFound
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@ -39,7 +40,7 @@ func (d *DashboardStore) GetPublicDashboard(ctx context.Context, accessToken str
|
||||
return err
|
||||
}
|
||||
if !has {
|
||||
return models.ErrPublicDashboardNotFound
|
||||
return dashboards.ErrPublicDashboardNotFound
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@ -69,7 +70,7 @@ func (d *DashboardStore) GenerateNewPublicDashboardUid(ctx context.Context) (str
|
||||
}
|
||||
}
|
||||
|
||||
return models.ErrPublicDashboardFailedGenerateUniqueUid
|
||||
return dashboards.ErrPublicDashboardFailedGenerateUniqueUid
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
@ -82,7 +83,7 @@ func (d *DashboardStore) GenerateNewPublicDashboardUid(ctx context.Context) (str
|
||||
// retrieves public dashboard configuration
|
||||
func (d *DashboardStore) GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboard, error) {
|
||||
if dashboardUid == "" {
|
||||
return nil, models.ErrDashboardIdentifierNotSet
|
||||
return nil, dashboards.ErrDashboardIdentifierNotSet
|
||||
}
|
||||
|
||||
pdRes := &models.PublicDashboard{OrgId: orgId, DashboardUid: dashboardUid}
|
||||
|
@ -5,13 +5,15 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// This is what the db sets empty time settings to
|
||||
@ -58,13 +60,13 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
t.Run("returns ErrPublicDashboardNotFound with empty uid", func(t *testing.T) {
|
||||
setup()
|
||||
_, _, err := dashboardStore.GetPublicDashboard(context.Background(), "")
|
||||
require.Error(t, models.ErrPublicDashboardIdentifierNotSet, err)
|
||||
require.Error(t, dashboards.ErrPublicDashboardIdentifierNotSet, err)
|
||||
})
|
||||
|
||||
t.Run("returns ErrPublicDashboardNotFound when PublicDashboard not found", func(t *testing.T) {
|
||||
setup()
|
||||
_, _, err := dashboardStore.GetPublicDashboard(context.Background(), "zzzzzz")
|
||||
require.Error(t, models.ErrPublicDashboardNotFound, err)
|
||||
require.Error(t, dashboards.ErrPublicDashboardNotFound, err)
|
||||
})
|
||||
|
||||
t.Run("returns ErrDashboardNotFound when Dashboard not found", func(t *testing.T) {
|
||||
@ -83,7 +85,7 @@ func TestIntegrationGetPublicDashboard(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, _, err = dashboardStore.GetPublicDashboard(context.Background(), "abc1234")
|
||||
require.Error(t, models.ErrDashboardNotFound, err)
|
||||
require.Error(t, dashboards.ErrDashboardNotFound, err)
|
||||
})
|
||||
}
|
||||
|
||||
@ -109,7 +111,7 @@ func TestIntegrationGetPublicDashboardConfig(t *testing.T) {
|
||||
t.Run("returns dashboard errDashboardIdentifierNotSet", func(t *testing.T) {
|
||||
setup()
|
||||
_, err := dashboardStore.GetPublicDashboardConfig(context.Background(), savedDashboard.OrgId, "")
|
||||
require.Error(t, models.ErrDashboardIdentifierNotSet, err)
|
||||
require.Error(t, dashboards.ErrDashboardIdentifierNotSet, err)
|
||||
})
|
||||
|
||||
t.Run("returns isPublic along with public dashboard when exists", func(t *testing.T) {
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
@ -492,12 +493,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
t.Run("should not find dashboard", func(t *testing.T) {
|
||||
d, err := dashboardStore.GetFolderByUID(context.Background(), orgId, dash.Uid)
|
||||
require.Nil(t, d)
|
||||
require.ErrorIs(t, err, models.ErrFolderNotFound)
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderNotFound)
|
||||
})
|
||||
t.Run("should search in organization", func(t *testing.T) {
|
||||
d, err := dashboardStore.GetFolderByUID(context.Background(), orgId+1, folder.Uid)
|
||||
require.Nil(t, d)
|
||||
require.ErrorIs(t, err, models.ErrFolderNotFound)
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderNotFound)
|
||||
})
|
||||
})
|
||||
|
||||
@ -516,12 +517,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
t.Run("should not find dashboard", func(t *testing.T) {
|
||||
d, err := dashboardStore.GetFolderByID(context.Background(), orgId, dash.Id)
|
||||
require.Nil(t, d)
|
||||
require.ErrorIs(t, err, models.ErrFolderNotFound)
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderNotFound)
|
||||
})
|
||||
t.Run("should search in organization", func(t *testing.T) {
|
||||
d, err := dashboardStore.GetFolderByID(context.Background(), orgId+1, folder.Id)
|
||||
require.Nil(t, d)
|
||||
require.ErrorIs(t, err, models.ErrFolderNotFound)
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderNotFound)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -124,7 +124,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
|
||||
}
|
||||
|
||||
_, err := dashboardStore.GetDashboard(context.Background(), &query)
|
||||
require.Equal(t, err, models.ErrDashboardIdentifierNotSet)
|
||||
require.Equal(t, err, dashboards.ErrDashboardIdentifierNotSet)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get dashboards by IDs & UIDs", func(t *testing.T) {
|
||||
@ -227,7 +227,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
|
||||
setup()
|
||||
deleteCmd := &models.DeleteDashboardCommand{Id: savedFolder.Id, ForceDeleteFolderRules: false}
|
||||
err := dashboardStore.DeleteDashboard(context.Background(), deleteCmd)
|
||||
require.True(t, errors.Is(err, models.ErrFolderContainsAlertRules))
|
||||
require.True(t, errors.Is(err, dashboards.ErrFolderContainsAlertRules))
|
||||
})
|
||||
|
||||
t.Run("Should be able to delete a dashboard folder and its children if force delete rules is enabled", func(t *testing.T) {
|
||||
@ -274,7 +274,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
|
||||
}
|
||||
|
||||
_, err := dashboardStore.SaveDashboard(cmd)
|
||||
require.Equal(t, err, models.ErrDashboardNotFound)
|
||||
require.Equal(t, err, dashboards.ErrDashboardNotFound)
|
||||
})
|
||||
|
||||
t.Run("Should not return error if no dashboard is found for update when dashboard id is zero", func(t *testing.T) {
|
||||
|
197
pkg/services/dashboards/errors.go
Normal file
197
pkg/services/dashboards/errors.go
Normal file
@ -0,0 +1,197 @@
|
||||
package dashboards
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
// Typed errors
|
||||
var (
|
||||
ErrDashboardNotFound = DashboardErr{
|
||||
Reason: "Dashboard not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardCorrupt = DashboardErr{
|
||||
Reason: "Dashboard data is missing or corrupt",
|
||||
StatusCode: 500,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardPanelNotFound = DashboardErr{
|
||||
Reason: "Dashboard panel not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardFolderNotFound = DashboardErr{
|
||||
Reason: "Folder not found",
|
||||
StatusCode: 404,
|
||||
}
|
||||
ErrDashboardWithSameUIDExists = DashboardErr{
|
||||
Reason: "A dashboard with the same uid already exists",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardWithSameNameInFolderExists = DashboardErr{
|
||||
Reason: "A dashboard with the same name in the folder already exists",
|
||||
StatusCode: 412,
|
||||
Status: "name-exists",
|
||||
}
|
||||
ErrDashboardVersionMismatch = DashboardErr{
|
||||
Reason: "The dashboard has been changed by someone else",
|
||||
StatusCode: 412,
|
||||
Status: "version-mismatch",
|
||||
}
|
||||
ErrDashboardTitleEmpty = DashboardErr{
|
||||
Reason: "Dashboard title cannot be empty",
|
||||
StatusCode: 400,
|
||||
Status: "empty-name",
|
||||
}
|
||||
ErrDashboardFolderCannotHaveParent = DashboardErr{
|
||||
Reason: "A Dashboard Folder cannot be added to another folder",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardsWithSameSlugExists = DashboardErr{
|
||||
Reason: "Multiple dashboards with the same slug exists",
|
||||
StatusCode: 412,
|
||||
}
|
||||
ErrDashboardFailedGenerateUniqueUid = DashboardErr{
|
||||
Reason: "Failed to generate unique dashboard id",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrDashboardTypeMismatch = DashboardErr{
|
||||
Reason: "Dashboard cannot be changed to a folder",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardFolderWithSameNameAsDashboard = DashboardErr{
|
||||
Reason: "Folder name cannot be the same as one of its dashboards",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardWithSameNameAsFolder = DashboardErr{
|
||||
Reason: "Dashboard name cannot be the same as folder",
|
||||
StatusCode: 400,
|
||||
Status: "name-match",
|
||||
}
|
||||
ErrDashboardFolderNameExists = DashboardErr{
|
||||
Reason: "A folder with that name already exists",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardUpdateAccessDenied = DashboardErr{
|
||||
Reason: "Access denied to save dashboard",
|
||||
StatusCode: 403,
|
||||
}
|
||||
ErrDashboardInvalidUid = DashboardErr{
|
||||
Reason: "uid contains illegal characters",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardUidTooLong = DashboardErr{
|
||||
Reason: "uid too long, max 40 characters",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardCannotSaveProvisionedDashboard = DashboardErr{
|
||||
Reason: "Cannot save provisioned dashboard",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardRefreshIntervalTooShort = DashboardErr{
|
||||
Reason: "Dashboard refresh interval is too low",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardCannotDeleteProvisionedDashboard = DashboardErr{
|
||||
Reason: "provisioned dashboard cannot be deleted",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardIdentifierNotSet = DashboardErr{
|
||||
Reason: "Unique identifier needed to be able to get a dashboard",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardIdentifierInvalid = DashboardErr{
|
||||
Reason: "Dashboard ID not a number",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardPanelIdentifierInvalid = DashboardErr{
|
||||
Reason: "Dashboard panel ID not a number",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrDashboardOrPanelIdentifierNotSet = DashboardErr{
|
||||
Reason: "Unique identifier needed to be able to get a dashboard panel",
|
||||
StatusCode: 400,
|
||||
}
|
||||
ErrProvisionedDashboardNotFound = DashboardErr{
|
||||
Reason: "Dashboard is not provisioned",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrDashboardThumbnailNotFound = DashboardErr{
|
||||
Reason: "Dashboard thumbnail not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardFailedGenerateUniqueUid = DashboardErr{
|
||||
Reason: "Failed to generate unique public dashboard id",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrPublicDashboardFailedGenerateAccesstoken = DashboardErr{
|
||||
Reason: "Failed to public dashboard access token",
|
||||
StatusCode: 500,
|
||||
}
|
||||
ErrPublicDashboardNotFound = DashboardErr{
|
||||
Reason: "Public dashboard not found",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardPanelNotFound = DashboardErr{
|
||||
Reason: "Panel not found in dashboard",
|
||||
StatusCode: 404,
|
||||
Status: "not-found",
|
||||
}
|
||||
ErrPublicDashboardIdentifierNotSet = DashboardErr{
|
||||
Reason: "No Uid for public dashboard specified",
|
||||
StatusCode: 400,
|
||||
}
|
||||
|
||||
ErrFolderNotFound = errors.New("folder not found")
|
||||
ErrFolderVersionMismatch = errors.New("the folder has been changed by someone else")
|
||||
ErrFolderTitleEmpty = errors.New("folder title cannot be empty")
|
||||
ErrFolderWithSameUIDExists = errors.New("a folder/dashboard with the same uid already exists")
|
||||
ErrFolderInvalidUID = errors.New("invalid uid for folder provided")
|
||||
ErrFolderSameNameExists = errors.New("a folder or dashboard in the general folder with the same name already exists")
|
||||
ErrFolderFailedGenerateUniqueUid = errors.New("failed to generate unique folder ID")
|
||||
ErrFolderAccessDenied = errors.New("access denied to folder")
|
||||
ErrFolderContainsAlertRules = errors.New("folder contains alert rules")
|
||||
)
|
||||
|
||||
// DashboardErr represents a dashboard error.
|
||||
type DashboardErr struct {
|
||||
StatusCode int
|
||||
Status string
|
||||
Reason string
|
||||
}
|
||||
|
||||
// Equal returns whether equal to another DashboardErr.
|
||||
func (e DashboardErr) Equal(o DashboardErr) bool {
|
||||
return o.StatusCode == e.StatusCode && o.Status == e.Status && o.Reason == e.Reason
|
||||
}
|
||||
|
||||
// Error returns the error message.
|
||||
func (e DashboardErr) Error() string {
|
||||
if e.Reason != "" {
|
||||
return e.Reason
|
||||
}
|
||||
return "Dashboard Error"
|
||||
}
|
||||
|
||||
// Body returns the error's response body, if applicable.
|
||||
func (e DashboardErr) Body() util.DynMap {
|
||||
if e.Status == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return util.DynMap{"status": e.Status, "message": e.Error()}
|
||||
}
|
||||
|
||||
type UpdatePluginDashboardError struct {
|
||||
PluginId string
|
||||
}
|
||||
|
||||
func (d UpdatePluginDashboardError) Error() string {
|
||||
return "Dashboard belongs to plugin"
|
||||
}
|
@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@ -21,11 +22,11 @@ func (dr *DashboardServiceImpl) GetPublicDashboard(ctx context.Context, accessTo
|
||||
}
|
||||
|
||||
if pubdash == nil || d == nil {
|
||||
return nil, models.ErrPublicDashboardNotFound
|
||||
return nil, dashboards.ErrPublicDashboardNotFound
|
||||
}
|
||||
|
||||
if !pubdash.IsEnabled {
|
||||
return nil, models.ErrPublicDashboardNotFound
|
||||
return nil, dashboards.ErrPublicDashboardNotFound
|
||||
}
|
||||
|
||||
ts := pubdash.BuildTimeSettings(d)
|
||||
@ -49,7 +50,7 @@ func (dr *DashboardServiceImpl) GetPublicDashboardConfig(ctx context.Context, or
|
||||
// to the database. It handles validations for sharing config and persistence
|
||||
func (dr *DashboardServiceImpl) SavePublicDashboardConfig(ctx context.Context, dto *dashboards.SavePublicDashboardConfigDTO) (*models.PublicDashboard, error) {
|
||||
if len(dto.DashboardUid) == 0 {
|
||||
return nil, models.ErrDashboardIdentifierNotSet
|
||||
return nil, dashboards.ErrDashboardIdentifierNotSet
|
||||
}
|
||||
|
||||
// set default value for time settings
|
||||
@ -125,13 +126,13 @@ func (dr *DashboardServiceImpl) updatePublicDashboardConfig(ctx context.Context,
|
||||
// dashboard and returns a metrics request to be sent to query backend
|
||||
func (dr *DashboardServiceImpl) BuildPublicDashboardMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *models.PublicDashboard, panelId int64) (dtos.MetricRequest, error) {
|
||||
if !publicDashboard.IsEnabled {
|
||||
return dtos.MetricRequest{}, models.ErrPublicDashboardNotFound
|
||||
return dtos.MetricRequest{}, dashboards.ErrPublicDashboardNotFound
|
||||
}
|
||||
|
||||
queriesByPanel := models.GetQueriesFromDashboard(dashboard.Data)
|
||||
|
||||
if _, ok := queriesByPanel[panelId]; !ok {
|
||||
return dtos.MetricRequest{}, models.ErrPublicDashboardPanelNotFound
|
||||
return dtos.MetricRequest{}, dashboards.ErrPublicDashboardPanelNotFound
|
||||
}
|
||||
|
||||
ts := publicDashboard.BuildTimeSettings(dashboard)
|
||||
|
@ -6,15 +6,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var timeSettings, _ = simplejson.NewJson([]byte(`{"from": "now-12", "to": "now"}`))
|
||||
@ -66,21 +67,21 @@ func TestGetPublicDashboard(t *testing.T) {
|
||||
d: &models.Dashboard{Uid: "mydashboard"},
|
||||
err: nil,
|
||||
},
|
||||
ErrResp: models.ErrPublicDashboardNotFound,
|
||||
ErrResp: dashboards.ErrPublicDashboardNotFound,
|
||||
DashResp: nil,
|
||||
},
|
||||
{
|
||||
Name: "returns ErrPublicDashboardNotFound if PublicDashboard missing",
|
||||
AccessToken: "abc123",
|
||||
StoreResp: &storeResp{pd: nil, d: nil, err: nil},
|
||||
ErrResp: models.ErrPublicDashboardNotFound,
|
||||
ErrResp: dashboards.ErrPublicDashboardNotFound,
|
||||
DashResp: nil,
|
||||
},
|
||||
{
|
||||
Name: "returns ErrPublicDashboardNotFound if Dashboard missing",
|
||||
AccessToken: "abc123",
|
||||
StoreResp: &storeResp{pd: nil, d: nil, err: nil},
|
||||
ErrResp: models.ErrPublicDashboardNotFound,
|
||||
ErrResp: dashboards.ErrPublicDashboardNotFound,
|
||||
DashResp: nil,
|
||||
},
|
||||
}
|
||||
|
@ -83,21 +83,21 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
|
||||
dash.SetUid(strings.TrimSpace(dash.Uid))
|
||||
|
||||
if dash.Title == "" {
|
||||
return nil, models.ErrDashboardTitleEmpty
|
||||
return nil, dashboards.ErrDashboardTitleEmpty
|
||||
}
|
||||
|
||||
if dash.IsFolder && dash.FolderId > 0 {
|
||||
return nil, models.ErrDashboardFolderCannotHaveParent
|
||||
return nil, dashboards.ErrDashboardFolderCannotHaveParent
|
||||
}
|
||||
|
||||
if dash.IsFolder && strings.EqualFold(dash.Title, models.RootFolderName) {
|
||||
return nil, models.ErrDashboardFolderNameExists
|
||||
return nil, dashboards.ErrDashboardFolderNameExists
|
||||
}
|
||||
|
||||
if !util.IsValidShortUID(dash.Uid) {
|
||||
return nil, models.ErrDashboardInvalidUid
|
||||
return nil, dashboards.ErrDashboardInvalidUid
|
||||
} else if util.IsShortUIDTooLong(dash.Uid) {
|
||||
return nil, models.ErrDashboardUidTooLong
|
||||
return nil, dashboards.ErrDashboardUidTooLong
|
||||
}
|
||||
|
||||
if err := validateDashboardRefreshInterval(dash); err != nil {
|
||||
@ -123,7 +123,7 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, models.ErrDashboardUpdateAccessDenied
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
|
||||
}
|
||||
|
||||
if provisionedData != nil {
|
||||
return nil, models.ErrDashboardCannotSaveProvisionedDashboard
|
||||
return nil, dashboards.ErrDashboardCannotSaveProvisionedDashboard
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,14 +144,14 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, models.ErrDashboardUpdateAccessDenied
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
} else {
|
||||
if canSave, err := guard.CanSave(); err != nil || !canSave {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, models.ErrDashboardUpdateAccessDenied
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ func validateDashboardRefreshInterval(dash *models.Dashboard) error {
|
||||
}
|
||||
|
||||
if d < minRefreshInterval {
|
||||
return models.ErrDashboardRefreshIntervalTooShort
|
||||
return dashboards.ErrDashboardRefreshIntervalTooShort
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -414,7 +414,7 @@ func (dr *DashboardServiceImpl) deleteDashboard(ctx context.Context, dashboardId
|
||||
}
|
||||
|
||||
if provisionedData != nil {
|
||||
return models.ErrDashboardCannotDeleteProvisionedDashboard
|
||||
return dashboards.ErrDashboardCannotDeleteProvisionedDashboard
|
||||
}
|
||||
}
|
||||
cmd := &models.DeleteDashboardCommand{OrgId: orgId, Id: dashboardId}
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
dashbboardservice "github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
@ -39,7 +39,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardNotFound, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardNotFound, err)
|
||||
})
|
||||
|
||||
// Given other organization
|
||||
@ -59,7 +59,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardNotFound, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardNotFound, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When creating a dashboard with same uid as dashboard in organization A, it should create a new dashboard in org B",
|
||||
@ -101,7 +101,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, int64(0), sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -121,7 +121,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
require.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.otherSavedFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -141,7 +141,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
require.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -162,7 +162,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
require.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -183,7 +183,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInGeneralFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -204,7 +204,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
require.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -225,7 +225,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
require.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInGeneralFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -246,7 +246,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -267,7 +267,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
require.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInGeneralFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -288,7 +288,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
require.Equal(t, models.ErrDashboardUpdateAccessDenied, err)
|
||||
require.Equal(t, dashboards.ErrDashboardUpdateAccessDenied, err)
|
||||
|
||||
assert.Equal(t, sc.savedDashInFolder.Id, sc.dashboardGuardianMock.DashId)
|
||||
assert.Equal(t, cmd.OrgId, sc.dashboardGuardianMock.OrgId)
|
||||
@ -429,7 +429,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardFolderNotFound, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardFolderNotFound, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating an existing dashboard by id without current version", canSave,
|
||||
@ -445,7 +445,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardVersionMismatch, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardVersionMismatch, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating an existing dashboard by id with current version", canSave,
|
||||
@ -485,7 +485,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardVersionMismatch, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardVersionMismatch, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating an existing dashboard by uid with current version", canSave,
|
||||
@ -524,7 +524,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardWithSameNameInFolderExists, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardWithSameNameInFolderExists, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When creating a dashboard with same name as dashboard in General folder",
|
||||
@ -540,7 +540,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardWithSameNameInFolderExists, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardWithSameNameInFolderExists, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When creating a folder with same name as existing folder", canSave,
|
||||
@ -556,7 +556,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardWithSameNameInFolderExists, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardWithSameNameInFolderExists, err)
|
||||
})
|
||||
})
|
||||
|
||||
@ -644,7 +644,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardWithSameUIDExists, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardWithSameUIDExists, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When creating a dashboard with same name as dashboard in other folder", canSave,
|
||||
@ -708,7 +708,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardTypeMismatch, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardTypeMismatch, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating existing dashboard to a folder using id", canSave,
|
||||
@ -724,7 +724,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardTypeMismatch, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardTypeMismatch, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating existing folder to a dashboard using uid", canSave,
|
||||
@ -740,7 +740,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardTypeMismatch, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardTypeMismatch, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating existing dashboard to a folder using uid", canSave,
|
||||
@ -756,7 +756,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardTypeMismatch, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardTypeMismatch, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating existing folder to a dashboard using title", canSave,
|
||||
@ -771,7 +771,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardWithSameNameAsFolder, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardWithSameNameAsFolder, err)
|
||||
})
|
||||
|
||||
permissionScenario(t, "When updating existing dashboard to a folder using title", canSave,
|
||||
@ -786,7 +786,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
}
|
||||
|
||||
err := callSaveWithError(cmd, sc.sqlStore)
|
||||
assert.Equal(t, models.ErrDashboardFolderWithSameNameAsDashboard, err)
|
||||
assert.Equal(t, dashboards.ErrDashboardFolderWithSameNameAsDashboard, err)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -796,7 +796,7 @@ func TestIntegrationIntegratedDashboardService(t *testing.T) {
|
||||
type permissionScenarioContext struct {
|
||||
dashboardGuardianMock *guardian.FakeDashboardGuardian
|
||||
sqlStore *sqlstore.SQLStore
|
||||
dashboardStore dashbboardservice.Store
|
||||
dashboardStore dashboards.Store
|
||||
savedFolder *models.Dashboard
|
||||
savedDashInFolder *models.Dashboard
|
||||
otherSavedFolder *models.Dashboard
|
||||
@ -913,7 +913,7 @@ func saveTestDashboard(t *testing.T, title string, orgID, folderID int64, sqlSto
|
||||
}),
|
||||
}
|
||||
|
||||
dto := dashbboardservice.SaveDashboardDTO{
|
||||
dto := dashboards.SaveDashboardDTO{
|
||||
OrgId: orgID,
|
||||
Dashboard: cmd.GetDashboardModel(),
|
||||
User: &models.SignedInUser{
|
||||
@ -950,7 +950,7 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore *sqlstore.
|
||||
}),
|
||||
}
|
||||
|
||||
dto := dashbboardservice.SaveDashboardDTO{
|
||||
dto := dashboards.SaveDashboardDTO{
|
||||
OrgId: orgID,
|
||||
Dashboard: cmd.GetDashboardModel(),
|
||||
User: &models.SignedInUser{
|
||||
@ -975,10 +975,10 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore *sqlstore.
|
||||
return res
|
||||
}
|
||||
|
||||
func toSaveDashboardDto(cmd models.SaveDashboardCommand) dashbboardservice.SaveDashboardDTO {
|
||||
func toSaveDashboardDto(cmd models.SaveDashboardCommand) dashboards.SaveDashboardDTO {
|
||||
dash := (&cmd).GetDashboardModel()
|
||||
|
||||
return dashbboardservice.SaveDashboardDTO{
|
||||
return dashboards.SaveDashboardDTO{
|
||||
Dashboard: dash,
|
||||
Message: cmd.Message,
|
||||
OrgId: cmd.OrgId,
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
m "github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
@ -21,7 +21,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
t.Run("Dashboard service tests", func(t *testing.T) {
|
||||
fakeStore := m.FakeDashboardStore{}
|
||||
fakeStore := dashboards.FakeDashboardStore{}
|
||||
defer fakeStore.AssertExpectations(t)
|
||||
service := &DashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -34,7 +34,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
t.Run("Save dashboard validation", func(t *testing.T) {
|
||||
dto := &m.SaveDashboardDTO{}
|
||||
dto := &dashboards.SaveDashboardDTO{}
|
||||
|
||||
t.Run("When saving a dashboard with empty title it should return error", func(t *testing.T) {
|
||||
titles := []string{"", " ", " \t "}
|
||||
@ -42,7 +42,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
for _, title := range titles {
|
||||
dto.Dashboard = models.NewDashboard(title)
|
||||
_, err := service.SaveDashboard(context.Background(), dto, false)
|
||||
require.Equal(t, err, models.ErrDashboardTitleEmpty)
|
||||
require.Equal(t, err, dashboards.ErrDashboardTitleEmpty)
|
||||
}
|
||||
})
|
||||
|
||||
@ -50,13 +50,13 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
dto.Dashboard = models.NewDashboardFolder("Folder")
|
||||
dto.Dashboard.FolderId = 1
|
||||
_, err := service.SaveDashboard(context.Background(), dto, false)
|
||||
require.Equal(t, err, models.ErrDashboardFolderCannotHaveParent)
|
||||
require.Equal(t, err, dashboards.ErrDashboardFolderCannotHaveParent)
|
||||
})
|
||||
|
||||
t.Run("Should return validation error if folder is named General", func(t *testing.T) {
|
||||
dto.Dashboard = models.NewDashboardFolder("General")
|
||||
_, err := service.SaveDashboard(context.Background(), dto, false)
|
||||
require.Equal(t, err, models.ErrDashboardFolderNameExists)
|
||||
require.Equal(t, err, dashboards.ErrDashboardFolderNameExists)
|
||||
})
|
||||
|
||||
t.Run("When saving a dashboard should validate uid", func(t *testing.T) {
|
||||
@ -68,9 +68,9 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
{Uid: " ", Error: nil},
|
||||
{Uid: " \t ", Error: nil},
|
||||
{Uid: "asdf90_-", Error: nil},
|
||||
{Uid: "asdf/90", Error: models.ErrDashboardInvalidUid},
|
||||
{Uid: "asdf/90", Error: dashboards.ErrDashboardInvalidUid},
|
||||
{Uid: " asdfghjklqwertyuiopzxcvbnmasdfghjklqwer ", Error: nil},
|
||||
{Uid: "asdfghjklqwertyuiopzxcvbnmasdfghjklqwertyuiopzxcvbnmasdfghjklqwertyuiopzxcvbnm", Error: models.ErrDashboardUidTooLong},
|
||||
{Uid: "asdfghjklqwertyuiopzxcvbnmasdfghjklqwertyuiopzxcvbnmasdfghjklqwertyuiopzxcvbnm", Error: dashboards.ErrDashboardUidTooLong},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@ -94,7 +94,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
dto.Dashboard.SetId(3)
|
||||
dto.User = &models.SignedInUser{UserId: 1}
|
||||
_, err := service.SaveDashboard(context.Background(), dto, false)
|
||||
require.Equal(t, err, models.ErrDashboardCannotSaveProvisionedDashboard)
|
||||
require.Equal(t, err, dashboards.ErrDashboardCannotSaveProvisionedDashboard)
|
||||
})
|
||||
|
||||
t.Run("Should not return validation error if dashboard is provisioned but UI updates allowed", func(t *testing.T) {
|
||||
@ -123,7 +123,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Save provisioned dashboard validation", func(t *testing.T) {
|
||||
dto := &m.SaveDashboardDTO{}
|
||||
dto := &dashboards.SaveDashboardDTO{}
|
||||
|
||||
t.Run("Should not return validation error if dashboard is provisioned", func(t *testing.T) {
|
||||
fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once()
|
||||
@ -157,7 +157,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Import dashboard validation", func(t *testing.T) {
|
||||
dto := &m.SaveDashboardDTO{}
|
||||
dto := &dashboards.SaveDashboardDTO{}
|
||||
|
||||
t.Run("Should return validation error if dashboard is provisioned", func(t *testing.T) {
|
||||
fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once()
|
||||
@ -167,7 +167,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
dto.Dashboard.SetId(3)
|
||||
dto.User = &models.SignedInUser{UserId: 1}
|
||||
_, err := service.ImportDashboard(context.Background(), dto)
|
||||
require.Equal(t, err, models.ErrDashboardCannotSaveProvisionedDashboard)
|
||||
require.Equal(t, err, dashboards.ErrDashboardCannotSaveProvisionedDashboard)
|
||||
})
|
||||
})
|
||||
|
||||
@ -182,7 +182,7 @@ func TestIntegrationDashboardService(t *testing.T) {
|
||||
t.Run("DeleteDashboard should fail to delete it when provisioning information is missing", func(t *testing.T) {
|
||||
fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(&models.DashboardProvisioning{}, nil).Once()
|
||||
err := service.DeleteDashboard(context.Background(), 1, 1)
|
||||
require.Equal(t, err, models.ErrDashboardCannotDeleteProvisionedDashboard)
|
||||
require.Equal(t, err, dashboards.ErrDashboardCannotDeleteProvisionedDashboard)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -94,7 +94,7 @@ func (f *FolderServiceImpl) GetFolderByID(ctx context.Context, user *models.Sign
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, models.ErrFolderAccessDenied
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return dashFolder, nil
|
||||
@ -111,7 +111,7 @@ func (f *FolderServiceImpl) GetFolderByUID(ctx context.Context, user *models.Sig
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, models.ErrFolderAccessDenied
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return dashFolder, nil
|
||||
@ -128,7 +128,7 @@ func (f *FolderServiceImpl) GetFolderByTitle(ctx context.Context, user *models.S
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, models.ErrFolderAccessDenied
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return dashFolder, nil
|
||||
@ -140,7 +140,7 @@ func (f *FolderServiceImpl) CreateFolder(ctx context.Context, user *models.Signe
|
||||
|
||||
trimmedUID := strings.TrimSpace(uid)
|
||||
if trimmedUID == accesscontrol.GeneralFolderUID {
|
||||
return nil, models.ErrFolderInvalidUID
|
||||
return nil, dashboards.ErrFolderInvalidUID
|
||||
}
|
||||
|
||||
dashFolder.SetUid(trimmedUID)
|
||||
@ -201,7 +201,7 @@ func (f *FolderServiceImpl) UpdateFolder(ctx context.Context, user *models.Signe
|
||||
dashFolder := query.Result
|
||||
|
||||
if !dashFolder.IsFolder {
|
||||
return models.ErrFolderNotFound
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
|
||||
cmd.UpdateDashboardModel(dashFolder, orgID, user.UserId)
|
||||
@ -254,7 +254,7 @@ func (f *FolderServiceImpl) DeleteFolder(ctx context.Context, user *models.Signe
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, models.ErrFolderAccessDenied
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
deleteCmd := models.DeleteDashboardCommand{OrgId: orgID, Id: dashFolder.Id, ForceDeleteFolderRules: forceDeleteRules}
|
||||
@ -271,32 +271,32 @@ func (f *FolderServiceImpl) MakeUserAdmin(ctx context.Context, orgID int64, user
|
||||
}
|
||||
|
||||
func toFolderError(err error) error {
|
||||
if errors.Is(err, models.ErrDashboardTitleEmpty) {
|
||||
return models.ErrFolderTitleEmpty
|
||||
if errors.Is(err, dashboards.ErrDashboardTitleEmpty) {
|
||||
return dashboards.ErrFolderTitleEmpty
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrDashboardUpdateAccessDenied) {
|
||||
return models.ErrFolderAccessDenied
|
||||
if errors.Is(err, dashboards.ErrDashboardUpdateAccessDenied) {
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrDashboardWithSameNameInFolderExists) {
|
||||
return models.ErrFolderSameNameExists
|
||||
if errors.Is(err, dashboards.ErrDashboardWithSameNameInFolderExists) {
|
||||
return dashboards.ErrFolderSameNameExists
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrDashboardWithSameUIDExists) {
|
||||
return models.ErrFolderWithSameUIDExists
|
||||
if errors.Is(err, dashboards.ErrDashboardWithSameUIDExists) {
|
||||
return dashboards.ErrFolderWithSameUIDExists
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrDashboardVersionMismatch) {
|
||||
return models.ErrFolderVersionMismatch
|
||||
if errors.Is(err, dashboards.ErrDashboardVersionMismatch) {
|
||||
return dashboards.ErrFolderVersionMismatch
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrDashboardNotFound) {
|
||||
return models.ErrFolderNotFound
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrDashboardFailedGenerateUniqueUid) {
|
||||
err = models.ErrFolderFailedGenerateUniqueUid
|
||||
if errors.Is(err, dashboards.ErrDashboardFailedGenerateUniqueUid) {
|
||||
err = dashboards.ErrFolderFailedGenerateUniqueUid
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -77,7 +77,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
|
||||
t.Run("When get folder by id should return access denied error", func(t *testing.T) {
|
||||
_, err := service.GetFolderByID(context.Background(), user, folderId, orgID)
|
||||
require.Equal(t, err, models.ErrFolderAccessDenied)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When get folder by id, with id = 0 should return default folder", func(t *testing.T) {
|
||||
@ -88,13 +88,13 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
|
||||
t.Run("When get folder by uid should return access denied error", func(t *testing.T) {
|
||||
_, err := service.GetFolderByUID(context.Background(), user, orgID, folderUID)
|
||||
require.Equal(t, err, models.ErrFolderAccessDenied)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When creating folder should return access denied error", func(t *testing.T) {
|
||||
store.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Times(2)
|
||||
_, err := service.CreateFolder(context.Background(), user, orgID, folder.Title, folderUID)
|
||||
require.Equal(t, err, models.ErrFolderAccessDenied)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When updating folder should return access denied error", func(t *testing.T) {
|
||||
@ -107,13 +107,13 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
Uid: folderUID,
|
||||
Title: "Folder-TEST",
|
||||
})
|
||||
require.Equal(t, err, models.ErrFolderAccessDenied)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When deleting folder by uid should return access denied error", func(t *testing.T) {
|
||||
_, err := service.DeleteFolder(context.Background(), user, orgID, folderUID, false)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, err, models.ErrFolderAccessDenied)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Cleanup(func() {
|
||||
@ -144,7 +144,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
dash.Id = rand.Int63()
|
||||
|
||||
_, err := service.CreateFolder(context.Background(), user, orgID, dash.Title, "general")
|
||||
require.ErrorIs(t, err, models.ErrFolderInvalidUID)
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderInvalidUID)
|
||||
})
|
||||
|
||||
t.Run("When updating folder should not return access denied error", func(t *testing.T) {
|
||||
@ -238,14 +238,14 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
ActualError error
|
||||
ExpectedError error
|
||||
}{
|
||||
{ActualError: models.ErrDashboardTitleEmpty, ExpectedError: models.ErrFolderTitleEmpty},
|
||||
{ActualError: models.ErrDashboardUpdateAccessDenied, ExpectedError: models.ErrFolderAccessDenied},
|
||||
{ActualError: models.ErrDashboardWithSameNameInFolderExists, ExpectedError: models.ErrFolderSameNameExists},
|
||||
{ActualError: models.ErrDashboardWithSameUIDExists, ExpectedError: models.ErrFolderWithSameUIDExists},
|
||||
{ActualError: models.ErrDashboardVersionMismatch, ExpectedError: models.ErrFolderVersionMismatch},
|
||||
{ActualError: models.ErrDashboardNotFound, ExpectedError: models.ErrFolderNotFound},
|
||||
{ActualError: models.ErrDashboardFailedGenerateUniqueUid, ExpectedError: models.ErrFolderFailedGenerateUniqueUid},
|
||||
{ActualError: models.ErrDashboardInvalidUid, ExpectedError: models.ErrDashboardInvalidUid},
|
||||
{ActualError: dashboards.ErrDashboardTitleEmpty, ExpectedError: dashboards.ErrFolderTitleEmpty},
|
||||
{ActualError: dashboards.ErrDashboardUpdateAccessDenied, ExpectedError: dashboards.ErrFolderAccessDenied},
|
||||
{ActualError: dashboards.ErrDashboardWithSameNameInFolderExists, ExpectedError: dashboards.ErrFolderSameNameExists},
|
||||
{ActualError: dashboards.ErrDashboardWithSameUIDExists, ExpectedError: dashboards.ErrFolderWithSameUIDExists},
|
||||
{ActualError: dashboards.ErrDashboardVersionMismatch, ExpectedError: dashboards.ErrFolderVersionMismatch},
|
||||
{ActualError: dashboards.ErrDashboardNotFound, ExpectedError: dashboards.ErrFolderNotFound},
|
||||
{ActualError: dashboards.ErrDashboardFailedGenerateUniqueUid, ExpectedError: dashboards.ErrFolderFailedGenerateUniqueUid},
|
||||
{ActualError: dashboards.ErrDashboardInvalidUid, ExpectedError: dashboards.ErrDashboardInvalidUid},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
@ -91,7 +91,7 @@ func (d *DashboardSnapshotStore) GetDashboardSnapshot(ctx context.Context, query
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return models.ErrDashboardSnapshotNotFound
|
||||
return dashboardsnapshots.ErrDashboardSnapshotNotFound
|
||||
}
|
||||
|
||||
query.Result = &snapshot
|
||||
|
8
pkg/services/dashboardsnapshots/errors.go
Normal file
8
pkg/services/dashboardsnapshots/errors.go
Normal file
@ -0,0 +1,8 @@
|
||||
package dashboardsnapshots
|
||||
|
||||
import "github.com/grafana/grafana/pkg/services/dashboards"
|
||||
|
||||
var ErrDashboardSnapshotNotFound = dashboards.DashboardErr{
|
||||
Reason: "Dashboard snapshot not found",
|
||||
StatusCode: 404,
|
||||
}
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -134,7 +135,7 @@ func getDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, dashboard *models.D
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
dashboard.SetId(dashboard.Id)
|
||||
@ -188,7 +189,7 @@ func insertTestDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, title string
|
||||
if affectedRows, err := sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -250,7 +251,7 @@ func updateTestDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, dashboard *m
|
||||
if affectedRows, err := sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
@ -173,11 +174,11 @@ func toLibraryElementError(err error, message string) response.Response {
|
||||
if errors.Is(err, errLibraryElementVersionMismatch) {
|
||||
return response.Error(412, errLibraryElementVersionMismatch.Error(), err)
|
||||
}
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
return response.Error(404, models.ErrFolderNotFound.Error(), err)
|
||||
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||
return response.Error(404, dashboards.ErrFolderNotFound.Error(), err)
|
||||
}
|
||||
if errors.Is(err, models.ErrFolderAccessDenied) {
|
||||
return response.Error(403, models.ErrFolderAccessDenied.Error(), err)
|
||||
if errors.Is(err, dashboards.ErrFolderAccessDenied) {
|
||||
return response.Error(403, dashboards.ErrFolderAccessDenied.Error(), err)
|
||||
}
|
||||
if errors.Is(err, errLibraryElementHasConnections) {
|
||||
return response.Error(403, errLibraryElementHasConnections.Error(), err)
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
@ -707,7 +708,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c context.Conte
|
||||
}
|
||||
|
||||
if len(folderUIDs) == 0 {
|
||||
return models.ErrFolderNotFound
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
|
||||
if len(folderUIDs) != 1 {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
)
|
||||
|
||||
@ -29,7 +30,7 @@ func (l *LibraryElementService) requireEditPermissionsOnFolder(ctx context.Conte
|
||||
}
|
||||
|
||||
if isGeneralFolder(folderID) && user.HasRole(models.ROLE_VIEWER) {
|
||||
return models.ErrFolderAccessDenied
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
folder, err := l.folderService.GetFolderByID(ctx, user, folderID, user.OrgId)
|
||||
if err != nil {
|
||||
@ -43,7 +44,7 @@ func (l *LibraryElementService) requireEditPermissionsOnFolder(ctx context.Conte
|
||||
return err
|
||||
}
|
||||
if !canEdit {
|
||||
return models.ErrFolderAccessDenied
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -66,7 +67,7 @@ func (l *LibraryElementService) requireViewPermissionsOnFolder(ctx context.Conte
|
||||
return err
|
||||
}
|
||||
if !canView {
|
||||
return models.ErrFolderAccessDenied
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -80,7 +81,7 @@ func (l *LibraryElementService) requireEditPermissionsOnDashboard(ctx context.Co
|
||||
return err
|
||||
}
|
||||
if !canEdit {
|
||||
return models.ErrDashboardUpdateAccessDenied
|
||||
return dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -77,7 +77,7 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to delete a folder uid that doesn't exist, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
err := sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.Uid+"xxxx")
|
||||
require.EqualError(t, err, models.ErrFolderNotFound.Error())
|
||||
require.EqualError(t, err, dashboards.ErrFolderNotFound.Error())
|
||||
})
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to delete a folder that contains disconnected elements, it should delete all disconnected elements too",
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@ -495,7 +496,7 @@ func toNamespaceErrorResponse(err error) response.Response {
|
||||
if errors.Is(err, ngmodels.ErrCannotEditNamespace) {
|
||||
return ErrResp(http.StatusForbidden, err, err.Error())
|
||||
}
|
||||
if errors.Is(err, models.ErrDashboardIdentifierNotSet) {
|
||||
if errors.Is(err, dashboards.ErrDashboardIdentifierNotSet) {
|
||||
return ErrResp(http.StatusBadRequest, err, err.Error())
|
||||
}
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/imguploader"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@ -111,7 +110,7 @@ func (s *ScreenshotImageService) NewImage(ctx context.Context, r *ngmodels.Alert
|
||||
if err != nil {
|
||||
// TODO: Check for screenshot upload failures. These images should still be
|
||||
// stored because we have a local disk path that could be useful.
|
||||
if errors.Is(err, models.ErrDashboardNotFound) {
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return nil, ErrNoDashboard
|
||||
}
|
||||
return nil, err
|
||||
|
@ -302,12 +302,12 @@ func (fr *FileReader) getOrCreateFolderID(ctx context.Context, cfg *config, serv
|
||||
cmd := &models.GetDashboardQuery{Slug: models.SlugifyTitle(folderName), OrgId: cfg.OrgID}
|
||||
err := fr.dashboardStore.GetDashboard(ctx, cmd)
|
||||
|
||||
if err != nil && !errors.Is(err, models.ErrDashboardNotFound) {
|
||||
if err != nil && !errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// dashboard folder not found. create one.
|
||||
if errors.Is(err, models.ErrDashboardNotFound) {
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
dash := &dashboards.SaveDashboardDTO{}
|
||||
dash.Dashboard = models.NewDashboardFolder(folderName)
|
||||
dash.Dashboard.IsFolder = true
|
||||
@ -315,7 +315,7 @@ func (fr *FileReader) getOrCreateFolderID(ctx context.Context, cfg *config, serv
|
||||
dash.OrgId = cfg.OrgID
|
||||
// set dashboard folderUid if given
|
||||
if cfg.FolderUID == accesscontrol.GeneralFolderUID {
|
||||
return 0, models.ErrFolderInvalidUID
|
||||
return 0, dashboards.ErrFolderInvalidUID
|
||||
}
|
||||
dash.Dashboard.SetUid(cfg.FolderUID)
|
||||
dbDash, err := service.SaveFolderForProvisionedDashboards(ctx, dash)
|
||||
|
@ -8,13 +8,14 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -405,7 +406,7 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = r.getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
|
||||
require.ErrorIs(t, err, models.ErrFolderInvalidUID)
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderInvalidUID)
|
||||
})
|
||||
|
||||
t.Run("Walking the folder with dashboards", func(t *testing.T) {
|
||||
@ -513,5 +514,5 @@ func (ffi FakeFileInfo) Sys() interface{} {
|
||||
type fakeDashboardStore struct{}
|
||||
|
||||
func (fds *fakeDashboardStore) GetDashboard(_ context.Context, _ *models.GetDashboardQuery) error {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func createDashboardJSON(data *simplejson.Json, lastModified time.Time, cfg *con
|
||||
dash.Dashboard.FolderId = folderID
|
||||
|
||||
if dash.Dashboard.Title == "" {
|
||||
return nil, models.ErrDashboardTitleEmpty
|
||||
return nil, dashboards.ErrDashboardTitleEmpty
|
||||
}
|
||||
|
||||
return dash, nil
|
||||
|
@ -79,7 +79,7 @@ func TestBrowserScreenshotService(t *testing.T) {
|
||||
s := NewBrowserScreenshotService(&d, r)
|
||||
|
||||
// a non-existent dashboard should return error
|
||||
d.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Return(models.ErrDashboardNotFound).Once()
|
||||
d.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Return(dashboards.ErrDashboardNotFound).Once()
|
||||
ctx := context.Background()
|
||||
opts := ScreenshotOptions{}
|
||||
screenshot, err := s.Take(ctx, opts)
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
)
|
||||
|
||||
func (ss *SQLStore) GetThumbnail(ctx context.Context, query *models.GetDashboardThumbnailCommand) (*models.DashboardThumbnail, error) {
|
||||
@ -25,7 +26,7 @@ func (ss *SQLStore) SaveThumbnail(ctx context.Context, cmd *models.SaveDashboard
|
||||
err := ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
existing, err := findThumbnailByMeta(sess, cmd.DashboardThumbnailMeta)
|
||||
|
||||
if err != nil && !errors.Is(err, models.ErrDashboardThumbnailNotFound) {
|
||||
if err != nil && !errors.Is(err, dashboards.ErrDashboardThumbnailNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -150,7 +151,7 @@ func findThumbnailByMeta(sess *DBSession, meta models.DashboardThumbnailMeta) (*
|
||||
exists, err := sess.Get(result)
|
||||
|
||||
if !exists {
|
||||
return nil, models.ErrDashboardThumbnailNotFound
|
||||
return nil, dashboards.ErrDashboardThumbnailNotFound
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -174,7 +175,7 @@ func findDashboardIdByThumbMeta(sess *DBSession, meta models.DashboardThumbnailM
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, models.ErrDashboardNotFound
|
||||
return nil, dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
return result, err
|
||||
|
@ -5,11 +5,13 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var theme = models.ThemeDark
|
||||
@ -313,7 +315,7 @@ func updateTestDashboard(t *testing.T, sqlStore *SQLStore, dashboard *models.Das
|
||||
if affectedRows, err := sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"xorm.io/xorm"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -151,7 +152,7 @@ func (m *folderHelper) generateNewDashboardUid(orgId int64) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return "", models.ErrDashboardFailedGenerateUniqueUid
|
||||
return "", dashboards.ErrDashboardFailedGenerateUniqueUid
|
||||
}
|
||||
|
||||
// based on SQLStore.UpdateDashboardACL()
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -461,7 +462,7 @@ func insertTestDashboard(t *testing.T, sqlStore *SQLStore, title string, orgId i
|
||||
if affectedRows, err := sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return models.ErrDashboardNotFound
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -222,7 +222,7 @@ func (hs *thumbService) GetImage(c *models.ReqContext) {
|
||||
Kind: models.ThumbnailKindDefault,
|
||||
})
|
||||
|
||||
if errors.Is(err, models.ErrDashboardThumbnailNotFound) {
|
||||
if errors.Is(err, dashboards.ErrDashboardThumbnailNotFound) {
|
||||
c.Resp.WriteHeader(404)
|
||||
return
|
||||
}
|
||||
|
@ -12,15 +12,17 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboardimport"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/tests/testinfra"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDashboardQuota(t *testing.T) {
|
||||
@ -173,19 +175,19 @@ providers:
|
||||
desc: "when updating provisioned dashboard using ID it should fail",
|
||||
dashboardData: fmt.Sprintf(`{"title":"just testing", "id": %d, "version": 1}`, dashboardID),
|
||||
expStatus: http.StatusBadRequest,
|
||||
expErrReason: models.ErrDashboardCannotSaveProvisionedDashboard.Reason,
|
||||
expErrReason: dashboards.ErrDashboardCannotSaveProvisionedDashboard.Reason,
|
||||
},
|
||||
{
|
||||
desc: "when updating provisioned dashboard using UID it should fail",
|
||||
dashboardData: fmt.Sprintf(`{"title":"just testing", "uid": %q, "version": 1}`, dashboardUID),
|
||||
expStatus: http.StatusBadRequest,
|
||||
expErrReason: models.ErrDashboardCannotSaveProvisionedDashboard.Reason,
|
||||
expErrReason: dashboards.ErrDashboardCannotSaveProvisionedDashboard.Reason,
|
||||
},
|
||||
{
|
||||
desc: "when updating dashboard using unknown ID, it should fail",
|
||||
dashboardData: `{"title":"just testing", "id": 42, "version": 1}`,
|
||||
expStatus: http.StatusNotFound,
|
||||
expErrReason: models.ErrDashboardNotFound.Reason,
|
||||
expErrReason: dashboards.ErrDashboardNotFound.Reason,
|
||||
},
|
||||
{
|
||||
desc: "when updating dashboard using unknown UID, it should succeed",
|
||||
@ -247,7 +249,7 @@ providers:
|
||||
dashboardErr := &errorResponseBody{}
|
||||
err = json.Unmarshal(b, dashboardErr)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, models.ErrDashboardCannotDeleteProvisionedDashboard.Reason, dashboardErr.Message)
|
||||
assert.Equal(t, dashboards.ErrDashboardCannotDeleteProvisionedDashboard.Reason, dashboardErr.Message)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user