Browse Source

Added validation to stop duplicate dashboards with same name from being saved

Torkel Ödegaard 11 years ago
parent
commit
0e3f91508e

+ 1 - 1
grafana

@@ -1 +1 @@
-Subproject commit 344812f1e0f0e804f9e9dd425168069d63c3fae3
+Subproject commit 34427f34e89fe3913523b5b236a149b88931b71d

+ 4 - 0
pkg/api/dashboard.go

@@ -69,6 +69,10 @@ func PostDashboard(c *middleware.Context) {
 
 	err := bus.Dispatch(&cmd)
 	if err != nil {
+		if err == m.ErrDashboardWithSameNameExists {
+			c.JsonApiErr(400, "Dashboard with the same title already exists", nil)
+			return
+		}
 		c.JsonApiErr(500, "Failed to save dashboard", err)
 		return
 	}

+ 2 - 3
pkg/models/dashboards.go

@@ -9,7 +9,8 @@ import (
 
 // Typed errors
 var (
-	ErrDashboardNotFound = errors.New("Account not found")
+	ErrDashboardNotFound           = errors.New("Account not found")
+	ErrDashboardWithSameNameExists = errors.New("A dashboard with the same name already exists")
 )
 
 type Dashboard struct {
@@ -39,8 +40,6 @@ type SearchDashboardsQuery struct {
 }
 
 type SaveDashboardCommand struct {
-	Id        string                 `json:"id"`
-	Title     string                 `json:"title"`
 	Dashboard map[string]interface{} `json:"dashboard"`
 	AccountId int64                  `json:"-"`
 

+ 11 - 1
pkg/stores/sqlstore/dashboards.go

@@ -17,7 +17,17 @@ func SaveDashboard(cmd *m.SaveDashboardCommand) error {
 	return inTransaction(func(sess *xorm.Session) error {
 		dash := cmd.GetDashboardModel()
 
-		var err error
+		// try get existing dashboard
+		existing := m.Dashboard{Slug: dash.Slug, AccountId: dash.AccountId}
+		hasExisting, err := sess.Get(&existing)
+		if err != nil {
+			return err
+		}
+
+		if hasExisting && dash.Id != existing.Id {
+			return m.ErrDashboardWithSameNameExists
+		}
+
 		if dash.Id == 0 {
 			_, err = sess.Insert(dash)
 		} else {

+ 70 - 0
pkg/stores/sqlstore/dashboards_test.go

@@ -0,0 +1,70 @@
+package sqlstore
+
+import (
+	"testing"
+
+	. "github.com/smartystreets/goconvey/convey"
+
+	m "github.com/torkelo/grafana-pro/pkg/models"
+)
+
+func TestDashboardDataAccess(t *testing.T) {
+
+	Convey("Testing DB", t, func() {
+		InitTestDB(t)
+
+		Convey("Given saved dashboard", func() {
+			var savedDash *m.Dashboard
+
+			cmd := m.SaveDashboardCommand{
+				AccountId: 1,
+				Dashboard: map[string]interface{}{
+					"id":    nil,
+					"title": "test dash 23",
+					"tags":  make([]interface{}, 0),
+				},
+			}
+
+			err := SaveDashboard(&cmd)
+			So(err, ShouldBeNil)
+
+			savedDash = cmd.Result
+
+			Convey("Should return dashboard model", func() {
+				So(savedDash.Title, ShouldEqual, "test dash 23")
+				So(savedDash.Slug, ShouldEqual, "test-dash-23")
+				So(savedDash.Id, ShouldNotEqual, 0)
+			})
+
+			Convey("Should be able to get dashboard", func() {
+				query := m.GetDashboardQuery{
+					Slug:      "test-dash-23",
+					AccountId: 1,
+				}
+
+				err := GetDashboard(&query)
+				So(err, ShouldBeNil)
+
+				So(query.Result.Title, ShouldEqual, "test dash 23")
+				So(query.Result.Slug, ShouldEqual, "test-dash-23")
+			})
+
+			Convey("Should not be able to save dashboard with same name", func() {
+				cmd := m.SaveDashboardCommand{
+					AccountId: 1,
+					Dashboard: map[string]interface{}{
+						"id":    nil,
+						"title": "test dash 23",
+						"tags":  make([]interface{}, 0),
+					},
+				}
+
+				err := SaveDashboard(&cmd)
+				So(err, ShouldNotBeNil)
+			})
+
+		})
+
+	})
+
+}

+ 0 - 0
pkg/stores/sqlstore/sqlstore_datasource.go → pkg/stores/sqlstore/datasource.go