mirror of
https://github.com/grafana/grafana.git
synced 2025-01-09 23:53:25 -06:00
parent
522a31c479
commit
2d4065600c
@ -89,6 +89,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/db"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/services/star/starimpl"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/services/teamguardian"
|
||||
teamguardianDatabase "github.com/grafana/grafana/pkg/services/teamguardian/database"
|
||||
@ -258,6 +259,7 @@ var wireBasicSet = wire.NewSet(
|
||||
wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)),
|
||||
ossaccesscontrol.ProvideDashboardPermissions,
|
||||
wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)),
|
||||
starimpl.ProvideService,
|
||||
)
|
||||
|
||||
var wireSet = wire.NewSet(
|
||||
|
54
pkg/services/star/model.go
Normal file
54
pkg/services/star/model.go
Normal file
@ -0,0 +1,54 @@
|
||||
package star
|
||||
|
||||
import "errors"
|
||||
|
||||
var ErrCommandValidationFailed = errors.New("command missing required fields")
|
||||
|
||||
type Star struct {
|
||||
ID int64 `xorm:"pk autoincr 'id'"`
|
||||
UserID int64 `xorm:"user_id"`
|
||||
DashboardID int64 `xorm:"dashboard_id"`
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// COMMANDS
|
||||
|
||||
type StarDashboardCommand struct {
|
||||
UserID int64 `xorm:"user_id"`
|
||||
DashboardID int64 `xorm:"dashboard_id"`
|
||||
}
|
||||
|
||||
func (cmd *StarDashboardCommand) Validate() error {
|
||||
if cmd.DashboardID == 0 || cmd.UserID == 0 {
|
||||
return ErrCommandValidationFailed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UnstarDashboardCommand struct {
|
||||
UserID int64 `xorm:"user_id"`
|
||||
DashboardID int64 `xorm:"dashboard_id"`
|
||||
}
|
||||
|
||||
func (cmd *UnstarDashboardCommand) Validate() error {
|
||||
if cmd.DashboardID == 0 || cmd.UserID == 0 {
|
||||
return ErrCommandValidationFailed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
// QUERIES
|
||||
|
||||
type GetUserStarsQuery struct {
|
||||
UserID int64 `xorm:"user_id"`
|
||||
}
|
||||
|
||||
type IsStarredByUserQuery struct {
|
||||
UserID int64 `xorm:"user_id"`
|
||||
DashboardID int64 `xorm:"dashboard_id"`
|
||||
}
|
||||
|
||||
type GetUserStarsResult struct {
|
||||
UserStars map[int64]bool
|
||||
}
|
12
pkg/services/star/star.go
Normal file
12
pkg/services/star/star.go
Normal file
@ -0,0 +1,12 @@
|
||||
package star
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
Add(ctx context.Context, cmd *StarDashboardCommand) error
|
||||
Delete(ctx context.Context, cmd *UnstarDashboardCommand) error
|
||||
IsStarredByUser(ctx context.Context, query *IsStarredByUserQuery) (bool, error)
|
||||
GetByUser(ctx context.Context, cmd *GetUserStarsQuery) (*GetUserStarsResult, error)
|
||||
}
|
42
pkg/services/star/starimpl/star.go
Normal file
42
pkg/services/star/starimpl/star.go
Normal file
@ -0,0 +1,42 @@
|
||||
package starimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/db"
|
||||
"github.com/grafana/grafana/pkg/services/star"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
store store
|
||||
}
|
||||
|
||||
func ProvideService(db db.DB) *Service {
|
||||
return &Service{
|
||||
store: &sqlStore{
|
||||
db: db,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) Add(ctx context.Context, cmd *star.StarDashboardCommand) error {
|
||||
if err := cmd.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.store.Insert(ctx, cmd)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, cmd *star.UnstarDashboardCommand) error {
|
||||
if err := cmd.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.store.Delete(ctx, cmd)
|
||||
}
|
||||
|
||||
func (s *Service) IsStarredByUser(ctx context.Context, query *star.IsStarredByUserQuery) (bool, error) {
|
||||
return s.store.Get(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) GetByUser(ctx context.Context, cmd *star.GetUserStarsQuery) (*star.GetUserStarsResult, error) {
|
||||
return s.store.List(ctx, cmd)
|
||||
}
|
69
pkg/services/star/starimpl/store.go
Normal file
69
pkg/services/star/starimpl/store.go
Normal file
@ -0,0 +1,69 @@
|
||||
package starimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/db"
|
||||
"github.com/grafana/grafana/pkg/services/star"
|
||||
)
|
||||
|
||||
type store interface {
|
||||
Get(ctx context.Context, query *star.IsStarredByUserQuery) (bool, error)
|
||||
Insert(ctx context.Context, cmd *star.StarDashboardCommand) error
|
||||
Delete(ctx context.Context, cmd *star.UnstarDashboardCommand) error
|
||||
List(ctx context.Context, query *star.GetUserStarsQuery) (*star.GetUserStarsResult, error)
|
||||
}
|
||||
|
||||
type sqlStore struct {
|
||||
db db.DB
|
||||
}
|
||||
|
||||
func (s *sqlStore) Get(ctx context.Context, query *star.IsStarredByUserQuery) (bool, error) {
|
||||
var isStarred bool
|
||||
err := s.db.WithDbSession(ctx, func(sess *sqlstore.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
|
||||
}
|
||||
|
||||
isStarred = len(results) != 0
|
||||
return nil
|
||||
})
|
||||
return isStarred, err
|
||||
}
|
||||
|
||||
func (s *sqlStore) Insert(ctx context.Context, cmd *star.StarDashboardCommand) error {
|
||||
return s.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
entity := star.Star{
|
||||
UserID: cmd.UserID,
|
||||
DashboardID: cmd.DashboardID,
|
||||
}
|
||||
|
||||
_, err := sess.Insert(&entity)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (s *sqlStore) Delete(ctx context.Context, cmd *star.UnstarDashboardCommand) error {
|
||||
return s.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
var rawSQL = "DELETE FROM star WHERE user_id=? and dashboard_id=?"
|
||||
_, err := sess.Exec(rawSQL, cmd.UserID, cmd.DashboardID)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (s *sqlStore) List(ctx context.Context, query *star.GetUserStarsQuery) (*star.GetUserStarsResult, error) {
|
||||
userStars := make(map[int64]bool)
|
||||
err := s.db.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
|
||||
var stars = make([]star.Star, 0)
|
||||
err := dbSession.Where("user_id=?", query.UserID).Find(&stars)
|
||||
for _, star := range stars {
|
||||
userStars[star.DashboardID] = true
|
||||
}
|
||||
return err
|
||||
})
|
||||
return &star.GetUserStarsResult{UserStars: userStars}, err
|
||||
}
|
60
pkg/services/star/starimpl/store_test.go
Normal file
60
pkg/services/star/starimpl/store_test.go
Normal file
@ -0,0 +1,60 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package starimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/star"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUserStarsDataAccess(t *testing.T) {
|
||||
t.Run("Testing User Stars Data Access", func(t *testing.T) {
|
||||
ss := sqlstore.InitTestDB(t)
|
||||
starStore := sqlStore{db: ss}
|
||||
|
||||
t.Run("Given saved star", func(t *testing.T) {
|
||||
cmd := star.StarDashboardCommand{
|
||||
DashboardID: 10,
|
||||
UserID: 12,
|
||||
}
|
||||
err := starStore.Insert(context.Background(), &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("IsStarredByUser should return true when starred", func(t *testing.T) {
|
||||
query := star.IsStarredByUserQuery{UserID: 12, DashboardID: 10}
|
||||
isStarred, err := starStore.Get(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.True(t, isStarred)
|
||||
})
|
||||
|
||||
t.Run("IsStarredByUser should return false when not starred", func(t *testing.T) {
|
||||
query := star.IsStarredByUserQuery{UserID: 12, DashboardID: 12}
|
||||
isStarred, err := starStore.Get(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.False(t, isStarred)
|
||||
})
|
||||
|
||||
t.Run("List should return a list of size 1", func(t *testing.T) {
|
||||
query := star.GetUserStarsQuery{UserID: 12}
|
||||
result, err := starStore.List(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(result.UserStars))
|
||||
})
|
||||
|
||||
t.Run("Delete should remove the star", func(t *testing.T) {
|
||||
deleteQuery := star.UnstarDashboardCommand{DashboardID: 10, UserID: 12}
|
||||
err := starStore.Delete(context.Background(), &deleteQuery)
|
||||
require.NoError(t, err)
|
||||
getQuery := star.IsStarredByUserQuery{UserID: 12, DashboardID: 10}
|
||||
isStarred, err := starStore.Get(context.Background(), &getQuery)
|
||||
require.NoError(t, err)
|
||||
require.False(t, isStarred)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
33
pkg/services/star/startest/fake.go
Normal file
33
pkg/services/star/startest/fake.go
Normal file
@ -0,0 +1,33 @@
|
||||
package startest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/star"
|
||||
)
|
||||
|
||||
type FakeStarService struct {
|
||||
ExpectedStars *star.Star
|
||||
ExpectedError error
|
||||
ExpectedUserStars *star.GetUserStarsResult
|
||||
}
|
||||
|
||||
func NewStarServiceFake() *FakeStarService {
|
||||
return &FakeStarService{}
|
||||
}
|
||||
|
||||
func (f *FakeStarService) IsStarredByUser(ctx context.Context, query *star.IsStarredByUserQuery) (bool, error) {
|
||||
return true, f.ExpectedError
|
||||
}
|
||||
|
||||
func (f *FakeStarService) Add(ctx context.Context, cmd *star.StarDashboardCommand) error {
|
||||
return f.ExpectedError
|
||||
}
|
||||
|
||||
func (f *FakeStarService) Delete(ctx context.Context, cmd *star.UnstarDashboardCommand) error {
|
||||
return f.ExpectedError
|
||||
}
|
||||
|
||||
func (f *FakeStarService) GetByUser(ctx context.Context, query *star.GetUserStarsQuery) (*star.GetUserStarsResult, error) {
|
||||
return f.ExpectedUserStars, f.ExpectedError
|
||||
}
|
Loading…
Reference in New Issue
Block a user