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() +}