integrat star service into APIs (#49220)

This commit is contained in:
ying-jeanne 2022-05-19 14:32:10 +02:00 committed by GitHub
parent 426324ad3e
commit e2ea064584
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 44 additions and 167 deletions

View File

@ -23,6 +23,7 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/guardian"
pref "github.com/grafana/grafana/pkg/services/preference" pref "github.com/grafana/grafana/pkg/services/preference"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/services/store" "github.com/grafana/grafana/pkg/services/store"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
@ -37,12 +38,8 @@ func (hs *HTTPServer) isDashboardStarredByUser(c *models.ReqContext, dashID int6
return false, nil return false, nil
} }
query := models.IsStarredByUserQuery{UserId: c.UserId, DashboardId: dashID} query := star.IsStarredByUserQuery{UserID: c.UserId, DashboardID: dashID}
if err := hs.SQLStore.IsStarredByUserCtx(c.Req.Context(), &query); err != nil { return hs.starService.IsStarredByUser(c.Req.Context(), &query)
return false, err
}
return query.Result, nil
} }
func dashboardGuardianResponse(err error) response.Response { func dashboardGuardianResponse(err error) response.Response {

View File

@ -64,6 +64,7 @@ import (
"github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/shorturls" "github.com/grafana/grafana/pkg/services/shorturls"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/services/store" "github.com/grafana/grafana/pkg/services/store"
"github.com/grafana/grafana/pkg/services/teamguardian" "github.com/grafana/grafana/pkg/services/teamguardian"
"github.com/grafana/grafana/pkg/services/thumbs" "github.com/grafana/grafana/pkg/services/thumbs"
@ -152,6 +153,7 @@ type HTTPServer struct {
entityEventsService store.EntityEventsService entityEventsService store.EntityEventsService
folderPermissionsService accesscontrol.FolderPermissionsService folderPermissionsService accesscontrol.FolderPermissionsService
dashboardPermissionsService accesscontrol.DashboardPermissionsService dashboardPermissionsService accesscontrol.DashboardPermissionsService
starService star.Service
} }
type ServerOptions struct { type ServerOptions struct {
@ -185,7 +187,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
dashboardsnapshotsService *dashboardsnapshots.Service, commentsService *comments.Service, pluginSettings *pluginSettings.Service, dashboardsnapshotsService *dashboardsnapshots.Service, commentsService *comments.Service, pluginSettings *pluginSettings.Service,
avatarCacheServer *avatar.AvatarCacheServer, preferenceService pref.Service, entityEventsService store.EntityEventsService, avatarCacheServer *avatar.AvatarCacheServer, preferenceService pref.Service, entityEventsService store.EntityEventsService,
teamsPermissionsService accesscontrol.TeamPermissionsService, folderPermissionsService accesscontrol.FolderPermissionsService, teamsPermissionsService accesscontrol.TeamPermissionsService, folderPermissionsService accesscontrol.FolderPermissionsService,
dashboardPermissionsService accesscontrol.DashboardPermissionsService, dashboardPermissionsService accesscontrol.DashboardPermissionsService, starService star.Service,
) (*HTTPServer, error) { ) (*HTTPServer, error) {
web.Env = cfg.Env web.Env = cfg.Env
m := web.New() m := web.New()
@ -262,6 +264,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
entityEventsService: entityEventsService, entityEventsService: entityEventsService,
folderPermissionsService: folderPermissionsService, folderPermissionsService: folderPermissionsService,
dashboardPermissionsService: dashboardPermissionsService, dashboardPermissionsService: dashboardPermissionsService,
starService: starService,
} }
if hs.Listener != nil { if hs.Listener != nil {
hs.log.Debug("Using provided listener") hs.log.Debug("Using provided listener")

View File

@ -6,22 +6,22 @@ import (
"github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web"
) )
func (hs *HTTPServer) GetStars(c *models.ReqContext) response.Response { func (hs *HTTPServer) GetStars(c *models.ReqContext) response.Response {
query := models.GetUserStarsQuery{ query := star.GetUserStarsQuery{
UserId: c.SignedInUser.UserId, UserID: c.SignedInUser.UserId,
} }
err := hs.SQLStore.GetUserStars(c.Req.Context(), &query) iuserstars, err := hs.starService.GetByUser(c.Req.Context(), &query)
if err != nil { if err != nil {
return response.Error(500, "Failed to get user stars", err) return response.Error(500, "Failed to get user stars", err)
} }
iuserstars := query.Result
uids := []string{} uids := []string{}
for dashboardId := range iuserstars { for dashboardId := range iuserstars.UserStars {
query := &models.GetDashboardQuery{ query := &models.GetDashboardQuery{
Id: dashboardId, Id: dashboardId,
OrgId: c.OrgId, OrgId: c.OrgId,
@ -40,13 +40,13 @@ func (hs *HTTPServer) StarDashboard(c *models.ReqContext) response.Response {
if err != nil { if err != nil {
return response.Error(http.StatusBadRequest, "id is invalid", err) return response.Error(http.StatusBadRequest, "id is invalid", err)
} }
cmd := models.StarDashboardCommand{UserId: c.UserId, DashboardId: id} cmd := star.StarDashboardCommand{UserID: c.UserId, DashboardID: id}
if cmd.DashboardId <= 0 { if cmd.DashboardID <= 0 {
return response.Error(400, "Missing dashboard id", nil) return response.Error(400, "Missing dashboard id", nil)
} }
if err := hs.SQLStore.StarDashboard(c.Req.Context(), &cmd); err != nil { if err := hs.starService.Add(c.Req.Context(), &cmd); err != nil {
return response.Error(500, "Failed to star dashboard", err) return response.Error(500, "Failed to star dashboard", err)
} }
@ -58,13 +58,13 @@ func (hs *HTTPServer) UnstarDashboard(c *models.ReqContext) response.Response {
if err != nil { if err != nil {
return response.Error(http.StatusBadRequest, "id is invalid", err) return response.Error(http.StatusBadRequest, "id is invalid", err)
} }
cmd := models.UnstarDashboardCommand{UserId: c.UserId, DashboardId: id} cmd := star.UnstarDashboardCommand{UserID: c.UserId, DashboardID: id}
if cmd.DashboardId <= 0 { if cmd.DashboardID <= 0 {
return response.Error(400, "Missing dashboard id", nil) return response.Error(400, "Missing dashboard id", nil)
} }
if err := hs.SQLStore.UnstarDashboard(c.Req.Context(), &cmd); err != nil { if err := hs.starService.Delete(c.Req.Context(), &cmd); err != nil {
return response.Error(500, "Failed to unstar dashboard", err) return response.Error(500, "Failed to unstar dashboard", err)
} }

View File

@ -19,6 +19,8 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/services/star/starimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@ -26,9 +28,11 @@ func TestDashboardDataAccess(t *testing.T) {
var sqlStore *sqlstore.SQLStore var sqlStore *sqlstore.SQLStore
var savedFolder, savedDash, savedDash2 *models.Dashboard var savedFolder, savedDash, savedDash2 *models.Dashboard
var dashboardStore *DashboardStore var dashboardStore *DashboardStore
var starService star.Service
setup := func() { setup := func() {
sqlStore = sqlstore.InitTestDB(t) sqlStore = sqlstore.InitTestDB(t)
starService = starimpl.ProvideService(sqlStore)
dashboardStore = ProvideDashboardStore(sqlStore) dashboardStore = ProvideDashboardStore(sqlStore)
savedFolder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod", "webapp") savedFolder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod", "webapp")
savedDash = insertTestDashboard(t, dashboardStore, "test dash 23", 1, savedFolder.Id, false, "prod", "webapp") savedDash = insertTestDashboard(t, dashboardStore, "test dash 23", 1, savedFolder.Id, false, "prod", "webapp")
@ -423,15 +427,15 @@ func TestDashboardDataAccess(t *testing.T) {
t.Run("Should be able to search for starred dashboards", func(t *testing.T) { t.Run("Should be able to search for starred dashboards", func(t *testing.T) {
setup() setup()
starredDash := insertTestDashboard(t, dashboardStore, "starred dash", 1, 0, false) starredDash := insertTestDashboard(t, dashboardStore, "starred dash", 1, 0, false)
err := sqlStore.StarDashboard(context.Background(), &models.StarDashboardCommand{ err := starService.Add(context.Background(), &star.StarDashboardCommand{
DashboardId: starredDash.Id, DashboardID: starredDash.Id,
UserId: 10, UserID: 10,
}) })
require.NoError(t, err) require.NoError(t, err)
err = sqlStore.StarDashboard(context.Background(), &models.StarDashboardCommand{ err = starService.Add(context.Background(), &star.StarDashboardCommand{
DashboardId: savedDash.Id, DashboardID: savedDash.Id,
UserId: 1, UserID: 1,
}) })
require.NoError(t, err) require.NoError(t, err)

View File

@ -5,19 +5,21 @@ import (
"sort" "sort"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
) )
func ProvideService(cfg *setting.Cfg, sqlstore *sqlstore.SQLStore) *SearchService { func ProvideService(cfg *setting.Cfg, sqlstore *sqlstore.SQLStore, starService star.Service) *SearchService {
s := &SearchService{ s := &SearchService{
Cfg: cfg, Cfg: cfg,
sortOptions: map[string]models.SortOption{ sortOptions: map[string]models.SortOption{
SortAlphaAsc.Name: SortAlphaAsc, SortAlphaAsc.Name: SortAlphaAsc,
SortAlphaDesc.Name: SortAlphaDesc, SortAlphaDesc.Name: SortAlphaDesc,
}, },
sqlstore: sqlstore, sqlstore: sqlstore,
starService: starService,
} }
return s return s
} }
@ -48,6 +50,7 @@ type SearchService struct {
Cfg *setting.Cfg Cfg *setting.Cfg
sortOptions map[string]models.SortOption sortOptions map[string]models.SortOption
sqlstore sqlstore.Store sqlstore sqlstore.Store
starService star.Service
} }
func (s *SearchService) SearchHandler(ctx context.Context, query *Query) error { func (s *SearchService) SearchHandler(ctx context.Context, query *Query) error {
@ -100,15 +103,15 @@ func sortedHits(unsorted models.HitList) models.HitList {
} }
func (s *SearchService) setStarredDashboards(ctx context.Context, userID int64, hits []*models.Hit) error { func (s *SearchService) setStarredDashboards(ctx context.Context, userID int64, hits []*models.Hit) error {
query := models.GetUserStarsQuery{ query := star.GetUserStarsQuery{
UserId: userID, UserID: userID,
} }
err := s.sqlstore.GetUserStars(ctx, &query) res, err := s.starService.GetByUser(ctx, &query)
if err != nil { if err != nil {
return err return err
} }
iuserstars := query.Result iuserstars := res.UserStars
for _, dashboard := range hits { for _, dashboard := range hits {
if _, ok := iuserstars[dashboard.ID]; ok { if _, ok := iuserstars[dashboard.ID]; ok {
dashboard.IsStarred = true dashboard.IsStarred = true

View File

@ -6,11 +6,14 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/services/star/startest"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestSearch_SortedResults(t *testing.T) { func TestSearch_SortedResults(t *testing.T) {
ss := startest.NewStarServiceFake()
ms := mockstore.NewSQLStoreMock() ms := mockstore.NewSQLStoreMock()
ms.ExpectedPersistedDashboards = models.HitList{ ms.ExpectedPersistedDashboards = models.HitList{
&models.Hit{ID: 16, Title: "CCAA", Type: "dash-db", Tags: []string{"BB", "AA"}}, &models.Hit{ID: 16, Title: "CCAA", Type: "dash-db", Tags: []string{"BB", "AA"}},
@ -20,9 +23,10 @@ func TestSearch_SortedResults(t *testing.T) {
&models.Hit{ID: 17, Title: "FOLDER", Type: "dash-folder"}, &models.Hit{ID: 17, Title: "FOLDER", Type: "dash-folder"},
} }
ms.ExpectedSignedInUser = &models.SignedInUser{IsGrafanaAdmin: true} ms.ExpectedSignedInUser = &models.SignedInUser{IsGrafanaAdmin: true}
ms.ExpectedUserStars = map[int64]bool{10: true, 12: true} ss.ExpectedUserStars = &star.GetUserStarsResult{UserStars: map[int64]bool{10: true, 12: true}}
svc := &SearchService{ svc := &SearchService{
sqlstore: ms, sqlstore: ms,
starService: ss,
} }
query := &Query{ query := &Query{

View File

@ -308,24 +308,6 @@ func (m *SQLStoreMock) UpdatePluginSettingVersion(ctx context.Context, cmd *mode
return m.ExpectedError return m.ExpectedError
} }
func (m *SQLStoreMock) IsStarredByUserCtx(ctx context.Context, query *models.IsStarredByUserQuery) error {
query.Result = false
return m.ExpectedError
}
func (m *SQLStoreMock) StarDashboard(ctx context.Context, cmd *models.StarDashboardCommand) error {
return m.ExpectedError
}
func (m *SQLStoreMock) UnstarDashboard(ctx context.Context, cmd *models.UnstarDashboardCommand) error {
return m.ExpectedError
}
func (m *SQLStoreMock) GetUserStars(ctx context.Context, query *models.GetUserStarsQuery) error {
query.Result = m.ExpectedUserStars
return m.ExpectedError
}
func (m *SQLStoreMock) GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error { func (m *SQLStoreMock) GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error {
return m.ExpectedError return m.ExpectedError
} }

View File

@ -1,68 +0,0 @@
package sqlstore
import (
"context"
"github.com/grafana/grafana/pkg/models"
)
func (ss *SQLStore) IsStarredByUserCtx(ctx context.Context, query *models.IsStarredByUserQuery) error {
return ss.WithDbSession(ctx, func(sess *DBSession) error {
rawSQL := "SELECT 1 from star where user_id=? and dashboard_id=?"
results, err := sess.Query(rawSQL, query.UserId, query.DashboardId)
if err != nil {
return err
}
if len(results) == 0 {
return nil
}
query.Result = true
return nil
})
}
func (ss *SQLStore) StarDashboard(ctx context.Context, cmd *models.StarDashboardCommand) error {
if cmd.DashboardId == 0 || cmd.UserId == 0 {
return models.ErrCommandValidationFailed
}
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
entity := models.Star{
UserId: cmd.UserId,
DashboardId: cmd.DashboardId,
}
_, err := sess.Insert(&entity)
return err
})
}
func (ss *SQLStore) UnstarDashboard(ctx context.Context, cmd *models.UnstarDashboardCommand) error {
if cmd.DashboardId == 0 || cmd.UserId == 0 {
return models.ErrCommandValidationFailed
}
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
var rawSQL = "DELETE FROM star WHERE user_id=? and dashboard_id=?"
_, err := sess.Exec(rawSQL, cmd.UserId, cmd.DashboardId)
return err
})
}
func (ss *SQLStore) GetUserStars(ctx context.Context, query *models.GetUserStarsQuery) error {
return ss.WithDbSession(ctx, func(dbSession *DBSession) error {
var stars = make([]models.Star, 0)
err := dbSession.Where("user_id=?", query.UserId).Find(&stars)
query.Result = make(map[int64]bool)
for _, star := range stars {
query.Result[star.DashboardId] = true
}
return err
})
}

View File

@ -1,44 +0,0 @@
//go:build integration
// +build integration
package sqlstore
import (
"context"
"testing"
"github.com/grafana/grafana/pkg/models"
"github.com/stretchr/testify/require"
)
func TestUserStarsDataAccess(t *testing.T) {
t.Run("Testing User Stars Data Access", func(t *testing.T) {
sqlStore := InitTestDB(t)
t.Run("Given saved star", func(t *testing.T) {
cmd := models.StarDashboardCommand{
DashboardId: 10,
UserId: 12,
}
err := sqlStore.StarDashboard(context.Background(), &cmd)
require.NoError(t, err)
t.Run("IsStarredByUser should return true when starred", func(t *testing.T) {
query := models.IsStarredByUserQuery{UserId: 12, DashboardId: 10}
err := sqlStore.IsStarredByUserCtx(context.Background(), &query)
require.NoError(t, err)
require.True(t, query.Result)
})
t.Run("IsStarredByUser should return false when not starred", func(t *testing.T) {
query := models.IsStarredByUserQuery{UserId: 12, DashboardId: 12}
err := sqlStore.IsStarredByUserCtx(context.Background(), &query)
require.NoError(t, err)
require.False(t, query.Result)
})
})
})
}

View File

@ -65,10 +65,6 @@ type Store interface {
GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error
UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error
UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error
IsStarredByUserCtx(ctx context.Context, query *models.IsStarredByUserQuery) error
StarDashboard(ctx context.Context, cmd *models.StarDashboardCommand) error
UnstarDashboard(ctx context.Context, cmd *models.UnstarDashboardCommand) error
GetUserStars(ctx context.Context, query *models.GetUserStarsQuery) error
GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error
GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error
UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error

View File

@ -11,7 +11,7 @@ type Service struct {
store store store store
} }
func ProvideService(db db.DB) *Service { func ProvideService(db db.DB) star.Service {
return &Service{ return &Service{
store: &sqlStore{ store: &sqlStore{
db: db, db: db,