[ISSUE-67901957] refactor dbManager
diff --git a/accessEntity/api_response.go b/accessEntity/api_response.go new file mode 100644 index 0000000..d61042c --- /dev/null +++ b/accessEntity/api_response.go
@@ -0,0 +1 @@ +package accessEntity
diff --git a/accessEntity/data.go b/accessEntity/data.go new file mode 100644 index 0000000..d61042c --- /dev/null +++ b/accessEntity/data.go
@@ -0,0 +1 @@ +package accessEntity
diff --git a/accessEntity/init.go b/accessEntity/init.go new file mode 100644 index 0000000..d61042c --- /dev/null +++ b/accessEntity/init.go
@@ -0,0 +1 @@ +package accessEntity
diff --git a/common/api.go b/common/api.go new file mode 100644 index 0000000..141e9fa --- /dev/null +++ b/common/api.go
@@ -0,0 +1,22 @@ +package common + +import ( + "encoding/json" + "net/http" + "strconv" +) + +func WriteError(w http.ResponseWriter, reason string, errorCode int, statusCode int) { + w.WriteHeader(statusCode) + resp := ErrorResponse{ + ResponseCode: strconv.Itoa(errorCode), + ResponseMessage: reason, + StatusCode: statusCode, + } + bytes, err := json.Marshal(resp) + if err != nil { + w.Write([]byte("unable to marshal errorResponse: " + err.Error())) + } else { + w.Write(bytes) + } +}
diff --git a/common/data.go b/common/data.go new file mode 100644 index 0000000..b750195 --- /dev/null +++ b/common/data.go
@@ -0,0 +1,84 @@ +package common + +import ( + "database/sql" + "github.com/apid/apid-core" + "strings" + "sync" +) + +type DbManager struct { + Data apid.DataService + Db apid.DB + DbMux sync.RWMutex + dbVersion string +} + +const ( + sql_GET_KMS_ATTRIBUTES_FOR_TENANT = `select entity_id, name, value from kms_attributes where tenant_id = $1` +) + +var ( + services apid.Services + log apid.LogService +) + +func SetApidServices(s apid.Services, l apid.LogService) { + services = s + log = l +} + +func (dbc *DbManager) SetDbVersion(version string) { + db, err := dbc.Data.DBVersion(version) + if err != nil { + log.Panicf("Unable to access database: %v", err) + } + dbc.DbMux.Lock() + dbc.Db = db + dbc.DbMux.Unlock() + dbc.dbVersion = version +} + +func (dbc *DbManager) GetDb() apid.DB { + dbc.DbMux.RLock() + defer dbc.DbMux.RUnlock() + return dbc.Db +} + +func (dbc *DbManager) GetDbVersion() string { + return dbc.dbVersion +} + +func (dbc *DbManager) GetKmsAttributes(tenantId string, entities ...string) map[string][]Attribute { + + db := dbc.Db + var attName, attValue, entity_id sql.NullString + // TODO : is there no other better way to do in caluse??? + sql := sql_GET_KMS_ATTRIBUTES_FOR_TENANT + ` and entity_id in ('` + strings.Join(entities, `','`) + `')` + mapOfAttributes := make(map[string][]Attribute) + attributes, err := db.Query(sql, tenantId) + defer attributes.Close() + if err != nil { + log.Error("Error while fetching attributes for tenant id : %s and entityId : %s", tenantId, err) + return mapOfAttributes + } + for attributes.Next() { + err := attributes.Scan( + &entity_id, + &attName, + &attValue, + ) + if err != nil { + log.Error("error fetching attributes for entityid ", entities, err) + return nil + } + if attName.Valid && entity_id.Valid { + att := Attribute{Name: attName.String, Value: attValue.String} + mapOfAttributes[entity_id.String] = append(mapOfAttributes[entity_id.String], att) + } else { + log.Debugf("Not valid. AttName: %s Entity_id: %s", attName.String, entity_id.String) + } + } + log.Debug("attributes returned for query ", sql, " are ", mapOfAttributes) + return mapOfAttributes +}
diff --git a/common/data_structs.go b/common/data_structs.go new file mode 100644 index 0000000..2a319fd --- /dev/null +++ b/common/data_structs.go
@@ -0,0 +1,68 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package common + +type Attribute struct { + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` + Kind string `json:"kind,omitempty"` +} + +type ErrorResponse struct { + ResponseCode string `json:"response_code,omitempty"` + ResponseMessage string `json:"response_message,omitempty"` + StatusCode int `json:"-"` + Kind string `json:"kind,omitempty"` +} + +func (e *ErrorResponse) Error() string { + return e.ResponseMessage +} + +type ApiProduct struct { + Id string `db:"id"` + Name string `db:"name"` + DisplayName string `db:"display_name"` + Description string `db:"description"` + ApiResources string `db:"api_resources"` + ApprovalType string `db:"approval_type"` + Scopes string `db:"scopes"` + Proxies string `db:"proxies"` + Environments string `db:"environments"` + Quota string `db:"quota"` + QuotaTimeUnit string `db:"quota_time_unit"` + QuotaInterval int64 `db:"quota_interval"` + CreatedAt string `db:"created_at"` + CreatedBy string `db:"created_by"` + UpdatedAt string `db:"updated_at"` + UpdatedBy string `db:"updated_by"` +} + +type App struct { + Id string `db:"id"` + Name string `db:"name"` + DisplayName string `db:"display_name"` + AccessType string `db:"access_type"` + CallbackUrl string `db:"callback_url"` + Status string `db:"status"` + AppFamily string `db:"app_family"` + CompanyId string `db:"company_id"` + DeveloperId string `db:"developer_id"` + ParentId string `db:"parent_id"` + Type string `db:"type"` + CreatedAt string `db:"created_at"` + CreatedBy string `db:"created_by"` + UpdatedAt string `db:"updated_at"` + UpdatedBy string `db:"updated_by"` +}
diff --git a/init.go b/init.go index 31a9649..5131f64 100644 --- a/init.go +++ b/init.go
@@ -16,6 +16,8 @@ import ( "github.com/apid/apid-core" + "github.com/apid/apidVerifyApiKey/accessEntity" + "github.com/apid/apidVerifyApiKey/common" "github.com/apid/apidVerifyApiKey/verifyApiKey" "sync" ) @@ -33,12 +35,15 @@ services = s log = services.Log().ForModule("apidApiMetadata") verifyApiKey.SetApidServices(services, log) + accessEntity.SetApidServices(services, log) + common.SetApidServices(services, log) log.Debug("start init") - log = services.Log() verifyDbMan := &verifyApiKey.DbManager{ - Data: services.Data(), - DbMux: sync.RWMutex{}, + DbManager: common.DbManager{ + Data: services.Data(), + DbMux: sync.RWMutex{}, + }, } verifyApiMan := &verifyApiKey.ApiManager{ DbMan: verifyDbMan,
diff --git a/interfaces.go b/interfaces.go index e97d424..0974bbd 100644 --- a/interfaces.go +++ b/interfaces.go
@@ -1,3 +1,16 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package apidVerifyApiKey import (
diff --git a/verifyApiKey/api.go b/verifyApiKey/api.go index ef7e194..18d6e51 100644 --- a/verifyApiKey/api.go +++ b/verifyApiKey/api.go
@@ -16,6 +16,7 @@ import ( "encoding/json" + "github.com/apid/apidVerifyApiKey/common" "io" "io/ioutil" "net/http" @@ -25,7 +26,7 @@ type ApiManagerInterface interface { InitAPI() HandleRequest(w http.ResponseWriter, r *http.Request) - verifyAPIKey(verifyApiKeyReq VerifyApiKeyRequest) (*VerifyApiKeySuccessResponse, *ErrorResponse) + verifyAPIKey(verifyApiKeyReq VerifyApiKeyRequest) (*VerifyApiKeySuccessResponse, *common.ErrorResponse) } type ApiManager struct { @@ -76,7 +77,7 @@ } -func setResponseHeader(errorResponse *ErrorResponse, w http.ResponseWriter) { +func setResponseHeader(errorResponse *common.ErrorResponse, w http.ResponseWriter) { if errorResponse.StatusCode != 0 { w.WriteHeader(errorResponse.StatusCode) } else { @@ -108,7 +109,7 @@ } // returns []byte to be written to client -func (apiM ApiManager) verifyAPIKey(verifyApiKeyReq VerifyApiKeyRequest) (*VerifyApiKeySuccessResponse, *ErrorResponse) { +func (apiM ApiManager) verifyAPIKey(verifyApiKeyReq VerifyApiKeyRequest) (*VerifyApiKeySuccessResponse, *common.ErrorResponse) { dataWrapper := VerifyApiKeyRequestResponseDataWrapper{ verifyApiKeyRequest: verifyApiKeyReq, @@ -200,7 +201,7 @@ } -func (apiM ApiManager) performValidations(dataWrapper VerifyApiKeyRequestResponseDataWrapper) *ErrorResponse { +func (apiM ApiManager) performValidations(dataWrapper VerifyApiKeyRequestResponseDataWrapper) *common.ErrorResponse { clientIdDetails := dataWrapper.verifyApiKeySuccessResponse.ClientId verifyApiKeyReq := dataWrapper.verifyApiKeyRequest appDetails := dataWrapper.verifyApiKeySuccessResponse.App @@ -275,7 +276,7 @@ func (a *ApiManager) enrichAttributes(dataWrapper *VerifyApiKeyRequestResponseDataWrapper) { - attributeMap := a.DbMan.getKmsAttributes(dataWrapper.tenant_id, dataWrapper.verifyApiKeySuccessResponse.ClientId.ClientId, dataWrapper.tempDeveloperDetails.Id, dataWrapper.verifyApiKeySuccessResponse.ApiProduct.Id, dataWrapper.verifyApiKeySuccessResponse.App.Id) + attributeMap := a.DbMan.GetKmsAttributes(dataWrapper.tenant_id, dataWrapper.verifyApiKeySuccessResponse.ClientId.ClientId, dataWrapper.tempDeveloperDetails.Id, dataWrapper.verifyApiKeySuccessResponse.ApiProduct.Id, dataWrapper.verifyApiKeySuccessResponse.App.Id) clientIdAttributes := attributeMap[dataWrapper.verifyApiKeySuccessResponse.ClientId.ClientId] developerAttributes := attributeMap[dataWrapper.tempDeveloperDetails.Id] @@ -288,13 +289,13 @@ dataWrapper.tempDeveloperDetails.Attributes = developerAttributes } -func errorResponse(reason, errorCode string, statusCode int) ErrorResponse { +func errorResponse(reason, errorCode string, statusCode int) common.ErrorResponse { if errorCode == "SEARCH_INTERNAL_ERROR" { log.Error(reason) } else { log.Debug(reason) } - resp := ErrorResponse{ + resp := common.ErrorResponse{ ResponseCode: errorCode, ResponseMessage: reason, StatusCode: statusCode,
diff --git a/verifyApiKey/api_test.go b/verifyApiKey/api_test.go index 5434019..86760e7 100644 --- a/verifyApiKey/api_test.go +++ b/verifyApiKey/api_test.go
@@ -25,6 +25,7 @@ "errors" "github.com/apid/apid-core" "github.com/apid/apid-core/factory" + "github.com/apid/apidVerifyApiKey/common" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "io/ioutil" @@ -47,18 +48,20 @@ var _ = BeforeEach(func() { var err error dataTestTempDir, err = ioutil.TempDir(testTempDirBase, "api_test_sqlite3") + Expect(err).NotTo(HaveOccurred()) serviceFactoryForTest := factory.DefaultServicesFactory() apid.Initialize(serviceFactoryForTest) config := apid.Config() config.Set("data_path", testTempDir) config.Set("log_level", "DEBUG") serviceFactoryForTest.Config().Set("local_storage_path", dataTestTempDir) - - Expect(err).NotTo(HaveOccurred()) + common.SetApidServices(serviceFactoryForTest, serviceFactoryForTest.Log()) dbMan = &DbManager{ - Data: serviceFactoryForTest.Data(), - DbMux: sync.RWMutex{}, + DbManager: common.DbManager{ + Data: serviceFactoryForTest.Data(), + DbMux: sync.RWMutex{}, + }, } dbMan.SetDbVersion(dataTestTempDir) @@ -77,7 +80,7 @@ Context("veriifyApiKey Api test ", func() { It("should return validation error for missing input fields", func() { - var respObj ErrorResponse + var respObj common.ErrorResponse reqInput := VerifyApiKeyRequest{ Key: "test", } @@ -91,7 +94,7 @@ Expect(respObj.ResponseCode).Should(Equal("Missing mandatory fields in the request : action organizationName uriPath")) }) It("should return validation error for inavlid key", func() { - var respObj ErrorResponse + var respObj common.ErrorResponse reqInput := VerifyApiKeyRequest{ Key: "invalid-key", Action: "verify", @@ -113,7 +116,7 @@ }) It("should return validation error for inavlid env", func() { setupApikeyDeveloperTestDb(dbMan.Db) - var respObj ErrorResponse + var respObj common.ErrorResponse reqInput := VerifyApiKeyRequest{ Key: "63tHSNLKJkcc6GENVWGT1Zw5gek7kVJ0", Action: "verify", @@ -135,7 +138,7 @@ }) It("should return validation error for inavlid resource", func() { setupApikeyDeveloperTestDb(dbMan.Db) - var respObj ErrorResponse + var respObj common.ErrorResponse reqInput := VerifyApiKeyRequest{ Key: "63tHSNLKJkcc6GENVWGT1Zw5gek7kVJ0", Action: "verify", @@ -157,7 +160,7 @@ }) It("should return validation error for inavlid proxies", func() { setupApikeyDeveloperTestDb(dbMan.Db) - var respObj ErrorResponse + var respObj common.ErrorResponse reqInput := VerifyApiKeyRequest{ Key: "63tHSNLKJkcc6GENVWGT1Zw5gek7kVJ0", Action: "verify",
diff --git a/verifyApiKey/data.go b/verifyApiKey/data.go index 8a2d1e6..56ae2d2 100644 --- a/verifyApiKey/data.go +++ b/verifyApiKey/data.go
@@ -14,82 +14,21 @@ package verifyApiKey import ( - "database/sql" "errors" "github.com/apid/apid-core" - "strings" - "sync" + "github.com/apid/apidVerifyApiKey/common" ) -type DbManager struct { - Data apid.DataService - Db apid.DB - DbMux sync.RWMutex - dbVersion string -} - -func (dbc *DbManager) SetDbVersion(version string) { - db, err := dbc.Data.DBVersion(version) - if err != nil { - log.Panicf("Unable to access database: %v", err) - } - dbc.DbMux.Lock() - dbc.Db = db - dbc.DbMux.Unlock() - dbc.dbVersion = version - // TODO : check if we need to release old Db here... -} - -func (dbc *DbManager) GetDb() apid.DB { - dbc.DbMux.RLock() - defer dbc.DbMux.RUnlock() - return dbc.Db -} - -func (dbc *DbManager) GetDbVersion() string { - return dbc.dbVersion -} - type DbManagerInterface interface { SetDbVersion(string) GetDb() apid.DB GetDbVersion() string - getKmsAttributes(tenantId string, entities ...string) map[string][]Attribute + GetKmsAttributes(tenantId string, entities ...string) map[string][]common.Attribute getApiKeyDetails(dataWrapper *VerifyApiKeyRequestResponseDataWrapper) error } -func (dbc *DbManager) getKmsAttributes(tenantId string, entities ...string) map[string][]Attribute { - - db := dbc.Db - var attName, attValue, entity_id sql.NullString - // TODO : is there no other better way to do in caluse??? - sql := sql_GET_KMS_ATTRIBUTES_FOR_TENANT + ` and entity_id in ('` + strings.Join(entities, `','`) + `')` - mapOfAttributes := make(map[string][]Attribute) - attributes, err := db.Query(sql, tenantId) - defer attributes.Close() - if err != nil { - log.Error("Error while fetching attributes for tenant id : %s and entityId : %s", tenantId, err) - return mapOfAttributes - } - for attributes.Next() { - err := attributes.Scan( - &entity_id, - &attName, - &attValue, - ) - if err != nil { - log.Error("error fetching attributes for entityid ", entities, err) - return nil - } - if attName.Valid && entity_id.Valid { - att := Attribute{Name: attName.String, Value: attValue.String} - mapOfAttributes[entity_id.String] = append(mapOfAttributes[entity_id.String], att) - } else { - log.Debugf("Not valid. AttName: %s Entity_id: %s", attName.String, entity_id.String) - } - } - log.Debug("attributes returned for query ", sql, " are ", mapOfAttributes) - return mapOfAttributes +type DbManager struct { + common.DbManager } func (dbc DbManager) getApiKeyDetails(dataWrapper *VerifyApiKeyRequestResponseDataWrapper) error {
diff --git a/verifyApiKey/data_test.go b/verifyApiKey/data_test.go index 4d5e93b..c864339 100644 --- a/verifyApiKey/data_test.go +++ b/verifyApiKey/data_test.go
@@ -16,6 +16,7 @@ import ( "github.com/apid/apid-core" "github.com/apid/apid-core/factory" + "github.com/apid/apidVerifyApiKey/common" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "io/ioutil" @@ -30,17 +31,18 @@ var _ = BeforeEach(func() { var err error dataTestTempDir, err = ioutil.TempDir(testTempDirBase, "sqlite3") - + Expect(err).NotTo(HaveOccurred()) s := factory.DefaultServicesFactory() apid.Initialize(s) config := apid.Config() config.Set("local_storage_path", dataTestTempDir) - - Expect(err).NotTo(HaveOccurred()) + common.SetApidServices(s, s.Log()) dbMan = &DbManager{ - Data: s.Data(), - DbMux: sync.RWMutex{}, + DbManager: common.DbManager{ + Data: s.Data(), + DbMux: sync.RWMutex{}, + }, } dbMan.SetDbVersion(dataTestTempDir) @@ -185,7 +187,7 @@ It("should get kms attributes", func() { setupKmsAttributesdata(dbMan.Db) - attributes := dbMan.getKmsAttributes("bc811169", "40753e12-a50a-429d-9121-e571eb4e43a9", "85629786-37c5-4e8c-bb45-208f3360d005", "50321842-d6ee-4e92-91b9-37234a7920c1", "test-invalid") + attributes := dbMan.GetKmsAttributes("bc811169", "40753e12-a50a-429d-9121-e571eb4e43a9", "85629786-37c5-4e8c-bb45-208f3360d005", "50321842-d6ee-4e92-91b9-37234a7920c1", "test-invalid") Expect(len(attributes)).Should(BeEquivalentTo(3)) Expect(len(attributes["40753e12-a50a-429d-9121-e571eb4e43a9"])).Should(BeEquivalentTo(1)) Expect(len(attributes["85629786-37c5-4e8c-bb45-208f3360d005"])).Should(BeEquivalentTo(2))
diff --git a/verifyApiKey/init.go b/verifyApiKey/init.go index 2f18a52..33ac046 100644 --- a/verifyApiKey/init.go +++ b/verifyApiKey/init.go
@@ -1,3 +1,16 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package verifyApiKey import (
diff --git a/verifyApiKey/verifyApiKeyStructs.go b/verifyApiKey/verifyApiKeyStructs.go index d7c810e..b2a93e6 100644 --- a/verifyApiKey/verifyApiKeyStructs.go +++ b/verifyApiKey/verifyApiKeyStructs.go
@@ -13,7 +13,10 @@ // limitations under the License. package verifyApiKey -import "errors" +import ( + "errors" + "github.com/apid/apidVerifyApiKey/common" +) type ClientIdDetails struct { ClientId string `json:"clientId,omitempty"` @@ -21,7 +24,7 @@ RedirectURIs []string `json:"redirectURIs,omitempty"` Status string `json:"status,omitempty"` // Attributes associated with the client Id. - Attributes []Attribute `json:"attributes,omitempty"` + Attributes []common.Attribute `json:"attributes,omitempty"` } type ApiProductDetails struct { @@ -40,8 +43,8 @@ Environments []string `json:"environments,omitempty"` Apiproxies []string `json:"apiproxies,omitempty"` // Attributes associated with the apiproduct. - Attributes []Attribute `json:"attributes,omitempty"` - Resources []string `json:"-"` + Attributes []common.Attribute `json:"attributes,omitempty"` + Resources []string `json:"-"` } type AppDetails struct { @@ -59,13 +62,7 @@ LastmodifiedBy string `json:"lastmodified_by,omitempty"` Company string `json:"company,omitempty"` // Attributes associated with the app. - Attributes []Attribute `json:"attributes,omitempty"` -} - -type Attribute struct { - Name string `json:"name,omitempty"` - Value string `json:"value,omitempty"` - Kind string `json:"kind,omitempty"` + Attributes []common.Attribute `json:"attributes,omitempty"` } type CompanyDetails struct { @@ -79,7 +76,7 @@ LastmodifiedAt string `json:"lastmodified_at,omitempty"` LastmodifiedBy string `json:"lastmodified_by,omitempty"` // Attributes associated with the company. - Attributes []Attribute `json:"attributes,omitempty"` + Attributes []common.Attribute `json:"attributes,omitempty"` } type DeveloperDetails struct { @@ -96,14 +93,7 @@ LastmodifiedBy string `json:"lastmodified_by,omitempty"` Company string `json:"company,omitempty"` // Attributes associated with the developer. - Attributes []Attribute `json:"attributes,omitempty"` -} - -type ErrorResponse struct { - ResponseCode string `json:"response_code,omitempty"` - ResponseMessage string `json:"response_message,omitempty"` - StatusCode int `json:"-"` - Kind string `json:"kind,omitempty"` + Attributes []common.Attribute `json:"attributes,omitempty"` } type VerifyApiKeyRequest struct {