blob: 160b79e3c685a25896a9519a86417cb9f84863cd [file]
// 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"
)
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,
}
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
DB_ERROR
DATA_ERROR
)
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.HandleConsumers).Methods("GET")
a.apiInitialized = true
log.Debug("API endpoints initialized")
}
func (a *ApiManager) HandleApps(w http.ResponseWriter, r *http.Request) {
}
func (a *ApiManager) HandleApiProducts(w http.ResponseWriter, r *http.Request) {
ids, err := extractIdentifiers(r.URL.Query())
if err != nil {
common.WriteError(w, err.Error(), INVALID_PARAMETERS, http.StatusBadRequest)
}
details, errRes := a.getApiProduct(ids)
if errRes != nil {
writeJson(errRes, w, r)
return
}
writeJson(details, w, r)
}
func (a *ApiManager) HandleCompanies(w http.ResponseWriter, r *http.Request) {
}
func (a *ApiManager) HandleCompanyDevelopers(w http.ResponseWriter, r *http.Request) {
}
func (a *ApiManager) HandleDevelopers(w http.ResponseWriter, r *http.Request) {
}
func (a *ApiManager) HandleConsumers(w http.ResponseWriter, r *http.Request) {
}
func extractIdentifiers(pars map[string][]string) (map[string]string, error) {
m := make(map[string]string)
for k, v := range pars {
k = strings.ToLower(k)
if Identifiers[k] {
if len(v) == 1 {
m[k] = v[0]
} else {
return nil, fmt.Errorf("each identifier must have only 1 value")
}
}
}
return m, nil
}
func (a *ApiManager) getApiProduct(ids map[string]string) (*ApiProductDetails, *common.ErrorResponse) {
valid, keyVals := parseIdentifiers(EndpointApiProduct, ids)
if !valid {
return nil, ErrInvalidPar
}
priKey, priVal, secKey, secVal := keyVals[0], keyVals[1], keyVals[2], keyVals[3]
prods, err := a.DbMan.GetApiProducts(priKey, priVal, secKey, secVal)
if err != nil {
log.Errorf("getApiProduct: %v", err)
return nil, newDbError(err)
}
var prod *common.ApiProduct
var attrs []common.Attribute
if len(prods) > 0 {
prod = &prods[0]
attrs = a.DbMan.GetKmsAttributes(prod.TenantId, prod.Id)[prod.Id]
}
return makeApiProductDetails(prod, attrs, priKey, priVal, secKey, secVal)
}
func makeApiProductDetails(prod *common.ApiProduct, attrs []common.Attribute, priKey, priVal, secKey, secVal string) (*ApiProductDetails, *common.ErrorResponse) {
var a *ApiProductDetails
if prod != nil {
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)
}
setResIdentifiers(a, priKey, priVal, secKey, secVal)
return a, nil
}
func setResIdentifiers(a *ApiProductDetails, priKey, priVal, secKey, secVal string) {
a.PrimaryIdentifierType = priKey
a.PrimaryIdentifierValue = priVal
a.SecondaryIdentifierType = secKey
a.PrimaryIdentifierValue = secVal
}
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
}
keyVals = append(keyVals, "", "")
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)
}
}