snapshot db protocol, cleanup
diff --git a/api.go b/api.go
index 3361c74..1aae5b6 100644
--- a/api.go
+++ b/api.go
@@ -5,6 +5,7 @@
"encoding/json"
"fmt"
"net/http"
+ "net/url"
)
type sucResponseDetail struct {
@@ -34,7 +35,11 @@
// handle client API
func handleRequest(w http.ResponseWriter, r *http.Request) {
- if r.Method != "POST" {
+
+ db := getDB()
+ if db == nil {
+ w.WriteHeader(http.StatusServiceUnavailable)
+ w.Write([]byte("initializing"))
return
}
@@ -42,6 +47,7 @@
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Unable to parse form"))
+ return
}
f := r.Form
@@ -50,16 +56,11 @@
if f.Get(elem) == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Missing element: %s", elem)))
+ return
}
}
- org := f.Get("organization")
- key := f.Get("key")
- path := f.Get("uriPath")
- env := f.Get("environment")
- action := f.Get("action")
-
- b, err := verifyAPIKey(key, path, env, org, action)
+ b, err := verifyAPIKey(f)
if err != nil {
log.Errorf("error: %s", err)
w.WriteHeader(http.StatusInternalServerError)
@@ -71,47 +72,39 @@
w.Write(b)
}
-// todo: The following was basically just copied from old APID - needs review.
-
// returns []byte to be written to client
-func verifyAPIKey(key, path, env, org, action string) ([]byte, error) {
- var (
- sSql string
- status, redirectionURIs string
- developerAppName, developerId string
- resName, resEnv, reason, errorCode string
- issuedAt, expiresAt int64
- )
+func verifyAPIKey(f url.Values) ([]byte, error) {
+
+ db := getDB()
+
+ key := f.Get("key")
+ org := f.Get("organization")
+ path := f.Get("uriPath")
+ env := f.Get("environment")
+ action := f.Get("action")
if key == "" || org == "" || path == "" || env == "" || action != "verify" {
log.Error("Input params Invalid/Incomplete")
- reason = "Input Params Incomplete or Invalid"
- errorCode = "INCORRECT_USER_INPUT"
+ reason := "Input Params Incomplete or Invalid"
+ errorCode := "INCORRECT_USER_INPUT"
return errorResponse(reason, errorCode)
}
- db, err := data.DB()
- if err != nil {
- log.Errorf("Unable to access DB")
- reason = err.Error()
- errorCode = "SEARCH_INTERNAL_ERROR"
- return errorResponse(reason, errorCode)
- }
+ sSql := "SELECT ap.api_resources, ap.environments, c.issued_at, c.status, a.callback_url, d.username, d.id FROM APP_CREDENTIAL AS c INNER JOIN APP AS a ON c.app_id = a.id INNER JOIN DEVELOPER AS d ON a.developer_id = d.id INNER JOIN APP_CREDENTIAL_APIPRODUCT_MAPPER as mp ON mp.appcred_id = c.id INNER JOIN API_PRODUCT as ap ON ap.id = mp.apiprdt_id WHERE (UPPER(d.status) = 'ACTIVE' AND mp.apiprdt_id = ap.id AND mp.app_id = a.id AND mp.appcred_id = c.id AND UPPER(mp.status) = 'APPROVED' AND UPPER(a.status) = 'APPROVED' AND c.id = '" + key + "' AND c._apid_scope = '" + org + "');"
- sSql = "SELECT ap.api_resources, ap.environments, c.issued_at, c.status, a.callback_url, d.username, d.id FROM APP_CREDENTIAL AS c INNER JOIN APP AS a ON c.app_id = a.id INNER JOIN DEVELOPER AS d ON a.developer_id = d.id INNER JOIN APP_CREDENTIAL_APIPRODUCT_MAPPER as mp ON mp.appcred_id = c.id INNER JOIN API_PRODUCT as ap ON ap.id = mp.apiprdt_id WHERE (UPPER(d.status) = 'ACTIVE' AND mp.apiprdt_id = ap.id AND mp.app_id = a.id AND mp.appcred_id = c.id AND UPPER(mp.status) = 'APPROVED' AND UPPER(a.status) = 'APPROVED' AND c.id = '" + key + "' AND c._apid_scope = '" + org + "');"
-
- err = db.QueryRow(sSql).Scan(&resName, &resEnv, &issuedAt, &status,
+ var status, redirectionURIs, developerAppName, developerId, resName, resEnv string
+ var issuedAt int64
+ err := db.QueryRow(sSql).Scan(&resName, &resEnv, &issuedAt, &status,
&redirectionURIs, &developerAppName, &developerId)
- expiresAt = -1
switch {
case err == sql.ErrNoRows:
- reason = "API Key verify failed for (" + key + ", " + org + ", " + path + ", " + env + ")"
- errorCode = "REQ_ENTRY_NOT_FOUND"
+ reason := "API Key verify failed for (" + key + ", " + org + ", " + path + ", " + env + ")"
+ errorCode := "REQ_ENTRY_NOT_FOUND"
return errorResponse(reason, errorCode)
case err != nil:
- reason = err.Error()
- errorCode = "SEARCH_INTERNAL_ERROR"
+ reason := err.Error()
+ errorCode := "SEARCH_INTERNAL_ERROR"
return errorResponse(reason, errorCode)
}
@@ -121,8 +114,8 @@
*/
result := validatePath(resName, path)
if result == false {
- reason = "Path Validation Failed (" + resName + " vs " + path + ")"
- errorCode = "PATH_VALIDATION_FAILED"
+ reason := "Path Validation Failed (" + resName + " vs " + path + ")"
+ errorCode := "PATH_VALIDATION_FAILED"
return errorResponse(reason, errorCode)
}
@@ -130,11 +123,12 @@
/* Verify if the ENV matches */
result = validateEnv(resEnv, env)
if result == false {
- reason = "ENV Validation Failed (" + resEnv + " vs " + env + ")"
- errorCode = "ENV_VALIDATION_FAILED"
+ reason := "ENV Validation Failed (" + resEnv + " vs " + env + ")"
+ errorCode := "ENV_VALIDATION_FAILED"
return errorResponse(reason, errorCode)
}
+ var expiresAt int64 = -1
resp := kmsResponseSuccess{
Type: "APIKeyContext",
RspInfo: sucResponseDetail{
diff --git a/api_test.go b/api_test.go
index 0a544f7..50e6107 100644
--- a/api_test.go
+++ b/api_test.go
@@ -1,71 +1,29 @@
package apidVerifyApiKey
import (
- "database/sql"
"encoding/json"
- "github.com/30x/apid"
- "github.com/30x/apid/factory"
- "github.com/apigee-labs/transicator/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"io/ioutil"
"net/http"
- "net/http/httptest"
"net/url"
- "os"
"strconv"
"strings"
)
var _ = Describe("api", func() {
- var tmpDir string
- var db apid.DB
- var server *httptest.Server
-
- BeforeSuite(func() {
- apid.Initialize(factory.DefaultServicesFactory())
-
- config := apid.Config()
- config.SetDefault("apigeesync_proxy_server_base", "X")
- config.SetDefault("apigeesync_consumer_key", "X")
- config.SetDefault("apigeesync_consumer_secret", "X")
- config.SetDefault("apigeesync_snapshot_server_base", "X")
- config.SetDefault("apigeesync_change_server_base", "X")
- config.SetDefault("apigeesync_log_level", "info")
-
- var err error
- tmpDir, err = ioutil.TempDir("", "api_test")
- Expect(err).NotTo(HaveOccurred())
-
- config.Set("data_path", tmpDir)
-
- // init() will create the tables
- apid.InitializePlugins()
-
- db, err = apid.Data().DB()
- Expect(err).NotTo(HaveOccurred())
- txn, err := db.Begin()
- Expect(err).ShouldNot(HaveOccurred())
- insertTestData(txn)
- txn.Commit()
- server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- if req.URL.Path == apiPath {
- handleRequest(w, req)
- }
- }))
- })
-
- AfterSuite(func() {
- apid.Events().Close()
- server.Close()
- os.RemoveAll(tmpDir)
- })
-
Context("verifyAPIKey() directly", func() {
It("should reject a bad key", func() {
- rsp, err := verifyAPIKey("credential_x", "/test", "Env_0", "Org_0", "verify")
+ v := url.Values{
+ "key": []string{"credential_x"},
+ "uriPath": []string{"/test"},
+ "environment": []string{"Env_0"},
+ "organization": []string{"Org_0"},
+ "action": []string{"verify"},
+ }
+ rsp, err := verifyAPIKey(v)
Expect(err).ShouldNot(HaveOccurred())
var respj kmsResponseFail
@@ -83,7 +41,14 @@
Expect(res).Should(BeTrue())
var respj kmsResponseFail
- rsp, err := verifyAPIKey("app_credential_0", "/test", "Env_0", "Org_0", "verify")
+ v := url.Values{
+ "key": []string{"app_credential_0"},
+ "path": []string{"/test"},
+ "env": []string{"Env_0"},
+ "organization": []string{"Org_0"},
+ "action": []string{"verify"},
+ }
+ rsp, err := verifyAPIKey(v)
Expect(err).ShouldNot(HaveOccurred())
json.Unmarshal(rsp, &respj)
@@ -94,7 +59,14 @@
It("should successfully verify good keys", func() {
for i := 1; i < 10; i++ {
resulti := strconv.FormatInt(int64(i), 10)
- rsp, err := verifyAPIKey("app_credential_"+resulti, "/test", "Env_0", "Org_0", "verify")
+ v := url.Values{
+ "key": []string{"app_credential_"+resulti},
+ "uriPath": []string{"/test"},
+ "environment": []string{"Env_0"},
+ "organization": []string{"Org_0"},
+ "action": []string{"verify"},
+ }
+ rsp, err := verifyAPIKey(v)
Expect(err).ShouldNot(HaveOccurred())
var respj kmsResponseSuccess
@@ -109,7 +81,7 @@
It("should reject a bad key", func() {
- uri, err := url.Parse(server.URL)
+ uri, err := url.Parse(testServer.URL)
uri.Path = apiPath
v := url.Values{}
@@ -137,7 +109,7 @@
It("should successfully verify a good key", func() {
- uri, err := url.Parse(server.URL)
+ uri, err := url.Parse(testServer.URL)
uri.Path = apiPath
v := url.Values{}
@@ -164,231 +136,3 @@
})
})
})
-
-func insertTestData(txn *sql.Tx) {
-
- for i := 0; i < 10; i++ {
- var rows []common.Row
- srvItems := common.Row{}
- result := strconv.FormatInt(int64(i), 10)
-
- scv := &common.ColumnVal{
- Value: "api_product_" + result,
- Type: 1,
- }
- srvItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "{/**, /test}",
- Type: 1,
- }
- srvItems["api_resources"] = scv
-
- scv = &common.ColumnVal{
- Value: "{Env_0, Env_1}",
- Type: 1,
- }
- srvItems["environments"] = scv
-
- scv = &common.ColumnVal{
- Value: "Org_0",
- Type: 1,
- }
- srvItems["_apid_scope"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_xxxx",
- Type: 1,
- }
- srvItems["tenant_id"] = scv
- rows = append(rows, srvItems)
- res := insertAPIproducts(rows, txn)
- Expect(res).Should(BeTrue())
- }
-
- for i := 0; i < 10; i++ {
- var rows []common.Row
- srvItems := common.Row{}
- result := strconv.FormatInt(int64(i), 10)
-
- scv := &common.ColumnVal{
- Value: "developer_id_" + result,
- Type: 1,
- }
- srvItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "test@apigee.com",
- Type: 1,
- }
- srvItems["email"] = scv
-
- scv = &common.ColumnVal{
- Value: "Active",
- Type: 1,
- }
- srvItems["status"] = scv
-
- scv = &common.ColumnVal{
- Value: "Apigee",
- Type: 1,
- }
- srvItems["firstName"] = scv
-
- scv = &common.ColumnVal{
- Value: "Google",
- Type: 1,
- }
- srvItems["lastName"] = scv
-
- scv = &common.ColumnVal{
- Value: "Org_0",
- Type: 1,
- }
- srvItems["_apid_scope"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_xxxx",
- Type: 1,
- }
- srvItems["tenant_id"] = scv
-
- rows = append(rows, srvItems)
- res := insertDevelopers(rows, txn)
- Expect(res).Should(BeTrue())
- }
-
- var j, k int
- for i := 0; i < 10; i++ {
- resulti := strconv.FormatInt(int64(i), 10)
- for j = k; j < 10+k; j++ {
- var rows []common.Row
-
- srvItems := common.Row{}
- resultj := strconv.FormatInt(int64(j), 10)
-
- scv := &common.ColumnVal{
- Value: "application_id_" + resultj,
- Type: 1,
- }
- srvItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "developer_id_" + resulti,
- Type: 1,
- }
- srvItems["developer_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "approved",
- Type: 1,
- }
- srvItems["status"] = scv
-
- scv = &common.ColumnVal{
- Value: "http://apigee.com",
- Type: 1,
- }
- srvItems["callback_url"] = scv
-
- scv = &common.ColumnVal{
- Value: "Org_0",
- Type: 1,
- }
- srvItems["_apid_scope"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_xxxx",
- Type: 1,
- }
- srvItems["tenant_id"] = scv
- rows = append(rows, srvItems)
- res := insertApplications(rows, txn)
- Expect(res).Should(BeTrue())
- }
- k = j
- }
-
- for i := 0; i < 10; i++ {
- var rows []common.Row
- srvItems := common.Row{}
- result := strconv.FormatInt(int64(i), 10)
-
- scv := &common.ColumnVal{
- Value: "app_credential_" + result,
- Type: 1,
- }
- srvItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "application_id_" + result,
- Type: 1,
- }
- srvItems["app_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "approved",
- Type: 1,
- }
- srvItems["status"] = scv
-
- scv = &common.ColumnVal{
- Value: "Org_0",
- Type: 1,
- }
- srvItems["_apid_scope"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_xxxx",
- Type: 1,
- }
- srvItems["tenant_id"] = scv
- rows = append(rows, srvItems)
- res := insertCredentials(rows, txn)
- Expect(res).Should(BeTrue())
- }
-
- for i := 0; i < 10; i++ {
- var rows []common.Row
- srvItems := common.Row{}
- result := strconv.FormatInt(int64(i), 10)
-
- scv := &common.ColumnVal{
- Value: "api_product_" + result,
- Type: 1,
- }
- srvItems["apiprdt_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "application_id_" + result,
- Type: 1,
- }
- srvItems["app_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "app_credential_" + result,
- Type: 1,
- }
- srvItems["appcred_id"] = scv
- scv = &common.ColumnVal{
- Value: "approved",
- Type: 1,
- }
- srvItems["status"] = scv
- scv = &common.ColumnVal{
- Value: "Org_0",
- Type: 1,
- }
- srvItems["_apid_scope"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_xxxx",
- Type: 1,
- }
- srvItems["tenant_id"] = scv
- rows = append(rows, srvItems)
- res := insertAPIProductMappers(rows, txn)
- Expect(res).Should(BeTrue())
- }
-
-}
diff --git a/init.go b/init.go
index b0a45e8..1465df1 100644
--- a/init.go
+++ b/init.go
@@ -2,6 +2,7 @@
import (
"github.com/30x/apid"
+ "sync"
)
const (
@@ -12,8 +13,23 @@
log apid.LogService
data apid.DataService
events apid.EventsService
+ unsafeDB apid.DB
+ dbMux sync.RWMutex
)
+func getDB() apid.DB {
+ dbMux.RLock()
+ db := unsafeDB
+ dbMux.RUnlock()
+ return db
+}
+
+func setDB(db apid.DB) {
+ dbMux.Lock()
+ unsafeDB = db
+ dbMux.Unlock()
+}
+
func init() {
apid.RegisterPlugin(initPlugin)
}
@@ -25,21 +41,7 @@
data = services.Data()
events = services.Events()
- db, err := data.DB()
- if err != nil {
- log.Panic("Unable to access DB", err)
- }
-
- var count int
- row := db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='API_PRODUCT' COLLATE NOCASE;")
- if err := row.Scan(&count); err != nil {
- log.Panic("Unable to setup database", err)
- }
- if count == 0 {
- createTables(db)
- }
-
- services.API().HandleFunc(apiPath, handleRequest)
+ services.API().HandleFunc(apiPath, handleRequest).Methods("POST")
events.Listen("ApigeeSync", &handler{})
log.Debug("end init")
@@ -49,7 +51,7 @@
func createTables(db apid.DB) {
_, err := db.Exec(`
-CREATE TABLE api_product (
+CREATE TABLE IF NOT EXISTS api_product (
id text,
tenant_id text,
name text,
@@ -68,7 +70,7 @@
updated_at int64,
updated_by text,
PRIMARY KEY (tenant_id, id));
-CREATE TABLE developer (
+CREATE TABLE IF NOT EXISTS developer (
id text,
tenant_id text,
username text,
@@ -86,7 +88,7 @@
updated_by text,
PRIMARY KEY (tenant_id, id)
);
-CREATE TABLE company (
+CREATE TABLE IF NOT EXISTS company (
id text,
tenant_id text,
name text,
@@ -99,7 +101,7 @@
_apid_scope text,
PRIMARY KEY (tenant_id, id)
);
-CREATE TABLE company_developer (
+CREATE TABLE IF NOT EXISTS company_developer (
tenant_id text,
company_id text,
developer_id text,
@@ -111,7 +113,7 @@
_apid_scope text,
PRIMARY KEY (tenant_id, company_id,developer_id)
);
-CREATE TABLE app (
+CREATE TABLE IF NOT EXISTS app (
id text,
tenant_id text,
name text,
@@ -130,7 +132,7 @@
_apid_scope text,
PRIMARY KEY (tenant_id, id)
);
-CREATE TABLE app_credential (
+CREATE TABLE IF NOT EXISTS app_credential (
id text,
tenant_id text,
consumer_secret text,
@@ -143,7 +145,7 @@
_apid_scope text,
PRIMARY KEY (tenant_id, id)
);
-CREATE TABLE app_credential_apiproduct_mapper (
+CREATE TABLE IF NOT EXISTS app_credential_apiproduct_mapper (
tenant_id text,
appcred_id text,
app_id text,
diff --git a/listener.go b/listener.go
index 9908f8d..e9398cd 100644
--- a/listener.go
+++ b/listener.go
@@ -15,65 +15,68 @@
func (h *handler) Handle(e apid.Event) {
- res := true
- db, err := data.DB()
- if err != nil {
- panic("Unable to access Sqlite DB")
- }
-
- txn, err := db.Begin()
- if err != nil {
- log.Error("Unable to create Sqlite transaction")
- return
- }
-
snapData, ok := e.(*common.Snapshot)
if ok {
- res = processSnapshot(snapData, txn)
+ processSnapshot(snapData)
} else {
changeSet, ok := e.(*common.ChangeList)
if ok {
- res = processChange(changeSet, txn)
+ processChange(changeSet)
} else {
- log.Errorf("Received Invalid event. This shouldn't happen!")
+ log.Errorf("Received Invalid event. Ignoring. %v", e)
}
}
- if res == true {
- txn.Commit()
- } else {
- txn.Rollback()
- }
return
}
-func processSnapshot(snapshot *common.Snapshot, txn *sql.Tx) bool {
+func processSnapshot(snapshot *common.Snapshot) {
- res := true
- log.Debugf("Process Snapshot data")
- /*
- * Iterate the tables, and insert the rows,
- * Commit them in bulk.
- */
- for _, payload := range snapshot.Tables {
- switch payload.Name {
- case "kms.developer":
- res = insertDevelopers(payload.Rows, txn)
- case "kms.app":
- res = insertApplications(payload.Rows, txn)
- case "kms.app_credential":
- res = insertCredentials(payload.Rows, txn)
- case "kms.api_product":
- res = insertAPIproducts(payload.Rows, txn)
- case "kms.app_credential_apiproduct_mapper":
- res = insertAPIProductMappers(payload.Rows, txn)
- }
- if res == false {
- log.Error("Error encountered in Downloading Snapshot for VerifyApiKey")
- return false
- }
+ log.Debugf("Snapshot received. Switching to DB version: %s", snapshot.SnapshotInfo)
+
+ db, err := data.DBVersion(snapshot.SnapshotInfo)
+ if err != nil {
+ log.Panicf("Unable to access database: %v", err)
}
- log.Debug("Downloading Snapshot for VerifyApiKey complete")
- return true
+
+ createTables(db)
+
+ if len(snapshot.Tables) > 0 {
+ txn, err := db.Begin()
+ if err != nil {
+ log.Panicf("Unable to create transaction: %v", err)
+ return
+ }
+
+ /*
+ * Iterate the tables, and insert the rows,
+ * Commit them in bulk.
+ */
+ ok := true
+ for _, payload := range snapshot.Tables {
+ switch payload.Name {
+ case "kms.developer":
+ ok = insertDevelopers(payload.Rows, txn)
+ case "kms.app":
+ ok = insertApplications(payload.Rows, txn)
+ case "kms.app_credential":
+ ok = insertCredentials(payload.Rows, txn)
+ case "kms.api_product":
+ ok = insertAPIproducts(payload.Rows, txn)
+ case "kms.app_credential_apiproduct_mapper":
+ ok = insertAPIProductMappers(payload.Rows, txn)
+ }
+ if !ok {
+ log.Error("Error encountered in Downloading Snapshot for VerifyApiKey")
+ txn.Rollback()
+ return
+ }
+ }
+ log.Debug("Downloading Snapshot for VerifyApiKey complete")
+ txn.Commit()
+ }
+
+ setDB(db)
+ return
}
/*
@@ -329,10 +332,18 @@
return true
}
-func processChange(changes *common.ChangeList, txn *sql.Tx) bool {
+func processChange(changes *common.ChangeList) {
+
+ db := getDB()
+
+ txn, err := db.Begin()
+ if err != nil {
+ log.Error("Unable to create transaction")
+ return
+ }
var rows []common.Row
- res := true
+ ok := true
log.Debugf("apigeeSyncEvent: %d changes", len(changes.Changes))
for _, payload := range changes.Changes {
@@ -342,81 +353,83 @@
switch payload.Operation {
case common.Insert:
rows = append(rows, payload.NewRow)
- res = insertDevelopers(rows, txn)
+ ok = insertDevelopers(rows, txn)
case common.Update:
- res = deleteObject("DEVELOPER", payload.OldRow, txn)
+ ok = deleteObject("DEVELOPER", payload.OldRow, txn)
rows = append(rows, payload.NewRow)
- res = insertDevelopers(rows, txn)
+ ok = insertDevelopers(rows, txn)
case common.Delete:
- res = deleteObject("DEVELOPER", payload.OldRow, txn)
+ ok = deleteObject("DEVELOPER", payload.OldRow, txn)
}
case "kms.app":
switch payload.Operation {
case common.Insert:
rows = append(rows, payload.NewRow)
- res = insertApplications(rows, txn)
+ ok = insertApplications(rows, txn)
case common.Update:
- res = deleteObject("APP", payload.OldRow, txn)
+ ok = deleteObject("APP", payload.OldRow, txn)
rows = append(rows, payload.NewRow)
- res = insertApplications(rows, txn)
+ ok = insertApplications(rows, txn)
case common.Delete:
- res = deleteObject("APP", payload.OldRow, txn)
+ ok = deleteObject("APP", payload.OldRow, txn)
}
case "kms.app_credential":
switch payload.Operation {
case common.Insert:
rows = append(rows, payload.NewRow)
- res = insertCredentials(rows, txn)
+ ok = insertCredentials(rows, txn)
case common.Update:
- res = deleteObject("APP_CREDENTIAL", payload.OldRow, txn)
+ ok = deleteObject("APP_CREDENTIAL", payload.OldRow, txn)
rows = append(rows, payload.NewRow)
- res = insertCredentials(rows, txn)
+ ok = insertCredentials(rows, txn)
case common.Delete:
- res = deleteObject("APP_CREDENTIAL", payload.OldRow, txn)
+ ok = deleteObject("APP_CREDENTIAL", payload.OldRow, txn)
}
case "kms.api_product":
switch payload.Operation {
case common.Insert:
rows = append(rows, payload.NewRow)
- res = insertAPIproducts(rows, txn)
+ ok = insertAPIproducts(rows, txn)
case common.Update:
- res = deleteObject("API_PRODUCT", payload.OldRow, txn)
+ ok = deleteObject("API_PRODUCT", payload.OldRow, txn)
rows = append(rows, payload.NewRow)
- res = insertAPIproducts(rows, txn)
+ ok = insertAPIproducts(rows, txn)
case common.Delete:
- res = deleteObject("API_PRODUCT", payload.OldRow, txn)
+ ok = deleteObject("API_PRODUCT", payload.OldRow, txn)
}
case "kms.app_credential_apiproduct_mapper":
switch payload.Operation {
case common.Insert:
rows = append(rows, payload.NewRow)
- res = insertAPIProductMappers(rows, txn)
+ ok = insertAPIProductMappers(rows, txn)
case common.Update:
- res = deleteAPIproductMapper(payload.OldRow, txn)
+ ok = deleteAPIproductMapper(payload.OldRow, txn)
rows = append(rows, payload.NewRow)
- res = insertAPIProductMappers(rows, txn)
+ ok = insertAPIProductMappers(rows, txn)
case common.Delete:
- res = deleteAPIproductMapper(payload.OldRow, txn)
+ ok = deleteAPIproductMapper(payload.OldRow, txn)
}
}
- if res == false {
+ if !ok {
log.Error("Sql Operation error. Operation rollbacked")
- return false
+ txn.Rollback()
+ return
}
}
- return true
+ txn.Commit()
+ return
}
/*
diff --git a/listener_test.go b/listener_test.go
index df89a27..af8b78a 100644
--- a/listener_test.go
+++ b/listener_test.go
@@ -6,9 +6,9 @@
"github.com/apigee-labs/transicator/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+ "net/url"
)
-var count int = 0
var _ = Describe("listener", func() {
It("should store data from ApigeeSync in the database", func(done Done) {
@@ -17,158 +17,120 @@
var event2 = common.ChangeList{}
/* API Product */
- srvItems := common.Row{}
- scv := &common.ColumnVal{
- Value: "ch_api_product_0",
- Type: 1,
+ srvItems := common.Row{
+ "id": {
+ Value: "ch_api_product_0",
+ Type: 1,
+ },
+ "apid_resources": {
+ Value: "{}",
+ Type: 1,
+ },
+ "environments": {
+ Value: "{Env_0, Env_1}",
+ Type: 1,
+ },
+ "tenant_id": {
+ Value: "tenant_id_0",
+ Type: 1,
+ },
+ "_apid_scope": {
+ Value: "test_org0",
+ Type: 1,
+ },
}
- srvItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "{}",
- Type: 1,
- }
- srvItems["api_resources"] = scv
-
- scv = &common.ColumnVal{
- Value: "{Env_0, Env_1}",
- Type: 1,
- }
- srvItems["environments"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_0",
- Type: 1,
- }
- srvItems["tenant_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "test_org0",
- Type: 1,
- }
- srvItems["_apid_scope"] = scv
/* DEVELOPER */
- devItems := common.Row{}
- scv = &common.ColumnVal{
- Value: "ch_developer_id_0",
- Type: 1,
+ devItems := common.Row{
+ "id": {
+ Value: "ch_developer_id_0",
+ Type: 1,
+ },
+ "status": {
+ Value: "Active",
+ Type: 1,
+ },
+ "tenant_id": {
+ Value: "tenant_id_0",
+ Type: 1,
+ },
+ "_apid_scope": {
+ Value: "test_org0",
+ Type: 1,
+ },
}
- devItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "Active",
- Type: 1,
- }
- devItems["status"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_0",
- Type: 1,
- }
- devItems["tenant_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "test_org0",
- Type: 1,
- }
- devItems["_apid_scope"] = scv
/* APP */
- appItems := common.Row{}
- scv = &common.ColumnVal{
- Value: "ch_application_id_0",
- Type: 1,
+ appItems := common.Row{
+ "id": {
+ Value: "ch_application_id_0",
+ Type: 1,
+ },
+ "developer_id": {
+ Value: "ch_developer_id_0",
+ Type: 1,
+ },
+ "status": {
+ Value: "Approved",
+ Type: 1,
+ },
+ "tenant_id": {
+ Value: "tenant_id_0",
+ Type: 1,
+ },
+ "_apid_scope": {
+ Value: "test_org0",
+ Type: 1,
+ },
}
- appItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "ch_developer_id_0",
- Type: 1,
- }
- appItems["developer_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_0",
- Type: 1,
- }
- appItems["tenant_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "Approved",
- Type: 1,
- }
- appItems["status"] = scv
-
- scv = &common.ColumnVal{
- Value: "test_org0",
- Type: 1,
- }
- appItems["_apid_scope"] = scv
/* CRED */
- credItems := common.Row{}
- scv = &common.ColumnVal{
- Value: "ch_app_credential_0",
- Type: 1,
+ credItems := common.Row{
+ "id": {
+ Value: "ch_app_credential_0",
+ Type: 1,
+ },
+ "app_id": {
+ Value: "ch_application_id_0",
+ Type: 1,
+ },
+ "tenant_id": {
+ Value: "tenant_id_0",
+ Type: 1,
+ },
+ "status": {
+ Value: "Approved",
+ Type: 1,
+ },
+ "_apid_scope": {
+ Value: "test_org0",
+ Type: 1,
+ },
}
- credItems["id"] = scv
-
- scv = &common.ColumnVal{
- Value: "ch_application_id_0",
- Type: 1,
- }
- credItems["app_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "tenant_id_0",
- Type: 1,
- }
- credItems["tenant_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "Approved",
- Type: 1,
- }
- credItems["status"] = scv
-
- scv = &common.ColumnVal{
- Value: "test_org0",
- Type: 1,
- }
- credItems["_apid_scope"] = scv
/* APP_CRED_APIPRD_MAPPER */
- mpItems := common.Row{}
- scv = &common.ColumnVal{
- Value: "ch_api_product_0",
- Type: 1,
+ mpItems := common.Row{
+ "apiprdt_id": {
+ Value: "ch_api_product_0",
+ Type: 1,
+ },
+ "app_id": {
+ Value: "ch_application_id_0",
+ Type: 1,
+ },
+ "appcred_id": {
+ Value: "ch_app_credential_0",
+ Type: 1,
+ },
+ "status": {
+ Value: "Approved",
+ Type: 1,
+ },
+ "_apid_scope": {
+ Value: "test_org0",
+ Type: 1,
+ },
}
- mpItems["apiprdt_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "ch_application_id_0",
- Type: 1,
- }
- mpItems["app_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "ch_app_credential_0",
- Type: 1,
- }
- mpItems["appcred_id"] = scv
-
- scv = &common.ColumnVal{
- Value: "Approved",
- Type: 1,
- }
- mpItems["status"] = scv
-
- scv = &common.ColumnVal{
- Value: "test_org0",
- Type: 1,
- }
- mpItems["_apid_scope"] = scv
event.Changes = []common.Change{
{
@@ -228,12 +190,21 @@
h := &test_handler{
"checkDatabase post Insertion",
func(e apid.Event) {
+ defer GinkgoRecover()
+
// ignore the first event, let standard listener process it
changeSet := e.(*common.ChangeList)
if len(changeSet.Changes) > 0 {
return
}
- rsp, err := verifyAPIKey("ch_app_credential_0", "/test", "Env_0", "test_org0", "verify")
+ v := url.Values{
+ "key": []string{"ch_app_credential_0"},
+ "uriPath": []string{"/test"},
+ "environment": []string{"Env_0"},
+ "organization": []string{"test_org0"},
+ "action": []string{"verify"},
+ }
+ rsp, err := verifyAPIKey(v)
Expect(err).ShouldNot(HaveOccurred())
var respj kmsResponseSuccess
json.Unmarshal(rsp, &respj)
diff --git a/verifyAPIKey_suite_test.go b/verifyAPIKey_suite_test.go
index c8f47fe..610d941 100644
--- a/verifyAPIKey_suite_test.go
+++ b/verifyAPIKey_suite_test.go
@@ -1,13 +1,291 @@
-package apidVerifyApiKey_test
+package apidVerifyApiKey
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
+ "github.com/30x/apid"
+ "github.com/30x/apid/factory"
+ "io/ioutil"
+ "net/http/httptest"
+ "net/http"
+ "os"
+ "strconv"
+ "github.com/apigee-labs/transicator/common"
)
+var (
+ testTempDir string
+ testServer *httptest.Server
+)
+
+var _ = BeforeSuite(func() {
+ apid.Initialize(factory.DefaultServicesFactory())
+
+ config := apid.Config()
+
+ var err error
+ testTempDir, err = ioutil.TempDir("", "api_test")
+ Expect(err).NotTo(HaveOccurred())
+
+ config.Set("data_path", testTempDir)
+
+ apid.InitializePlugins()
+
+ db, err := apid.Data().DB()
+ Expect(err).NotTo(HaveOccurred())
+ setDB(db)
+ createTables(db)
+ insertTestData(db)
+ testServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ if req.URL.Path == apiPath {
+ handleRequest(w, req)
+ }
+ }))
+})
+
+var _ = AfterSuite(func() {
+ apid.Events().Close()
+ if testServer != nil {
+ testServer.Close()
+ }
+ os.RemoveAll(testTempDir)
+})
+
func TestVerifyAPIKey(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "VerifyAPIKey Suite")
}
+
+func insertTestData(db apid.DB) {
+
+ txn, err := db.Begin()
+ Expect(err).ShouldNot(HaveOccurred())
+
+ for i := 0; i < 10; i++ {
+ var rows []common.Row
+ srvItems := common.Row{}
+ result := strconv.FormatInt(int64(i), 10)
+
+ scv := &common.ColumnVal{
+ Value: "api_product_" + result,
+ Type: 1,
+ }
+ srvItems["id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "{/**, /test}",
+ Type: 1,
+ }
+ srvItems["api_resources"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "{Env_0, Env_1}",
+ Type: 1,
+ }
+ srvItems["environments"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "Org_0",
+ Type: 1,
+ }
+ srvItems["_apid_scope"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "tenant_id_xxxx",
+ Type: 1,
+ }
+ srvItems["tenant_id"] = scv
+ rows = append(rows, srvItems)
+ res := insertAPIproducts(rows, txn)
+ Expect(res).Should(BeTrue())
+ }
+
+ for i := 0; i < 10; i++ {
+ var rows []common.Row
+ srvItems := common.Row{}
+ result := strconv.FormatInt(int64(i), 10)
+
+ scv := &common.ColumnVal{
+ Value: "developer_id_" + result,
+ Type: 1,
+ }
+ srvItems["id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "test@apigee.com",
+ Type: 1,
+ }
+ srvItems["email"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "Active",
+ Type: 1,
+ }
+ srvItems["status"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "Apigee",
+ Type: 1,
+ }
+ srvItems["firstName"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "Google",
+ Type: 1,
+ }
+ srvItems["lastName"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "Org_0",
+ Type: 1,
+ }
+ srvItems["_apid_scope"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "tenant_id_xxxx",
+ Type: 1,
+ }
+ srvItems["tenant_id"] = scv
+
+ rows = append(rows, srvItems)
+ res := insertDevelopers(rows, txn)
+ Expect(res).Should(BeTrue())
+ }
+
+ var j, k int
+ for i := 0; i < 10; i++ {
+ resulti := strconv.FormatInt(int64(i), 10)
+ for j = k; j < 10+k; j++ {
+ var rows []common.Row
+
+ srvItems := common.Row{}
+ resultj := strconv.FormatInt(int64(j), 10)
+
+ scv := &common.ColumnVal{
+ Value: "application_id_" + resultj,
+ Type: 1,
+ }
+ srvItems["id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "developer_id_" + resulti,
+ Type: 1,
+ }
+ srvItems["developer_id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "approved",
+ Type: 1,
+ }
+ srvItems["status"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "http://apigee.com",
+ Type: 1,
+ }
+ srvItems["callback_url"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "Org_0",
+ Type: 1,
+ }
+ srvItems["_apid_scope"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "tenant_id_xxxx",
+ Type: 1,
+ }
+ srvItems["tenant_id"] = scv
+ rows = append(rows, srvItems)
+ res := insertApplications(rows, txn)
+ Expect(res).Should(BeTrue())
+ }
+ k = j
+ }
+
+ for i := 0; i < 10; i++ {
+ var rows []common.Row
+ srvItems := common.Row{}
+ result := strconv.FormatInt(int64(i), 10)
+
+ scv := &common.ColumnVal{
+ Value: "app_credential_" + result,
+ Type: 1,
+ }
+ srvItems["id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "application_id_" + result,
+ Type: 1,
+ }
+ srvItems["app_id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "approved",
+ Type: 1,
+ }
+ srvItems["status"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "Org_0",
+ Type: 1,
+ }
+ srvItems["_apid_scope"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "tenant_id_xxxx",
+ Type: 1,
+ }
+ srvItems["tenant_id"] = scv
+ rows = append(rows, srvItems)
+ res := insertCredentials(rows, txn)
+ Expect(res).Should(BeTrue())
+ }
+
+ for i := 0; i < 10; i++ {
+ var rows []common.Row
+ srvItems := common.Row{}
+ result := strconv.FormatInt(int64(i), 10)
+
+ scv := &common.ColumnVal{
+ Value: "api_product_" + result,
+ Type: 1,
+ }
+ srvItems["apiprdt_id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "application_id_" + result,
+ Type: 1,
+ }
+ srvItems["app_id"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "app_credential_" + result,
+ Type: 1,
+ }
+ srvItems["appcred_id"] = scv
+ scv = &common.ColumnVal{
+ Value: "approved",
+ Type: 1,
+ }
+ srvItems["status"] = scv
+ scv = &common.ColumnVal{
+ Value: "Org_0",
+ Type: 1,
+ }
+ srvItems["_apid_scope"] = scv
+
+ scv = &common.ColumnVal{
+ Value: "tenant_id_xxxx",
+ Type: 1,
+ }
+ srvItems["tenant_id"] = scv
+ rows = append(rows, srvItems)
+ res := insertAPIProductMappers(rows, txn)
+ Expect(res).Should(BeTrue())
+ }
+
+ txn.Commit()
+}