Access Entity (#27)
* [ISSUE-67901957] refactor
* [ISSUE-67901957] update glide.yaml
* [ISSUE-67901957] refactor dbManager
* [ISSUE-67901957] add "entities/apiproducts" endpoint
* [ISSUE-67901957] fix bug
* [ISSUE-67901957] implement all endpoints
* [ISSUE-67901957] fix bugs
* [ISSUE-67901957] add org
* [ISSUE-67901957] fix bugs
* [ISSUE-67901957] add tests, change identifiers to outermost
* [ISSUE-67901957] add db tests
* [ISSUE-67901957] 404 for no resources
* [ISSUE-67901957] update glide.yaml
* [ISSUE-67901957] fix bug
* [ISSUE-67901957] fix bug
* [ISSUE-67901957] add api tests
* [ISSUE-67901957] do not omit empty json fields
* [ISSUE-67901957] update api specs
* [ISSUE-67901957] address comments
* [ISSUE-67901957] correct typos
* [ISSUE-67901957] address comments, prevent SQL injection
* [ISSUE-67901957] add coverage to travis
diff --git a/.travis.yml b/.travis.yml
index 9a1d122..8ba8205 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,4 +12,4 @@
- glide up --strip-vendor
script:
- - go test $(glide novendor)
+ - go test -covermode=atomic $(glide novendor)
diff --git a/accessEntity/accessEntity_suite_test.go b/accessEntity/accessEntity_suite_test.go
new file mode 100644
index 0000000..7ffc503
--- /dev/null
+++ b/accessEntity/accessEntity_suite_test.go
@@ -0,0 +1,56 @@
+// 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 accessEntity
+
+import (
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+
+ "github.com/apid/apid-core"
+ "github.com/apid/apid-core/factory"
+ "github.com/apid/apidVerifyApiKey/common"
+ "io/ioutil"
+ "os"
+ "testing"
+ "time"
+)
+
+var testTempDirBase string
+
+func initSetup(s apid.Services) (apid.PluginData, error) {
+ SetApidServices(s, apid.Log())
+ common.SetApidServices(s, s.Log())
+ return common.PluginData, nil
+}
+
+var _ = BeforeSuite(func() {
+ apid.RegisterPlugin(initSetup, common.PluginData)
+ var err error
+ testTempDirBase, err = ioutil.TempDir("", "verify_apikey_")
+ Expect(err).Should(Succeed())
+ apid.Initialize(factory.DefaultServicesFactory())
+ apid.InitializePlugins("0.0.0")
+ go services.API().Listen()
+ time.Sleep(time.Second)
+}, 2)
+
+var _ = AfterSuite(func() {
+ apid.Events().Close()
+ Expect(os.RemoveAll(testTempDirBase)).Should(Succeed())
+})
+
+func TestVerifyAPIKey(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "AccessEntity Suite")
+}
diff --git a/accessEntity/api.go b/accessEntity/api.go
new file mode 100644
index 0000000..d70306d
--- /dev/null
+++ b/accessEntity/api.go
@@ -0,0 +1,721 @@
+// 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 accessEntity
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/apid/apidVerifyApiKey/common"
+ "net/http"
+ "strconv"
+ "strings"
+)
+
+const (
+ AccessEntityPath = "/entities"
+ EndpointApp = "/apps"
+ EndpointApiProduct = "/apiproducts"
+ EndpointCompany = "/companies"
+ EndpointCompanyDeveloper = "/companydevelopers"
+ EndpointDeveloper = "/developers"
+ EndpointAppCredentials = "/appcredentials"
+)
+
+const (
+ IdentifierAppId = "appid"
+ IdentifierApiProductName = "apiproductname"
+ IdentifierAppName = "appname"
+ IdentifierApiResource = "apiresource"
+ IdentifierDeveloperId = "developerid"
+ IdentifierDeveloperEmail = "developeremail"
+ IdentifierConsumerKey = "consumerkey"
+ IdentifierCompanyName = "companyname"
+ IdentifierOrganization = "organization"
+)
+
+const (
+ TypeDeveloper = "developer"
+ TypeCompany = "company"
+ TypeApp = "app"
+ TypeConsumerKey = "consumerkey"
+)
+
+const (
+ AppTypeDeveloper = "DEVELOPER"
+ AppTypeCompany = "COMPANY"
+)
+
+const (
+ StatusApproved = "APPROVED"
+ StatusRevoked = "REVOKED"
+ StatusExpired = "EXPIRED"
+)
+
+var (
+ Identifiers = map[string]bool{
+ "appid": true,
+ "apiproductname": true,
+ "appname": true,
+ "apiresource": true,
+ "developerid": true,
+ "companyname": true,
+ "developeremail": true,
+ "consumerkey": true,
+ }
+
+ ErrInvalidPar = &common.ErrorResponse{
+ ResponseCode: strconv.Itoa(INVALID_PARAMETERS),
+ ResponseMessage: "Invalid Identifiers",
+ StatusCode: http.StatusBadRequest,
+ }
+
+ ErrNotFound = &common.ErrorResponse{
+ ResponseCode: strconv.Itoa(NOT_FOUND),
+ ResponseMessage: "Resource Not Found",
+ StatusCode: http.StatusNotFound,
+ }
+
+ IdentifierTree = map[string]map[string][]string{
+ EndpointApiProduct: {
+ IdentifierApiProductName: {},
+ IdentifierAppId: {IdentifierApiResource},
+ IdentifierAppName: {IdentifierApiResource, IdentifierDeveloperEmail, IdentifierDeveloperId, IdentifierCompanyName},
+ IdentifierConsumerKey: {IdentifierApiResource},
+ },
+ EndpointApp: {
+ IdentifierAppId: {},
+ IdentifierAppName: {IdentifierDeveloperEmail, IdentifierDeveloperId, IdentifierCompanyName},
+ IdentifierConsumerKey: {},
+ },
+ EndpointCompany: {
+ IdentifierAppId: {},
+ IdentifierCompanyName: {},
+ IdentifierConsumerKey: {},
+ },
+ EndpointCompanyDeveloper: {
+ IdentifierCompanyName: {},
+ },
+ EndpointAppCredentials: {
+ IdentifierConsumerKey: {},
+ },
+ EndpointDeveloper: {
+ IdentifierDeveloperEmail: {},
+ IdentifierAppId: {},
+ IdentifierDeveloperId: {},
+ IdentifierConsumerKey: {},
+ },
+ }
+)
+
+const (
+ INVALID_PARAMETERS = iota
+ // Server DB Error
+ DB_ERROR
+ // Invalid/Wrong Data in DB data. This probably means something wrong happened in upstream PG/Transicator.
+ DATA_ERROR
+ // 404
+ NOT_FOUND
+)
+
+type ApiManager struct {
+ DbMan DbManagerInterface
+ AccessEntityPath string
+ apiInitialized bool
+}
+
+func (a *ApiManager) InitAPI() {
+ if a.apiInitialized {
+ return
+ }
+ services.API().HandleFunc(a.AccessEntityPath+EndpointApp, a.HandleApps).Methods("GET")
+ services.API().HandleFunc(a.AccessEntityPath+EndpointApiProduct, a.HandleApiProducts).Methods("GET")
+ services.API().HandleFunc(a.AccessEntityPath+EndpointCompany, a.HandleCompanies).Methods("GET")
+ services.API().HandleFunc(a.AccessEntityPath+EndpointCompanyDeveloper, a.HandleCompanyDevelopers).Methods("GET")
+ services.API().HandleFunc(a.AccessEntityPath+EndpointDeveloper, a.HandleDevelopers).Methods("GET")
+ services.API().HandleFunc(a.AccessEntityPath+EndpointAppCredentials, a.HandleAppCredentials).Methods("GET")
+ a.apiInitialized = true
+ log.Debug("API endpoints initialized")
+}
+
+func (a *ApiManager) handleEndpoint(endpoint string, w http.ResponseWriter, r *http.Request) {
+ ids, org, err := extractIdentifiers(r.URL.Query())
+ if err != nil {
+ common.WriteError(w, err.Error(), INVALID_PARAMETERS, http.StatusBadRequest)
+ }
+ var res interface{}
+ var errRes *common.ErrorResponse
+ switch endpoint {
+ case EndpointApp:
+ res, errRes = a.getApp(org, ids)
+ case EndpointApiProduct:
+ res, errRes = a.getApiProduct(org, ids)
+ case EndpointCompany:
+ res, errRes = a.getCompany(org, ids)
+ case EndpointCompanyDeveloper:
+ res, errRes = a.getCompanyDeveloper(org, ids)
+ case EndpointDeveloper:
+ res, errRes = a.getDeveloper(org, ids)
+ case EndpointAppCredentials:
+ res, errRes = a.getAppCredential(org, ids)
+ }
+
+ if errRes != nil {
+ w.WriteHeader(errRes.StatusCode)
+ writeJson(errRes, w, r)
+ return
+ }
+ writeJson(res, w, r)
+}
+
+func (a *ApiManager) HandleApps(w http.ResponseWriter, r *http.Request) {
+ a.handleEndpoint(EndpointApp, w, r)
+}
+
+func (a *ApiManager) HandleApiProducts(w http.ResponseWriter, r *http.Request) {
+ a.handleEndpoint(EndpointApiProduct, w, r)
+}
+
+func (a *ApiManager) HandleCompanies(w http.ResponseWriter, r *http.Request) {
+ a.handleEndpoint(EndpointCompany, w, r)
+}
+
+func (a *ApiManager) HandleCompanyDevelopers(w http.ResponseWriter, r *http.Request) {
+ a.handleEndpoint(EndpointCompanyDeveloper, w, r)
+}
+func (a *ApiManager) HandleDevelopers(w http.ResponseWriter, r *http.Request) {
+ a.handleEndpoint(EndpointDeveloper, w, r)
+}
+
+func (a *ApiManager) HandleAppCredentials(w http.ResponseWriter, r *http.Request) {
+ a.handleEndpoint(EndpointAppCredentials, w, r)
+}
+
+func extractIdentifiers(pars map[string][]string) (map[string]string, string, error) {
+ m := make(map[string]string)
+ orgs := pars[IdentifierOrganization]
+ if len(orgs) == 0 {
+ return nil, "", fmt.Errorf("no org specified")
+ }
+ org := orgs[0]
+ for k, v := range pars {
+ k = strings.ToLower(k)
+ if Identifiers[k] {
+ if len(v) == 1 {
+ m[k] = v[0]
+ } else {
+ return nil, org, fmt.Errorf("each identifier must have only 1 value")
+ }
+ }
+ }
+ return m, org, nil
+}
+
+func (a *ApiManager) getCompanyDeveloper(org string, ids map[string]string) (*CompanyDevelopersSuccessResponse, *common.ErrorResponse) {
+ valid, keyVals := parseIdentifiers(EndpointCompanyDeveloper, ids)
+ if !valid {
+ return nil, ErrInvalidPar
+ }
+ priKey, priVal := keyVals[0], keyVals[1]
+
+ devs, err := a.DbMan.GetCompanyDevelopers(org, priKey, priVal, "", "")
+ if err != nil {
+ log.Errorf("getCompanyDeveloper: %v", err)
+ return nil, newDbError(err)
+ }
+
+ if len(devs) == 0 {
+ return nil, ErrNotFound
+ }
+
+ var details []*CompanyDeveloperDetails
+ for _, dev := range devs {
+ comName, err := a.DbMan.GetComNames(dev.CompanyId, TypeCompany)
+ if err != nil || len(comName) == 0 {
+ log.Errorf("getCompanyDeveloper: %v", err)
+ return nil, newDbError(err)
+ }
+ email, err := a.DbMan.GetDevEmailByDevId(dev.DeveloperId)
+ if err != nil {
+ log.Errorf("getCompanyDeveloper: %v", err)
+ return nil, newDbError(err)
+ }
+ detail := makeComDevDetails(&dev, comName[0], email)
+ details = append(details, detail)
+ }
+ return &CompanyDevelopersSuccessResponse{
+ CompanyDevelopers: details,
+ Organization: org,
+ PrimaryIdentifierType: priKey,
+ PrimaryIdentifierValue: priVal,
+ }, nil
+}
+
+func (a *ApiManager) getDeveloper(org string, ids map[string]string) (*DeveloperSuccessResponse, *common.ErrorResponse) {
+ valid, keyVals := parseIdentifiers(EndpointDeveloper, ids)
+ if !valid {
+ return nil, ErrInvalidPar
+ }
+ priKey, priVal := keyVals[0], keyVals[1]
+
+ devs, err := a.DbMan.GetDevelopers(org, priKey, priVal, "", "")
+ if err != nil {
+ log.Errorf("getDeveloper: %v", err)
+ return nil, newDbError(err)
+ }
+
+ if len(devs) == 0 {
+ return nil, ErrNotFound
+ }
+ dev := &devs[0]
+
+ attrs := a.DbMan.GetKmsAttributes(dev.TenantId, dev.Id)[dev.Id]
+ comNames, err := a.DbMan.GetComNames(dev.Id, TypeDeveloper)
+ if err != nil {
+ log.Errorf("getDeveloper: %v", err)
+ return nil, newDbError(err)
+ }
+ appNames, err := a.DbMan.GetAppNames(dev.Id, TypeDeveloper)
+ if err != nil {
+ log.Errorf("getDeveloper: %v", err)
+ return nil, newDbError(err)
+ }
+ details := makeDevDetails(dev, appNames, comNames, attrs)
+ return &DeveloperSuccessResponse{
+ Developer: details,
+ Organization: org,
+ PrimaryIdentifierType: priKey,
+ PrimaryIdentifierValue: priVal,
+ }, nil
+}
+
+func (a *ApiManager) getCompany(org string, ids map[string]string) (*CompanySuccessResponse, *common.ErrorResponse) {
+ valid, keyVals := parseIdentifiers(EndpointCompany, ids)
+ if !valid {
+ return nil, ErrInvalidPar
+ }
+ priKey, priVal := keyVals[0], keyVals[1]
+
+ coms, err := a.DbMan.GetCompanies(org, priKey, priVal, "", "")
+ if err != nil {
+ log.Errorf("getCompany: %v", err)
+ return nil, newDbError(err)
+ }
+
+ if len(coms) == 0 {
+ return nil, ErrNotFound
+ }
+ com := &coms[0]
+
+ attrs := a.DbMan.GetKmsAttributes(com.TenantId, com.Id)[com.Id]
+ appNames, err := a.DbMan.GetAppNames(com.Id, TypeCompany)
+ if err != nil {
+ log.Errorf("getCompany: %v", err)
+ return nil, newDbError(err)
+ }
+ details := makeCompanyDetails(com, appNames, attrs)
+ return &CompanySuccessResponse{
+ Company: details,
+ Organization: org,
+ PrimaryIdentifierType: priKey,
+ PrimaryIdentifierValue: priVal,
+ }, nil
+}
+
+func (a *ApiManager) getApiProduct(org string, ids map[string]string) (*ApiProductSuccessResponse, *common.ErrorResponse) {
+ valid, keyVals := parseIdentifiers(EndpointApiProduct, ids)
+ if !valid {
+ return nil, ErrInvalidPar
+ }
+ priKey, priVal, secKey, secVal := keyVals[0], keyVals[1], "", ""
+ if len(keyVals) > 2 {
+ secKey, secVal = keyVals[2], keyVals[3]
+ }
+ prods, err := a.DbMan.GetApiProducts(org, priKey, priVal, secKey, secVal)
+ if err != nil {
+ log.Errorf("getApiProduct: %v", err)
+ return nil, newDbError(err)
+ }
+
+ var attrs []common.Attribute
+ if len(prods) == 0 {
+ return nil, ErrNotFound
+ }
+ prod := &prods[0]
+ attrs = a.DbMan.GetKmsAttributes(prod.TenantId, prod.Id)[prod.Id]
+ details, errRes := makeApiProductDetails(prod, attrs)
+ if errRes != nil {
+ return nil, errRes
+ }
+
+ return &ApiProductSuccessResponse{
+ ApiProduct: details,
+ Organization: org,
+ PrimaryIdentifierType: priKey,
+ PrimaryIdentifierValue: priVal,
+ SecondaryIdentifierType: secKey,
+ SecondaryIdentifierValue: secVal,
+ }, nil
+}
+
+func (a *ApiManager) getAppCredential(org string, ids map[string]string) (*AppCredentialSuccessResponse, *common.ErrorResponse) {
+ valid, keyVals := parseIdentifiers(EndpointApiProduct, ids)
+ if !valid {
+ return nil, ErrInvalidPar
+ }
+ priKey, priVal := keyVals[0], keyVals[1]
+
+ appCreds, err := a.DbMan.GetAppCredentials(org, priKey, priVal, "", "")
+ if err != nil {
+ log.Errorf("getAppCredential: %v", err)
+ return nil, newDbError(err)
+ }
+
+ if len(appCreds) == 0 {
+ return nil, ErrNotFound
+ }
+ appCred := &appCreds[0]
+ attrs := a.DbMan.GetKmsAttributes(appCred.TenantId, appCred.Id)[appCred.Id]
+ apps, err := a.DbMan.GetApps(org, IdentifierAppId, appCred.AppId, "", "")
+ if err != nil {
+ log.Errorf("getAppCredential: %v", err)
+ return nil, newDbError(err)
+ }
+
+ if len(apps) == 0 {
+ log.Errorf("getAppCredential: No App with id=%v", appCred.AppId)
+ return &AppCredentialSuccessResponse{
+ AppCredential: nil,
+ Organization: org,
+ }, nil
+ }
+ app := &apps[0]
+ cd, errRes := a.getCredDetails(appCred, app.Status)
+ if errRes != nil {
+ return nil, errRes
+ }
+ devStatus := ""
+ if app.DeveloperId != "" {
+ devStatus, err = a.DbMan.GetStatus(app.DeveloperId, AppTypeDeveloper)
+ if err != nil {
+ log.Errorf("getAppCredential error get status: %v", err)
+ return nil, newDbError(err)
+ }
+ }
+ cks := makeConsumerKeyStatusDetails(app, cd, devStatus)
+ details := makeAppCredentialDetails(appCred, cks, []string{app.CallbackUrl}, attrs)
+ return &AppCredentialSuccessResponse{
+ AppCredential: details,
+ Organization: org,
+ PrimaryIdentifierType: priKey,
+ PrimaryIdentifierValue: priVal,
+ }, nil
+}
+
+func (a *ApiManager) getApp(org string, ids map[string]string) (*AppSuccessResponse, *common.ErrorResponse) {
+ valid, keyVals := parseIdentifiers(EndpointApp, ids)
+ if !valid {
+ return nil, ErrInvalidPar
+ }
+ priKey, priVal, secKey, secVal := keyVals[0], keyVals[1], "", ""
+ if len(keyVals) > 2 {
+ secKey, secVal = keyVals[2], keyVals[3]
+ }
+
+ apps, err := a.DbMan.GetApps(org, priKey, priVal, secKey, secVal)
+ if err != nil {
+ log.Errorf("getApp: %v", err)
+ return nil, newDbError(err)
+ }
+
+ var app *common.App
+ var attrs []common.Attribute
+
+ if len(apps) == 0 {
+ return nil, ErrNotFound
+ }
+
+ app = &apps[0]
+ attrs = a.DbMan.GetKmsAttributes(app.TenantId, app.Id)[app.Id]
+ prods, err := a.DbMan.GetApiProductNames(app.Id, TypeApp)
+ if err != nil {
+ log.Errorf("getApp error getting productNames: %v", err)
+ return nil, newDbError(err)
+ }
+ parStatus, err := a.DbMan.GetStatus(app.ParentId, app.Type)
+ if err != nil {
+ log.Errorf("getApp error getting parent status: %v", err)
+ return nil, newDbError(err)
+ }
+ creds, err := a.DbMan.GetAppCredentials(org, IdentifierAppId, app.Id, "", "")
+ if err != nil {
+ log.Errorf("getApp error getting parent status: %v", err)
+ return nil, newDbError(err)
+ }
+ var credDetails []*CredentialDetails
+ for _, cred := range creds {
+ detail, errRes := a.getCredDetails(&cred, app.Status)
+ if errRes != nil {
+ return nil, errRes
+ }
+ credDetails = append(credDetails, detail)
+ }
+
+ parent, errRes := a.getAppParent(app.ParentId, app.Type)
+ if errRes != nil {
+ return nil, errRes
+ }
+ details, errRes := makeAppDetails(app, parent, parStatus, prods, credDetails, attrs)
+ if errRes != nil {
+ return nil, errRes
+ }
+ return &AppSuccessResponse{
+ App: details,
+ Organization: org,
+ PrimaryIdentifierType: priKey,
+ PrimaryIdentifierValue: priVal,
+ SecondaryIdentifierType: secKey,
+ SecondaryIdentifierValue: secVal,
+ }, nil
+}
+
+func (a *ApiManager) getAppParent(id string, parentType string) (string, *common.ErrorResponse) {
+ switch parentType {
+ case AppTypeDeveloper:
+ return id, nil
+ case AppTypeCompany:
+ names, err := a.DbMan.GetComNames(id, TypeCompany)
+ if err != nil {
+ return "", newDbError(err)
+ }
+ if len(names) == 0 {
+ log.Warnf("getAppParent: No company with id=%v", id)
+ return "", nil
+ }
+ return names[0], nil
+ }
+ return "", nil
+}
+
+func makeConsumerKeyStatusDetails(app *common.App, c *CredentialDetails, devStatus string) *ConsumerKeyStatusDetails {
+ return &ConsumerKeyStatusDetails{
+ AppCredential: c,
+ AppID: c.AppID,
+ AppName: app.Name,
+ AppStatus: app.Status,
+ AppType: app.Type,
+ DeveloperID: app.DeveloperId,
+ DeveloperStatus: devStatus,
+ IsValidKey: strings.EqualFold(c.Status, StatusApproved),
+ }
+}
+
+func makeAppCredentialDetails(ac *common.AppCredential, cks *ConsumerKeyStatusDetails, redirectUrl []string, attrs []common.Attribute) *AppCredentialDetails {
+ return &AppCredentialDetails{
+ AppID: ac.AppId,
+ AppName: cks.AppName,
+ Attributes: attrs,
+ ConsumerKey: ac.Id,
+ ConsumerKeyStatus: cks,
+ ConsumerSecret: ac.ConsumerSecret,
+ DeveloperID: cks.DeveloperID,
+ RedirectUris: redirectUrl,
+ Scopes: common.JsonToStringArray(ac.Scopes),
+ Status: ac.Status,
+ }
+}
+
+func makeApiProductDetails(prod *common.ApiProduct, attrs []common.Attribute) (*ApiProductDetails, *common.ErrorResponse) {
+ var a *ApiProductDetails
+ if prod != nil {
+ var quotaLimit int
+ var err error
+ if prod.Quota != "" {
+ quotaLimit, err = strconv.Atoi(prod.Quota)
+ if err != nil {
+ return nil, newDataError(err)
+ }
+ }
+
+ a = &ApiProductDetails{
+ ApiProxies: common.JsonToStringArray(prod.Proxies),
+ ApiResources: common.JsonToStringArray(prod.ApiResources),
+ ApprovalType: prod.ApprovalType,
+ Attributes: attrs,
+ CreatedAt: prod.CreatedAt,
+ CreatedBy: prod.CreatedBy,
+ Description: prod.Description,
+ DisplayName: prod.DisplayName,
+ Environments: common.JsonToStringArray(prod.Environments),
+ ID: prod.Id,
+ LastModifiedAt: prod.UpdatedAt,
+ LastModifiedBy: prod.UpdatedBy,
+ Name: prod.Name,
+ QuotaInterval: prod.QuotaInterval,
+ QuotaLimit: int64(quotaLimit),
+ QuotaTimeUnit: prod.QuotaTimeUnit,
+ Scopes: common.JsonToStringArray(prod.Scopes),
+ }
+ } else {
+ a = new(ApiProductDetails)
+ }
+ return a, nil
+}
+
+func makeAppDetails(app *common.App, parent string, parentStatus string, prods []string, creds []*CredentialDetails, attrs []common.Attribute) (*AppDetails, *common.ErrorResponse) {
+ var a *AppDetails
+ if app != nil {
+ a = &AppDetails{
+ AccessType: app.AccessType,
+ ApiProducts: prods,
+ AppCredentials: creds,
+ AppFamily: app.AppFamily,
+ AppParentID: parent,
+ AppParentStatus: parentStatus,
+ AppType: app.Type,
+ Attributes: attrs,
+ CallbackUrl: app.CallbackUrl,
+ CreatedAt: app.CreatedAt,
+ CreatedBy: app.CreatedBy,
+ DisplayName: app.DisplayName,
+ Id: app.Id,
+ LastModifiedAt: app.UpdatedAt,
+ LastModifiedBy: app.UpdatedBy,
+ Name: app.Name,
+ Status: app.Status,
+ }
+ } else {
+ a = new(AppDetails)
+ }
+ return a, nil
+}
+
+func makeCompanyDetails(com *common.Company, appNames []string, attrs []common.Attribute) *CompanyDetails {
+ return &CompanyDetails{
+ Apps: appNames,
+ Attributes: attrs,
+ CreatedAt: com.CreatedAt,
+ CreatedBy: com.CreatedBy,
+ DisplayName: com.DisplayName,
+ ID: com.Id,
+ LastModifiedAt: com.UpdatedAt,
+ LastModifiedBy: com.UpdatedBy,
+ Name: com.Name,
+ Status: com.Status,
+ }
+}
+
+func makeDevDetails(dev *common.Developer, appNames []string, comNames []string, attrs []common.Attribute) *DeveloperDetails {
+ return &DeveloperDetails{
+ Apps: appNames,
+ Attributes: attrs,
+ Companies: comNames,
+ CreatedAt: dev.CreatedAt,
+ CreatedBy: dev.CreatedBy,
+ Email: dev.Email,
+ FirstName: dev.FirstName,
+ ID: dev.Id,
+ LastModifiedAt: dev.UpdatedAt,
+ LastModifiedBy: dev.UpdatedBy,
+ LastName: dev.LastName,
+ Password: dev.Password,
+ Status: dev.Status,
+ UserName: dev.UserName,
+ }
+}
+
+func makeComDevDetails(comDev *common.CompanyDeveloper, comName, devEmail string) *CompanyDeveloperDetails {
+ return &CompanyDeveloperDetails{
+ CompanyName: comName,
+ CreatedAt: comDev.CreatedAt,
+ CreatedBy: comDev.CreatedBy,
+ DeveloperEmail: devEmail,
+ LastModifiedAt: comDev.UpdatedAt,
+ LastModifiedBy: comDev.UpdatedBy,
+ Roles: common.JsonToStringArray(comDev.Roles),
+ }
+}
+
+func (a *ApiManager) getCredDetails(cred *common.AppCredential, appStatus string) (*CredentialDetails, *common.ErrorResponse) {
+
+ refs, err := a.DbMan.GetApiProductNames(cred.Id, TypeConsumerKey)
+ if err != nil {
+ log.Errorf("Error when getting product reference list")
+ return nil, newDbError(err)
+ }
+ return &CredentialDetails{
+ ApiProductReferences: refs,
+ AppID: cred.AppId,
+ AppStatus: appStatus,
+ Attributes: a.DbMan.GetKmsAttributes(cred.TenantId, cred.Id)[cred.Id],
+ ConsumerKey: cred.Id,
+ ConsumerSecret: cred.ConsumerSecret,
+ ExpiresAt: cred.ExpiresAt,
+ IssuedAt: cred.IssuedAt,
+ MethodType: cred.MethodType,
+ Scopes: common.JsonToStringArray(cred.Scopes),
+ Status: cred.Status,
+ }, nil
+}
+
+func parseIdentifiers(endpoint string, ids map[string]string) (valid bool, keyVals []string) {
+ if len(ids) > 2 {
+ return false, nil
+ }
+ if m := IdentifierTree[endpoint]; m != nil {
+ for key, val := range ids {
+ if m[key] != nil {
+ keyVals = append(keyVals, key, val)
+ for _, id := range m[key] {
+ if ids[id] != "" {
+ keyVals = append(keyVals, id, ids[id])
+ return true, keyVals
+ }
+ }
+ if len(ids) == 2 {
+ return false, nil
+ }
+ return true, keyVals
+ }
+ }
+ }
+ return false, nil
+}
+
+func newDbError(err error) *common.ErrorResponse {
+ return &common.ErrorResponse{
+ ResponseCode: strconv.Itoa(DB_ERROR),
+ ResponseMessage: err.Error(),
+ StatusCode: http.StatusInternalServerError,
+ }
+}
+
+func newDataError(err error) *common.ErrorResponse {
+ return &common.ErrorResponse{
+ ResponseCode: strconv.Itoa(DATA_ERROR),
+ ResponseMessage: err.Error(),
+ StatusCode: http.StatusInternalServerError,
+ }
+}
+
+func writeJson(obj interface{}, w http.ResponseWriter, r *http.Request) {
+ bytes, err := json.Marshal(obj)
+ if err != nil {
+ log.Error("unable to marshal errorResponse: " + err.Error())
+ w.Write([]byte("unable to marshal errorResponse: " + err.Error()))
+ } else {
+ w.Header().Set("Content-Type", "application/json")
+ w.Write(bytes)
+ }
+}
diff --git a/accessEntity/api_response.go b/accessEntity/api_response.go
new file mode 100644
index 0000000..ea1e65c
--- /dev/null
+++ b/accessEntity/api_response.go
@@ -0,0 +1,313 @@
+// 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 accessEntity
+
+import "github.com/apid/apidVerifyApiKey/common"
+
+type ApiProductSuccessResponse struct {
+ // api product
+ ApiProduct *ApiProductDetails `json:"apiProduct"`
+ // Organization Identifier/Name
+ Organization string `json:"organization"`
+ // primary identifier type
+ PrimaryIdentifierType string `json:"primaryIdentifierType"`
+ // primary identifier value
+ PrimaryIdentifierValue string `json:"primaryIdentifierValue"`
+ // secondary identifier type
+ SecondaryIdentifierType string `json:"secondaryIdentifierType"`
+ // secondary identifier value
+ SecondaryIdentifierValue string `json:"secondaryIdentifierValue"`
+}
+
+type AppCredentialSuccessResponse struct {
+ // app credential
+ AppCredential *AppCredentialDetails `json:"appCredential"`
+ // Organization Identifier/Name
+ Organization string `json:"organization"`
+ // primary identifier type
+ PrimaryIdentifierType string `json:"primaryIdentifierType"`
+ // primary identifier value
+ PrimaryIdentifierValue string `json:"primaryIdentifierValue"`
+}
+
+type AppSuccessResponse struct {
+ // app
+ App *AppDetails `json:"app"`
+ // Organization Identifier/Name
+ Organization string `json:"organization"`
+ // primary identifier type
+ PrimaryIdentifierType string `json:"primaryIdentifierType"`
+ // primary identifier value
+ PrimaryIdentifierValue string `json:"primaryIdentifierValue"`
+ // secondary identifier type
+ SecondaryIdentifierType string `json:"secondaryIdentifierType"`
+ // secondary identifier value
+ SecondaryIdentifierValue string `json:"secondaryIdentifierValue"`
+}
+
+type CompanyDevelopersSuccessResponse struct {
+ // company developers
+ CompanyDevelopers []*CompanyDeveloperDetails `json:"companyDevelopers"`
+ // Organization Identifier/Name
+ Organization string `json:"organization"`
+ // primary identifier type
+ PrimaryIdentifierType string `json:"primaryIdentifierType"`
+ // primary identifier value
+ PrimaryIdentifierValue string `json:"primaryIdentifierValue"`
+}
+
+type CompanySuccessResponse struct {
+ // company
+ Company *CompanyDetails `json:"company"`
+ // Organization Identifier/Name
+ Organization string `json:"organization"`
+ // primary identifier type
+ PrimaryIdentifierType string `json:"primaryIdentifierType"`
+ // primary identifier value
+ PrimaryIdentifierValue string `json:"primaryIdentifierValue"`
+}
+
+type DeveloperSuccessResponse struct {
+ // developer
+ Developer *DeveloperDetails `json:"developer"`
+ // Organization Identifier/Name
+ Organization string `json:"organization"`
+ // primary identifier type
+ PrimaryIdentifierType string `json:"primaryIdentifierType"`
+ // primary identifier value
+ PrimaryIdentifierValue string `json:"primaryIdentifierValue"`
+}
+
+type ApiProductDetails struct {
+ // api proxies
+ ApiProxies []string `json:"apiProxies"`
+ // api resources
+ ApiResources []string `json:"apiResources"`
+ // approval type
+ ApprovalType string `json:"approvalType"`
+ // Attributes associated with the apiproduct.
+ Attributes []common.Attribute `json:"attributes"`
+ // ISO-8601
+ CreatedAt string `json:"createdAt"`
+ // created by
+ CreatedBy string `json:"createdBy"`
+ // description
+ Description string `json:"description"`
+ // display name
+ DisplayName string `json:"displayName"`
+ // environments
+ Environments []string `json:"environments"`
+ // id
+ ID string `json:"id"`
+ // ISO-8601
+ LastModifiedAt string `json:"lastModifiedAt"`
+ // last modified by
+ LastModifiedBy string `json:"lastModifiedBy"`
+ // name
+ Name string `json:"name"`
+ // quota interval
+ QuotaInterval int64 `json:"quotaInterval"`
+ // quota limit
+ QuotaLimit int64 `json:"quotaLimit"`
+ // quota time unit
+ QuotaTimeUnit string `json:"quotaTimeUnit"`
+ // scopes
+ Scopes []string `json:"scopes"`
+}
+
+type AppDetails struct {
+
+ // access type
+ AccessType string `json:"accessType"`
+ // api products
+ ApiProducts []string `json:"apiProducts"`
+ // app credentials
+ AppCredentials []*CredentialDetails `json:"appCredentials"`
+ // app family
+ AppFamily string `json:"appFamily"`
+ // app parent, developer's Id or company's name
+ AppParentID string `json:"appParentId"`
+ // app parent status
+ AppParentStatus string `json:"appParentStatus"`
+ // Developer or Company
+ AppType string `json:"appType"`
+ // Attributes associated with the app.
+ Attributes []common.Attribute `json:"attributes"`
+ // callback Url
+ CallbackUrl string `json:"callbackUrl"`
+ // ISO-8601
+ CreatedAt string `json:"createdAt"`
+ // created by
+ CreatedBy string `json:"createdBy"`
+ // display name
+ DisplayName string `json:"displayName"`
+ // id
+ Id string `json:"id"`
+ // ISO-8601
+ LastModifiedAt string `json:"lastModifiedAt"`
+ // last modified by
+ LastModifiedBy string `json:"lastModifiedBy"`
+ // name
+ Name string `json:"name"`
+ // status
+ Status string `json:"status"`
+}
+
+type CredentialDetails struct {
+ // api product references
+ ApiProductReferences []string `json:"apiProductReferences"`
+ // app Id
+ AppID string `json:"appId"`
+ // app status
+ AppStatus string `json:"appStatus"`
+ // Attributes associated with the client Id.
+ Attributes []common.Attribute `json:"attributes"`
+ // consumer key
+ ConsumerKey string `json:"consumerKey"`
+ // consumer secret
+ ConsumerSecret string `json:"consumerSecret"`
+ // expires at
+ ExpiresAt string `json:"expiresAt"`
+ // issued at
+ IssuedAt string `json:"issuedAt"`
+ // method type
+ MethodType string `json:"methodType"`
+ // scopes
+ Scopes []string `json:"scopes"`
+ // status
+ Status string `json:"status"`
+}
+
+/*
+type ApiProductReferenceDetails struct {
+ // status of the api product
+ Status string `json:"status"`
+ // name of the api product
+ ApiProduct string `json:"apiProduct"`
+}
+*/
+type AppCredentialDetails struct {
+ // app Id
+ AppID string `json:"appId"`
+ // app name
+ AppName string `json:"appName"`
+ // Attributes associated with the app credential
+ Attributes []common.Attribute `json:"attributes"`
+ // consumer key
+ ConsumerKey string `json:"consumerKey"`
+ // consumer key status
+ ConsumerKeyStatus *ConsumerKeyStatusDetails `json:"consumerKeyStatus"`
+ // consumer secret
+ ConsumerSecret string `json:"consumerSecret"`
+ // developer Id
+ DeveloperID string `json:"developerId"`
+ // redirect uris
+ RedirectUris []string `json:"redirectURIs"`
+ // scopes
+ Scopes []string `json:"scopes"`
+ // status
+ Status string `json:"status"`
+}
+
+type ConsumerKeyStatusDetails struct {
+ // app credential
+ AppCredential *CredentialDetails `json:"appCredential"`
+ // app Id
+ AppID string `json:"appId"`
+ // app name
+ AppName string `json:"appName"`
+ // app status
+ AppStatus string `json:"appStatus"`
+ // app type
+ AppType string `json:"appType"`
+ // developer Id
+ DeveloperID string `json:"developerId"`
+ // developer status
+ DeveloperStatus string `json:"developerStatus"`
+ // is valid key
+ IsValidKey bool `json:"isValidKey"`
+}
+
+type CompanyDetails struct {
+
+ // apps
+ Apps []string `json:"apps"`
+ // Attributes associated with the company.
+ Attributes []common.Attribute `json:"attributes"`
+ // ISO-8601
+ CreatedAt string `json:"createdAt"`
+ // created by
+ CreatedBy string `json:"createdBy"`
+ // display name
+ DisplayName string `json:"displayName"`
+ // id
+ ID string `json:"id"`
+ // ISO-8601
+ LastModifiedAt string `json:"lastModifiedAt"`
+ // last modified by
+ LastModifiedBy string `json:"lastModifiedBy"`
+ // name
+ Name string `json:"name"`
+ // status
+ Status string `json:"status"`
+}
+
+type CompanyDeveloperDetails struct {
+ // company name
+ CompanyName string `json:"companyName"`
+ // ISO-8601
+ CreatedAt string `json:"createdAt"`
+ // created by
+ CreatedBy string `json:"createdBy"`
+ // developer email
+ DeveloperEmail string `json:"developerEmail"`
+ // ISO-8601
+ LastModifiedAt string `json:"lastModifiedAt"`
+ // last modified by
+ LastModifiedBy string `json:"lastModifiedBy"`
+ // roles
+ Roles []string `json:"roles"`
+}
+
+type DeveloperDetails struct {
+ // apps
+ Apps []string `json:"apps"`
+ // Attributes associated with the developer.
+ Attributes []common.Attribute `json:"attributes"`
+ // companies
+ Companies []string `json:"companies"`
+ // ISO-8601
+ CreatedAt string `json:"createdAt"`
+ // created by
+ CreatedBy string `json:"createdBy"`
+ // email
+ Email string `json:"email"`
+ // first name
+ FirstName string `json:"firstName"`
+ // id
+ ID string `json:"id"`
+ // ISO-8601
+ LastModifiedAt string `json:"lastModifiedAt"`
+ // last modified by
+ LastModifiedBy string `json:"lastModifiedBy"`
+ // last name
+ LastName string `json:"lastName"`
+ // password
+ Password string `json:"password"`
+ // status
+ Status string `json:"status"`
+ // user name
+ UserName string `json:"userName"`
+}
diff --git a/accessEntity/api_test.go b/accessEntity/api_test.go
new file mode 100644
index 0000000..7f46f07
--- /dev/null
+++ b/accessEntity/api_test.go
@@ -0,0 +1,776 @@
+// 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 accessEntity
+
+import (
+ "encoding/json"
+ "github.com/apid/apidVerifyApiKey/common"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strconv"
+ "time"
+)
+
+const (
+ apiTestUrl = "http://127.0.0.1:9000"
+)
+
+var _ = Describe("API Tests", func() {
+ var apiMan *ApiManager
+ testCount := 0
+ client := &http.Client{}
+ dbMan := &DummyDbMan{}
+ var attrs []common.Attribute
+ var testId string
+ clientGet := func(path string, pars map[string][]string) (int, []byte) {
+ uri, err := url.Parse(apiTestUrl + path)
+ Expect(err).Should(Succeed())
+ query := url.Values(pars)
+ uri.RawQuery = query.Encode()
+ httpReq, err := http.NewRequest("GET", uri.String(), nil)
+ Expect(err).Should(Succeed())
+ res, err := client.Do(httpReq)
+ Expect(err).Should(Succeed())
+ defer res.Body.Close()
+ responseBody, err := ioutil.ReadAll(res.Body)
+ Expect(err).Should(Succeed())
+ return res.StatusCode, responseBody
+ }
+
+ BeforeEach(func() {
+ testCount++
+ testId = "test-" + strconv.Itoa(testCount)
+ apiMan = &ApiManager{
+ DbMan: dbMan,
+ AccessEntityPath: AccessEntityPath + strconv.Itoa(testCount),
+ apiInitialized: false,
+ }
+ attrs = setAttrs(dbMan, testId)
+ apiMan.InitAPI()
+ time.Sleep(100 * time.Millisecond)
+ })
+
+ It("ApiProduct", func() {
+ testProd := []common.ApiProduct{
+ {
+ Id: testId,
+ Name: "apstest",
+ DisplayName: "apstest",
+ Description: "",
+ ApiResources: "{/**}",
+ ApprovalType: "AUTO",
+ Scopes: `{foo,bar}`,
+ Proxies: `{aps,perfBenchmark}`,
+ Environments: `{prod,test}`,
+ Quota: "10000000",
+ QuotaTimeUnit: "MINUTE",
+ QuotaInterval: 1,
+ CreatedAt: "2017-08-18 22:12:49.363+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-08-18 22:26:50.153+00:00",
+ UpdatedBy: "haoming@apid.git",
+ TenantId: "515211e9",
+ },
+ }
+
+ expected := ApiProductSuccessResponse{
+ ApiProduct: &ApiProductDetails{
+ ApiProxies: []string{"aps", "perfBenchmark"},
+ ApiResources: []string{"/**"},
+ ApprovalType: testProd[0].ApprovalType,
+ Attributes: attrs,
+ CreatedAt: testProd[0].CreatedAt,
+ CreatedBy: testProd[0].CreatedBy,
+ Description: testProd[0].Description,
+ DisplayName: testProd[0].DisplayName,
+ Environments: []string{"prod", "test"},
+ ID: testProd[0].Id,
+ LastModifiedAt: testProd[0].UpdatedAt,
+ LastModifiedBy: testProd[0].UpdatedBy,
+ Name: testProd[0].Name,
+ QuotaInterval: testProd[0].QuotaInterval,
+ QuotaLimit: 10000000,
+ QuotaTimeUnit: testProd[0].QuotaTimeUnit,
+ Scopes: []string{"foo", "bar"},
+ },
+ Organization: "test-org",
+ PrimaryIdentifierType: IdentifierAppName,
+ PrimaryIdentifierValue: "test-app",
+ SecondaryIdentifierType: IdentifierDeveloperId,
+ SecondaryIdentifierValue: "test-dev",
+ }
+
+ testData := [][]common.ApiProduct{
+ testProd,
+ nil,
+ testProd,
+ testProd,
+ }
+
+ testPars := []map[string][]string{
+ // positive
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppName: {"test-app"},
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ // negative
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppName: {"test-app"},
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ {
+ IdentifierAppName: {"test-app"},
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ {
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ }
+
+ results := [][]interface{}{
+ {http.StatusOK, expected},
+ {http.StatusNotFound, nil},
+ {http.StatusBadRequest, nil},
+ {http.StatusBadRequest, nil},
+ }
+
+ for i, data := range testData {
+ dbMan.apiProducts = data
+ code, body := clientGet(apiMan.AccessEntityPath+EndpointApiProduct, testPars[i])
+ Expect(code).Should(Equal(results[i][0]))
+ if results[i][1] != nil {
+ var res ApiProductSuccessResponse
+ Expect(json.Unmarshal(body, &res)).Should(Succeed())
+ Expect(res).Should(Equal(results[i][1]))
+ }
+ }
+
+ })
+
+ It("Apps", func() {
+ testApp := []common.App{
+ {
+ Id: testId,
+ TenantId: "515211e9",
+ Name: "apstest",
+ DisplayName: "apstest",
+ AccessType: "READ",
+ CallbackUrl: "https://www.google.com",
+ Status: "APPROVED",
+ AppFamily: "default",
+ CompanyId: "",
+ DeveloperId: "e41f04e8-9d3f-470a-8bfd-c7939945896c",
+ ParentId: "e41f04e8-9d3f-470a-8bfd-c7939945896c",
+ Type: "DEVELOPER",
+ CreatedAt: "2017-08-18 22:13:18.325+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-08-18 22:13:18.325+00:00",
+ UpdatedBy: "haoming@apid.git",
+ },
+ }
+
+ testComApp := []common.App{
+ {
+ Id: testId,
+ TenantId: "515211e9",
+ Name: "apstest",
+ DisplayName: "apstest",
+ AccessType: "READ",
+ CallbackUrl: "https://www.google.com",
+ Status: "APPROVED",
+ AppFamily: "default",
+ CompanyId: "a94f75e2-69b0-44af-8776-155df7c7d22e",
+ DeveloperId: "",
+ ParentId: "a94f75e2-69b0-44af-8776-155df7c7d22e",
+ Type: "COMPANY",
+ CreatedAt: "2017-08-18 22:13:18.325+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-08-18 22:13:18.325+00:00",
+ UpdatedBy: "haoming@apid.git",
+ },
+ }
+
+ testProductNames := []string{"foo", "bar"}
+ testStatus := "test-status"
+ testCreds := []common.AppCredential{
+ {
+ Id: testId,
+ TenantId: "515211e9",
+ ConsumerSecret: "secret1",
+ AppId: testId,
+ MethodType: "GET",
+ Status: "APPROVED",
+ IssuedAt: "2017-08-18 22:13:18.35+00:00",
+ ExpiresAt: "2018-08-18 22:13:18.35+00:00",
+ AppStatus: "APPROVED",
+ Scopes: "{foo,bar}",
+ CreatedAt: "2017-08-18 22:13:18.35+00:00",
+ CreatedBy: "-NA-",
+ UpdatedAt: "2017-08-18 22:13:18.352+00:00",
+ UpdatedBy: "-NA-",
+ },
+ }
+ expected := AppSuccessResponse{
+ App: &AppDetails{
+ AccessType: testApp[0].AccessType,
+ ApiProducts: testProductNames,
+ AppCredentials: []*CredentialDetails{
+ {
+ ApiProductReferences: testProductNames,
+ AppID: testCreds[0].AppId,
+ AppStatus: testApp[0].Status,
+ Attributes: attrs,
+ ConsumerKey: testCreds[0].Id,
+ ConsumerSecret: testCreds[0].ConsumerSecret,
+ ExpiresAt: testCreds[0].ExpiresAt,
+ IssuedAt: testCreds[0].IssuedAt,
+ MethodType: testCreds[0].MethodType,
+ Scopes: []string{"foo", "bar"},
+ Status: testCreds[0].Status,
+ },
+ },
+ AppFamily: testApp[0].AppFamily,
+ AppParentID: testApp[0].ParentId,
+ AppParentStatus: testStatus,
+ AppType: testApp[0].Type,
+ Attributes: attrs,
+ CallbackUrl: testApp[0].CallbackUrl,
+ CreatedAt: testApp[0].CreatedAt,
+ CreatedBy: testApp[0].CreatedBy,
+ DisplayName: testApp[0].DisplayName,
+ Id: testApp[0].Id,
+ LastModifiedAt: testApp[0].UpdatedAt,
+ LastModifiedBy: testApp[0].UpdatedBy,
+ Name: testApp[0].Name,
+ Status: testApp[0].Status,
+ },
+ Organization: "test-org",
+ PrimaryIdentifierType: IdentifierAppName,
+ PrimaryIdentifierValue: "test-app",
+ SecondaryIdentifierType: IdentifierDeveloperId,
+ SecondaryIdentifierValue: "test-dev",
+ }
+
+ expectedComApp := AppSuccessResponse{
+ App: &AppDetails{
+ AccessType: testComApp[0].AccessType,
+ ApiProducts: testProductNames,
+ AppCredentials: []*CredentialDetails{
+ {
+ ApiProductReferences: testProductNames,
+ AppID: testCreds[0].AppId,
+ AppStatus: testComApp[0].Status,
+ Attributes: attrs,
+ ConsumerKey: testCreds[0].Id,
+ ConsumerSecret: testCreds[0].ConsumerSecret,
+ ExpiresAt: testCreds[0].ExpiresAt,
+ IssuedAt: testCreds[0].IssuedAt,
+ MethodType: testCreds[0].MethodType,
+ Scopes: []string{"foo", "bar"},
+ Status: testCreds[0].Status,
+ },
+ },
+ AppFamily: testComApp[0].AppFamily,
+ AppParentID: "testcompanyhflxv",
+ AppParentStatus: testStatus,
+ AppType: testComApp[0].Type,
+ Attributes: attrs,
+ CallbackUrl: testComApp[0].CallbackUrl,
+ CreatedAt: testComApp[0].CreatedAt,
+ CreatedBy: testComApp[0].CreatedBy,
+ DisplayName: testComApp[0].DisplayName,
+ Id: testComApp[0].Id,
+ LastModifiedAt: testComApp[0].UpdatedAt,
+ LastModifiedBy: testComApp[0].UpdatedBy,
+ Name: testComApp[0].Name,
+ Status: testComApp[0].Status,
+ },
+ Organization: "test-org",
+ PrimaryIdentifierType: IdentifierAppName,
+ PrimaryIdentifierValue: "test-app",
+ SecondaryIdentifierType: IdentifierDeveloperId,
+ SecondaryIdentifierValue: "test-dev",
+ }
+
+ testData := [][]common.App{
+ testApp,
+ testComApp,
+ nil,
+ testApp,
+ testApp,
+ }
+
+ testPars := []map[string][]string{
+ // positive
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppName: {"test-app"},
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppName: {"test-app"},
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ // negative
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppName: {"test-app"},
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ {
+ IdentifierAppName: {"test-app"},
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ {
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ }
+
+ results := [][]interface{}{
+ {http.StatusOK, expected},
+ {http.StatusOK, expectedComApp},
+ {http.StatusNotFound, nil},
+ {http.StatusBadRequest, nil},
+ {http.StatusBadRequest, nil},
+ }
+
+ dbMan.apiProductNames = testProductNames
+ dbMan.status = testStatus
+ dbMan.appCredentials = testCreds
+ for i, data := range testData {
+ dbMan.apps = data
+ dbMan.comNames = []string{"testcompanyhflxv"}
+ code, body := clientGet(apiMan.AccessEntityPath+EndpointApp, testPars[i])
+ Expect(code).Should(Equal(results[i][0]))
+ if results[i][1] != nil {
+ var res AppSuccessResponse
+ Expect(json.Unmarshal(body, &res)).Should(Succeed())
+ Expect(res).Should(Equal(results[i][1]))
+ }
+ }
+
+ })
+
+ It("Company", func() {
+ testCom := []common.Company{
+ {
+ Id: testId,
+ TenantId: "515211e9",
+ Name: "testcompanyhflxv",
+ DisplayName: "testcompanyhflxv",
+ Status: "ACTIVE",
+ CreatedAt: "2017-11-02 16:00:16.287+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-11-02 16:00:16.287+00:00",
+ UpdatedBy: "haoming@apid.git",
+ },
+ }
+
+ testAppNames := []string{"foo", "bar"}
+
+ expected := CompanySuccessResponse{
+ Company: &CompanyDetails{
+ Apps: testAppNames,
+ Attributes: attrs,
+ CreatedAt: testCom[0].CreatedAt,
+ CreatedBy: testCom[0].CreatedBy,
+ DisplayName: testCom[0].DisplayName,
+ ID: testCom[0].Id,
+ LastModifiedAt: testCom[0].UpdatedAt,
+ LastModifiedBy: testCom[0].UpdatedBy,
+ Name: testCom[0].Name,
+ Status: testCom[0].Status,
+ },
+ Organization: "test-org",
+ PrimaryIdentifierType: IdentifierAppId,
+ PrimaryIdentifierValue: "test-app",
+ }
+
+ testData := [][]common.Company{
+ testCom,
+ nil,
+ testCom,
+ testCom,
+ }
+
+ testPars := []map[string][]string{
+ // positive
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppId: {"test-app"},
+ },
+ // negative
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppId: {"test-app"},
+ },
+ {
+ IdentifierAppId: {"test-app"},
+ },
+ {
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ }
+
+ results := [][]interface{}{
+ {http.StatusOK, expected},
+ {http.StatusNotFound, nil},
+ {http.StatusBadRequest, nil},
+ {http.StatusBadRequest, nil},
+ }
+
+ dbMan.appNames = testAppNames
+
+ for i, data := range testData {
+ dbMan.companies = data
+ code, body := clientGet(apiMan.AccessEntityPath+EndpointCompany, testPars[i])
+ Expect(code).Should(Equal(results[i][0]))
+ if results[i][1] != nil {
+ var res CompanySuccessResponse
+ Expect(json.Unmarshal(body, &res)).Should(Succeed())
+ Expect(res).Should(Equal(results[i][1]))
+ }
+ }
+
+ })
+
+ It("Developer", func() {
+ testDev := []common.Developer{
+ {
+ Id: testId,
+ TenantId: "515211e9",
+ UserName: "haoming",
+ FirstName: "haoming",
+ LastName: "zhang",
+ Password: "111",
+ Email: "bar@google.com",
+ Status: "ACTIVE",
+ EncryptedPassword: "222",
+ Salt: "333",
+ CreatedAt: "2017-08-16 22:39:46.669+00:00",
+ CreatedBy: "foo@google.com",
+ UpdatedAt: "2017-08-16 22:39:46.669+00:00",
+ UpdatedBy: "foo@google.com",
+ },
+ }
+
+ testAppNames := []string{"foo", "bar"}
+ testComNames := []string{"foo", "bar"}
+
+ expected := DeveloperSuccessResponse{
+ Developer: &DeveloperDetails{
+ Apps: testAppNames,
+ Attributes: attrs,
+ Companies: testComNames,
+ CreatedAt: testDev[0].CreatedAt,
+ CreatedBy: testDev[0].CreatedBy,
+ Email: testDev[0].Email,
+ FirstName: testDev[0].FirstName,
+ ID: testDev[0].Id,
+ LastModifiedAt: testDev[0].UpdatedAt,
+ LastModifiedBy: testDev[0].UpdatedBy,
+ LastName: testDev[0].LastName,
+ Password: testDev[0].Password,
+ Status: testDev[0].Status,
+ UserName: testDev[0].UserName,
+ },
+ Organization: "test-org",
+ PrimaryIdentifierType: IdentifierAppId,
+ PrimaryIdentifierValue: "test-app",
+ }
+
+ testData := [][]common.Developer{
+ testDev,
+ nil,
+ testDev,
+ testDev,
+ }
+
+ testPars := []map[string][]string{
+ // positive
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppId: {"test-app"},
+ },
+ // negative
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierAppId: {"test-app"},
+ },
+ {
+ IdentifierAppId: {"test-app"},
+ },
+ {
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ }
+
+ results := [][]interface{}{
+ {http.StatusOK, expected},
+ {http.StatusNotFound, nil},
+ {http.StatusBadRequest, nil},
+ {http.StatusBadRequest, nil},
+ }
+
+ dbMan.appNames = testAppNames
+ dbMan.comNames = testComNames
+
+ for i, data := range testData {
+ dbMan.developers = data
+ code, body := clientGet(apiMan.AccessEntityPath+EndpointDeveloper, testPars[i])
+ Expect(code).Should(Equal(results[i][0]))
+ if results[i][1] != nil {
+ var res DeveloperSuccessResponse
+ Expect(json.Unmarshal(body, &res)).Should(Succeed())
+ Expect(res).Should(Equal(results[i][1]))
+ }
+ }
+
+ })
+
+ It("AppCredential", func() {
+ testAppCred := []common.AppCredential{
+ {
+ Id: testId,
+ TenantId: "515211e9",
+ ConsumerSecret: "secret1",
+ AppId: testId,
+ MethodType: "GET",
+ Status: "APPROVED",
+ IssuedAt: "2017-08-18 22:13:18.35+00:00",
+ ExpiresAt: "2018-08-18 22:13:18.35+00:00",
+ AppStatus: "APPROVED",
+ Scopes: "{foo,bar}",
+ CreatedAt: "2017-08-18 22:13:18.35+00:00",
+ CreatedBy: "-NA-",
+ UpdatedAt: "2017-08-18 22:13:18.352+00:00",
+ UpdatedBy: "-NA-",
+ },
+ }
+ testApp := []common.App{
+ {
+ Id: testId,
+ TenantId: "515211e9",
+ Name: "apstest",
+ DisplayName: "apstest",
+ AccessType: "READ",
+ CallbackUrl: "https://www.google.com",
+ Status: "APPROVED",
+ AppFamily: "default",
+ CompanyId: "",
+ DeveloperId: "e41f04e8-9d3f-470a-8bfd-c7939945896c",
+ ParentId: "e41f04e8-9d3f-470a-8bfd-c7939945896c",
+ Type: "DEVELOPER",
+ CreatedAt: "2017-08-18 22:13:18.325+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-08-18 22:13:18.325+00:00",
+ UpdatedBy: "haoming@apid.git",
+ },
+ }
+
+ testProductNames := []string{"foo", "bar"}
+ testStatus := "test-status"
+
+ expected := AppCredentialSuccessResponse{
+ AppCredential: &AppCredentialDetails{
+ AppID: testAppCred[0].AppId,
+ AppName: testApp[0].Name,
+ Attributes: attrs,
+ ConsumerKey: testAppCred[0].Id,
+ ConsumerKeyStatus: &ConsumerKeyStatusDetails{
+ AppCredential: &CredentialDetails{
+ ApiProductReferences: testProductNames,
+ AppID: testAppCred[0].AppId,
+ AppStatus: testApp[0].Status,
+ Attributes: attrs,
+ ConsumerKey: testAppCred[0].Id,
+ ConsumerSecret: testAppCred[0].ConsumerSecret,
+ ExpiresAt: testAppCred[0].ExpiresAt,
+ IssuedAt: testAppCred[0].IssuedAt,
+ MethodType: testAppCred[0].MethodType,
+ Scopes: []string{"foo", "bar"},
+ Status: testAppCred[0].Status,
+ },
+ AppID: testAppCred[0].AppId,
+ AppName: testApp[0].Name,
+ AppStatus: testApp[0].Status,
+ AppType: testApp[0].Type,
+ DeveloperID: testApp[0].DeveloperId,
+ DeveloperStatus: testStatus,
+ IsValidKey: true,
+ },
+ ConsumerSecret: testAppCred[0].ConsumerSecret,
+ DeveloperID: testApp[0].DeveloperId,
+ RedirectUris: []string{testApp[0].CallbackUrl},
+ Scopes: []string{"foo", "bar"},
+ Status: testAppCred[0].Status,
+ },
+ Organization: "test-org",
+ PrimaryIdentifierType: IdentifierConsumerKey,
+ PrimaryIdentifierValue: "test-key",
+ }
+
+ testData := [][]common.AppCredential{
+ testAppCred,
+ nil,
+ testAppCred,
+ testAppCred,
+ }
+
+ testPars := []map[string][]string{
+ // positive
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierConsumerKey: {"test-key"},
+ },
+ // negative
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierConsumerKey: {"test-key"},
+ },
+ {
+ IdentifierConsumerKey: {"test-key"},
+ },
+ {
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ }
+
+ results := [][]interface{}{
+ {http.StatusOK, expected},
+ {http.StatusNotFound, nil},
+ {http.StatusBadRequest, nil},
+ {http.StatusBadRequest, nil},
+ }
+
+ dbMan.apiProductNames = testProductNames
+ dbMan.status = testStatus
+ dbMan.apps = testApp
+ for i, data := range testData {
+ dbMan.appCredentials = data
+ code, body := clientGet(apiMan.AccessEntityPath+EndpointAppCredentials, testPars[i])
+ Expect(code).Should(Equal(results[i][0]))
+ if results[i][1] != nil {
+ var res AppCredentialSuccessResponse
+ Expect(json.Unmarshal(body, &res)).Should(Succeed())
+ Expect(res).Should(Equal(results[i][1]))
+ }
+ }
+ })
+
+ It("CompanyDeveloper", func() {
+ testDev := []common.CompanyDeveloper{
+ {
+ TenantId: "515211e9",
+ CompanyId: "a94f75e2-69b0-44af-8776-155df7c7d22e",
+ DeveloperId: "590f33bf-f05c-48c1-bb93-183759bd9ee1",
+ Roles: "{foo,bar}",
+ CreatedAt: "2017-11-02 16:00:16.287+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-11-02 16:00:16.287+00:00",
+ UpdatedBy: "haoming@apid.git",
+ },
+ }
+
+ testComNames := []string{"foo"}
+ testEmail := "haoming@apid.git"
+
+ expected := CompanyDevelopersSuccessResponse{
+ CompanyDevelopers: []*CompanyDeveloperDetails{
+ {
+ CompanyName: testComNames[0],
+ CreatedAt: testDev[0].CreatedAt,
+ CreatedBy: testDev[0].CreatedBy,
+ DeveloperEmail: testEmail,
+ LastModifiedAt: testDev[0].UpdatedAt,
+ LastModifiedBy: testDev[0].UpdatedBy,
+ Roles: []string{"foo", "bar"},
+ },
+ },
+ Organization: "test-org",
+ PrimaryIdentifierType: IdentifierCompanyName,
+ PrimaryIdentifierValue: "test-com",
+ }
+
+ testData := [][]common.CompanyDeveloper{
+ testDev,
+ nil,
+ testDev,
+ testDev,
+ }
+
+ testPars := []map[string][]string{
+ // positive
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierCompanyName: {"test-com"},
+ },
+ // negative
+ {
+ IdentifierOrganization: {"test-org"},
+ IdentifierCompanyName: {"test-com"},
+ },
+ {
+ IdentifierCompanyName: {"test-com"},
+ },
+ {
+ IdentifierDeveloperId: {"test-dev"},
+ },
+ }
+
+ results := [][]interface{}{
+ {http.StatusOK, expected},
+ {http.StatusNotFound, nil},
+ {http.StatusBadRequest, nil},
+ {http.StatusBadRequest, nil},
+ }
+
+ dbMan.comNames = testComNames
+ dbMan.email = testEmail
+
+ for i, data := range testData {
+ dbMan.companyDevelopers = data
+ code, body := clientGet(apiMan.AccessEntityPath+EndpointCompanyDeveloper, testPars[i])
+ Expect(code).Should(Equal(results[i][0]))
+ if results[i][1] != nil {
+ var res CompanyDevelopersSuccessResponse
+ Expect(json.Unmarshal(body, &res)).Should(Succeed())
+ Expect(res).Should(Equal(results[i][1]))
+ }
+ }
+
+ })
+})
+
+func setAttrs(dbMan *DummyDbMan, id string) []common.Attribute {
+ dbMan.attrs = map[string][]common.Attribute{
+ id: {
+ {
+ Name: "foo",
+ Value: "bar",
+ },
+ {
+ Name: "bar",
+ Value: "foo",
+ },
+ },
+ }
+ return dbMan.attrs[id]
+}
diff --git a/accessEntity/data.go b/accessEntity/data.go
new file mode 100644
index 0000000..50fcd93
--- /dev/null
+++ b/accessEntity/data.go
@@ -0,0 +1,763 @@
+// 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 accessEntity
+
+import (
+ "database/sql"
+ "fmt"
+ "github.com/apid/apidVerifyApiKey/common"
+ "strings"
+)
+
+const (
+ sql_select_api_product = `SELECT * FROM kms_api_product AS ap `
+ sql_select_tenant_org = ` (SELECT o.tenant_id FROM kms_organization AS o WHERE o.name=?)`
+)
+
+type DbManager struct {
+ common.DbManager
+}
+
+func (d *DbManager) GetApiProductNames(id string, idType string) ([]string, error) {
+ var query string
+ switch idType {
+ case TypeConsumerKey:
+ query = selectApiProductsById(
+ selectAppCredentialMapperByConsumerKey(
+ "?",
+ "apiprdt_id",
+ ),
+ "name",
+ )
+ case TypeApp:
+ query = selectApiProductsById(
+ selectAppCredentialMapperByAppId(
+ "?",
+ "apiprdt_id",
+ ),
+ "name",
+ )
+ default:
+ return nil, fmt.Errorf("unsupported idType")
+ }
+
+ rows, err := d.GetDb().Query(query, id)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ var names []string
+ for rows.Next() {
+ name := sql.NullString{}
+ err = rows.Scan(&name)
+ if err != nil {
+ return nil, err
+ }
+ if name.Valid {
+ names = append(names, name.String)
+ }
+ }
+ return names, nil
+}
+
+func (d *DbManager) GetComNameByComId(comId string) (string, error) {
+ query := selectCompanyByComId(
+ "?",
+ "name",
+ )
+ name := sql.NullString{}
+ err := d.GetDb().QueryRow(query, comId).Scan(&name)
+ if err != nil || !name.Valid {
+ return "", err
+ }
+ return name.String, nil
+}
+
+func (d *DbManager) GetDevEmailByDevId(devId string) (string, error) {
+ query := selectDeveloperById(
+ "?",
+ "email",
+ )
+ email := sql.NullString{}
+ err := d.GetDb().QueryRow(query, devId).Scan(&email)
+ if err != nil || !email.Valid {
+ return "", err
+ }
+ return email.String, nil
+}
+
+func (d *DbManager) GetComNames(id string, idType string) ([]string, error) {
+ var query string
+ switch idType {
+ case TypeDeveloper:
+ query = selectCompanyByComId(
+ selectCompanyDeveloperByDevId(
+ "?",
+ "company_id",
+ ),
+ "name",
+ )
+ case TypeCompany:
+ query = selectCompanyByComId(
+ "?",
+ "name",
+ )
+ default:
+ return nil, fmt.Errorf("unsupported idType")
+ }
+
+ rows, err := d.GetDb().Query(query, id)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ var names []string
+ for rows.Next() {
+ name := sql.NullString{}
+ err = rows.Scan(&name)
+ if err != nil {
+ return nil, err
+ }
+ if name.Valid {
+ names = append(names, name.String)
+ }
+ }
+ return names, nil
+}
+
+func (d *DbManager) GetAppNames(id string, t string) ([]string, error) {
+ var query string
+ switch t {
+ case TypeDeveloper:
+ query = selectAppByDevId(
+ "?",
+ "name",
+ )
+ case TypeCompany:
+ query = selectAppByComId(
+ "?",
+ "name",
+ )
+ default:
+ return nil, fmt.Errorf("app type not supported")
+ }
+ rows, err := d.GetDb().Query(query, id)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ var names []string
+ for rows.Next() {
+ name := sql.NullString{}
+ err = rows.Scan(&name)
+ if err != nil {
+ return nil, err
+ }
+ if name.Valid {
+ names = append(names, name.String)
+ }
+ }
+ return names, nil
+}
+
+func (d *DbManager) GetStatus(id, t string) (string, error) {
+ var query string
+ switch t {
+ case AppTypeDeveloper:
+ query = selectDeveloperById(
+ "?",
+ "status",
+ )
+ case AppTypeCompany:
+ query = selectCompanyByComId(
+ "?",
+ "status",
+ )
+ }
+ status := sql.NullString{}
+ err := d.GetDb().QueryRow(query, id).Scan(&status)
+ if err != nil || !status.Valid {
+ return "", err
+ }
+
+ return status.String, nil
+}
+
+func (d *DbManager) GetApiProducts(org, priKey, priVal, secKey, secVal string) (apiProducts []common.ApiProduct, err error) {
+ if priKey == IdentifierAppId {
+ apiProducts, err = d.getApiProductsByAppId(priVal, org)
+ if err != nil {
+ return
+ }
+ } else if priKey == IdentifierApiProductName {
+ apiProducts, err = d.getApiProductsByName(priVal, org)
+ if err != nil {
+ return
+ }
+ } else if priKey == IdentifierAppName {
+ switch secKey {
+ case IdentifierDeveloperEmail:
+ apiProducts, err = d.getApiProductsByAppName(priVal, secVal, "", "", org)
+ case IdentifierDeveloperId:
+ apiProducts, err = d.getApiProductsByAppName(priVal, "", secVal, "", org)
+ case IdentifierCompanyName:
+ apiProducts, err = d.getApiProductsByAppName(priVal, "", "", secVal, org)
+ case IdentifierApiResource:
+ fallthrough
+ case "":
+ apiProducts, err = d.getApiProductsByAppName(priVal, "", "", "", org)
+ }
+ if err != nil {
+ return
+ }
+ } else if priKey == IdentifierConsumerKey {
+ apiProducts, err = d.getApiProductsByConsumerKey(priVal, org)
+ if err != nil {
+ return
+ }
+ }
+
+ if secKey == IdentifierApiResource {
+ apiProducts = filterApiProductsByResource(apiProducts, secVal)
+ }
+ return
+}
+
+func (d *DbManager) GetApps(org, priKey, priVal, secKey, secVal string) (apps []common.App, err error) {
+ switch priKey {
+ case IdentifierAppId:
+ return d.getAppByAppId(priVal, org)
+ case IdentifierAppName:
+ switch secKey {
+ case IdentifierDeveloperEmail:
+ return d.getAppByAppName(priVal, secVal, "", "", org)
+ case IdentifierDeveloperId:
+ return d.getAppByAppName(priVal, "", secVal, "", org)
+ case IdentifierCompanyName:
+ return d.getAppByAppName(priVal, "", "", secVal, org)
+ case "":
+ return d.getAppByAppName(priVal, "", "", "", org)
+ }
+ case IdentifierConsumerKey:
+ return d.getAppByConsumerKey(priVal, org)
+ }
+ return
+}
+
+func (d *DbManager) GetCompanies(org, priKey, priVal, secKey, secVal string) (companies []common.Company, err error) {
+ switch priKey {
+ case IdentifierAppId:
+ return d.getCompanyByAppId(priVal, org)
+ case IdentifierCompanyName:
+ return d.getCompanyByName(priVal, org)
+ case IdentifierConsumerKey:
+ return d.getCompanyByConsumerKey(priVal, org)
+ }
+ return
+}
+
+func (d *DbManager) GetCompanyDevelopers(org, priKey, priVal, secKey, secVal string) (companyDevelopers []common.CompanyDeveloper, err error) {
+ if priKey == IdentifierCompanyName {
+ return d.getCompanyDeveloperByComName(priVal, org)
+ }
+ return
+}
+
+func (d *DbManager) GetAppCredentials(org, priKey, priVal, secKey, secVal string) (appCredentials []common.AppCredential, err error) {
+
+ switch priKey {
+ case IdentifierConsumerKey:
+ return d.getAppCredentialByConsumerKey(priVal, org)
+ case IdentifierAppId:
+ return d.getAppCredentialByAppId(priVal, org)
+ }
+ return
+}
+
+func (d *DbManager) GetDevelopers(org, priKey, priVal, secKey, secVal string) (developers []common.Developer, err error) {
+ switch priKey {
+ case IdentifierAppId:
+ return d.getDeveloperByAppId(priVal, org)
+ case IdentifierDeveloperEmail:
+ return d.getDeveloperByEmail(priVal, org)
+ case IdentifierConsumerKey:
+ return d.getDeveloperByConsumerKey(priVal, org)
+ case IdentifierDeveloperId:
+ return d.getDeveloperById(priVal, org)
+ }
+ return
+}
+
+func (d *DbManager) getApiProductsByName(apiProdName string, org string) (apiProducts []common.ApiProduct, err error) {
+ err = d.GetDb().QueryStructs(&apiProducts,
+ sql_select_api_product+
+ `WHERE ap.name = ? AND ap.tenant_id IN `+
+ sql_select_tenant_org,
+ apiProdName,
+ org,
+ )
+ return
+}
+
+func (d *DbManager) getApiProductsByAppId(appId string, org string) (apiProducts []common.ApiProduct, err error) {
+ cols := []string{"*"}
+ query := selectApiProductsById(
+ selectAppCredentialMapperByAppId(
+ "?",
+ "apiprdt_id",
+ ),
+ cols...,
+ ) + " AND ap.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getApiProductsByAppId: %v", query)
+ err = d.GetDb().QueryStructs(&apiProducts, query, appId, org)
+ return
+}
+
+func (d *DbManager) getApiProductsByConsumerKey(consumerKey string, org string) (apiProducts []common.ApiProduct, err error) {
+ cols := []string{"*"}
+ query := selectApiProductsById(
+ selectAppCredentialMapperByConsumerKey(
+ "?",
+ "apiprdt_id",
+ ),
+ cols...,
+ ) + " AND ap.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getApiProductsByConsumerKey: %v", query)
+ err = d.GetDb().QueryStructs(&apiProducts, query, consumerKey, org)
+ return
+}
+
+func (d *DbManager) getApiProductsByAppName(appName, devEmail, devId, comName, org string) (apiProducts []common.ApiProduct, err error) {
+ cols := []string{"*"}
+ var appQuery string
+ args := []interface{}{appName}
+ switch {
+ case devEmail != "":
+ appQuery = selectAppByNameAndDeveloperId(
+ "?",
+ selectDeveloperByEmail(
+ "?",
+ "id",
+ ),
+ "id",
+ )
+ args = append(args, devEmail)
+ case devId != "":
+ appQuery = selectAppByNameAndDeveloperId(
+ "?",
+ "?",
+ "id",
+ )
+ args = append(args, devId)
+ case comName != "":
+ appQuery = selectAppByNameAndCompanyId(
+ "?",
+ selectCompanyByName(
+ "?",
+ "id",
+ ),
+ "id",
+ )
+ args = append(args, comName)
+ default:
+ appQuery = selectAppByName(
+ "?",
+ "id",
+ )
+ }
+
+ args = append(args, org)
+
+ query := selectApiProductsById(
+ selectAppCredentialMapperByAppId(
+ appQuery,
+ "apiprdt_id",
+ ),
+ cols...,
+ ) + " AND ap.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getApiProductsByAppName: %v", query)
+ err = d.GetDb().QueryStructs(&apiProducts, query, args...)
+ return
+}
+
+func (d *DbManager) getAppByAppId(id, org string) (apps []common.App, err error) {
+ cols := []string{"*"}
+ query := selectAppById(
+ "?",
+ cols...,
+ ) + " AND a.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getAppByAppId: %v \n %v", query, id)
+ err = d.GetDb().QueryStructs(&apps, query, id, org)
+ return
+}
+
+func (d *DbManager) getAppByAppName(appName, devEmail, devId, comName, org string) (apps []common.App, err error) {
+ cols := []string{"*"}
+ var query string
+ args := []interface{}{appName}
+ switch {
+ case devEmail != "":
+ query = selectAppByNameAndDeveloperId(
+ "?",
+ selectDeveloperByEmail(
+ "?",
+ "id",
+ ),
+ cols...,
+ )
+ args = append(args, devEmail)
+ case devId != "":
+ query = selectAppByNameAndDeveloperId(
+ "?",
+ "?",
+ cols...,
+ )
+ args = append(args, devId)
+ case comName != "":
+ query = selectAppByNameAndCompanyId(
+ "?",
+ selectCompanyByName(
+ "?",
+ "id",
+ ),
+ cols...,
+ )
+ args = append(args, comName)
+ default:
+ query = selectAppByName(
+ "?",
+ cols...,
+ )
+ }
+
+ args = append(args, org)
+
+ query += " AND a.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getAppByAppName: %v", query)
+ err = d.GetDb().QueryStructs(&apps, query, args...)
+ return
+}
+
+func (d *DbManager) getAppByConsumerKey(consumerKey, org string) (apps []common.App, err error) {
+ cols := []string{"*"}
+ query := selectAppById(
+ selectAppCredentialMapperByConsumerKey(
+ "?",
+ "app_id",
+ ),
+ cols...,
+ ) + " AND a.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getAppByConsumerKey: %v", query)
+ err = d.GetDb().QueryStructs(&apps, query, consumerKey, org)
+ return
+}
+
+func (d *DbManager) getAppCredentialByConsumerKey(consumerKey, org string) (appCredentials []common.AppCredential, err error) {
+ cols := []string{"*"}
+ query := selectAppCredentialByConsumerKey(
+ "?",
+ cols...,
+ ) + " AND ac.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getAppCredentialByConsumerKey: %v", query)
+ err = d.GetDb().QueryStructs(&appCredentials, query, consumerKey, org)
+ return
+}
+
+func (d *DbManager) getAppCredentialByAppId(appId, org string) (appCredentials []common.AppCredential, err error) {
+ cols := []string{"*"}
+ query := selectAppCredentialByConsumerKey(
+ selectAppCredentialMapperByAppId(
+ "?",
+ "appcred_id",
+ ),
+ cols...,
+ ) + " AND ac.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getAppCredentialByAppId: %v", query)
+ err = d.GetDb().QueryStructs(&appCredentials, query, appId, org)
+ return
+}
+
+func (d *DbManager) getCompanyByAppId(appId, org string) (companies []common.Company, err error) {
+ cols := []string{"*"}
+ query := selectCompanyByComId(
+ selectAppById(
+ "?",
+ "company_id",
+ ),
+ cols...,
+ ) + " AND com.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getCompanyByAppId: %v", query)
+ err = d.GetDb().QueryStructs(&companies, query, appId, org)
+ return
+}
+
+func (d *DbManager) getCompanyByName(name, org string) (companies []common.Company, err error) {
+ cols := []string{"*"}
+ query := selectCompanyByName(
+ "?",
+ cols...,
+ ) + " AND com.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getCompanyByName: %v", query)
+ err = d.GetDb().QueryStructs(&companies, query, name, org)
+ return
+}
+
+func (d *DbManager) getCompanyByConsumerKey(consumerKey, org string) (companies []common.Company, err error) {
+ cols := []string{"*"}
+ query := selectCompanyByComId(
+ selectAppById(
+ selectAppCredentialMapperByConsumerKey(
+ "?",
+ "app_id",
+ ),
+ "company_id",
+ ),
+ cols...,
+ ) + " AND com.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getCompanyByConsumerKey: %v", query)
+ err = d.GetDb().QueryStructs(&companies, query, consumerKey, org)
+ return
+}
+
+func (d *DbManager) getCompanyDeveloperByComName(comName, org string) (companyDevelopers []common.CompanyDeveloper, err error) {
+ cols := []string{"*"}
+ query := selectCompanyDeveloperByComId(
+ selectCompanyByName(
+ "?",
+ "id",
+ ),
+ cols...,
+ ) + " AND cd.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getCompanyDeveloperByComName: %v", query)
+ err = d.GetDb().QueryStructs(&companyDevelopers, query, comName, org)
+ return
+}
+
+func (d *DbManager) getDeveloperByAppId(appId, org string) (developers []common.Developer, err error) {
+ cols := []string{"*"}
+ query := selectDeveloperById(
+ selectAppById(
+ "?",
+ "developer_id",
+ ),
+ cols...,
+ ) + " AND dev.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getDeveloperByAppId: %v", query)
+ err = d.GetDb().QueryStructs(&developers, query, appId, org)
+ return
+}
+
+func (d *DbManager) getDeveloperByConsumerKey(consumerKey, org string) (developers []common.Developer, err error) {
+ cols := []string{"*"}
+ query := selectDeveloperById(
+ selectAppById(
+ selectAppCredentialMapperByConsumerKey(
+ "?",
+ "app_id",
+ ),
+ "developer_id",
+ ),
+ cols...,
+ ) + " AND dev.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getDeveloperByConsumerKey: %v", query)
+ err = d.GetDb().QueryStructs(&developers, query, consumerKey, org)
+ return
+}
+
+func (d *DbManager) getDeveloperByEmail(email, org string) (developers []common.Developer, err error) {
+ cols := []string{"*"}
+ query := selectDeveloperByEmail(
+ "?",
+ cols...,
+ ) + " AND dev.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getDeveloperByEmail: %v", query)
+ err = d.GetDb().QueryStructs(&developers, query, email, org)
+ return
+}
+
+func (d *DbManager) getDeveloperById(id, org string) (developers []common.Developer, err error) {
+ cols := []string{"*"}
+ query := selectDeveloperById(
+ "?",
+ cols...,
+ ) + " AND dev.tenant_id IN " + sql_select_tenant_org
+ //log.Debugf("getDeveloperById: %v", query)
+ err = d.GetDb().QueryStructs(&developers, query, id, org)
+ return
+}
+
+func selectApiProductsById(idQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_api_product AS ap WHERE ap.id IN (" +
+ idQuery +
+ ")"
+
+ return query
+}
+
+func selectAppCredentialMapperByAppId(idQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_app_credential_apiproduct_mapper AS acm WHERE acm.app_id IN (" +
+ idQuery +
+ ")"
+ return query
+}
+
+func selectAppCredentialMapperByConsumerKey(keyQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_app_credential_apiproduct_mapper AS acm WHERE acm.appcred_id IN (" +
+ keyQuery +
+ ")"
+ return query
+}
+
+func selectAppByName(nameQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_app AS a WHERE a.name IN (" +
+ nameQuery +
+ ")"
+ return query
+}
+
+func selectAppById(appIdQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_app AS a WHERE a.id IN (" +
+ appIdQuery +
+ ")"
+ return query
+}
+
+func selectAppByComId(comIdQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_app AS a WHERE a.company_id IN (" +
+ comIdQuery +
+ ")"
+ return query
+}
+
+func selectAppByDevId(devIdQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_app AS a WHERE a.developer_id IN (" +
+ devIdQuery +
+ ")"
+ return query
+}
+
+func selectAppByNameAndDeveloperId(nameQuery string, developerIdQuery string, colNames ...string) string {
+ query := selectAppByName(nameQuery, colNames...) +
+ " AND developer_id IN (" +
+ developerIdQuery +
+ ")"
+ return query
+}
+
+func selectAppByNameAndCompanyId(nameQuery string, companyIdQuery string, colNames ...string) string {
+ query := selectAppByName(nameQuery, colNames...) +
+ " AND company_id IN (" +
+ companyIdQuery +
+ ")"
+ return query
+}
+
+func selectDeveloperByEmail(emailQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_developer AS dev WHERE dev.email IN (" +
+ emailQuery +
+ ")"
+ return query
+}
+
+func selectDeveloperById(idQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_developer AS dev WHERE dev.id IN (" +
+ idQuery +
+ ")"
+ return query
+}
+
+func selectCompanyByName(nameQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_company AS com WHERE com.name IN (" +
+ nameQuery +
+ ")"
+ return query
+}
+
+func selectCompanyByComId(comIdQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_company AS com WHERE com.id IN (" +
+ comIdQuery +
+ ")"
+ return query
+}
+
+func selectCompanyDeveloperByComId(comIdQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_company_developer AS cd WHERE cd.company_id IN (" +
+ comIdQuery +
+ ")"
+ return query
+}
+
+func selectCompanyDeveloperByDevId(devIdQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_company_developer AS cd WHERE cd.developer_id IN (" +
+ devIdQuery +
+ ")"
+ return query
+}
+
+func selectAppCredentialByConsumerKey(consumerQuery string, colNames ...string) string {
+ query := "SELECT " +
+ strings.Join(colNames, ",") +
+ " FROM kms_app_credential AS ac WHERE ac.id IN (" +
+ consumerQuery +
+ ")"
+ return query
+}
+
+func filterApiProductsByResource(apiProducts []common.ApiProduct, resource string) []common.ApiProduct {
+ //log.Debugf("Before filter: %v", apiProducts)
+ var prods []common.ApiProduct
+ for _, prod := range apiProducts {
+ resources := common.JsonToStringArray(prod.ApiResources)
+ if Contains(resources, resource) {
+ prods = append(prods, prod)
+ }
+ }
+ //log.Debugf("After filter: %v", prods)
+ return prods
+}
+
+func Contains(sl []string, str string) bool {
+ for _, s := range sl {
+ if s == str {
+ return true
+ }
+ }
+ return false
+}
diff --git a/accessEntity/data_test.go b/accessEntity/data_test.go
new file mode 100644
index 0000000..e0e873f
--- /dev/null
+++ b/accessEntity/data_test.go
@@ -0,0 +1,556 @@
+// 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 accessEntity
+
+import (
+ "github.com/apid/apid-core"
+ "github.com/apid/apidVerifyApiKey/common"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "io/ioutil"
+ "sync"
+)
+
+const (
+ fileDataTest = "data_test.sql"
+ // SQL Injection
+ // If select foo from bar where id in (' + condition + ') is used,
+ // the hacked sql would be like "select XXX from XXX where id in ('1') or ('1'=='1');"
+ sqlInjectionStmt = "1') or ('1'=='1"
+)
+
+var _ = Describe("DataTest", func() {
+
+ Context("query Db to get entities", func() {
+ var dataTestTempDir string
+ var dbMan *DbManager
+ BeforeEach(func() {
+ var err error
+ dataTestTempDir, err = ioutil.TempDir(testTempDirBase, "sqlite3")
+ Expect(err).NotTo(HaveOccurred())
+ services.Config().Set("local_storage_path", dataTestTempDir)
+
+ dbMan = &DbManager{
+ DbManager: common.DbManager{
+ Data: services.Data(),
+ DbMux: sync.RWMutex{},
+ },
+ }
+ dbMan.SetDbVersion(dataTestTempDir)
+ setupTestDb(dbMan.GetDb())
+ })
+
+ Describe("Get structs", func() {
+ It("should get apiProducts", func() {
+ testData := [][]string{
+ //positive tests
+ {IdentifierApiProductName, "apstest", "", "", "apid-haoming"},
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", "apid-haoming"},
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", IdentifierApiResource, "/**", "apid-haoming"},
+ {IdentifierAppName, "apstest", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "abcd", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "abcd", IdentifierApiResource, "/**", "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierDeveloperId, "e41f04e8-9d3f-470a-8bfd-c7939945896c", "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierDeveloperEmail, "bar@google.com", "apid-haoming"},
+ {IdentifierAppName, "testappahhis", IdentifierCompanyName, "testcompanyhflxv", "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierApiResource, "/**", "apid-haoming"},
+ // negative tests
+ {IdentifierApiProductName, "apstest", "", "", "non-existent"},
+ {IdentifierApiProductName, "non-existent", "", "", "apid-haoming"},
+ {IdentifierAppId, "non-existent", "", "", "apid-haoming"},
+ {IdentifierAppId, "non-existent", IdentifierApiResource, "non-existent", "apid-haoming"},
+ {IdentifierAppName, "non-existent", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "non-existent", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "non-existent", IdentifierApiResource, "non-existent", "apid-haoming"},
+ {IdentifierAppName, "non-existent", IdentifierDeveloperId, "non-existent", "apid-haoming"},
+ {IdentifierAppName, "non-existent", IdentifierDeveloperEmail, "non-existent", "apid-haoming"},
+ {IdentifierAppName, "non-existent", IdentifierCompanyName, "non-existent", "apid-haoming"},
+ {IdentifierAppName, "non-existent", IdentifierApiResource, "non-existent", "apid-haoming"},
+ // SQL Injection
+ {IdentifierApiProductName, "apstest", "", "", sqlInjectionStmt},
+ {IdentifierApiProductName, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierAppId, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierAppName, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierConsumerKey, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierDeveloperId, sqlInjectionStmt, "apid-haoming"},
+ {IdentifierAppName, "testappahhis", IdentifierDeveloperEmail, sqlInjectionStmt, "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierCompanyName, sqlInjectionStmt, "apid-haoming"},
+ }
+
+ var expectedDevApiProd = common.ApiProduct{
+ Id: "b7e0970c-4677-4b05-8105-5ea59fdcf4e7",
+ Name: "apstest",
+ DisplayName: "apstest",
+ Description: "",
+ ApiResources: "{/**}",
+ ApprovalType: "AUTO",
+ Scopes: `{""}`,
+ Proxies: `{aps,perfBenchmark}`,
+ Environments: `{prod,test}`,
+ Quota: "10000000",
+ QuotaTimeUnit: "MINUTE",
+ QuotaInterval: 1,
+ CreatedAt: "2017-08-18 22:12:49.363+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-08-18 22:26:50.153+00:00",
+ UpdatedBy: "haoming@apid.git",
+ TenantId: "515211e9",
+ }
+
+ var expectedComApiProd = common.ApiProduct{
+ Id: "fea8a6d5-8d34-477f-ac82-c397eaec06af",
+ Name: "testproductsdljnkpt",
+ DisplayName: "testproductsdljnkpt",
+ Description: "",
+ ApiResources: "{/res1}",
+ ApprovalType: "AUTO",
+ Scopes: `{}`,
+ Proxies: `{}`,
+ Environments: `{test}`,
+ Quota: "",
+ QuotaTimeUnit: "",
+ QuotaInterval: 0,
+ CreatedAt: "2017-11-02 16:00:15.608+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-11-02 16:00:18.125+00:00",
+ UpdatedBy: "haoming@apid.git",
+ TenantId: "515211e9",
+ }
+
+ results := [][]common.ApiProduct{
+ {expectedDevApiProd},
+ {expectedDevApiProd},
+ {expectedDevApiProd},
+ {expectedDevApiProd},
+ {expectedDevApiProd},
+ {expectedDevApiProd},
+ {expectedDevApiProd},
+ {expectedDevApiProd},
+ {expectedComApiProd},
+ {expectedDevApiProd},
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ }
+
+ for i, data := range testData {
+ priKey, priVal, secKey, secVal, org := data[0], data[1], data[2], data[3], data[4]
+ prods, err := dbMan.GetApiProducts(org, priKey, priVal, secKey, secVal)
+ Expect(err).Should(Succeed())
+ if len(results[i]) > 0 {
+ Expect(prods).Should(Equal(results[i]))
+ } else {
+ Expect(prods).Should(BeZero())
+ }
+ }
+ })
+
+ It("should get apps", func() {
+ testData := [][]string{
+ //positive tests
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", "apid-haoming"},
+ {IdentifierAppName, "apstest", "", "", "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierDeveloperId, "e41f04e8-9d3f-470a-8bfd-c7939945896c", "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierDeveloperEmail, "bar@google.com", "apid-haoming"},
+ {IdentifierAppName, "testappahhis", IdentifierCompanyName, "testcompanyhflxv", "apid-haoming"},
+ {IdentifierConsumerKey, "abcd", "", "", "apid-haoming"},
+ // negative tests
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", "non-existent"},
+ {IdentifierAppId, "non-existent", "", "", "apid-haoming"},
+ {IdentifierAppName, "non-existent", "", "", "apid-haoming"},
+ {IdentifierAppName, "non-existent", IdentifierDeveloperId, "non-existent", "apid-haoming"},
+ {IdentifierAppName, "non-existent", IdentifierDeveloperEmail, "non-existent", "apid-haoming"},
+ {IdentifierAppName, "non-existent", IdentifierCompanyName, "non-existent", "apid-haoming"},
+ {IdentifierConsumerKey, "non-existent", "", "", "apid-haoming"},
+ // SQL Injection
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", sqlInjectionStmt},
+ {IdentifierAppId, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierAppName, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierDeveloperId, sqlInjectionStmt, "apid-haoming"},
+ {IdentifierAppName, "apstest", IdentifierDeveloperEmail, sqlInjectionStmt, "apid-haoming"},
+ {IdentifierAppName, "testappahhis", IdentifierCompanyName, sqlInjectionStmt, "apid-haoming"},
+ {IdentifierConsumerKey, sqlInjectionStmt, "", "", "apid-haoming"},
+ }
+
+ var expectedDevApp = common.App{
+ Id: "408ad853-3fa0-402f-90ee-103de98d71a5",
+ TenantId: "515211e9",
+ Name: "apstest",
+ DisplayName: "apstest",
+ AccessType: "READ",
+ CallbackUrl: "https://www.google.com",
+ Status: "APPROVED",
+ AppFamily: "default",
+ CompanyId: "",
+ DeveloperId: "e41f04e8-9d3f-470a-8bfd-c7939945896c",
+ ParentId: "e41f04e8-9d3f-470a-8bfd-c7939945896c",
+ Type: "DEVELOPER",
+ CreatedAt: "2017-08-18 22:13:18.325+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-08-18 22:13:18.325+00:00",
+ UpdatedBy: "haoming@apid.git",
+ }
+
+ var expectedComApp = common.App{
+ Id: "35608afe-2715-4064-bb4d-3cbb4e82c474",
+ TenantId: "515211e9",
+ Name: "testappahhis",
+ DisplayName: "testappahhis",
+ AccessType: "READ",
+ CallbackUrl: "",
+ Status: "APPROVED",
+ AppFamily: "default",
+ CompanyId: "a94f75e2-69b0-44af-8776-155df7c7d22e",
+ DeveloperId: "",
+ ParentId: "a94f75e2-69b0-44af-8776-155df7c7d22e",
+ Type: "COMPANY",
+ CreatedAt: "2017-11-02 16:00:16.504+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-11-02 16:00:16.504+00:00",
+ UpdatedBy: "haoming@apid.git",
+ }
+
+ results := [][]common.App{
+ {expectedDevApp},
+ {expectedDevApp},
+ {expectedDevApp},
+ {expectedDevApp},
+ {expectedComApp},
+ {expectedDevApp},
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ }
+
+ for i, data := range testData {
+ priKey, priVal, secKey, secVal, org := data[0], data[1], data[2], data[3], data[4]
+ apps, err := dbMan.GetApps(org, priKey, priVal, secKey, secVal)
+ Expect(err).Should(Succeed())
+ if len(results[i]) > 0 {
+ Expect(apps).Should(Equal(results[i]))
+ } else {
+ Expect(apps).Should(BeZero())
+ }
+ }
+ })
+
+ It("should get Companies", func() {
+ testData := [][]string{
+ //positive tests
+ {IdentifierAppId, "35608afe-2715-4064-bb4d-3cbb4e82c474", "", "", "apid-haoming"},
+ {IdentifierCompanyName, "testcompanyhflxv", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "wxyz", "", "", "apid-haoming"},
+ // negative tests
+ {IdentifierAppId, "35608afe-2715-4064-bb4d-3cbb4e82c474", "", "", "non-existent"},
+ {IdentifierAppId, "non-existent", "", "", "apid-haoming"},
+ {IdentifierCompanyName, "non-existent", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "non-existent", "", "", "apid-haoming"},
+ // SQL Injection
+ {IdentifierAppId, "35608afe-2715-4064-bb4d-3cbb4e82c474", "", "", sqlInjectionStmt},
+ {IdentifierAppId, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierCompanyName, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierConsumerKey, sqlInjectionStmt, "", "", "apid-haoming"},
+ }
+
+ var expectedCom = common.Company{
+ Id: "a94f75e2-69b0-44af-8776-155df7c7d22e",
+ TenantId: "515211e9",
+ Name: "testcompanyhflxv",
+ DisplayName: "testcompanyhflxv",
+ Status: "ACTIVE",
+ CreatedAt: "2017-11-02 16:00:16.287+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-11-02 16:00:16.287+00:00",
+ UpdatedBy: "haoming@apid.git",
+ }
+
+ results := [][]common.Company{
+ {expectedCom},
+ {expectedCom},
+ {expectedCom},
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ }
+
+ for i, data := range testData {
+ priKey, priVal, secKey, secVal, org := data[0], data[1], data[2], data[3], data[4]
+ apps, err := dbMan.GetCompanies(org, priKey, priVal, secKey, secVal)
+ Expect(err).Should(Succeed())
+ if len(results[i]) > 0 {
+ Expect(apps).Should(Equal(results[i]))
+ } else {
+ Expect(apps).Should(BeZero())
+ }
+ }
+ })
+
+ It("should get developers", func() {
+ testData := [][]string{
+ //positive tests
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "abcd", "", "", "apid-haoming"},
+ {IdentifierDeveloperEmail, "bar@google.com", "", "", "apid-haoming"},
+ {IdentifierDeveloperId, "e41f04e8-9d3f-470a-8bfd-c7939945896c", "", "", "apid-haoming"},
+
+ // negative tests
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", "non-existent"},
+ {IdentifierAppId, "non-existent", "", "", "apid-haoming"},
+ {IdentifierConsumerKey, "non-existent", "", "", "apid-haoming"},
+ {IdentifierDeveloperEmail, "non-existent", "", "", "apid-haoming"},
+ {IdentifierDeveloperId, "non-existent", "", "", "apid-haoming"},
+ // SQL Injection
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", sqlInjectionStmt},
+ {IdentifierAppId, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierConsumerKey, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierDeveloperEmail, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierDeveloperId, sqlInjectionStmt, "", "", "apid-haoming"},
+ }
+
+ var expectedDev = common.Developer{
+ Id: "e41f04e8-9d3f-470a-8bfd-c7939945896c",
+ TenantId: "515211e9",
+ UserName: "haoming",
+ FirstName: "haoming",
+ LastName: "zhang",
+ Password: "",
+ Email: "bar@google.com",
+ Status: "ACTIVE",
+ EncryptedPassword: "",
+ Salt: "",
+ CreatedAt: "2017-08-16 22:39:46.669+00:00",
+ CreatedBy: "foo@google.com",
+ UpdatedAt: "2017-08-16 22:39:46.669+00:00",
+ UpdatedBy: "foo@google.com",
+ }
+
+ results := [][]common.Developer{
+ {expectedDev},
+ {expectedDev},
+ {expectedDev},
+ {expectedDev},
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ }
+
+ for i, data := range testData {
+ priKey, priVal, secKey, secVal, org := data[0], data[1], data[2], data[3], data[4]
+ prods, err := dbMan.GetDevelopers(org, priKey, priVal, secKey, secVal)
+ Expect(err).Should(Succeed())
+ if len(results[i]) > 0 {
+ Expect(prods).Should(Equal(results[i]))
+ } else {
+ Expect(prods).Should(BeZero())
+ }
+ }
+ })
+
+ It("should get appCredentials", func() {
+ testData := [][]string{
+ // positive tests
+ {IdentifierConsumerKey, "abcd", "", "", "apid-haoming"},
+ {IdentifierAppId, "408ad853-3fa0-402f-90ee-103de98d71a5", "", "", "apid-haoming"},
+ // negative tests
+ {IdentifierConsumerKey, "abcd", "", "", "non-existent"},
+ {IdentifierConsumerKey, "non-existent", "", "", "apid-haoming"},
+ {IdentifierAppId, "non-existent", "", "", "apid-haoming"},
+ // SQL Injection
+ {IdentifierConsumerKey, "abcd", "", "", sqlInjectionStmt},
+ {IdentifierConsumerKey, sqlInjectionStmt, "", "", "apid-haoming"},
+ {IdentifierAppId, sqlInjectionStmt, "", "", "apid-haoming"},
+ }
+
+ var expectedCred = common.AppCredential{
+ Id: "abcd",
+ TenantId: "515211e9",
+ ConsumerSecret: "secret1",
+ AppId: "408ad853-3fa0-402f-90ee-103de98d71a5",
+ MethodType: "",
+ Status: "APPROVED",
+ IssuedAt: "2017-08-18 22:13:18.35+00:00",
+ ExpiresAt: "",
+ AppStatus: "",
+ Scopes: "{}",
+ CreatedAt: "2017-08-18 22:13:18.35+00:00",
+ CreatedBy: "-NA-",
+ UpdatedAt: "2017-08-18 22:13:18.352+00:00",
+ UpdatedBy: "-NA-",
+ }
+
+ results := [][]common.AppCredential{
+ {expectedCred},
+ {expectedCred},
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ }
+
+ for i, data := range testData {
+ priKey, priVal, secKey, secVal, org := data[0], data[1], data[2], data[3], data[4]
+ prods, err := dbMan.GetAppCredentials(org, priKey, priVal, secKey, secVal)
+ Expect(err).Should(Succeed())
+ if len(results[i]) > 0 {
+ Expect(prods).Should(Equal(results[i]))
+ } else {
+ Expect(prods).Should(BeZero())
+ }
+ }
+ })
+
+ It("should get CompanyDevelopers", func() {
+ testData := [][]string{
+ // positive tests
+ {IdentifierCompanyName, "testcompanyhflxv", "", "", "apid-haoming"},
+ // negative tests
+ {IdentifierCompanyName, "testcompanyhflxv", "", "", "non-existent"},
+ {IdentifierCompanyName, "non-existent", "", "", "apid-haoming"},
+ // SQL Injection
+ {IdentifierCompanyName, "testcompanyhflxv", "", "", sqlInjectionStmt},
+ {IdentifierCompanyName, sqlInjectionStmt, "", "", "apid-haoming"},
+ }
+
+ var expectedComDev = common.CompanyDeveloper{
+ TenantId: "515211e9",
+ CompanyId: "a94f75e2-69b0-44af-8776-155df7c7d22e",
+ DeveloperId: "590f33bf-f05c-48c1-bb93-183759bd9ee1",
+ Roles: "admin",
+ CreatedAt: "2017-11-02 16:00:16.287+00:00",
+ CreatedBy: "haoming@apid.git",
+ UpdatedAt: "2017-11-02 16:00:16.287+00:00",
+ UpdatedBy: "haoming@apid.git",
+ }
+
+ results := [][]common.CompanyDeveloper{
+ {expectedComDev},
+ nil,
+ nil,
+ nil,
+ nil,
+ }
+
+ for i, data := range testData {
+ priKey, priVal, secKey, secVal, org := data[0], data[1], data[2], data[3], data[4]
+ prods, err := dbMan.GetCompanyDevelopers(org, priKey, priVal, secKey, secVal)
+ Expect(err).Should(Succeed())
+ if len(results[i]) > 0 {
+ Expect(prods).Should(Equal(results[i]))
+ } else {
+ Expect(prods).Should(BeZero())
+ }
+ }
+ })
+
+ })
+
+ Describe("utils", func() {
+ It("GetApiProductNamesByConsumerKey", func() {
+ data := "abcd"
+ expected := []string{"apstest"}
+ Expect(dbMan.GetApiProductNames(data, TypeConsumerKey)).Should(Equal(expected))
+
+ data = "408ad853-3fa0-402f-90ee-103de98d71a5"
+ expected = []string{"apstest"}
+ Expect(dbMan.GetApiProductNames(data, TypeApp)).Should(Equal(expected))
+ })
+
+ It("GetAppNames", func() {
+ data := "a94f75e2-69b0-44af-8776-155df7c7d22e"
+ expected := []string{"testappahhis"}
+ Expect(dbMan.GetAppNames(data, TypeCompany)).Should(Equal(expected))
+
+ data = "e41f04e8-9d3f-470a-8bfd-c7939945896c"
+ expected = []string{"apstest"}
+ Expect(dbMan.GetAppNames(data, TypeDeveloper)).Should(Equal(expected))
+ })
+
+ It("GetComNames", func() {
+ data := "8ba5b747-5104-4a40-89ca-a0a51798fe34"
+ expected := []string{"DevCompany"}
+ Expect(dbMan.GetComNames(data, TypeCompany)).Should(Equal(expected))
+ data = "590f33bf-f05c-48c1-bb93-183759bd9ee1"
+ expected = []string{"testcompanyhflxv"}
+ Expect(dbMan.GetComNames(data, TypeDeveloper)).Should(Equal(expected))
+ })
+
+ It("GetDevEmailByDevId", func() {
+ data := "e41f04e8-9d3f-470a-8bfd-c7939945896c"
+ expected := "bar@google.com"
+ Expect(dbMan.GetDevEmailByDevId(data)).Should(Equal(expected))
+ })
+
+ It("GetStatus", func() {
+ data := "e41f04e8-9d3f-470a-8bfd-c7939945896c"
+ expected := "ACTIVE"
+ Expect(dbMan.GetStatus(data, AppTypeDeveloper)).Should(Equal(expected))
+ data = "8ba5b747-5104-4a40-89ca-a0a51798fe34"
+ expected = "ACTIVE"
+ Expect(dbMan.GetStatus(data, AppTypeCompany)).Should(Equal(expected))
+ })
+
+ })
+
+ })
+
+})
+
+func setupTestDb(db apid.DB) {
+ bytes, err := ioutil.ReadFile(fileDataTest)
+ Expect(err).Should(Succeed())
+ query := string(bytes)
+ _, err = db.Exec(query)
+ Expect(err).Should(Succeed())
+}
diff --git a/accessEntity/data_test.sql b/accessEntity/data_test.sql
new file mode 100644
index 0000000..8b1590a
--- /dev/null
+++ b/accessEntity/data_test.sql
@@ -0,0 +1,61 @@
+-- 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.
+
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE kms_app (id text,tenant_id text,name text,display_name text,access_type text,callback_url text,status text,app_family text,company_id text,developer_id text,parent_id text,type text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_app" VALUES('408ad853-3fa0-402f-90ee-103de98d71a5','515211e9','apstest','apstest','READ','https://www.google.com','APPROVED','default','','e41f04e8-9d3f-470a-8bfd-c7939945896c','e41f04e8-9d3f-470a-8bfd-c7939945896c','DEVELOPER','2017-08-18 22:13:18.325+00:00','haoming@apid.git','2017-08-18 22:13:18.325+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_app" VALUES('ae053aee-f12d-4591-84ef-2e6ae0d4205d','515211e9','apigee-remote-proxy','','','','APPROVED','default','','590f33bf-f05c-48c1-bb93-183759bd9ee1','590f33bf-f05c-48c1-bb93-183759bd9ee1','DEVELOPER','2017-09-20 23:05:59.125+00:00','haoming@apid.git','2017-09-20 23:05:59.125+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_app" VALUES('35608afe-2715-4064-bb4d-3cbb4e82c474','515211e9','testappahhis','testappahhis','READ','','APPROVED','default','a94f75e2-69b0-44af-8776-155df7c7d22e','','a94f75e2-69b0-44af-8776-155df7c7d22e','COMPANY','2017-11-02 16:00:16.504+00:00','haoming@apid.git','2017-11-02 16:00:16.504+00:00','haoming@apid.git','515211e9');
+CREATE TABLE kms_attributes (tenant_id text,entity_id text,cust_id text,org_id text,dev_id text,comp_id text,apiprdt_id text,app_id text,appcred_id text,name text,type text,value text,_change_selector text, primary key (tenant_id,entity_id,name,type));
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.isSmbOrganization','ORGANIZATION','false','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.mgmtGroup','ORGANIZATION','management-edgex','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.isEdgexEnabled','ORGANIZATION','true','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','e2cc4caf-40d6-4ecb-8149-ed32d04184b2','','','','','','features.isCpsEnabled','ORGANIZATION','true','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','b7e0970c-4677-4b05-8105-5ea59fdcf4e7','','','','','b7e0970c-4677-4b05-8105-5ea59fdcf4e7','','','access','APIPRODUCT','public','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','408ad853-3fa0-402f-90ee-103de98d71a5','','','','','','408ad853-3fa0-402f-90ee-103de98d71a5','','DisplayName','APP','apstest','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','408ad853-3fa0-402f-90ee-103de98d71a5','','','','','','408ad853-3fa0-402f-90ee-103de98d71a5','','Notes','APP','','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','db90a25a-15c8-42ad-96c1-63ed9682b5a9','','','','','db90a25a-15c8-42ad-96c1-63ed9682b5a9','','','access','APIPRODUCT','public','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','','','','','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','DisplayName','APP','apigee-remote-proxy','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','','','','','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','Notes','APP','','515211e9');
+INSERT INTO "kms_attributes" VALUES('515211e9','fea8a6d5-8d34-477f-ac82-c397eaec06af','','','','','fea8a6d5-8d34-477f-ac82-c397eaec06af','','','Company','APIPRODUCT','Apigee','515211e9');
+CREATE TABLE kms_company (id text,tenant_id text,name text,display_name text,status text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_company" VALUES('8ba5b747-5104-4a40-89ca-a0a51798fe34','515211e9','DevCompany','East India Company','ACTIVE','2017-08-15 03:29:02.449+00:00','haoming@apid.git','2017-08-15 03:29:02.449+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_company" VALUES('a94f75e2-69b0-44af-8776-155df7c7d22e','515211e9','testcompanyhflxv','testcompanyhflxv','ACTIVE','2017-11-02 16:00:16.287+00:00','haoming@apid.git','2017-11-02 16:00:16.287+00:00','haoming@apid.git','515211e9');
+CREATE TABLE kms_company_developer (tenant_id text,company_id text,developer_id text,roles text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (tenant_id,company_id,developer_id));
+INSERT INTO "kms_company_developer" VALUES('515211e9','a94f75e2-69b0-44af-8776-155df7c7d22e','590f33bf-f05c-48c1-bb93-183759bd9ee1','admin','2017-11-02 16:00:16.287+00:00','haoming@apid.git','2017-11-02 16:00:16.287+00:00','haoming@apid.git','515211e9');
+CREATE TABLE kms_developer (id text,tenant_id text,username text,first_name text,last_name text,password text,email text,status text,encrypted_password text,salt text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_developer" VALUES('e41f04e8-9d3f-470a-8bfd-c7939945896c','515211e9','haoming','haoming','zhang','','bar@google.com','ACTIVE','','','2017-08-16 22:39:46.669+00:00','foo@google.com','2017-08-16 22:39:46.669+00:00','foo@google.com','515211e9');
+INSERT INTO "kms_developer" VALUES('47d862db-884f-4b8e-9649-fe6d0be1a739','515211e9','qwe','qwe','qwe','','barfoo@google.com','ACTIVE','','','2017-10-12 19:12:48.306+00:00','haoming@apid.git','2017-10-12 19:12:48.306+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_developer" VALUES('590f33bf-f05c-48c1-bb93-183759bd9ee1','515211e9','remoteproxy','remote','proxy','','fooo@google.com','ACTIVE','','','2017-09-20 23:03:52.327+00:00','haoming@apid.git','2017-09-20 23:03:52.327+00:00','haoming@apid.git','515211e9');
+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, last_sequence text DEFAULT '', primary key (id));
+INSERT INTO "edgex_apid_cluster" VALUES('950b30f1-8c41-4bf5-94a3-f10c104ff5d4','apid-haomingOrgCluster','','X-sZXhaOymL6VtWnNQqK7uPsFyPvZYq6FFnrc8','2017-08-23 23:31:49.134+00:00','temp@google.com','2017-08-23 23:31:49.134+00:00','temp@google.com','950b30f1-8c41-4bf5-94a3-f10c104ff5d4','');
+CREATE TABLE kms_api_product (id text,tenant_id text,name text,display_name text,description text,api_resources text,approval_type text,scopes text,proxies text,environments text,quota text,quota_time_unit text,quota_interval integer,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_api_product" VALUES('b7e0970c-4677-4b05-8105-5ea59fdcf4e7','515211e9','apstest','apstest','','{/**}','AUTO','{""}','{aps,perfBenchmark}','{prod,test}','10000000','MINUTE',1,'2017-08-18 22:12:49.363+00:00','haoming@apid.git','2017-08-18 22:26:50.153+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('8501392f-c5f7-4d6a-8841-e038ad5913b4','515211e9','ApigeenTestApp','ApigeenTestApp','','{/}','AUTO','{scope1,scope2,scope3}','{}','{prod,test}','','',NULL,'2017-09-20 22:29:06.451+00:00','haoming@apid.git','2017-09-20 22:29:06.451+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('e4ae89d0-ea47-4b23-b0dc-2723efb15c84','515211e9','ApigeenTestApp2','ApigeenTestApp2','','{/}','AUTO','{scope1,scope2,scope3}','{}','{prod,test}','','',NULL,'2017-09-20 22:29:08.988+00:00','haoming@apid.git','2017-09-20 22:29:08.988+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('07419482-e5a1-4fd0-9d78-3560ba522b44','515211e9','ApigeenTestApp3','ApigeenTestApp3','','{/}','AUTO','{}','{}','{prod,test}','','',NULL,'2017-09-20 22:29:11.482+00:00','haoming@apid.git','2017-09-20 22:29:11.482+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('db90a25a-15c8-42ad-96c1-63ed9682b5a9','515211e9','apigee-remote-proxy','apigee-remote-proxy','','{/**,/}','AUTO','{""}','{apigee-remote-proxy}','{prod,test}','','',NULL,'2017-09-20 23:05:09.234+00:00','haoming@apid.git','2017-09-20 23:05:09.234+00:00','haoming@apid.git','515211e9');
+INSERT INTO "kms_api_product" VALUES('fea8a6d5-8d34-477f-ac82-c397eaec06af','515211e9','testproductsdljnkpt','testproductsdljnkpt','','{/res1}','AUTO','{}','{}','{test}','','',NULL,'2017-11-02 16:00:15.608+00:00','haoming@apid.git','2017-11-02 16:00:18.125+00:00','haoming@apid.git','515211e9');
+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));
+INSERT INTO "kms_app_credential" VALUES('abcd','515211e9','secret1','408ad853-3fa0-402f-90ee-103de98d71a5','','APPROVED','2017-08-18 22:13:18.35+00:00','','','{}','2017-08-18 22:13:18.35+00:00','-NA-','2017-08-18 22:13:18.352+00:00','-NA-','515211e9');
+INSERT INTO "kms_app_credential" VALUES('dcba','515211e9','secret2','ae053aee-f12d-4591-84ef-2e6ae0d4205d','','APPROVED','2017-09-20 23:05:59.148+00:00','','','{}','2017-09-20 23:05:59.148+00:00','-NA-','2017-09-20 23:05:59.151+00:00','-NA-','515211e9');
+INSERT INTO "kms_app_credential" VALUES('wxyz','515211e9','secret3','35608afe-2715-4064-bb4d-3cbb4e82c474','','APPROVED','2017-11-02 16:00:16.512+00:00','','','{}','2017-11-02 16:00:16.512+00:00','-NA-','2017-11-02 16:00:16.514+00:00','-NA-','515211e9');
+CREATE TABLE kms_app_credential_apiproduct_mapper (tenant_id text,appcred_id text,app_id text,apiprdt_id text,status text,_change_selector text, primary key (tenant_id,appcred_id,app_id,apiprdt_id));
+INSERT INTO "kms_app_credential_apiproduct_mapper" VALUES('515211e9','abcd','408ad853-3fa0-402f-90ee-103de98d71a5','b7e0970c-4677-4b05-8105-5ea59fdcf4e7','APPROVED','515211e9');
+INSERT INTO "kms_app_credential_apiproduct_mapper" VALUES('515211e9','dcba','ae053aee-f12d-4591-84ef-2e6ae0d4205d','db90a25a-15c8-42ad-96c1-63ed9682b5a9','APPROVED','515211e9');
+INSERT INTO "kms_app_credential_apiproduct_mapper" VALUES('515211e9','wxyz','35608afe-2715-4064-bb4d-3cbb4e82c474','fea8a6d5-8d34-477f-ac82-c397eaec06af','APPROVED','515211e9');
+CREATE TABLE kms_organization (id text,name text,display_name text,type text,tenant_id text,customer_id text,description text,created_at blob,created_by text,updated_at blob,updated_by text,_change_selector text, primary key (id,tenant_id));
+INSERT INTO "kms_organization" VALUES('e2cc4caf-40d6-4ecb-8149-ed32d04184b2','apid-haoming','apid-haoming','paid','515211e9','94cd5075-7f33-4afb-9545-a53a254277a1','','2017-08-16 22:16:06.544+00:00','foobar@google.com','2017-08-16 22:29:23.046+00:00','foobar@google.com','515211e9');
+COMMIT;
diff --git a/pluginData.go b/accessEntity/init.go
similarity index 73%
copy from pluginData.go
copy to accessEntity/init.go
index 0ebe61b..ed5de94 100644
--- a/pluginData.go
+++ b/accessEntity/init.go
@@ -11,15 +11,18 @@
// 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 accessEntity
-package apidVerifyApiKey
+import (
+ "github.com/apid/apid-core"
+)
-import "github.com/apid/apid-core"
+var (
+ services apid.Services
+ log apid.LogService
+)
-var pluginData = apid.PluginData{
- Name: "apidVerifyAPIKey",
- Version: "0.0.4",
- ExtraData: map[string]interface{}{
- "schemaVersion": "0.0.3",
- },
+func SetApidServices(s apid.Services, l apid.LogService) {
+ services = s
+ log = l
}
diff --git a/accessEntity/interfaces.go b/accessEntity/interfaces.go
new file mode 100644
index 0000000..a580762
--- /dev/null
+++ b/accessEntity/interfaces.go
@@ -0,0 +1,40 @@
+// 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 accessEntity
+
+import (
+ "github.com/apid/apidVerifyApiKey/common"
+ "net/http"
+)
+
+type ApiManagerInterface interface {
+ common.ApiManagerInterface
+ HandleRequest(w http.ResponseWriter, r *http.Request)
+}
+
+type DbManagerInterface interface {
+ common.DbManagerInterface
+ GetApiProducts(org, priKey, priVal, secKey, secVal string) (apiProducts []common.ApiProduct, err error)
+ GetApps(org, priKey, priVal, secKey, secVal string) (apps []common.App, err error)
+ GetCompanies(org, priKey, priVal, secKey, secVal string) (companies []common.Company, err error)
+ GetCompanyDevelopers(org, priKey, priVal, secKey, secVal string) (companyDevelopers []common.CompanyDeveloper, err error)
+ GetAppCredentials(org, priKey, priVal, secKey, secVal string) (appCredentials []common.AppCredential, err error)
+ GetDevelopers(org, priKey, priVal, secKey, secVal string) (developers []common.Developer, err error)
+ // utils
+ GetApiProductNames(id string, idType string) ([]string, error)
+ GetAppNames(id string, idType string) ([]string, error)
+ GetComNames(id string, idType string) ([]string, error)
+ GetDevEmailByDevId(devId string) (string, error)
+ GetStatus(id, t string) (string, error)
+}
diff --git a/accessEntity/mock_test.go b/accessEntity/mock_test.go
new file mode 100644
index 0000000..18a9bbc
--- /dev/null
+++ b/accessEntity/mock_test.go
@@ -0,0 +1,89 @@
+// 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 accessEntity
+
+import (
+ "github.com/apid/apidVerifyApiKey/common"
+)
+
+type DummyDbMan struct {
+ apiProducts []common.ApiProduct
+ apps []common.App
+ companies []common.Company
+ companyDevelopers []common.CompanyDeveloper
+ appCredentials []common.AppCredential
+ developers []common.Developer
+ apiProductNames []string
+ appNames []string
+ comNames []string
+ email string
+ status string
+ attrs map[string][]common.Attribute
+ err error
+}
+
+func (d *DummyDbMan) SetDbVersion(string) {
+
+}
+func (d *DummyDbMan) GetDbVersion() string {
+ return ""
+}
+
+func (d *DummyDbMan) GetKmsAttributes(tenantId string, entities ...string) map[string][]common.Attribute {
+ return d.attrs
+}
+
+func (d *DummyDbMan) GetApiProducts(org, priKey, priVal, secKey, secVal string) (apiProducts []common.ApiProduct, err error) {
+ return d.apiProducts, d.err
+}
+
+func (d *DummyDbMan) GetApps(org, priKey, priVal, secKey, secVal string) (apps []common.App, err error) {
+ return d.apps, d.err
+}
+
+func (d *DummyDbMan) GetCompanies(org, priKey, priVal, secKey, secVal string) (companies []common.Company, err error) {
+ return d.companies, d.err
+}
+
+func (d *DummyDbMan) GetCompanyDevelopers(org, priKey, priVal, secKey, secVal string) (companyDevelopers []common.CompanyDeveloper, err error) {
+ return d.companyDevelopers, d.err
+}
+
+func (d *DummyDbMan) GetAppCredentials(org, priKey, priVal, secKey, secVal string) (appCredentials []common.AppCredential, err error) {
+ return d.appCredentials, d.err
+}
+
+func (d *DummyDbMan) GetDevelopers(org, priKey, priVal, secKey, secVal string) (developers []common.Developer, err error) {
+ return d.developers, d.err
+}
+
+func (d *DummyDbMan) GetApiProductNames(id string, idType string) ([]string, error) {
+ return d.apiProductNames, d.err
+}
+
+func (d *DummyDbMan) GetAppNames(id string, idType string) ([]string, error) {
+ return d.appNames, d.err
+}
+
+func (d *DummyDbMan) GetComNames(id string, idType string) ([]string, error) {
+ return d.comNames, d.err
+}
+
+func (d *DummyDbMan) GetDevEmailByDevId(devId string) (string, error) {
+ return d.email, d.err
+}
+
+func (d *DummyDbMan) GetStatus(id, t string) (string, error) {
+ return d.status, d.err
+}
diff --git a/verifyAPIKey_suite_test.go b/apidApiMetadata_suite_test.go
similarity index 86%
rename from verifyAPIKey_suite_test.go
rename to apidApiMetadata_suite_test.go
index fdb5ed2..a66271f 100644
--- a/verifyAPIKey_suite_test.go
+++ b/apidApiMetadata_suite_test.go
@@ -11,7 +11,6 @@
// 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 (
@@ -25,25 +24,17 @@
const testTempDirBase = "./tmp/"
-var (
- testTempDir string
- testSyncHandler apigeeSyncHandler
-)
-
var _ = BeforeSuite(func() {
_ = os.MkdirAll(testTempDirBase, os.ModePerm)
})
var _ = AfterSuite(func() {
apid.Events().Close()
- if testServer != nil {
- testServer.Close()
- }
os.RemoveAll(testTempDirBase)
})
-func TestVerifyAPIKey(t *testing.T) {
+func TestApiMetadata(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "VerifyAPIKey Suite")
}
diff --git a/common/api.go b/common/api.go
new file mode 100644
index 0000000..9b3f243
--- /dev/null
+++ b/common/api.go
@@ -0,0 +1,35 @@
+// 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
+
+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..a592f97
--- /dev/null
+++ b/common/data.go
@@ -0,0 +1,110 @@
+// 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
+
+import (
+ "database/sql"
+ "encoding/json"
+ "github.com/apid/apid-core"
+ "strings"
+ "sync"
+ "unicode/utf8"
+)
+
+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
+ 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)
+ }
+ }
+ return mapOfAttributes
+}
+
+func JsonToStringArray(fjson string) []string {
+ var array []string
+ if err := json.Unmarshal([]byte(fjson), &array); err == nil {
+ return array
+ }
+ s := strings.TrimPrefix(fjson, "{")
+ s = strings.TrimSuffix(s, "}")
+ if utf8.RuneCountInString(s) > 0 {
+ array = strings.Split(s, ",")
+ }
+ return array
+}
diff --git a/common/data_structs.go b/common/data_structs.go
new file mode 100644
index 0000000..77c0911
--- /dev/null
+++ b/common/data_structs.go
@@ -0,0 +1,127 @@
+// 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"`
+ TenantId string `db:"tenant_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"`
+ TenantId string `db:"tenant_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"`
+}
+
+type AppCredential struct {
+ Id string `db:"id"`
+ TenantId string `db:"tenant_id"`
+ ConsumerSecret string `db:"consumer_secret"`
+ AppId string `db:"app_id"`
+ MethodType string `db:"method_type"`
+ Status string `db:"status"`
+ IssuedAt string `db:"issued_at"`
+ ExpiresAt string `db:"expires_at"`
+ AppStatus string `db:"app_status"`
+ Scopes string `db:"scopes"`
+ CreatedAt string `db:"created_at"`
+ CreatedBy string `db:"created_by"`
+ UpdatedAt string `db:"updated_at"`
+ UpdatedBy string `db:"updated_by"`
+}
+
+type Company struct {
+ Id string `db:"id"`
+ TenantId string `db:"tenant_id"`
+ Name string `db:"name"`
+ DisplayName string `db:"display_name"`
+ Status string `db:"status"`
+ CreatedAt string `db:"created_at"`
+ CreatedBy string `db:"created_by"`
+ UpdatedAt string `db:"updated_at"`
+ UpdatedBy string `db:"updated_by"`
+}
+
+type Developer struct {
+ Id string `db:"id"`
+ TenantId string `db:"tenant_id"`
+ UserName string `db:"username"`
+ FirstName string `db:"first_name"`
+ LastName string `db:"last_name"`
+ Password string `db:"password"`
+ Email string `db:"email"`
+ Status string `db:"status"`
+ EncryptedPassword string `db:"encrypted_password"`
+ Salt string `db:"salt"`
+ CreatedAt string `db:"created_at"`
+ CreatedBy string `db:"created_by"`
+ UpdatedAt string `db:"updated_at"`
+ UpdatedBy string `db:"updated_by"`
+}
+
+type CompanyDeveloper struct {
+ TenantId string `db:"tenant_id"`
+ CompanyId string `db:"company_id"`
+ DeveloperId string `db:"developer_id"`
+ Roles string `db:"roles"`
+ CreatedAt string `db:"created_at"`
+ CreatedBy string `db:"created_by"`
+ UpdatedAt string `db:"updated_at"`
+ UpdatedBy string `db:"updated_by"`
+}
diff --git a/pluginData.go b/common/interfaces.go
similarity index 71%
copy from pluginData.go
copy to common/interfaces.go
index 0ebe61b..59249b5 100644
--- a/pluginData.go
+++ b/common/interfaces.go
@@ -11,15 +11,14 @@
// 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
-package apidVerifyApiKey
+type ApiManagerInterface interface {
+ InitAPI()
+}
-import "github.com/apid/apid-core"
-
-var pluginData = apid.PluginData{
- Name: "apidVerifyAPIKey",
- Version: "0.0.4",
- ExtraData: map[string]interface{}{
- "schemaVersion": "0.0.3",
- },
+type DbManagerInterface interface {
+ SetDbVersion(string)
+ GetDbVersion() string
+ GetKmsAttributes(tenantId string, entities ...string) map[string][]Attribute
}
diff --git a/pluginData.go b/common/pluginData.go
similarity index 86%
rename from pluginData.go
rename to common/pluginData.go
index 0ebe61b..89a7c11 100644
--- a/pluginData.go
+++ b/common/pluginData.go
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package common
import "github.com/apid/apid-core"
-var pluginData = apid.PluginData{
+var PluginData = apid.PluginData{
Name: "apidVerifyAPIKey",
- Version: "0.0.4",
+ Version: "0.1.0",
ExtraData: map[string]interface{}{
- "schemaVersion": "0.0.3",
+ "schemaVersion": "0.1.0",
},
}
diff --git a/glide.yaml b/glide.yaml
index 7f8edff..da46400 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-package: github.com/apid/apidVerifyAPIKey
+package: github.com/apid/apidVerifyApiKey
import:
- package: github.com/apid/apid-core
version: master
diff --git a/init.go b/init.go
index 37e5a0b..b147a1a 100644
--- a/init.go
+++ b/init.go
@@ -15,13 +15,11 @@
package apidVerifyApiKey
import (
- "sync"
-
"github.com/apid/apid-core"
-)
-
-const (
- apiPath = "/verifiers/apikey"
+ "github.com/apid/apidVerifyApiKey/accessEntity"
+ "github.com/apid/apidVerifyApiKey/common"
+ "github.com/apid/apidVerifyApiKey/verifyApiKey"
+ "sync"
)
var (
@@ -30,33 +28,50 @@
)
func init() {
- apid.RegisterPlugin(initPlugin, pluginData)
+ apid.RegisterPlugin(initPlugin, common.PluginData)
}
func initPlugin(s apid.Services) (apid.PluginData, error) {
services = s
-
- log = services.Log().ForModule("apidVerifyAPIKey")
+ log = services.Log().ForModule("apidApiMetadata")
+ verifyApiKey.SetApidServices(services, log)
+ accessEntity.SetApidServices(services, log)
+ common.SetApidServices(services, log)
log.Debug("start init")
+ initManagers(services)
+ log.Debug("end init")
- log = services.Log()
- dbMan := &dbManager{
- data: services.Data(),
- dbMux: sync.RWMutex{},
+ return common.PluginData, nil
+}
+
+func initManagers(services apid.Services) apigeeSyncHandler {
+ verifyDbMan := &verifyApiKey.DbManager{
+ DbManager: common.DbManager{
+ Data: services.Data(),
+ DbMux: sync.RWMutex{},
+ },
}
- apiMan := apiManager{
- dbMan: dbMan,
- verifiersEndpoint: apiPath,
+ verifyApiMan := &verifyApiKey.ApiManager{
+ DbMan: verifyDbMan,
+ VerifiersEndpoint: verifyApiKey.ApiPath,
+ }
+
+ entityDbMan := &accessEntity.DbManager{
+ DbManager: common.DbManager{
+ Data: services.Data(),
+ DbMux: sync.RWMutex{},
+ },
+ }
+
+ entityApiMan := &accessEntity.ApiManager{
+ DbMan: entityDbMan,
+ AccessEntityPath: accessEntity.AccessEntityPath,
}
syncHandler := apigeeSyncHandler{
- dbMan: dbMan,
- apiMan: apiMan,
+ dbMans: []common.DbManagerInterface{verifyDbMan, entityDbMan},
+ apiMans: []common.ApiManagerInterface{verifyApiMan, entityApiMan},
}
-
syncHandler.initListener(services)
-
- log.Debug("end init")
-
- return pluginData, nil
+ return syncHandler
}
diff --git a/listener.go b/listener.go
index db136f6..7f2ec69 100644
--- a/listener.go
+++ b/listener.go
@@ -16,7 +16,8 @@
import (
"github.com/apid/apid-core"
- "github.com/apigee-labs/transicator/common"
+ "github.com/apid/apidVerifyApiKey/common"
+ tran "github.com/apigee-labs/transicator/common"
)
const (
@@ -24,8 +25,8 @@
)
type apigeeSyncHandler struct {
- dbMan dbManagerInterface
- apiMan apiManager
+ dbMans []common.DbManagerInterface
+ apiMans []common.ApiManagerInterface
}
func (h *apigeeSyncHandler) initListener(services apid.Services) {
@@ -36,16 +37,22 @@
return "verifyAPIKey"
}
-func (h *apigeeSyncHandler) processSnapshot(snapshot *common.Snapshot) {
+func (h *apigeeSyncHandler) processSnapshot(snapshot *tran.Snapshot) {
log.Debugf("Snapshot received. Switching to DB version: %s", snapshot.SnapshotInfo)
- h.dbMan.setDbVersion(snapshot.SnapshotInfo)
- h.apiMan.InitAPI()
+ // set db version for all packages
+ for _, dbMan := range h.dbMans {
+ dbMan.SetDbVersion(snapshot.SnapshotInfo)
+ }
+ // idempotent init api for all packages
+ for _, apiMan := range h.apiMans {
+ apiMan.InitAPI()
+ }
log.Debug("Snapshot processed")
}
func (h *apigeeSyncHandler) Handle(e apid.Event) {
- if snapData, ok := e.(*common.Snapshot); ok {
+ if snapData, ok := e.(*tran.Snapshot); ok {
h.processSnapshot(snapData)
} else {
log.Debugf("Received event. No action required for verifyApiKey plugin. Ignoring. %v", e)
diff --git a/listener_test.go b/listener_test.go
index 7ba8379..c82b96a 100644
--- a/listener_test.go
+++ b/listener_test.go
@@ -17,12 +17,11 @@
import (
"github.com/apid/apid-core"
"github.com/apid/apid-core/factory"
- "github.com/apigee-labs/transicator/common"
+ tran "github.com/apigee-labs/transicator/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"io/ioutil"
"os"
- "sync"
)
var _ = Describe("listener", func() {
@@ -39,22 +38,7 @@
Expect(err).NotTo(HaveOccurred())
apid.InitializePlugins("")
-
- db, err := apid.Data().DB()
- Expect(err).NotTo(HaveOccurred())
-
- dbMan := &dbManager{
- data: s.Data(),
- dbMux: sync.RWMutex{},
- db: db,
- }
-
- listnerTestSyncHandler = apigeeSyncHandler{
- dbMan: dbMan,
- apiMan: apiManager{},
- }
-
- listnerTestSyncHandler.initListener(s)
+ listnerTestSyncHandler = initManagers(s)
})
var _ = AfterEach(func() {
@@ -64,24 +48,28 @@
Context("Apigee Sync Event Processing", func() {
It("should set DB to appropriate version", func() {
- s := &common.Snapshot{
+ s := &tran.Snapshot{
SnapshotInfo: "test_snapshot",
- Tables: []common.Table{},
+ Tables: []tran.Table{},
}
listnerTestSyncHandler.Handle(s)
- Expect(listnerTestSyncHandler.dbMan.getDbVersion()).Should(BeEquivalentTo(s.SnapshotInfo))
+ for _, dbMan := range listnerTestSyncHandler.dbMans {
+ Expect(dbMan.GetDbVersion()).Should(BeEquivalentTo(s.SnapshotInfo))
+ }
})
It("should not change version for chang event", func() {
- version := listnerTestSyncHandler.dbMan.getDbVersion()
- s := &common.Change{
+ version := listnerTestSyncHandler.dbMans[0].GetDbVersion()
+ s := &tran.Change{
ChangeSequence: 12321,
Table: "",
}
- testSyncHandler.Handle(s)
- Expect(listnerTestSyncHandler.dbMan.getDbVersion() == version).Should(BeTrue())
+ listnerTestSyncHandler.Handle(s)
+ for _, dbMan := range listnerTestSyncHandler.dbMans {
+ Expect(dbMan.GetDbVersion() == version).Should(BeTrue())
+ }
})
diff --git a/api.go b/verifyApiKey/api.go
similarity index 89%
rename from api.go
rename to verifyApiKey/api.go
index 36c5058..18d6e51 100644
--- a/api.go
+++ b/verifyApiKey/api.go
@@ -12,39 +12,40 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
"encoding/json"
+ "github.com/apid/apidVerifyApiKey/common"
"io"
"io/ioutil"
"net/http"
"strings"
)
-type apiManagerInterface interface {
+type ApiManagerInterface interface {
InitAPI()
- handleRequest(w http.ResponseWriter, r *http.Request)
- verifyAPIKey(verifyApiKeyReq VerifyApiKeyRequest) (*VerifyApiKeySuccessResponse, *ErrorResponse)
+ HandleRequest(w http.ResponseWriter, r *http.Request)
+ verifyAPIKey(verifyApiKeyReq VerifyApiKeyRequest) (*VerifyApiKeySuccessResponse, *common.ErrorResponse)
}
-type apiManager struct {
- dbMan dbManagerInterface
- verifiersEndpoint string
+type ApiManager struct {
+ DbMan DbManagerInterface
+ VerifiersEndpoint string
apiInitialized bool
}
-func (a *apiManager) InitAPI() {
+func (a *ApiManager) InitAPI() {
if a.apiInitialized {
return
}
- services.API().HandleFunc(a.verifiersEndpoint, a.handleRequest).Methods("POST")
+ services.API().HandleFunc(a.VerifiersEndpoint, a.HandleRequest).Methods("POST")
a.apiInitialized = true
log.Debug("API endpoints initialized")
}
// handle client API
-func (a *apiManager) handleRequest(w http.ResponseWriter, r *http.Request) {
+func (a *ApiManager) HandleRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
@@ -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,
@@ -116,7 +117,7 @@
dataWrapper.verifyApiKeySuccessResponse.ClientId.ClientId = verifyApiKeyReq.Key
dataWrapper.verifyApiKeySuccessResponse.Environment = verifyApiKeyReq.EnvironmentName
- err := apiM.dbMan.getApiKeyDetails(&dataWrapper)
+ err := apiM.DbMan.getApiKeyDetails(&dataWrapper)
switch {
case err != nil && err.Error() == "InvalidApiKey":
@@ -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
@@ -273,9 +274,9 @@
}
-func (a *apiManager) enrichAttributes(dataWrapper *VerifyApiKeyRequestResponseDataWrapper) {
+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/api_ShortListApiProduct_test.go b/verifyApiKey/api_ShortListApiProduct_test.go
similarity index 99%
rename from api_ShortListApiProduct_test.go
rename to verifyApiKey/api_ShortListApiProduct_test.go
index 72c999e..732fda4 100644
--- a/api_ShortListApiProduct_test.go
+++ b/verifyApiKey/api_ShortListApiProduct_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
. "github.com/onsi/ginkgo"
diff --git a/api_performValidations_test.go b/verifyApiKey/api_performValidations_test.go
similarity index 98%
rename from api_performValidations_test.go
rename to verifyApiKey/api_performValidations_test.go
index afcb225..f7dcdb3 100644
--- a/api_performValidations_test.go
+++ b/verifyApiKey/api_performValidations_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
"encoding/json"
@@ -33,7 +33,7 @@
apid.Initialize(factory.DefaultServicesFactory())
log = factory.DefaultServicesFactory().Log()
- a := apiManager{}
+ a := ApiManager{}
Context("performValidationsTest tests", func() {
It("happy-path", func() {
@@ -343,7 +343,7 @@
}
Expect(actual).Should(Equal(td.expectedResult))
})
- It("resources not configured in db", func() {
+ It("resources not configured in Db", func() {
td := performValidationsTestDataStruct{
expectedResult: "",
expectedWhenValidateProxyEnvIsTrue: "",
@@ -395,7 +395,7 @@
}
Expect(actual).Should(Equal(td.expectedResult))
})
- It("proxies not configured in db", func() {
+ It("proxies not configured in Db", func() {
td := performValidationsTestDataStruct{
expectedResult: "",
expectedWhenValidateProxyEnvIsTrue: "",
@@ -447,7 +447,7 @@
}
Expect(actual).Should(Equal(td.expectedResult))
})
- It("environments not configured in db", func() {
+ It("environments not configured in Db", func() {
td := performValidationsTestDataStruct{
expectedResult: "",
expectedWhenValidateProxyEnvIsTrue: "",
diff --git a/api_test.go b/verifyApiKey/api_test.go
similarity index 91%
rename from api_test.go
rename to verifyApiKey/api_test.go
index 50c6bbc..97e226f 100644
--- a/api_test.go
+++ b/verifyApiKey/api_test.go
@@ -11,7 +11,7 @@
// 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
+package verifyApiKey
// TODO: end to end IT tests
// 1. happy path for developer
@@ -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"
@@ -42,34 +43,36 @@
var _ = Describe("end to end tests", func() {
var dataTestTempDir string
- var dbMan *dbManager
+ var dbMan *DbManager
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)
+ common.SetApidServices(serviceFactoryForTest, serviceFactoryForTest.Log())
- Expect(err).NotTo(HaveOccurred())
-
- dbMan = &dbManager{
- data: serviceFactoryForTest.Data(),
- dbMux: sync.RWMutex{},
+ dbMan = &DbManager{
+ DbManager: common.DbManager{
+ Data: serviceFactoryForTest.Data(),
+ DbMux: sync.RWMutex{},
+ },
}
- dbMan.setDbVersion(dataTestTempDir)
+ dbMan.SetDbVersion(dataTestTempDir)
- apiMan := apiManager{
- dbMan: dbMan,
- verifiersEndpoint: apiPath,
+ apiMan := ApiManager{
+ DbMan: dbMan,
+ VerifiersEndpoint: ApiPath,
}
testServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- if req.URL.Path == apiPath {
- apiMan.handleRequest(w, req)
+ if req.URL.Path == ApiPath {
+ apiMan.HandleRequest(w, req)
}
}))
@@ -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",
@@ -112,8 +115,8 @@
Expect(respObj.ResponseCode).Should(Equal("oauth.v2.InvalidApiKey"))
})
It("should return validation error for inavlid env", func() {
- setupApikeyDeveloperTestDb(dbMan.db)
- var respObj ErrorResponse
+ setupApikeyDeveloperTestDb(dbMan.Db)
+ var respObj common.ErrorResponse
reqInput := VerifyApiKeyRequest{
Key: "63tHSNLKJkcc6GENVWGT1Zw5gek7kVJ0",
Action: "verify",
@@ -134,8 +137,8 @@
Expect(respObj.ResponseCode).Should(Equal("oauth.v2.InvalidApiKeyForGivenResource"))
})
It("should return validation error for inavlid resource", func() {
- setupApikeyDeveloperTestDb(dbMan.db)
- var respObj ErrorResponse
+ setupApikeyDeveloperTestDb(dbMan.Db)
+ var respObj common.ErrorResponse
reqInput := VerifyApiKeyRequest{
Key: "63tHSNLKJkcc6GENVWGT1Zw5gek7kVJ0",
Action: "verify",
@@ -156,8 +159,8 @@
Expect(respObj.ResponseCode).Should(Equal("oauth.v2.InvalidApiKeyForGivenResource"))
})
It("should return validation error for inavlid proxies", func() {
- setupApikeyDeveloperTestDb(dbMan.db)
- var respObj ErrorResponse
+ setupApikeyDeveloperTestDb(dbMan.Db)
+ var respObj common.ErrorResponse
reqInput := VerifyApiKeyRequest{
Key: "63tHSNLKJkcc6GENVWGT1Zw5gek7kVJ0",
Action: "verify",
@@ -178,7 +181,7 @@
Expect(respObj.ResponseCode).Should(Equal("oauth.v2.InvalidApiKeyForGivenResource"))
})
It("should peform verify api key for developer happy path", func() {
- setupApikeyDeveloperTestDb(dbMan.db)
+ setupApikeyDeveloperTestDb(dbMan.Db)
var respObj VerifyApiKeySuccessResponse
reqInput := VerifyApiKeyRequest{
@@ -229,7 +232,7 @@
})
It("should peform verify api key for company happy path", func() {
- setupApikeyCompanyTestDb(dbMan.db)
+ setupApikeyCompanyTestDb(dbMan.Db)
var respObj VerifyApiKeySuccessResponse
reqInput := VerifyApiKeyRequest{
@@ -283,11 +286,14 @@
func performTestOperation(jsonBody string, expectedResponseCode int) ([]byte, error) {
uri, err := url.Parse(testServer.URL)
- uri.Path = apiPath
+ uri.Path = ApiPath
client := &http.Client{}
httpReq, err := http.NewRequest("POST", uri.String(), strings.NewReader(string(jsonBody)))
httpReq.Header.Set("Content-Type", "application/json")
res, err := client.Do(httpReq)
+ if err != nil {
+ return nil, err
+ }
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
diff --git a/data.go b/verifyApiKey/data.go
similarity index 60%
rename from data.go
rename to verifyApiKey/data.go
index e2d974e..769a92d 100644
--- a/data.go
+++ b/verifyApiKey/data.go
@@ -11,90 +11,25 @@
// 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
+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
+type DbManagerInterface interface {
+ common.DbManagerInterface
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 {
+func (dbc DbManager) getApiKeyDetails(dataWrapper *VerifyApiKeyRequestResponseDataWrapper) error {
- db := dbc.db
+ db := dbc.Db
err := db.QueryRow(sql_GET_API_KEY_DETAILS_SQL, dataWrapper.verifyApiKeyRequest.Key, dataWrapper.verifyApiKeyRequest.OrganizationName).
Scan(
@@ -144,9 +79,9 @@
return err
}
-func (dbc dbManager) getApiProductsForApiKey(key, tenantId string) []ApiProductDetails {
+func (dbc DbManager) getApiProductsForApiKey(key, tenantId string) []ApiProductDetails {
- db := dbc.db
+ db := dbc.Db
allProducts := []ApiProductDetails{}
var proxies, environments, resources string
@@ -174,9 +109,9 @@
&environments,
&resources,
)
- apiProductDetais.Apiproxies = jsonToStringArray(proxies)
- apiProductDetais.Environments = jsonToStringArray(environments)
- apiProductDetais.Resources = jsonToStringArray(resources)
+ apiProductDetais.Apiproxies = common.JsonToStringArray(proxies)
+ apiProductDetais.Environments = common.JsonToStringArray(environments)
+ apiProductDetais.Resources = common.JsonToStringArray(resources)
allProducts = append(allProducts, apiProductDetais)
}
diff --git a/data_helper_test.go b/verifyApiKey/data_helper_test.go
similarity index 99%
rename from data_helper_test.go
rename to verifyApiKey/data_helper_test.go
index c5fa0e4..74c19a5 100644
--- a/data_helper_test.go
+++ b/verifyApiKey/data_helper_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
"github.com/apid/apid-core"
diff --git a/data_test.go b/verifyApiKey/data_test.go
similarity index 93%
rename from data_test.go
rename to verifyApiKey/data_test.go
index 2a6bdb6..c864339 100644
--- a/data_test.go
+++ b/verifyApiKey/data_test.go
@@ -11,11 +11,12 @@
// 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
+package verifyApiKey
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"
@@ -24,30 +25,31 @@
var _ = Describe("DataTest", func() {
- Context("query db to get api key details", func() {
+ Context("query Db to get api key details", func() {
var dataTestTempDir string
- var dbMan *dbManager
+ var dbMan *DbManager
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)
+ common.SetApidServices(s, s.Log())
- Expect(err).NotTo(HaveOccurred())
-
- dbMan = &dbManager{
- data: s.Data(),
- dbMux: sync.RWMutex{},
+ dbMan = &DbManager{
+ DbManager: common.DbManager{
+ Data: s.Data(),
+ DbMux: sync.RWMutex{},
+ },
}
- dbMan.setDbVersion(dataTestTempDir)
+ dbMan.SetDbVersion(dataTestTempDir)
})
It("should get compnay getApiKeyDetails for happy path", func() {
- setupApikeyCompanyTestDb(dbMan.db)
+ setupApikeyCompanyTestDb(dbMan.Db)
dataWrapper := VerifyApiKeyRequestResponseDataWrapper{
verifyApiKeyRequest: VerifyApiKeyRequest{
@@ -90,7 +92,7 @@
})
It("should get developer ApiKeyDetails - happy path", func() {
- setupApikeyDeveloperTestDb(dbMan.db)
+ setupApikeyDeveloperTestDb(dbMan.Db)
dataWrapper := VerifyApiKeyRequestResponseDataWrapper{
verifyApiKeyRequest: VerifyApiKeyRequest{
@@ -134,7 +136,7 @@
It("should throw error when apikey not found", func() {
- setupApikeyCompanyTestDb(dbMan.db)
+ setupApikeyCompanyTestDb(dbMan.Db)
dataWrapper := VerifyApiKeyRequestResponseDataWrapper{
verifyApiKeyRequest: VerifyApiKeyRequest{
OrganizationName: "apigee-mcrosrvc-client0001",
@@ -148,7 +150,7 @@
It("should get api products ", func() {
- setupApikeyCompanyTestDb(dbMan.db)
+ setupApikeyCompanyTestDb(dbMan.Db)
apiProducts := dbMan.getApiProductsForApiKey("63tHSNLKJkcc6GENVWGT1Zw5gek7kVJ0", "bc811169")
Expect(len(apiProducts)).Should(BeEquivalentTo(1))
@@ -176,7 +178,7 @@
It("should return empty array when no api products found", func() {
- setupApikeyCompanyTestDb(dbMan.db)
+ setupApikeyCompanyTestDb(dbMan.Db)
apiProducts := dbMan.getApiProductsForApiKey("invalid-LKJkcc6GENVWGT1Zw5gek7kVJ0", "bc811169")
Expect(len(apiProducts)).Should(BeEquivalentTo(0))
@@ -184,8 +186,8 @@
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")
+ setupKmsAttributesdata(dbMan.Db)
+ 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/pluginData.go b/verifyApiKey/init.go
similarity index 70%
copy from pluginData.go
copy to verifyApiKey/init.go
index 0ebe61b..33ac046 100644
--- a/pluginData.go
+++ b/verifyApiKey/init.go
@@ -11,15 +11,22 @@
// 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
-package apidVerifyApiKey
+import (
+ "github.com/apid/apid-core"
+)
-import "github.com/apid/apid-core"
+const (
+ ApiPath = "/verifiers/apikey"
+)
-var pluginData = apid.PluginData{
- Name: "apidVerifyAPIKey",
- Version: "0.0.4",
- ExtraData: map[string]interface{}{
- "schemaVersion": "0.0.3",
- },
+var (
+ services apid.Services
+ log apid.LogService
+)
+
+func SetApidServices(s apid.Services, l apid.LogService) {
+ services = s
+ log = l
}
diff --git a/kmsDataTest.sql b/verifyApiKey/kmsDataTest.sql
similarity index 100%
rename from kmsDataTest.sql
rename to verifyApiKey/kmsDataTest.sql
diff --git a/sqlQueries.go b/verifyApiKey/sqlQueries.go
similarity index 98%
rename from sqlQueries.go
rename to verifyApiKey/sqlQueries.go
index 504af9a..3a1525e 100644
--- a/sqlQueries.go
+++ b/verifyApiKey/sqlQueries.go
@@ -11,7 +11,7 @@
// 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
+package verifyApiKey
const sql_GET_API_KEY_DETAILS_SQL = `
SELECT
diff --git a/verifyAPIKey_suite_test.go b/verifyApiKey/verifyAPIKey_suite_test.go
similarity index 79%
copy from verifyAPIKey_suite_test.go
copy to verifyApiKey/verifyAPIKey_suite_test.go
index fdb5ed2..67873e7 100644
--- a/verifyAPIKey_suite_test.go
+++ b/verifyApiKey/verifyAPIKey_suite_test.go
@@ -12,26 +12,28 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/apid/apid-core"
+ "io/ioutil"
"os"
"testing"
)
-const testTempDirBase = "./tmp/"
+var testTempDirBase string
var (
- testTempDir string
- testSyncHandler apigeeSyncHandler
+ testTempDir string
)
var _ = BeforeSuite(func() {
- _ = os.MkdirAll(testTempDirBase, os.ModePerm)
+ var err error
+ testTempDirBase, err = ioutil.TempDir("", "verify_apikey_")
+ Expect(err).Should(Succeed())
})
var _ = AfterSuite(func() {
@@ -39,8 +41,7 @@
if testServer != nil {
testServer.Close()
}
- os.RemoveAll(testTempDirBase)
-
+ Expect(os.RemoveAll(testTempDirBase)).Should(Succeed())
})
func TestVerifyAPIKey(t *testing.T) {
diff --git a/verifyApiKeyStructs.go b/verifyApiKey/verifyApiKeyStructs.go
similarity index 89%
rename from verifyApiKeyStructs.go
rename to verifyApiKey/verifyApiKeyStructs.go
index 28f345b..b2a93e6 100644
--- a/verifyApiKeyStructs.go
+++ b/verifyApiKey/verifyApiKeyStructs.go
@@ -11,9 +11,12 @@
// 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
+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 {
diff --git a/verifyApiKeyUtil.go b/verifyApiKey/verifyApiKeyUtil.go
similarity index 77%
rename from verifyApiKeyUtil.go
rename to verifyApiKey/verifyApiKeyUtil.go
index a7d2451..85aa8c5 100644
--- a/verifyApiKeyUtil.go
+++ b/verifyApiKey/verifyApiKeyUtil.go
@@ -12,13 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
- "encoding/json"
"regexp"
"strings"
- "unicode/utf8"
)
/*
@@ -56,20 +54,6 @@
return len(fs) == 0
}
-func jsonToStringArray(fjson string) []string {
- var array []string
- if err := json.Unmarshal([]byte(fjson), &array); err == nil {
- return array
- }
- s := strings.TrimPrefix(fjson, "{")
- s = strings.TrimSuffix(s, "}")
- if utf8.RuneCountInString(s) > 0 {
- array = strings.Split(s, ",")
- }
- log.Debug("unmarshall error for string, performing custom unmarshal ", fjson, " and result is : ", array)
- return array
-}
-
func contains(givenArray []string, searchString string) bool {
for _, element := range givenArray {
if element == searchString {
diff --git a/verifyApiKeyUtil_test.go b/verifyApiKey/verifyApiKeyUtil_test.go
similarity index 81%
rename from verifyApiKeyUtil_test.go
rename to verifyApiKey/verifyApiKeyUtil_test.go
index 4e17289..0ff7f22 100644
--- a/verifyApiKeyUtil_test.go
+++ b/verifyApiKey/verifyApiKeyUtil_test.go
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
+ "github.com/apid/apidVerifyApiKey/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"reflect"
@@ -40,30 +41,30 @@
})
})
-var _ = Describe("Validate jsonToStringArray", func() {
+var _ = Describe("Validate common.JsonToStringArray", func() {
It("should tranform simple valid json", func() {
- array := jsonToStringArray("[\"test-1\", \"test-2\"]")
+ array := common.JsonToStringArray("[\"test-1\", \"test-2\"]")
Expect(reflect.DeepEqual(array, []string{"test-1", "test-2"})).Should(BeTrue())
})
It("should tranform simple single valid json", func() {
- array := jsonToStringArray("[\"test-1\"]")
+ array := common.JsonToStringArray("[\"test-1\"]")
Expect(reflect.DeepEqual(array, []string{"test-1"})).Should(BeTrue())
})
It("should tranform simple fake json", func() {
- s := jsonToStringArray("{test-1,test-2}")
+ s := common.JsonToStringArray("{test-1,test-2}")
Expect(reflect.DeepEqual(s, []string{"test-1", "test-2"})).Should(BeTrue())
})
It("should tranform simple single valued fake json", func() {
- s := jsonToStringArray("{test-1}")
+ s := common.JsonToStringArray("{test-1}")
Expect(reflect.DeepEqual(s, []string{"test-1"})).Should(BeTrue())
})
It("space between fields considered as valid char", func() {
- s := jsonToStringArray("{test-1, test-2}")
+ s := common.JsonToStringArray("{test-1, test-2}")
Expect(reflect.DeepEqual(s, []string{"test-1", " test-2"})).Should(BeTrue())
})
It("remove only last braces", func() {
- s := jsonToStringArray("{test-1,test-2}}")
+ s := common.JsonToStringArray("{test-1,test-2}}")
Expect(reflect.DeepEqual(s, []string{"test-1", "test-2}"})).Should(BeTrue())
})
diff --git a/verifyApiKeyUtil_validate_path_test.go b/verifyApiKey/verifyApiKeyUtil_validate_path_test.go
similarity index 98%
rename from verifyApiKeyUtil_validate_path_test.go
rename to verifyApiKey/verifyApiKeyUtil_validate_path_test.go
index eb91d8f..7399309 100644
--- a/verifyApiKeyUtil_validate_path_test.go
+++ b/verifyApiKey/verifyApiKeyUtil_validate_path_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package apidVerifyApiKey
+package verifyApiKey
import (
. "github.com/onsi/ginkgo"