package api import ( "net/http" "time" "github.com/grafana/grafana-app-sdk/logging" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/services/apiserver" "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/star" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/web" ) type API struct { starService star.Service client K8sClients } func ProvideApi( cfg *setting.Cfg, // for namespacer features featuremgmt.FeatureToggles, starService star.Service, configProvider apiserver.DirectRestConfigProvider, ) *API { //nolint:staticcheck // not yet migrated to OpenFeature if features.IsEnabledGlobally(featuremgmt.FlagKubernetesStars) { starService = nil // don't use it } return &API{ starService: starService, client: &k8sClients{ namespacer: request.GetNamespaceMapper(cfg), configProvider: configProvider, }, } } func (api *API) GetStars(c *contextmodel.ReqContext) response.Response { if api.starService == nil { stars, err := api.client.GetStars(c) if err != nil { logging.FromContext(c.Req.Context()).With("logger", "star.api").Warn("error", "err", err) } return response.JSON(http.StatusOK, stars) } query := star.GetUserStarsQuery{ UserID: c.UserID, } iuserstars, err := api.starService.GetByUser(c.Req.Context(), &query) if err != nil { return response.Error(http.StatusInternalServerError, "Failed to get user stars", err) } uids := []string{} for uid := range iuserstars.UserStars { uids = append(uids, uid) } return response.JSON(http.StatusOK, uids) } // swagger:route POST /user/stars/dashboard/uid/{dashboard_uid} signed_in_user starDashboardByUID // // Star a dashboard. // // Stars the given Dashboard for the actual user. // // Responses: // 200: okResponse // 400: badRequestError // 401: unauthorisedError // 403: forbiddenError // 500: internalServerError func (api *API) StarDashboardByUID(c *contextmodel.ReqContext) response.Response { uid := web.Params(c.Req)[":uid"] if uid == "" { return response.Error(http.StatusBadRequest, "Invalid dashboard UID", nil) } if api.starService == nil { err := api.client.AddStar(c, uid) if err != nil { return response.Error(http.StatusInternalServerError, "Failed to star dashboard", err) } return response.Success("Dashboard starred!") } userID, err := identity.UserIdentifier(c.GetID()) if err != nil { return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil) } dashboardID, rsp := api.client.GetDashboardID(c, uid) if rsp != nil { return rsp } cmd := star.StarDashboardCommand{UserID: userID, DashboardID: dashboardID, DashboardUID: uid, OrgID: c.GetOrgID(), Updated: time.Now()} if err := api.starService.Add(c.Req.Context(), &cmd); err != nil { return response.Error(http.StatusInternalServerError, "Failed to star dashboard", err) } return response.Success("Dashboard starred!") } // swagger:route DELETE /user/stars/dashboard/uid/{dashboard_uid} signed_in_user unstarDashboardByUID // // Unstar a dashboard. // // Deletes the starring of the given Dashboard for the actual user. // // Responses: // 200: okResponse // 400: badRequestError // 401: unauthorisedError // 403: forbiddenError // 500: internalServerError func (api *API) UnstarDashboardByUID(c *contextmodel.ReqContext) response.Response { uid := web.Params(c.Req)[":uid"] if uid == "" { return response.Error(http.StatusBadRequest, "Invalid dashboard UID", nil) } if api.starService == nil { err := api.client.RemoveStar(c, uid) if err != nil { return response.Error(http.StatusInternalServerError, "Failed to unstar dashboard", err) } return response.Success("Dashboard unstarred") } userID, err := identity.UserIdentifier(c.GetID()) if err != nil { return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil) } cmd := star.UnstarDashboardCommand{UserID: userID, DashboardUID: uid, OrgID: c.GetOrgID()} if err := api.starService.Delete(c.Req.Context(), &cmd); err != nil { return response.Error(http.StatusInternalServerError, "Failed to unstar dashboard", err) } return response.Success("Dashboard unstarred") } // swagger:parameters starDashboard type StarDashboardParams struct { // in:path // required:true DashboardID string `json:"dashboard_id"` } // swagger:parameters starDashboardByUID type StarDashboardByUIDParams struct { // in:path // required:true DashboardUID string `json:"dashboard_uid"` } // swagger:parameters unstarDashboard type UnstarDashboardParams struct { // in:path // required:true DashboardID string `json:"dashboard_id"` } // swagger:parameters unstarDashboardByUID type UnstarDashboardByUIDParams struct { // in:path // required:true DashboardUID string `json:"dashboard_uid"` }