Skip to content

Commit

Permalink
Added org endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Buhr committed Jan 7, 2015
1 parent 64c3168 commit 277b259
Show file tree
Hide file tree
Showing 15 changed files with 386 additions and 50 deletions.
207 changes: 207 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ func GetSpecForApi(APIID string) *APISpec {
return spec
}

func GetSpecForOrg(APIID string) *APISpec {
var aKey string
for k, v := range(ApiSpecRegister) {
if v.OrgID == APIID {
return v
}
aKey = k
}

// If we can't find a spec, it doesn;t matter, because we default to Redis anyway, grab whatever you can find
return ApiSpecRegister[aKey]
}

// ---- TODO: This changes the URL structure of the API completely ----
// ISSUE: If Session stores are stored with API specs, then managing keys will need to be done per store, i.e. add to all stores,
// remove from all stores, update to all stores, stores handle quotas separately though because they are localised! Keys will
Expand Down Expand Up @@ -399,6 +412,200 @@ func keyHandler(w http.ResponseWriter, r *http.Request) {
DoJSONWrite(w, code, responseMessage)
}

func orgHandler(w http.ResponseWriter, r *http.Request) {
keyName := r.URL.Path[len("/tyk/org/keys/"):]
filter := r.FormValue("filter")
var responseMessage []byte
var code int

if r.Method == "POST" || r.Method == "PUT" {
responseMessage, code = handleOrgAddOrUpdate(keyName, r)

} else if r.Method == "GET" {

if keyName != "" {
// Return single org detail
responseMessage, code = handleGetOrgDetail(keyName)
} else {
// Return list of keys
responseMessage, code = handleGetAllOrgKeys(filter, "")
}


} else if r.Method == "DELETE" {
// Remove a key
responseMessage, code = handleDeleteOrgKey(keyName)

} else {
// Return Not supported message (and code)
code = 405
responseMessage = createError("Method not supported")
}

DoJSONWrite(w, code, responseMessage)
}

func handleOrgAddOrUpdate(keyName string, r *http.Request) ([]byte, int) {
success := true
decoder := json.NewDecoder(r.Body)
var responseMessage []byte
var newSession SessionState
err := decoder.Decode(&newSession)
code := 200

if err != nil {
log.Error("Couldn't decode new session object")
log.Error(err)
code = 400
success = false
responseMessage = createError("Request malformed")
} else {
// Update our session object (create it)

spec := GetSpecForOrg(keyName)
if spec == nil {
responseMessage = createError("No such organisation found in Active API list")
return responseMessage, 400
}

spec.OrgSessionManager.UpdateSession(keyName, newSession, 0)

log.WithFields(logrus.Fields{
"key": keyName,
}).Info("New key added or updated.")
success = true
}

var action string
if r.Method == "POST" {
action = "added"
} else {
action = "modified"
}

if success {
response := APIModifyKeySuccess{
keyName,
"ok",
action}

responseMessage, err = json.Marshal(&response)

if err != nil {
log.Error("Could not create response message")
log.Error(err)
code = 500
responseMessage = []byte(E_SYSTEM_ERROR)
}
}

return responseMessage, code
}

func handleGetOrgDetail(ORGID string) ([]byte, int) {
success := true
var responseMessage []byte
var err error
code := 200

thiSpec := GetSpecForOrg(ORGID)
if thiSpec == nil {
notFound := APIStatusMessage{"error", "Org not found"}
responseMessage, _ = json.Marshal(&notFound)
return responseMessage, 400
}

thisSession, ok := thiSpec.OrgSessionManager.GetSessionDetail(ORGID)
if !ok {
success = false
} else {
responseMessage, err = json.Marshal(&thisSession)
if err != nil {
log.Error("Marshalling failed")
log.Error(err)
success = false
}
}

if !success {
notFound := APIStatusMessage{"error", "Org not found"}
responseMessage, _ = json.Marshal(&notFound)
code = 404
log.WithFields(logrus.Fields{
"Org": ORGID,
}).Info("Attempted key retrieval - failure.")
} else {
log.WithFields(logrus.Fields{
"Org": ORGID,
}).Info("Attempted key retrieval - success.")
}

return responseMessage, code
}

func handleGetAllOrgKeys(filter, ORGID string) ([]byte, int) {
success := true
var responseMessage []byte
code := 200

var err error

thiSpec := GetSpecForOrg(ORGID)
if thiSpec == nil {
notFound := APIStatusMessage{"error", "ORG not found"}
responseMessage, _ = json.Marshal(&notFound)
return responseMessage, 400
}

sessions := thiSpec.OrgSessionManager.GetSessions(filter)
sessionsObj := APIAllKeys{sessions}

responseMessage, err = json.Marshal(&sessionsObj)
if err != nil {
log.Error("Marshalling failed")
log.Error(err)
success = false
code = 500
}

if success {
return responseMessage, code
}

log.Info("Attempted orgs retrieval - success.")
return []byte(E_SYSTEM_ERROR), code

}

func handleDeleteOrgKey(ORGID string) ([]byte, int) {
var responseMessage []byte
var err error

thiSpec := GetSpecForOrg(ORGID)
if thiSpec == nil {
notFound := APIStatusMessage{"error", "Org not found"}
responseMessage, _ = json.Marshal(&notFound)
return responseMessage, 400
}

thiSpec.OrgSessionManager.RemoveSession(ORGID)
code := 200

statusObj := APIModifyKeySuccess{ORGID, "ok", "deleted"}
responseMessage, err = json.Marshal(&statusObj)

if err != nil {
log.Error("Marshalling failed")
log.Error(err)
return []byte(E_SYSTEM_ERROR), 500
}

log.WithFields(logrus.Fields{
"key": ORGID,
}).Info("Attempted org key deletion - success.")

return responseMessage, code
}
func resetHandler(w http.ResponseWriter, r *http.Request) {
var responseMessage []byte
var code int
Expand Down
7 changes: 6 additions & 1 deletion api_definition_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ type APISpec struct {
AuthManager AuthorisationHandler
SessionManager SessionHandler
OAuthManager *OAuthManager
OrgSessionManager SessionHandler
EventPaths map[tykcommon.TykEvent][]TykEventHandler
Health HealthChecker
}
Expand Down Expand Up @@ -192,11 +193,14 @@ func (a *APIDefinitionLoader) MakeSpec(thisAppConfig tykcommon.APIDefinition) AP
switch newAppSpec.APIDefinition.SessionProvider.Name {
case DefaultSessionProvider:
newAppSpec.SessionManager = &DefaultSessionManager{}
newAppSpec.OrgSessionManager = &DefaultSessionManager{}
default:
newAppSpec.SessionManager = &DefaultSessionManager{}
newAppSpec.OrgSessionManager = &DefaultSessionManager{}
}
} else {
newAppSpec.SessionManager = &DefaultSessionManager{}
newAppSpec.OrgSessionManager = &DefaultSessionManager{}
}

// Set up Event Handlers
Expand Down Expand Up @@ -390,10 +394,11 @@ func (a *APIDefinitionLoader) getExtendedPathSpecs(apiVersionDef tykcommon.Versi
return combinedPath, false
}

func (a *APISpec) Init(AuthStore StorageHandler, SessionStore StorageHandler, healthStorageHandler StorageHandler) {
func (a *APISpec) Init(AuthStore StorageHandler, SessionStore StorageHandler, healthStorageHandler StorageHandler, orgStorageHandler StorageHandler) {
a.AuthManager.Init(AuthStore)
a.SessionManager.Init(SessionStore)
a.Health.Init(healthStorageHandler)
a.OrgSessionManager.Init(orgStorageHandler)
}

func (a *APISpec) getURLStatus(stat URLStatus) RequestStatus {
Expand Down
3 changes: 2 additions & 1 deletion api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ func MakeSampleAPI() *APISpec {
thisSpec := createDefinitionFromString(apiTestDef)
redisStore := RedisStorageManager{KeyPrefix: "apikey-"}
healthStore := &RedisStorageManager{KeyPrefix: "apihealth."}
thisSpec.Init(&redisStore, &redisStore, healthStore)
orgStore := &RedisStorageManager{KeyPrefix: "orgKey."}
thisSpec.Init(&redisStore, &redisStore, healthStore, orgStore)

specs := []APISpec{thisSpec}
newMuxes := http.NewServeMux()
Expand Down
3 changes: 1 addition & 2 deletions auth_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ func (b DefaultSessionManager) GetSessionDetail(keyName string) (SessionState, b
}

if marshalErr := json.Unmarshal([]byte(jsonKeyVal), &thisSession); marshalErr != nil {
log.Error("Couldn't unmarshal session object")
log.Error(marshalErr)
log.Error("Couldn't unmarshal session object (may be cache miss): ", marshalErr)
return thisSession, false
}

Expand Down
12 changes: 8 additions & 4 deletions batch_requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ func createBatchTestSession() SessionState {
func getBatchTestChain(spec APISpec) http.Handler {
redisStore := RedisStorageManager{KeyPrefix: "apikey-"}
healthStore := &RedisStorageManager{KeyPrefix: "apihealth."}
spec.Init(&redisStore, &redisStore, healthStore)
orgStore := &RedisStorageManager{KeyPrefix: "orgKey."}
spec.Init(&redisStore, &redisStore, healthStore, orgStore)
remote, _ := url.Parse("http://httpbin.org/")
proxy := TykNewSingleHostReverseProxy(remote)
proxyHandler := http.HandlerFunc(ProxyHandler(proxy, spec))
Expand Down Expand Up @@ -119,7 +120,8 @@ func TestBatchSuccess(t *testing.T) {
spec := createDefinitionFromString(BatchTestDef)
redisStore := RedisStorageManager{KeyPrefix: "apikey-"}
healthStore := &RedisStorageManager{KeyPrefix: "apihealth."}
spec.Init(&redisStore, &redisStore, healthStore)
orgStore := &RedisStorageManager{KeyPrefix: "orgKey."}
spec.Init(&redisStore, &redisStore, healthStore, orgStore)

batchHandler := BatchRequestHandler{API: &spec}

Expand Down Expand Up @@ -165,7 +167,8 @@ func TestMakeSyncRequest(t *testing.T) {
spec := createDefinitionFromString(BatchTestDef)
redisStore := RedisStorageManager{KeyPrefix: "apikey-"}
healthStore := &RedisStorageManager{KeyPrefix: "apihealth."}
spec.Init(&redisStore, &redisStore, healthStore)
orgStore := &RedisStorageManager{KeyPrefix: "orgKey."}
spec.Init(&redisStore, &redisStore, healthStore, orgStore)

batchHandler := BatchRequestHandler{API: &spec}

Expand Down Expand Up @@ -194,7 +197,8 @@ func TestMakeASyncRequest(t *testing.T) {
spec := createDefinitionFromString(BatchTestDef)
redisStore := RedisStorageManager{KeyPrefix: "apikey-"}
healthStore := &RedisStorageManager{KeyPrefix: "apihealth."}
spec.Init(&redisStore, &redisStore, healthStore)
orgStore := &RedisStorageManager{KeyPrefix: "orgKey."}
spec.Init(&redisStore, &redisStore, healthStore, orgStore)

batchHandler := BatchRequestHandler{API: &spec}

Expand Down
1 change: 1 addition & 0 deletions event_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const (
EVENT_AuthFailure tykcommon.TykEvent = "AuthFailure"
EVENT_KeyExpired tykcommon.TykEvent = "KeyExpired"
EVENT_VersionFailure tykcommon.TykEvent = "VersionFailure"
EVENT_OrgQuotaExceeded tykcommon.TykEvent = "OrgQuotaExceeded"
)

// EventMetaDefault is a standard embedded struct to be used with custom event metadata types, gives an interface for
Expand Down
Loading

0 comments on commit 277b259

Please sign in to comment.