mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PublicDashboards: Accept AccessToken for pubdash creation (#74134)
* Add Access token input * add unit tests to access token * if else logic to not call find on empty string * update var naming
This commit is contained in:
parent
b8dd081d8a
commit
8833f360ec
@ -155,6 +155,12 @@ func (api *Api) CreatePublicDashboard(c *contextmodel.ReqContext) response.Respo
|
||||
return response.Err(ErrInvalidUid.Errorf("CreatePublicDashboard: invalid Uid %s", uid))
|
||||
}
|
||||
|
||||
//validate accessToken
|
||||
accessToken := pdDTO.AccessToken
|
||||
if accessToken != "" && !validation.IsValidAccessToken(accessToken) {
|
||||
return response.Err(ErrInvalidAccessToken.Errorf("CreatePublicDashboard: invalid Access Token %s", accessToken))
|
||||
}
|
||||
|
||||
// Always set the orgID and userID from the session
|
||||
dto := &SavePublicDashboardDTO{
|
||||
UserId: c.UserID,
|
||||
|
@ -448,6 +448,24 @@ func TestApiCreatePublicDashboard(t *testing.T) {
|
||||
ShouldCallService: true,
|
||||
JsonBody: `{ "uid": "123abc", "isEnabled": true}`,
|
||||
},
|
||||
{
|
||||
Name: "returns 400 when access token is invalid",
|
||||
ExpectedHttpResponse: http.StatusBadRequest,
|
||||
publicDashboard: nil,
|
||||
SaveDashboardErr: nil,
|
||||
User: userAdmin,
|
||||
ShouldCallService: false,
|
||||
JsonBody: `{ "AccessToken": "123abc", "isEnabled": true }`,
|
||||
},
|
||||
{
|
||||
Name: "returns 200 when access token is valid",
|
||||
ExpectedHttpResponse: http.StatusOK,
|
||||
publicDashboard: &PublicDashboard{IsEnabled: true},
|
||||
SaveDashboardErr: nil,
|
||||
User: userAdmin,
|
||||
ShouldCallService: true,
|
||||
JsonBody: `{ "accessToken": "d64457c699644079b50230cfefddb211", "isEnabled": true}`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
@ -21,7 +21,8 @@ var (
|
||||
ErrInvalidTimeRange = errutil.BadRequest("publicdashboards.invalidTimeRange", errutil.WithPublicMessage("Invalid time range"))
|
||||
ErrInvalidShareType = errutil.BadRequest("publicdashboards.invalidShareType", errutil.WithPublicMessage("Invalid share type"))
|
||||
ErrDashboardIsPublic = errutil.BadRequest("publicdashboards.dashboardIsPublic", errutil.WithPublicMessage("Dashboard is already public"))
|
||||
ErrPublicDashboardUidExists = errutil.BadRequest("publicdashboards.uidExists", errutil.WithPublicMessage("Public Dashboard Uid exists"))
|
||||
ErrPublicDashboardUidExists = errutil.BadRequest("publicdashboards.uidExists", errutil.WithPublicMessage("Public Dashboard Uid already exists"))
|
||||
ErrPublicDashboardAccessTokenExists = errutil.BadRequest("publicdashboards.accessTokenExists", errutil.WithPublicMessage("Public Dashboard Access Token already exists"))
|
||||
|
||||
ErrPublicDashboardNotEnabled = errutil.Forbidden("publicdashboards.notEnabled", errutil.WithPublicMessage("Public dashboard paused"))
|
||||
)
|
||||
|
@ -57,6 +57,7 @@ type PublicDashboard struct {
|
||||
|
||||
type PublicDashboardDTO struct {
|
||||
Uid string `json:"uid"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
TimeSelectionEnabled *bool `json:"timeSelectionEnabled"`
|
||||
IsEnabled *bool `json:"isEnabled"`
|
||||
AnnotationsEnabled *bool `json:"annotationsEnabled"`
|
||||
|
@ -429,23 +429,33 @@ func GenerateAccessToken() (string, error) {
|
||||
|
||||
func (pd *PublicDashboardServiceImpl) newCreatePublicDashboard(ctx context.Context, dto *SavePublicDashboardDTO) (*PublicDashboard, error) {
|
||||
//Check if uid already exists, if none then auto generate
|
||||
existingPubdash, _ := pd.store.Find(ctx, dto.PublicDashboard.Uid)
|
||||
if existingPubdash != nil {
|
||||
return nil, ErrPublicDashboardUidExists.Errorf("Create: public dashboard uid %s already exists", dto.PublicDashboard.Uid)
|
||||
}
|
||||
|
||||
var err error
|
||||
uid := dto.PublicDashboard.Uid
|
||||
if dto.PublicDashboard.Uid == "" {
|
||||
|
||||
if uid != "" {
|
||||
existingPubdash, _ := pd.store.Find(ctx, uid)
|
||||
if existingPubdash != nil {
|
||||
return nil, ErrPublicDashboardUidExists.Errorf("Create: public dashboard uid %s already exists", uid)
|
||||
}
|
||||
} else {
|
||||
uid, err = pd.NewPublicDashboardUid(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
accessToken, err := pd.NewPublicDashboardAccessToken(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
//Check if accessToken already exists, if none then auto generate
|
||||
accessToken := dto.PublicDashboard.AccessToken
|
||||
if accessToken != "" {
|
||||
existingPubdash, _ := pd.store.FindByAccessToken(ctx, accessToken)
|
||||
if existingPubdash != nil {
|
||||
return nil, ErrPublicDashboardAccessTokenExists.Errorf("Create: public dashboard access token %s already exists", accessToken)
|
||||
}
|
||||
} else {
|
||||
accessToken, err = pd.NewPublicDashboardAccessToken(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
isEnabled := returnValueOrDefault(dto.PublicDashboard.IsEnabled, false)
|
||||
|
@ -856,9 +856,11 @@ func TestCreatePublicDashboard(t *testing.T) {
|
||||
assert.Equal(t, dto.PublicDashboard.Uid, pubdash.Uid)
|
||||
})
|
||||
|
||||
t.Run("Throws an error when pubdash with generated access token already exists", func(t *testing.T) {
|
||||
t.Run("Throws an error when pubdash with given access token input already exists", func(t *testing.T) {
|
||||
dashboard := dashboards.NewDashboard("testDashie")
|
||||
pubdash := &PublicDashboard{
|
||||
Uid: "ExistingUid",
|
||||
AccessToken: "ExistingAccessToken",
|
||||
IsEnabled: true,
|
||||
AnnotationsEnabled: false,
|
||||
DashboardUid: "NOTTHESAME",
|
||||
@ -869,7 +871,7 @@ func TestCreatePublicDashboard(t *testing.T) {
|
||||
publicDashboardStore := &FakePublicDashboardStore{}
|
||||
publicDashboardStore.On("FindDashboard", mock.Anything, mock.Anything, mock.Anything).Return(dashboard, nil)
|
||||
publicDashboardStore.On("Find", mock.Anything, mock.Anything).Return(nil, nil)
|
||||
publicDashboardStore.On("FindByAccessToken", mock.Anything, mock.Anything).Return(pubdash, nil)
|
||||
publicDashboardStore.On("FindByAccessToken", mock.Anything, "ExistingAccessToken").Return(pubdash, nil)
|
||||
publicDashboardStore.On("FindByDashboardUid", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrPublicDashboardNotFound.Errorf(""))
|
||||
|
||||
serviceWrapper := ProvideServiceWrapper(publicDashboardStore)
|
||||
@ -886,14 +888,76 @@ func TestCreatePublicDashboard(t *testing.T) {
|
||||
OrgID: dashboard.OrgID,
|
||||
UserId: 7,
|
||||
PublicDashboard: &PublicDashboardDTO{
|
||||
IsEnabled: &isEnabled,
|
||||
AccessToken: "ExistingAccessToken",
|
||||
IsEnabled: &isEnabled,
|
||||
},
|
||||
}
|
||||
|
||||
_, err := service.Create(context.Background(), SignedInUser, dto)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, err, ErrPublicDashboardAccessTokenExists.Errorf("Create: public dashboard access token %s already exists", dto.PublicDashboard.AccessToken))
|
||||
})
|
||||
|
||||
t.Run("Create public dashboard with given pubdash access token", func(t *testing.T) {
|
||||
sqlStore := db.InitTestDB(t)
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
publicdashboardStore := database.ProvideStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures())
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{}, nil)
|
||||
serviceWrapper := ProvideServiceWrapper(publicdashboardStore)
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
store: publicdashboardStore,
|
||||
serviceWrapper: serviceWrapper,
|
||||
}
|
||||
|
||||
isEnabled := true
|
||||
|
||||
dto := &SavePublicDashboardDTO{
|
||||
DashboardUid: dashboard.UID,
|
||||
UserId: 7,
|
||||
OrgID: dashboard.OrgID,
|
||||
PublicDashboard: &PublicDashboardDTO{
|
||||
AccessToken: "GivenAccessToken",
|
||||
IsEnabled: &isEnabled,
|
||||
},
|
||||
}
|
||||
|
||||
_, err = service.Create(context.Background(), SignedInUser, dto)
|
||||
require.NoError(t, err)
|
||||
|
||||
pubdash, err := service.FindByDashboardUid(context.Background(), dashboard.OrgID, dashboard.UID)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, dto.PublicDashboard.AccessToken, pubdash.AccessToken)
|
||||
})
|
||||
|
||||
t.Run("Throws an error when pubdash with generated access token already exists", func(t *testing.T) {
|
||||
dashboard := dashboards.NewDashboard("testDashie")
|
||||
pubdash := &PublicDashboard{
|
||||
IsEnabled: true,
|
||||
AnnotationsEnabled: false,
|
||||
DashboardUid: "NOTTHESAME",
|
||||
OrgId: dashboard.OrgID,
|
||||
TimeSettings: timeSettings,
|
||||
}
|
||||
|
||||
publicDashboardStore := &FakePublicDashboardStore{}
|
||||
publicDashboardStore.On("FindByAccessToken", mock.Anything, mock.Anything).Return(pubdash, nil)
|
||||
|
||||
serviceWrapper := ProvideServiceWrapper(publicDashboardStore)
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
store: publicDashboardStore,
|
||||
serviceWrapper: serviceWrapper,
|
||||
}
|
||||
|
||||
_, err := service.NewPublicDashboardAccessToken(context.Background())
|
||||
require.Error(t, err)
|
||||
require.Equal(t, err, ErrInternalServerError.Errorf("failed to generate a unique accessToken for public dashboard"))
|
||||
publicDashboardStore.AssertNotCalled(t, "Create")
|
||||
})
|
||||
|
||||
t.Run("Returns error if public dashboard exists", func(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user