From 92ca9751f226e9de2a9ea719a7539540ff3d8206 Mon Sep 17 00:00:00 2001 From: Victor Vrantchan Date: Thu, 5 May 2016 14:14:44 -0400 Subject: [PATCH] assign workflows --- device/device.go | 29 ++++++++++++-- device/device_test.go | 89 +++++++++++++++++++++++++++++++++++++++++++ main.go | 32 ++++++++-------- 3 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 device/device_test.go diff --git a/device/device.go b/device/device.go index 30270626..85a1926a 100644 --- a/device/device.go +++ b/device/device.go @@ -20,7 +20,7 @@ var ErrNoRowsModified = errors.New("DB: No rows affected") // Device represents an iOS or OS X Computer type Device struct { // Primary key is UUID - UUID string `json:"uuid"` + UUID string `json:"uuid" db:"device_uuid"` UDID string `json:"udid"` SerialNumber *string `json:"serial_number,omitempty" db:"serial_number,omitempty"` OSVersion *string `json:"os_version,omitempty" db:"os_version,omitempty"` @@ -35,6 +35,7 @@ type Device struct { Token *string `json:"token,omitempty" db:"apple_mdm_token,omitempty"` UnlockToken *string `json:"unlock_token,omitempty" db:"unlock_token,omitempty"` Enrolled *bool `json:"enrolled,omitempty" db:"mdm_enrolled,omitempty"` + Workflow string `json:"workflow,omitempty" db:"workflow_uuid"` } // Profile is an Enrollment profile. @@ -49,6 +50,7 @@ type Datastore interface { // RemoveDevice() error // AllDevices() DeviceList,error GetProfileForDevice(udid string) (*Profile, error) + Save(string, *Device) error } type config struct { @@ -161,7 +163,7 @@ func (db pgDatastore) SaveDevice(dev *Device) error { apple_push_magic=$3, apple_mdm_token=$4, mdm_enrolled=$5 - WHERE uuid=$1` + WHERE device_uuid=$1` result, err := db.Exec( update, dev.UUID, @@ -179,6 +181,19 @@ func (db pgDatastore) SaveDevice(dev *Device) error { return nil } +func (db pgDatastore) Save(msg string, dev *Device) error { + var stmt string + switch msg { + case "assign": + stmt = `INSERT INTO device_workflow VALUES (:device_uuid, :workflow_uuid);` + } + _, err := db.NamedExec(stmt, dev) + if err != nil { + return err + } + return nil +} + // GetProfileForDevice returns an enrollment profile for a specific device // For now there's a single profile stored on disk func (db pgDatastore) GetProfileForDevice(uuid string) (*Profile, error) { @@ -194,7 +209,7 @@ func migrate(db *sqlx.DB) { schema := ` CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE TABLE IF NOT EXISTS devices ( - uuid uuid PRIMARY KEY + device_uuid uuid PRIMARY KEY DEFAULT uuid_generate_v4(), udid text UNIQUE NOT NULL, serial_number text, @@ -208,6 +223,12 @@ func migrate(db *sqlx.DB) { apple_push_magic text, mdm_enrolled boolean, awaiting_configuration boolean - );` + ); + + CREATE TABLE IF NOT EXISTS device_workflow ( + device_uuid uuid REFERENCES devices, + workflow_uuid uuid REFERENCES workflows, + PRIMARY KEY (device_uuid, workflow_uuid) + );` db.MustExec(schema) } diff --git a/device/device_test.go b/device/device_test.go new file mode 100644 index 00000000..e8b915cc --- /dev/null +++ b/device/device_test.go @@ -0,0 +1,89 @@ +package device + +import ( + "fmt" + "os" + "testing" + + "github.com/jmoiron/sqlx" +) + +var ( + store Datastore + testConn = "user=micromdm password=micromdm dbname=micromdm sslmode=disable" + db *sqlx.DB + workflows []string + devices []string +) + +func TestMain(m *testing.M) { + setup() + retCode := m.Run() + teardown(db) + os.Exit(retCode) +} + +func setup() { + db = newDB("postgres") + schema := ` + CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + CREATE TABLE IF NOT EXISTS workflows ( + workflow_uuid uuid PRIMARY KEY + DEFAULT uuid_generate_v4(), + name text UNIQUE NOT NULL + );` + db.MustExec(schema) + store = NewDB("postgres", testConn) + var uuid string + err := db.QueryRow(`INSERT INTO workflows (name) VALUES ($1) RETURNING workflow_uuid;`, "com.micromdm.test").Scan(&uuid) + if err != nil { + panic(err) + } + workflows = append(workflows, uuid) + var deviceuuid string + err = db.QueryRow(`INSERT INTO devices (udid) VALUES ($1) RETURNING device_uuid;`, "aFooDevice").Scan(&deviceuuid) + if err != nil { + panic(err) + } + devices = append(devices, deviceuuid) +} + +func newDB(driver string) *sqlx.DB { + db, err := sqlx.Open(driver, testConn) + if err != nil { + panic(err) + } + return db +} + +func teardown(db *sqlx.DB) { + drop := ` + DROP TABLE IF EXISTS device_workflow; + DROP TABLE IF EXISTS devices; + DROP TABLE IF EXISTS workflows; + ` + db.MustExec(drop) +} + +func TestDBSave(t *testing.T) { + fmt.Println(workflows) + fmt.Println(devices) + dev := &Device{ + UUID: devices[0], + Workflow: workflows[0], + } + err := store.Save("assign", dev) + if err != nil { + t.Fatal(err) + } + var result []struct { + DeviceUUID string `db:"device_uuid"` + WorkflowUUID string `db:"workflow_uuid"` + } + err = db.Select(&result, `SELECT device_uuid, workflow_uuid FROM device_workflow`) + if err != nil { + t.Fatal(err) + } + fmt.Println(result) + +} diff --git a/main.go b/main.go index 658eb9f4..77dc388e 100644 --- a/main.go +++ b/main.go @@ -78,6 +78,22 @@ func main() { os.Exit(1) } + //profileDB must exist before workflowDB + // TODO this is getting messy and migrations should be handled by a separate thing + profileDB := profile.NewDB( + "postgres", + *flPGconn, + profile.Logger(logger), + profile.Debug(), + ) + + workflowDB := workflow.NewDB( + "postgres", + *flPGconn, + workflow.Logger(logger), + workflow.Debug(), + ) + deviceDB := device.NewDB( "postgres", *flPGconn, @@ -119,22 +135,6 @@ func main() { ) connectHandler := connect.ServiceHandler(ctx, connectSvc) - //profileDB must exist before workflowDB - // TODO this is getting messy and migrations should be handled by a separate thing - profileDB := profile.NewDB( - "postgres", - *flPGconn, - profile.Logger(logger), - profile.Debug(), - ) - - workflowDB := workflow.NewDB( - "postgres", - *flPGconn, - workflow.Logger(logger), - workflow.Debug(), - ) - workflowSvc := workflow.NewService(workflow.DB(workflowDB)) workflowHandler := workflow.ServiceHandler(ctx, workflowSvc) // profiles