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:
Lucy Chen 2023-09-01 10:21:54 -04:00 committed by GitHub
parent b8dd081d8a
commit 8833f360ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 114 additions and 14 deletions

View File

@ -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,

View File

@ -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 {

View File

@ -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"))
)

View File

@ -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"`

View File

@ -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)

View File

@ -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) {