publicdashboards: split create/update api paths (#57940)

This PR splits the create and update paths for public dashboards and includes assorted refactors toward a proper REST API. Additionally, we removed the concept of a "public dashboard config" in favor of "public dashboard" 

Co-authored-by: juanicabanas <juan.cabanas@grafana.com>
Co-authored-by: Ezequiel Victorero <ezequiel.victorero@grafana.com>
This commit is contained in:
Jeff Levin
2022-11-03 11:30:12 -08:00
committed by GitHub
co-authored by juanicabanas Ezequiel Victorero
parent 0367f61bb3
commit 6fcc5b42c0
24 changed files with 996 additions and 612 deletions
+72 -24
View File
@@ -15,8 +15,8 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/publicdashboards"
"github.com/grafana/grafana/pkg/services/publicdashboards/internal/tokens"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web"
)
@@ -73,10 +73,15 @@ func (api *Api) RegisterAPIEndpoints() {
auth(middleware.ReqSignedIn, accesscontrol.EvalPermission(dashboards.ActionDashboardsRead, uidScope)),
routing.Wrap(api.GetPublicDashboard))
// Create/Update Public Dashboard
// Create Public Dashboard
api.RouteRegister.Post("/api/dashboards/uid/:dashboardUid/public-dashboards",
auth(middleware.ReqOrgAdmin, accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)),
routing.Wrap(api.SavePublicDashboard))
routing.Wrap(api.CreatePublicDashboard))
// Update Public Dashboard
api.RouteRegister.Put("/api/dashboards/uid/:dashboardUid/public-dashboards/:uid",
auth(middleware.ReqOrgAdmin, accesscontrol.EvalPermission(dashboards.ActionDashboardsPublicWrite, uidScope)),
routing.Wrap(api.UpdatePublicDashboard))
// Delete Public dashboard
api.RouteRegister.Delete("/api/dashboards/uid/:dashboardUid/public-dashboards/:uid",
@@ -94,59 +99,103 @@ func (api *Api) ListPublicDashboards(c *models.ReqContext) response.Response {
return response.JSON(http.StatusOK, resp)
}
// GetPublicDashboard Gets public dashboard configuration for dashboard
// GET /api/dashboards/uid/:uid/public-config
// GetPublicDashboard Gets public dashboard for dashboard
// GET /api/dashboards/uid/:uid/public-dashboards
func (api *Api) GetPublicDashboard(c *models.ReqContext) response.Response {
// exit if we don't have a valid dashboardUid
dashboardUid := web.Params(c.Req)[":dashboardUid"]
if dashboardUid == "" || !util.IsValidShortUID(dashboardUid) {
if !tokens.IsValidShortUID(dashboardUid) {
api.handleError(c.Req.Context(), http.StatusBadRequest, "GetPublicDashboard: no valid dashboardUid", dashboards.ErrDashboardIdentifierNotSet)
}
pdc, err := api.PublicDashboardService.FindByDashboardUid(c.Req.Context(), c.OrgID, web.Params(c.Req)[":dashboardUid"])
pd, err := api.PublicDashboardService.FindByDashboardUid(c.Req.Context(), c.OrgID, web.Params(c.Req)[":dashboardUid"])
if err != nil {
return api.handleError(c.Req.Context(), http.StatusInternalServerError, "GetPublicDashboardConfig: failed to get public dashboard config", err)
return api.handleError(c.Req.Context(), http.StatusInternalServerError, "GetPublicDashboard: failed to get public dashboard ", err)
}
return response.JSON(http.StatusOK, pdc)
if pd == nil {
return api.handleError(c.Req.Context(), http.StatusNotFound, "GetPublicDashboard: public dashboard not found", ErrPublicDashboardNotFound)
}
return response.JSON(http.StatusOK, pd)
}
// SavePublicDashboard Sets public dashboard configuration for dashboard
// POST /api/dashboards/uid/:uid/public-config
func (api *Api) SavePublicDashboard(c *models.ReqContext) response.Response {
// CreatePublicDashboard Sets public dashboard for dashboard
// POST /api/dashboards/uid/:uid/public-dashboards
func (api *Api) CreatePublicDashboard(c *models.ReqContext) response.Response {
// exit if we don't have a valid dashboardUid
dashboardUid := web.Params(c.Req)[":dashboardUid"]
if dashboardUid == "" || !util.IsValidShortUID(dashboardUid) {
api.handleError(c.Req.Context(), http.StatusBadRequest, "SavePublicDashboard: invalid dashboardUid", dashboards.ErrDashboardIdentifierNotSet)
if !tokens.IsValidShortUID(dashboardUid) {
return api.handleError(c.Req.Context(), http.StatusBadRequest, "CreatePublicDashboard: invalid dashboardUid", dashboards.ErrDashboardIdentifierInvalid)
}
pubdash := &PublicDashboard{}
if err := web.Bind(c.Req, pubdash); err != nil {
return response.Error(http.StatusBadRequest, "SavePublicDashboard: bad request data", err)
pd := &PublicDashboard{}
if err := web.Bind(c.Req, pd); err != nil {
return api.handleError(c.Req.Context(), http.StatusBadRequest, "CreatePublicDashboard: bad request data", err)
}
// Always set the orgID and userID from the session
pubdash.OrgId = c.OrgID
pd.OrgId = c.OrgID
dto := SavePublicDashboardDTO{
UserId: c.UserID,
OrgId: c.OrgID,
DashboardUid: dashboardUid,
PublicDashboard: pubdash,
PublicDashboard: pd,
}
//Create the public dashboard
pd, err := api.PublicDashboardService.Create(c.Req.Context(), c.SignedInUser, &dto)
if err != nil {
return api.handleError(c.Req.Context(), http.StatusInternalServerError, "CreatePublicDashboard: failed to create public dashboard", err)
}
return response.JSON(http.StatusOK, pd)
}
// UpdatePublicDashboard Sets public dashboard for dashboard
// PUT /api/dashboards/uid/:uid/public-dashboards
func (api *Api) UpdatePublicDashboard(c *models.ReqContext) response.Response {
// exit if we don't have a valid dashboardUid
dashboardUid := web.Params(c.Req)[":dashboardUid"]
if !tokens.IsValidShortUID(dashboardUid) {
return api.handleError(c.Req.Context(), http.StatusBadRequest, "UpdatePublicDashboard: invalid dashboardUid", dashboards.ErrDashboardIdentifierInvalid)
}
uid := web.Params(c.Req)[":uid"]
if !tokens.IsValidShortUID(uid) {
return api.handleError(c.Req.Context(), http.StatusBadRequest, "UpdatePublicDashboard: invalid public dashboard uid", ErrPublicDashboardIdentifierNotSet)
}
pd := &PublicDashboard{}
if err := web.Bind(c.Req, pd); err != nil {
return api.handleError(c.Req.Context(), http.StatusBadRequest, "UpdatePublicDashboard: bad request data", err)
}
// Always set the orgID and userID from the session
pd.OrgId = c.OrgID
pd.Uid = uid
dto := SavePublicDashboardDTO{
UserId: c.UserID,
OrgId: c.OrgID,
DashboardUid: dashboardUid,
PublicDashboard: pd,
}
// Save the public dashboard
pubdash, err := api.PublicDashboardService.Save(c.Req.Context(), c.SignedInUser, &dto)
pd, err := api.PublicDashboardService.Update(c.Req.Context(), c.SignedInUser, &dto)
if err != nil {
return api.handleError(c.Req.Context(), http.StatusInternalServerError, "SavePublicDashboardConfig: failed to save public dashboard configuration", err)
return api.handleError(c.Req.Context(), http.StatusInternalServerError, "UpdatePublicDashboard: failed to update public dashboard", err)
}
return response.JSON(http.StatusOK, pubdash)
return response.JSON(http.StatusOK, pd)
}
// Delete a public dashboard
// DELETE /api/dashboards/uid/:dashboardUid/public-dashboards/:uid
func (api *Api) DeletePublicDashboard(c *models.ReqContext) response.Response {
uid := web.Params(c.Req)[":uid"]
if uid == "" || !util.IsValidShortUID(uid) {
if !tokens.IsValidShortUID(uid) {
return api.handleError(c.Req.Context(), http.StatusBadRequest, "DeletePublicDashboard: invalid dashboard uid", dashboards.ErrDashboardIdentifierNotSet)
}
@@ -171,7 +220,6 @@ func (api *Api) handleError(ctx context.Context, code int, message string, err e
return response.Error(publicDashboardErr.StatusCode, publicDashboardErr.Error(), publicDashboardErr)
}
// handle dashboard errors as well
var dashboardErr dashboards.DashboardErr
if ok := errors.As(err, &dashboardErr); ok {
return response.Error(dashboardErr.StatusCode, dashboardErr.Error(), dashboardErr)