Merge pull request #51 from 30x/accesstoken-endpoint

Add accesstoken endpoint for gateway to use in microservice requests
diff --git a/data.go b/data.go
index 3bd5591..a60902c 100644
--- a/data.go
+++ b/data.go
@@ -371,18 +371,32 @@
 
 	log.Debugf("findScopesForId: %s", configId)
 
-	var scope string
+	var scope sql.NullString
 	db := getDB()
 
-	rows, err := db.Query("select DISTINCT scope from EDGEX_DATA_SCOPE where apid_cluster_id = $1", configId)
+	query := `
+		SELECT scope FROM edgex_data_scope WHERE apid_cluster_id = $1
+		UNION
+		SELECT org_scope FROM edgex_data_scope WHERE apid_cluster_id = $2
+		UNION
+		SELECT env_scope FROM edgex_data_scope WHERE apid_cluster_id = $3
+	`
+
+	rows, err := db.Query(query, configId, configId, configId)
 	if err != nil {
 		log.Errorf("Failed to query EDGEX_DATA_SCOPE: %v", err)
 		return
 	}
 	defer rows.Close()
 	for rows.Next() {
-		rows.Scan(&scope)
-		scopes = append(scopes, scope)
+		err = rows.Scan(&scope)
+		if err != nil {
+			log.Errorf("Failed to get scopes from EDGEX_DATA_SCOPE: %v", err)
+			return
+		}
+		if scope.Valid && scope.String != "" {
+			scopes = append(scopes, scope.String)
+		}
 	}
 
 	log.Debugf("scopes: %v", scopes)
diff --git a/dockertests/master-schema.sql b/dockertests/master-schema.sql
index b53c815..18c424b 100644
--- a/dockertests/master-schema.sql
+++ b/dockertests/master-schema.sql
@@ -12,6 +12,8 @@
     updated timestamp without time zone,
     updated_by text,
     _change_selector text,
+    org_scope character varying(36),
+    env_scope character varying(36),
     CONSTRAINT apid_cluster_pkey PRIMARY KEY (id)
 );
 
diff --git a/listener_test.go b/listener_test.go
index 218cc0a..d48c70e 100644
--- a/listener_test.go
+++ b/listener_test.go
@@ -20,6 +20,8 @@
 
 	"github.com/apigee-labs/transicator/common"
 	"os"
+	"reflect"
+	"sort"
 )
 
 var _ = Describe("listener", func() {
@@ -144,11 +146,11 @@
 			Expect(ds.Scope).To(Equal("s2"))
 
 			scopes := findScopesForId("a")
-			Expect(len(scopes)).To(Equal(2))
-			Expect(scopes[0]).To(Equal("s1"))
-			Expect(scopes[1]).To(Equal("s2"))
-
-			//restore the last snapshot
+			Expect(len(scopes)).To(Equal(6))
+			expectedScopes := []string{"s1", "s2", "org_scope_1", "env_scope_1", "env_scope_2", "env_scope_3"}
+			sort.Strings(scopes)
+			sort.Strings(expectedScopes)
+			Expect(reflect.DeepEqual(scopes, expectedScopes)).To(BeTrue())
 		}, 3)
 	})
 
diff --git a/snapshot.go b/snapshot.go
index 960b4fc..3040b24 100644
--- a/snapshot.go
+++ b/snapshot.go
@@ -172,33 +172,12 @@
 	tables = make(map[string]bool)
 
 	log.Debug("Extracting table names from snapshot")
-	if snapshot.Tables == nil {
-		//if this panic ever fires, it's a bug
-		db, err := dataService.DBVersion(snapshot.SnapshotInfo)
-		if err != nil {
-			log.Panicf("Database inaccessible: %v", err)
-		}
-		rows, err := db.Query("SELECT DISTINCT tableName FROM _transicator_tables;")
-		if err != nil {
-			log.Panicf("Unable to read in known snapshot tables from sqlite file")
-		}
-		for rows.Next() {
-			var tableName string
-			rows.Scan(&tableName)
-			if err != nil {
-				log.Panic("Error scaning tableNames from _transicator_tables")
-			}
-			tables[tableName] = true
-		}
-
-	} else {
-
-		for _, table := range snapshot.Tables {
-			tables[table.Name] = true
-		}
+	//if this panic ever fires, it's a bug
+	db, err := dataService.DBVersion(snapshot.SnapshotInfo)
+	if err != nil {
+		log.Panicf("Database inaccessible: %v", err)
 	}
-	return tables
-
+	return extractTablesFromDB(db)
 }
 
 func extractTablesFromDB(db apid.DB) (tables map[string]bool) {
diff --git a/sql/init_listener_test_duplicate_apids.sql b/sql/init_listener_test_duplicate_apids.sql
index bc3cd87..b230bb9 100644
--- a/sql/init_listener_test_duplicate_apids.sql
+++ b/sql/init_listener_test_duplicate_apids.sql
@@ -36,6 +36,8 @@
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','scope',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org',25,1);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env',25,1);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org_scope',1043,0);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env_scope',1043,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created',1114,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created_by',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','updated',1114,0);
@@ -44,7 +46,7 @@
 CREATE TABLE "edgex_apid_cluster" (id text,name text,description text,umbrella_org_app_name text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,created_by,_change_selector));
 INSERT INTO "edgex_apid_cluster" VALUES('bootstrap','mitch-gcp-cluster','','X-5NF3iDkQLtQt6uPp4ELYhuOkzL5BbSMgf3Gx','2017-02-27 07:39:22.179+00:00','fierrom@google.com','2017-02-27 07:39:22.179+00:00','fierrom@google.com','bootstrap');
 INSERT INTO "edgex_apid_cluster" VALUES('bootstrap2','mitch-gcp-cluster','','X-5NF3iDkQLtQt6uPp4ELYhuOkzL5BbSMgf3Gx','2017-02-27 07:39:22.179+00:00','fierrom@google.com','2017-02-27 07:39:22.179+00:00','fierrom@google.com','bootstrap');
-CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
-INSERT INTO "edgex_data_scope" VALUES('dataScope1','bootstrap','43aef41d','edgex_gcp1','test','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','fierrom@google.com','bootstrap');
-INSERT INTO "edgex_data_scope" VALUES('dataScope2','bootstrap','43aef41d','edgex_gcp1','test','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','sendtofierro@gmail.com','bootstrap');
+CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,org_scope text,env_scope text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
+INSERT INTO "edgex_data_scope" VALUES('dataScope1','bootstrap','43aef41d','edgex_gcp1','test','org_scope_1','env_scope_1','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','fierrom@google.com','bootstrap');
+INSERT INTO "edgex_data_scope" VALUES('dataScope2','bootstrap','43aef41d','edgex_gcp1','test','org_scope_1','env_scope_2','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','sendtofierro@gmail.com','bootstrap');
 COMMIT;
diff --git a/sql/init_listener_test_no_datascopes.sql b/sql/init_listener_test_no_datascopes.sql
index 4820311..e8c2b57 100644
--- a/sql/init_listener_test_no_datascopes.sql
+++ b/sql/init_listener_test_no_datascopes.sql
@@ -36,6 +36,8 @@
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','scope',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org',25,1);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env',25,1);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org_scope',1043,0);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env_scope',1043,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created',1114,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created_by',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','updated',1114,0);
@@ -45,6 +47,6 @@
 CREATE TABLE "edgex_apid_cluster" (id text,name text,description text,umbrella_org_app_name text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,created_by,_change_selector));
 INSERT INTO "edgex_apid_cluster" VALUES('i','n','d','o', 'c', 'c', 'u','u', 'i');
 
-CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
+CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,org_scope text,env_scope text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
 
 COMMIT;
diff --git a/sql/init_listener_test_valid_snapshot.sql b/sql/init_listener_test_valid_snapshot.sql
index 415250b..a8d5e62 100644
--- a/sql/init_listener_test_valid_snapshot.sql
+++ b/sql/init_listener_test_valid_snapshot.sql
@@ -36,6 +36,8 @@
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','scope',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org',25,1);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env',25,1);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org_scope',1043,0);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env_scope',1043,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created',1114,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created_by',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','updated',1114,0);
@@ -45,9 +47,9 @@
 CREATE TABLE "edgex_apid_cluster" (id text,name text,description text,umbrella_org_app_name text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,created_by,_change_selector));
 INSERT INTO "edgex_apid_cluster" VALUES('i','n','d','o', 'c', 'c', 'u','u', 'i');
 
-CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,org,env,_change_selector));
-INSERT INTO "edgex_data_scope" VALUES('i','a','s1','o','e1','c','c','u','u','a');
-INSERT INTO "edgex_data_scope" VALUES('i','a','s1','o','e2','c','c','u','u','a');
-INSERT INTO "edgex_data_scope" VALUES('k','a','s2','o','e3','c','c','u','u','a');
+CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,org_scope text,env_scope text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
+INSERT INTO "edgex_data_scope" VALUES('i','a','s1','o','e1','org_scope_1','env_scope_1','c','c','u','u','a');
+INSERT INTO "edgex_data_scope" VALUES('i','a','s1','o','e2','org_scope_1','env_scope_2','c','c','u','u','a');
+INSERT INTO "edgex_data_scope" VALUES('k','a','s2','o','e3','org_scope_1','env_scope_3','c','c','u','u','a');
 
 COMMIT;
diff --git a/sql/init_mock_boot_db.sql b/sql/init_mock_boot_db.sql
index 0e4cda2..ec8e67a 100644
--- a/sql/init_mock_boot_db.sql
+++ b/sql/init_mock_boot_db.sql
@@ -36,6 +36,8 @@
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','scope',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org',25,1);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env',25,1);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org_scope',1043,0);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env_scope',1043,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created',1114,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created_by',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','updated',1114,0);
@@ -43,7 +45,7 @@
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','_change_selector',25,1);
 CREATE TABLE "edgex_apid_cluster" (id text,name text,description text,umbrella_org_app_name text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,created_by,created_by,created_by,created_by,_change_selector));
 INSERT INTO "edgex_apid_cluster" VALUES('bootstrap','mitch-gcp-cluster','','X-5NF3iDkQLtQt6uPp4ELYhuOkzL5BbSMgf3Gx','2017-02-27 07:39:22.179+00:00','fierrom@google.com','2017-02-27 07:39:22.179+00:00','fierrom@google.com','bootstrap');
-CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
-INSERT INTO "edgex_data_scope" VALUES('dataScope1','bootstrap','43aef41d','edgex_gcp1','test','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','fierrom@google.com','bootstrap');
-INSERT INTO "edgex_data_scope" VALUES('dataScope2','bootstrap','43aef41d','edgex_gcp1','test','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','sendtofierro@gmail.com','bootstrap');
+CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,org_scope text,env_scope text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
+INSERT INTO "edgex_data_scope" VALUES('dataScope1','bootstrap','43aef41d','edgex_gcp1','test','org_scope_1','env_scope_1','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','fierrom@google.com','bootstrap');
+INSERT INTO "edgex_data_scope" VALUES('dataScope2','bootstrap','43aef41d','edgex_gcp1','test','org_scope_1','env_scope_2','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','sendtofierro@gmail.com','bootstrap');
 COMMIT;
diff --git a/sql/init_mock_db.sql b/sql/init_mock_db.sql
index f1b8471..f257d8b 100644
--- a/sql/init_mock_db.sql
+++ b/sql/init_mock_db.sql
@@ -127,6 +127,8 @@
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','scope',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org',25,1);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env',25,1);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','org_scope',1043,0);
+INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','env_scope',1043,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created',1114,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','created_by',25,0);
 INSERT INTO "_transicator_tables" VALUES('edgex_data_scope','updated',1114,0);
@@ -230,9 +232,9 @@
 INSERT INTO "kms_organization" VALUES('ff0b5496-c674-4531-9443-ace334504f59','edgex_gcp1','edgex_gcp1','paid','43aef41d','307eadd7-c6d7-4ec1-b433-59bcd22cd06d','','2017-02-25 00:17:58.159+00:00','vbhangale@apigee.com','2017-02-25 00:18:14.729+00:00','vbhangale@apigee.com','43aef41d');
 CREATE TABLE "edgex_apid_cluster" (id text,name text,description text,umbrella_org_app_name text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,created_by,created_by,created_by,created_by,_change_selector));
 INSERT INTO "edgex_apid_cluster" VALUES('bootstrap','mitch-gcp-cluster','','X-5NF3iDkQLtQt6uPp4ELYhuOkzL5BbSMgf3Gx','2017-02-27 07:39:22.179+00:00','fierrom@google.com','2017-02-27 07:39:22.179+00:00','fierrom@google.com','bootstrap');
-CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
-INSERT INTO "edgex_data_scope" VALUES('dataScope1','bootstrap','43aef41d','edgex_gcp1','test','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','fierrom@google.com','bootstrap');
-INSERT INTO "edgex_data_scope" VALUES('dataScope2','bootstrap','43aef41d','edgex_gcp1','test','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','sendtofierro@gmail.com','bootstrap');
+CREATE TABLE "edgex_data_scope" (id text,apid_cluster_id text,scope text,org text,env text,org_scope text,env_scope text,created blob,created_by text,updated blob,updated_by text,_change_selector text, primary key (id,apid_cluster_id,apid_cluster_id,org,env,_change_selector));
+INSERT INTO "edgex_data_scope" VALUES('dataScope1','bootstrap','43aef41d','edgex_gcp1','test','org_scope_1','env_scope_1','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','fierrom@google.com','bootstrap');
+INSERT INTO "edgex_data_scope" VALUES('dataScope2','bootstrap','43aef41d','edgex_gcp1','test','org_scope_1','env_scope_2','2017-02-27 07:40:25.094+00:00','fierrom@google.com','2017-02-27 07:40:25.094+00:00','sendtofierro@gmail.com','bootstrap');
 CREATE TABLE "kms_app_credential" (id text,tenant_id text,consumer_secret text,app_id text,method_type text,status text,issued_at blob,expires_at blob,app_status text,scopes text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id,app_id,issued_at,expires_at));
 INSERT INTO "kms_app_credential" VALUES('xA9QylNTGQxKGYtHXwvmx8ldDaIJMAEx','43aef41d','lscGO3lfs3zh8iQ','87c20a31-a504-4ed5-89a5-700adfbb0142','','APPROVED','2017-02-27 07:45:22.774+00:00','','','{}','2017-02-27 07:45:22.774+00:00','-NA-','2017-02-27 07:45:22.877+00:00','-NA-','43aef41d');
 INSERT INTO "kms_app_credential" VALUES('ds986MejQqoWRSSeC0UTIPSJ3rtaG2xv','43aef41d','5EBOSSQrLOLO9siN','8f5c9b86-0783-439c-b8e6-7ab9549e30e8','','APPROVED','2017-02-27 07:43:23.263+00:00','','','{}','2017-02-27 07:43:23.263+00:00','-NA-','2017-02-27 07:48:16.717+00:00','-NA-','43aef41d');