Auth: Move star service to identity interface (#73114)

* move star service to identity interface

* Update pkg/services/auth/identity/requester.go

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>

* Update pkg/services/contexthandler/model/model.go

---------

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
Jo 2023-08-10 17:17:27 +02:00 committed by GitHub
parent 0dcba0952e
commit 89c7116720
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 150 additions and 13 deletions

View File

@ -6,6 +6,7 @@ import (
"strconv"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/services/auth/identity"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/star"
@ -39,15 +40,25 @@ func (api *API) getDashboardHelper(ctx context.Context, orgID int64, id int64, u
result, err := api.dashboardService.GetDashboard(ctx, &query)
if err != nil {
return nil, response.Error(404, "Dashboard not found", err)
return nil, response.Error(http.StatusNotFound, "Dashboard not found", err)
}
return result, nil
}
func (api *API) GetStars(c *contextmodel.ReqContext) response.Response {
namespace, identifier := c.SignedInUser.GetNamespacedID()
if namespace != identity.NamespaceUser && namespace != identity.NamespaceServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
}
query := star.GetUserStarsQuery{
UserID: c.SignedInUser.UserID,
UserID: userID,
}
iuserstars, err := api.starService.GetByUser(c.Req.Context(), &query)
@ -61,7 +72,7 @@ func (api *API) GetStars(c *contextmodel.ReqContext) response.Response {
for id := range iuserstars.UserStars {
ids = append(ids, id)
}
starredDashboards, err := api.dashboardService.GetDashboards(c.Req.Context(), &dashboards.GetDashboardsQuery{DashboardIDs: ids, OrgID: c.OrgID})
starredDashboards, err := api.dashboardService.GetDashboards(c.Req.Context(), &dashboards.GetDashboardsQuery{DashboardIDs: ids, OrgID: c.SignedInUser.GetOrgID()})
if err != nil {
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to fetch dashboards", err)
}
@ -72,7 +83,7 @@ func (api *API) GetStars(c *contextmodel.ReqContext) response.Response {
}
}
return response.JSON(200, uids)
return response.JSON(http.StatusOK, uids)
}
// swagger:route POST /user/stars/dashboard/{dashboard_id} signed_in_user starDashboard
@ -90,14 +101,24 @@ func (api *API) GetStars(c *contextmodel.ReqContext) response.Response {
// 403: forbiddenError
// 500: internalServerError
func (api *API) StarDashboard(c *contextmodel.ReqContext) response.Response {
id, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
namespace, identifier := c.SignedInUser.GetNamespacedID()
if namespace != identity.NamespaceUser && namespace != identity.NamespaceServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
}
idString := web.Params(c.Req)[":id"]
id, err := strconv.ParseInt(idString, 10, 64)
if err != nil {
return response.Error(http.StatusBadRequest, "Invalid dashboard ID", nil)
}
cmd := star.StarDashboardCommand{UserID: c.UserID, DashboardID: id}
cmd := star.StarDashboardCommand{UserID: userID, DashboardID: id}
if cmd.DashboardID <= 0 {
return response.Error(400, "Missing dashboard id", nil)
return response.Error(http.StatusBadRequest, "Missing dashboard id", nil)
}
if err := api.starService.Add(c.Req.Context(), &cmd); err != nil {
@ -124,13 +145,24 @@ func (api *API) StarDashboardByUID(c *contextmodel.ReqContext) response.Response
if uid == "" {
return response.Error(http.StatusBadRequest, "Invalid dashboard UID", nil)
}
dash, rsp := api.getDashboardHelper(c.Req.Context(), c.OrgID, 0, uid)
namespace, identifier := c.SignedInUser.GetNamespacedID()
if namespace != identity.NamespaceUser && namespace != identity.NamespaceServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
}
dash, rsp := api.getDashboardHelper(c.Req.Context(), c.SignedInUser.GetOrgID(), 0, uid)
if rsp != nil {
return rsp
}
cmd := star.StarDashboardCommand{UserID: c.UserID, DashboardID: dash.ID}
cmd := star.StarDashboardCommand{UserID: userID, DashboardID: dash.ID}
if err := api.starService.Add(c.Req.Context(), &cmd); err != nil {
return response.Error(http.StatusInternalServerError, "Failed to star dashboard", err)
@ -161,9 +193,19 @@ func (api *API) UnstarDashboard(c *contextmodel.ReqContext) response.Response {
return response.Error(http.StatusBadRequest, "Invalid dashboard ID", nil)
}
cmd := star.UnstarDashboardCommand{UserID: c.UserID, DashboardID: id}
namespace, identifier := c.SignedInUser.GetNamespacedID()
if namespace != identity.NamespaceUser && namespace != identity.NamespaceServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
}
cmd := star.UnstarDashboardCommand{UserID: userID, DashboardID: id}
if cmd.DashboardID <= 0 {
return response.Error(400, "Missing dashboard id", nil)
return response.Error(http.StatusBadRequest, "Missing dashboard id", nil)
}
if err := api.starService.Delete(c.Req.Context(), &cmd); err != nil {
@ -190,12 +232,23 @@ func (api *API) UnstarDashboardByUID(c *contextmodel.ReqContext) response.Respon
if uid == "" {
return response.Error(http.StatusBadRequest, "Invalid dashboard UID", nil)
}
dash, rsp := api.getDashboardHelper(c.Req.Context(), c.OrgID, 0, uid)
namespace, identifier := c.SignedInUser.GetNamespacedID()
if namespace != identity.NamespaceUser && namespace != identity.NamespaceServiceAccount {
return response.Error(http.StatusBadRequest, "Only users and service accounts can star dashboards", nil)
}
userID, err := identity.IntIdentifier(namespace, identifier)
if err != nil {
return response.Error(http.StatusInternalServerError, "Invalid user ID", err)
}
dash, rsp := api.getDashboardHelper(c.Req.Context(), c.SignedInUser.GetOrgID(), 0, uid)
if rsp != nil {
return rsp
}
cmd := star.UnstarDashboardCommand{UserID: c.UserID, DashboardID: dash.ID}
cmd := star.UnstarDashboardCommand{UserID: userID, DashboardID: dash.ID}
if err := api.starService.Delete(c.Req.Context(), &cmd); err != nil {
return response.Error(http.StatusInternalServerError, "Failed to unstar dashboard", err)

View File

@ -0,0 +1,84 @@
package api
import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/star/startest"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/web"
)
func TestStarDashboard(t *testing.T) {
api := ProvideApi(startest.NewStarServiceFake(), dashboards.NewFakeDashboardService(t))
testCases := []struct {
name string
signedInUser *user.SignedInUser
expectedStatus int
params map[string]string
}{
{
name: "Star dashboard with user",
params: map[string]string{
":id": "1",
},
signedInUser: &user.SignedInUser{
UserID: 1,
OrgID: 1,
IsAnonymous: false,
},
expectedStatus: 200,
},
{
name: "Star dashboard with anonymous user",
params: map[string]string{
":id": "1",
},
signedInUser: &user.SignedInUser{
UserID: 0,
OrgID: 1,
IsAnonymous: true,
},
expectedStatus: 400,
},
{
name: "Star dashboard with API Key",
params: map[string]string{
":id": "1",
},
signedInUser: &user.SignedInUser{
UserID: 0,
OrgID: 1,
ApiKeyID: 3,
IsAnonymous: false,
},
expectedStatus: 400,
},
{
name: "Star dashboard with Service Account",
params: map[string]string{
":id": "1",
},
signedInUser: &user.SignedInUser{
UserID: 1,
OrgID: 3,
IsServiceAccount: true,
},
expectedStatus: 200,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
req := web.SetURLParams(&http.Request{}, tc.params)
c := &contextmodel.ReqContext{SignedInUser: tc.signedInUser, Context: &web.Context{Req: req}}
resp := api.StarDashboard(c)
assert.Equal(t, tc.expectedStatus, resp.Status())
})
}
}