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"