Enforce uniqueness on query name (#915)

* Enforce uniqueness on query name

close #914

* catching the already exists error in MySQL
This commit is contained in:
Mike Arpaia 2017-01-16 15:20:15 -07:00 committed by GitHub
parent 630ba45448
commit 5cc5220e5b
6 changed files with 59 additions and 3 deletions

8
glide.lock generated
View file

@ -1,5 +1,5 @@
hash: e9cd204c0dd7e3e9102a2e0c87cc722101473f0d8fd31b05ec7f88837dd1d529
updated: 2017-01-04T15:27:20.412164218-08:00
hash: ab1d436e71559ecedf062ac07e6086d96fbcfab9d20854b1b3f78867a6b3a94c
updated: 2017-01-16T14:44:49.6595886-07:00
imports:
- name: github.com/alecthomas/template
version: a0175ee3bccc567396460bf5acd36800cb10c49c
@ -137,6 +137,8 @@ imports:
subpackages:
- assert
- require
- name: github.com/VividCortex/mysqlerr
version: 93e3dc264d50c8ea98844075ef84224cacdc0c91
- name: github.com/WatchBeam/clock
version: d5a6612f3d9a070b964adc65dbd94c6080458f83
- name: golang.org/x/crypto
@ -167,7 +169,7 @@ imports:
- name: gopkg.in/go-playground/validator.v8
version: 5f57d2222ad794d0dffb07e664ea05e2ee07d60c
- name: gopkg.in/natefinch/lumberjack.v2
version: dd45e6a67c53f673bb49ca8a001fd3a63ceb640e
version: 514cbda263a734ae8caac038dadf05f8f3f9f738
- name: gopkg.in/yaml.v2
version: e4d366fc3c7938e2958e662b4258c7a89e1f0e3e
testImports: []

View file

@ -60,3 +60,4 @@ import:
- redis
- package: github.com/jmoiron/sqlx
- package: github.com/kolide/goose
- package: github.com/VividCortex/mysqlerr

View file

@ -183,3 +183,23 @@ func testLoadPacksForQueries(t *testing.T, ds kolide.Datastore) {
checkPacks(t, []kolide.Pack{*p2, *p3}, q1.Packs)
checkPacks(t, []kolide.Pack{*p1, *p3}, q2.Packs)
}
func testDuplicateNewQuery(t *testing.T, ds kolide.Datastore) {
user := test.NewUser(t, ds, "Mike Arpaia", "marpaia", "mike@kolide.co", true)
q1, err := ds.NewQuery(&kolide.Query{
Name: "foo",
Query: "select * from time;",
AuthorID: user.ID,
})
require.Nil(t, err)
assert.NotZero(t, q1.ID)
_, err = ds.NewQuery(&kolide.Query{
Name: "foo",
Query: "select * from osquery_info;",
})
// Note that we can't do the actual type assertion here because existsError
// is private to the individual datastore implementations
assert.Contains(t, err.Error(), "already exists in the datastore")
}

View file

@ -67,4 +67,5 @@ var testFunctions = [...]func(*testing.T, kolide.Datastore){
testAddLabelToPackTwice,
testGenerateHostStatusStatistics,
testMarkHostSeen,
testDuplicateNewQuery,
}

View file

@ -0,0 +1,24 @@
package tables
import "database/sql"
func init() {
MigrationClient.AddMigration(Up_20170111133013, Down_20170111133013)
}
func Up_20170111133013(tx *sql.Tx) error {
_, err := tx.Exec(
"ALTER TABLE `queries` " +
"ADD CONSTRAINT `constraint_query_name_unique` " +
"UNIQUE (`name`);",
)
return err
}
func Down_20170111133013(tx *sql.Tx) error {
_, err := tx.Exec(
"ALTER TABLE `queries` " +
"DROP INDEX `constraint_query_name_unique`;",
)
return err
}

View file

@ -3,6 +3,8 @@ package mysql
import (
"database/sql"
"github.com/VividCortex/mysqlerr"
"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"github.com/kolide/kolide-ose/server/kolide"
"github.com/pkg/errors"
@ -37,6 +39,12 @@ func (d *Datastore) NewQuery(query *kolide.Query) (*kolide.Query, error) {
) VALUES ( ?, ?, ?, ?, ? )
`
result, err := d.db.Exec(sql, query.Name, query.Description, query.Query, query.Saved, query.AuthorID)
if driverErr, ok := err.(*mysql.MySQLError); ok {
if driverErr.Number == mysqlerr.ER_DUP_ENTRY {
// TODO: this shouldn't require an ID parameter
return nil, alreadyExists("Query", 0)
}
}
if err != nil {
return nil, errors.Wrap(err, "inserting new query")
}