github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/api.go (about)

     1  // Tyk Gateway API
     2  //
     3  // The code below describes the Tyk Gateway API
     4  // Version: 2.8.0
     5  //
     6  //     Schemes: https, http
     7  //     Host: localhost
     8  //     BasePath: /tyk/
     9  //
    10  //     Consumes:
    11  //     - application/json
    12  //
    13  //     Produces:
    14  //     - application/json
    15  //
    16  //     Security:
    17  //     - api_key:
    18  //
    19  //     SecurityDefinitions:
    20  //     api_key:
    21  //          type: apiKey
    22  //          name: X-Tyk-Authorization
    23  //          in: header
    24  //
    25  // swagger:meta
    26  package gateway
    27  
    28  import (
    29  	"bytes"
    30  	"context"
    31  	"encoding/base64"
    32  	"encoding/json"
    33  	"errors"
    34  	"fmt"
    35  	"io/ioutil"
    36  	"net/http"
    37  	"net/url"
    38  	"os"
    39  	"path/filepath"
    40  	"strconv"
    41  	"strings"
    42  	"sync"
    43  	"time"
    44  
    45  	"github.com/gorilla/mux"
    46  	uuid "github.com/satori/go.uuid"
    47  	"github.com/sirupsen/logrus"
    48  	"golang.org/x/crypto/bcrypt"
    49  
    50  	"github.com/TykTechnologies/tyk/apidef"
    51  	"github.com/TykTechnologies/tyk/config"
    52  	"github.com/TykTechnologies/tyk/ctx"
    53  	"github.com/TykTechnologies/tyk/headers"
    54  	"github.com/TykTechnologies/tyk/storage"
    55  	"github.com/TykTechnologies/tyk/user"
    56  )
    57  
    58  // apiModifyKeySuccess represents when a Key modification was successful
    59  //
    60  // swagger:model apiModifyKeySuccess
    61  type apiModifyKeySuccess struct {
    62  	// in:body
    63  	Key     string `json:"key"`
    64  	Status  string `json:"status"`
    65  	Action  string `json:"action"`
    66  	KeyHash string `json:"key_hash,omitempty"`
    67  }
    68  
    69  // apiStatusMessage represents an API status message
    70  //
    71  // swagger:model apiStatusMessage
    72  type apiStatusMessage struct {
    73  	Status string `json:"status"`
    74  	// Response details
    75  	Message string `json:"message"`
    76  }
    77  
    78  func apiOk(msg string) apiStatusMessage {
    79  	return apiStatusMessage{"ok", msg}
    80  }
    81  
    82  func apiError(msg string) apiStatusMessage {
    83  	return apiStatusMessage{"error", msg}
    84  }
    85  
    86  // paginationStatus provides more information about a paginated data set
    87  type paginationStatus struct {
    88  	PageNum   int `json:"page_num"`
    89  	PageTotal int `json:"page_total"`
    90  	PageSize  int `json:"page_size"`
    91  }
    92  
    93  type paginatedOAuthClientTokens struct {
    94  	Pagination paginationStatus
    95  	Tokens     []OAuthClientToken
    96  }
    97  
    98  func doJSONWrite(w http.ResponseWriter, code int, obj interface{}) {
    99  	w.Header().Set(headers.ContentType, headers.ApplicationJSON)
   100  	w.WriteHeader(code)
   101  	if err := json.NewEncoder(w).Encode(obj); err != nil {
   102  		http.Error(w, err.Error(), http.StatusInternalServerError)
   103  	}
   104  	if code != http.StatusOK {
   105  		job := instrument.NewJob("SystemAPIError")
   106  		job.Event(strconv.Itoa(code))
   107  	}
   108  }
   109  
   110  type MethodNotAllowedHandler struct{}
   111  
   112  func (m MethodNotAllowedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   113  	doJSONWrite(w, http.StatusMethodNotAllowed, apiError("Method not supported"))
   114  }
   115  
   116  func addSecureAndCacheHeaders(next http.HandlerFunc) http.HandlerFunc {
   117  	return func(w http.ResponseWriter, r *http.Request) {
   118  		// Setting OWASP Secure Headers
   119  		w.Header().Set("X-Content-Type-Options", "nosniff")
   120  		w.Header().Set("X-XSS-Protection", "1; mode=block")
   121  		w.Header().Set("X-Frame-Options", "DENY")
   122  		w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
   123  
   124  		// Avoid Caching of tokens
   125  		w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
   126  		w.Header().Set("Pragma", "no-cache")
   127  		w.Header().Set("Expires", "0")
   128  		next(w, r)
   129  	}
   130  }
   131  
   132  func allowMethods(next http.HandlerFunc, methods ...string) http.HandlerFunc {
   133  	return func(w http.ResponseWriter, r *http.Request) {
   134  		for _, method := range methods {
   135  			if r.Method == method {
   136  				next(w, r)
   137  				return
   138  			}
   139  		}
   140  		doJSONWrite(w, http.StatusMethodNotAllowed, apiError("Method not supported"))
   141  	}
   142  }
   143  
   144  func getSpecForOrg(orgID string) *APISpec {
   145  	apisMu.RLock()
   146  	defer apisMu.RUnlock()
   147  	for _, v := range apisByID {
   148  		if v.OrgID == orgID {
   149  			return v
   150  		}
   151  	}
   152  
   153  	// If we can't find a spec, it doesn't matter, because we default to Redis anyway, grab whatever you can find
   154  	for _, v := range apisByID {
   155  		return v
   156  	}
   157  	return nil
   158  }
   159  
   160  func getApisIdsForOrg(orgID string) []string {
   161  	result := []string{}
   162  
   163  	showAll := orgID == ""
   164  	apisMu.RLock()
   165  	defer apisMu.RUnlock()
   166  	for _, v := range apisByID {
   167  		if v.OrgID == orgID || showAll {
   168  			result = append(result, v.APIID)
   169  		}
   170  	}
   171  
   172  	return result
   173  }
   174  
   175  func checkAndApplyTrialPeriod(keyName, apiId string, newSession *user.SessionState, isHashed bool) {
   176  
   177  	// Check the policies to see if we are forcing an expiry on the key
   178  	for _, polID := range newSession.GetPolicyIDs() {
   179  		policiesMu.RLock()
   180  		policy, ok := policiesByID[polID]
   181  		policiesMu.RUnlock()
   182  		if !ok {
   183  			continue
   184  		}
   185  		// Are we foring an expiry?
   186  		if policy.KeyExpiresIn > 0 {
   187  			// We are, does the key exist?
   188  			_, found := getKeyDetail(keyName, apiId, isHashed)
   189  			if !found {
   190  				// this is a new key, lets expire it
   191  				newSession.Expires = time.Now().Unix() + policy.KeyExpiresIn
   192  			}
   193  		}
   194  	}
   195  }
   196  
   197  func applyPoliciesAndSave(keyName string, session *user.SessionState, spec *APISpec, isHashed bool) error {
   198  	// use basic middleware to apply policies to key/session (it also saves it)
   199  	mw := BaseMiddleware{
   200  		Spec: spec,
   201  	}
   202  	if err := mw.ApplyPolicies(session); err != nil {
   203  		return err
   204  	}
   205  
   206  	lifetime := session.Lifetime(spec.SessionLifetime)
   207  	if err := spec.SessionManager.UpdateSession(keyName, session, lifetime, isHashed); err != nil {
   208  		return err
   209  	}
   210  
   211  	return nil
   212  }
   213  
   214  func resetAPILimits(accessRights map[string]user.AccessDefinition) {
   215  	for apiID := range accessRights {
   216  		// reset API-level limit to nil if it has a zero-value
   217  		if access := accessRights[apiID]; access.Limit != nil && *access.Limit == (user.APILimit{}) {
   218  			access.Limit = nil
   219  			accessRights[apiID] = access
   220  		}
   221  	}
   222  }
   223  
   224  func doAddOrUpdate(keyName string, newSession *user.SessionState, dontReset bool, isHashed bool) error {
   225  	// field last_updated plays an important role in in-mem rate limiter
   226  	// so update last_updated to current timestamp only if suppress_reset wasn't set to 1
   227  	if !dontReset {
   228  		newSession.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
   229  	}
   230  
   231  	if len(newSession.GetAccessRights()) > 0 {
   232  		// reset API-level limit to nil if any has a zero-value
   233  		resetAPILimits(newSession.AccessRights)
   234  		// We have a specific list of access rules, only add / update those
   235  		for apiId := range newSession.GetAccessRights() {
   236  			apiSpec := getApiSpec(apiId)
   237  			if apiSpec == nil {
   238  				log.WithFields(logrus.Fields{
   239  					"prefix":      "api",
   240  					"key":         keyName,
   241  					"org_id":      newSession.OrgID,
   242  					"api_id":      apiId,
   243  					"user_id":     "system",
   244  					"user_ip":     "--",
   245  					"path":        "--",
   246  					"server_name": "system",
   247  				}).Error("Could not add key for this API ID, API doesn't exist.")
   248  				return errors.New("API must be active to add keys")
   249  			}
   250  			checkAndApplyTrialPeriod(keyName, apiId, newSession, isHashed)
   251  
   252  			// Lets reset keys if they are edited by admin
   253  			if !apiSpec.DontSetQuotasOnCreate {
   254  				// Reset quote by default
   255  				if !dontReset {
   256  					apiSpec.SessionManager.ResetQuota(keyName, newSession, isHashed)
   257  					newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
   258  				}
   259  
   260  				// apply polices (if any) and save key
   261  				if err := applyPoliciesAndSave(keyName, newSession, apiSpec, isHashed); err != nil {
   262  					return err
   263  				}
   264  			}
   265  		}
   266  	} else {
   267  		// nothing defined, add key to ALL
   268  		if !config.Global().AllowMasterKeys {
   269  			log.Error("Master keys disallowed in configuration, key not added.")
   270  			return errors.New("Master keys not allowed")
   271  		}
   272  		log.Warning("No API Access Rights set, adding key to ALL.")
   273  		apisMu.RLock()
   274  		defer apisMu.RUnlock()
   275  		for _, spec := range apisByID {
   276  			if !dontReset {
   277  				spec.SessionManager.ResetQuota(keyName, newSession, isHashed)
   278  				newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
   279  			}
   280  			checkAndApplyTrialPeriod(keyName, spec.APIID, newSession, isHashed)
   281  
   282  			// apply polices (if any) and save key
   283  			if err := applyPoliciesAndSave(keyName, newSession, spec, isHashed); err != nil {
   284  				return err
   285  			}
   286  		}
   287  	}
   288  
   289  	log.WithFields(logrus.Fields{
   290  		"prefix":      "api",
   291  		"key":         obfuscateKey(keyName),
   292  		"expires":     newSession.Expires,
   293  		"org_id":      newSession.OrgID,
   294  		"api_id":      "--",
   295  		"user_id":     "system",
   296  		"user_ip":     "--",
   297  		"path":        "--",
   298  		"server_name": "system",
   299  	}).Info("Key added or updated.")
   300  	return nil
   301  }
   302  
   303  // ---- TODO: This changes the URL structure of the API completely ----
   304  // 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,
   305  // remove from all stores, update to all stores, stores handle quotas separately though because they are localised! Keys will
   306  // need to be managed by API, but only for GetDetail, GetList, UpdateKey and DeleteKey
   307  
   308  func setSessionPassword(session *user.SessionState) {
   309  	session.BasicAuthData.Hash = user.HashBCrypt
   310  	newPass, err := bcrypt.GenerateFromPassword([]byte(session.BasicAuthData.Password), 10)
   311  	if err != nil {
   312  		log.Error("Could not hash password, setting to plaintext, error was: ", err)
   313  		session.BasicAuthData.Hash = user.HashPlainText
   314  		return
   315  	}
   316  
   317  	session.BasicAuthData.Password = string(newPass)
   318  }
   319  
   320  func getKeyDetail(key, apiID string, hashed bool) (user.SessionState, bool) {
   321  	sessionManager := FallbackKeySesionManager
   322  	if spec := getApiSpec(apiID); spec != nil {
   323  		sessionManager = spec.SessionManager
   324  	}
   325  
   326  	return sessionManager.SessionDetail(key, hashed)
   327  }
   328  
   329  func handleAddOrUpdate(keyName string, r *http.Request, isHashed bool) (interface{}, int) {
   330  	suppressReset := r.URL.Query().Get("suppress_reset") == "1"
   331  
   332  	// decode payload
   333  	newSession := user.SessionState{
   334  		Mutex: &sync.RWMutex{},
   335  	}
   336  
   337  	contents, _ := ioutil.ReadAll(r.Body)
   338  	r.Body = ioutil.NopCloser(bytes.NewReader(contents))
   339  
   340  	if err := json.Unmarshal(contents, &newSession); err != nil {
   341  		log.Error("Couldn't decode new session object: ", err)
   342  		return apiError("Request malformed"), http.StatusBadRequest
   343  	}
   344  
   345  	mw := BaseMiddleware{}
   346  	mw.ApplyPolicies(&newSession)
   347  
   348  	// DO ADD OR UPDATE
   349  
   350  	// get original session in case of update and preserve fields that SHOULD NOT be updated
   351  	originalKey := user.SessionState{
   352  		Mutex: &sync.RWMutex{},
   353  	}
   354  	if r.Method == http.MethodPut {
   355  		found := false
   356  		for apiID := range newSession.AccessRights {
   357  			originalKey, found = getKeyDetail(keyName, apiID, isHashed)
   358  			if found {
   359  				break
   360  			}
   361  		}
   362  		if !found {
   363  			log.Error("Could not find key when updating")
   364  			return apiError("Key is not found"), http.StatusNotFound
   365  		}
   366  
   367  		// don't change fields related to quota and rate limiting if was passed as "suppress_reset=1"
   368  		if suppressReset {
   369  			// save existing quota_renews and last_updated if suppress_reset was passed
   370  			// (which means don't reset quota or rate counters)
   371  			// - leaving quota_renews as 0 will force quota limiter to start new renewal period
   372  			// - setting new last_updated with force rate limiter to start new "per" rating period
   373  
   374  			// on session level
   375  			newSession.QuotaRenews = originalKey.QuotaRenews
   376  			newSession.LastUpdated = originalKey.LastUpdated
   377  
   378  			// on ACL API limit level
   379  			for apiID, access := range originalKey.GetAccessRights() {
   380  				if access.Limit == nil {
   381  					continue
   382  				}
   383  				if newAccess, ok := newSession.GetAccessRightByAPIID(apiID); ok && newAccess.Limit != nil {
   384  					newAccess.Limit.QuotaRenews = access.Limit.QuotaRenews
   385  					newSession.AccessRights[apiID] = newAccess
   386  				}
   387  			}
   388  		}
   389  	} else {
   390  		newSession.DateCreated = time.Now()
   391  		keyName = generateToken(newSession.OrgID, keyName)
   392  	}
   393  
   394  	// Update our session object (create it)
   395  	if newSession.BasicAuthData.Password != "" {
   396  		// If we are using a basic auth user, then we need to make the keyname explicit against the OrgId in order to differentiate it
   397  		// Only if it's NEW
   398  		switch r.Method {
   399  		case http.MethodPost:
   400  			// It's a create, so lets hash the password
   401  			setSessionPassword(&newSession)
   402  		case http.MethodPut:
   403  			if originalKey.BasicAuthData.Password != newSession.BasicAuthData.Password {
   404  				// passwords dont match assume it's new, lets hash it
   405  				log.Debug("Passwords dont match, original: ", originalKey.BasicAuthData.Password)
   406  				log.Debug("New: newSession.BasicAuthData.Password")
   407  				log.Debug("Changing password")
   408  				setSessionPassword(&newSession)
   409  			}
   410  		}
   411  	}
   412  
   413  	if r.Method == http.MethodPost || storage.TokenOrg(keyName) != "" {
   414  		// use new key format if key gets created or updating key with new format
   415  		if err := doAddOrUpdate(keyName, &newSession, suppressReset, isHashed); err != nil {
   416  			return apiError("Failed to create key, ensure security settings are correct."), http.StatusInternalServerError
   417  		}
   418  	} else {
   419  
   420  		newFormatKey := generateToken(newSession.OrgID, keyName)
   421  		// search as a custom key
   422  		_, err := FallbackKeySesionManager.Store().GetKey(newFormatKey)
   423  
   424  		if err == nil {
   425  			// update new format key for custom keys, as it was found then its a customKey
   426  			keyName = newFormatKey
   427  		}
   428  
   429  		if err := doAddOrUpdate(keyName, &newSession, suppressReset, isHashed); err != nil {
   430  			return apiError("Failed to create key, ensure security settings are correct."), http.StatusInternalServerError
   431  		}
   432  	}
   433  
   434  	action := "modified"
   435  	event := EventTokenUpdated
   436  	if r.Method == http.MethodPost {
   437  		action = "added"
   438  		event = EventTokenCreated
   439  	}
   440  	FireSystemEvent(event, EventTokenMeta{
   441  		EventMetaDefault: EventMetaDefault{Message: "Key modified."},
   442  		Org:              newSession.OrgID,
   443  		Key:              keyName,
   444  	})
   445  
   446  	response := apiModifyKeySuccess{
   447  		Key:    keyName,
   448  		Status: "ok",
   449  		Action: action,
   450  	}
   451  
   452  	// add key hash for newly created key
   453  	if config.Global().HashKeys && r.Method == http.MethodPost {
   454  		if isHashed {
   455  			response.KeyHash = keyName
   456  		} else {
   457  			response.KeyHash = storage.HashKey(keyName)
   458  		}
   459  	}
   460  
   461  	return response, http.StatusOK
   462  }
   463  
   464  func handleGetDetail(sessionKey, apiID string, byHash bool) (interface{}, int) {
   465  	if byHash && !config.Global().HashKeys {
   466  		return apiError("Key requested by hash but key hashing is not enabled"), http.StatusBadRequest
   467  	}
   468  
   469  	sessionManager := FallbackKeySesionManager
   470  	spec := getApiSpec(apiID)
   471  	if spec != nil {
   472  		sessionManager = spec.SessionManager
   473  	}
   474  
   475  	session := user.SessionState{Mutex: &sync.RWMutex{}}
   476  	var ok bool
   477  	session, ok = sessionManager.SessionDetail(sessionKey, byHash)
   478  
   479  	if !ok {
   480  		return apiError("Key not found"), http.StatusNotFound
   481  	}
   482  
   483  	mw := BaseMiddleware{Spec: spec}
   484  	mw.ApplyPolicies(&session)
   485  
   486  	if session.QuotaMax != -1 {
   487  		quotaKey := QuotaKeyPrefix + storage.HashKey(sessionKey)
   488  		if byHash {
   489  			quotaKey = QuotaKeyPrefix + sessionKey
   490  		}
   491  
   492  		if usedQuota, err := FallbackKeySesionManager.Store().GetRawKey(quotaKey); err == nil {
   493  			qInt, _ := strconv.Atoi(usedQuota)
   494  			remaining := session.QuotaMax - int64(qInt)
   495  
   496  			if remaining < 0 {
   497  				session.QuotaRemaining = 0
   498  			} else {
   499  				session.QuotaRemaining = remaining
   500  			}
   501  		} else {
   502  			log.WithFields(logrus.Fields{
   503  				"prefix":  "api",
   504  				"key":     obfuscateKey(quotaKey),
   505  				"message": err,
   506  				"status":  "ok",
   507  			}).Info("Can't retrieve key quota")
   508  		}
   509  	}
   510  
   511  	// populate remaining quota for API limits (if any)
   512  	for id, access := range session.GetAccessRights() {
   513  		if access.Limit == nil || access.Limit.QuotaMax == -1 || access.Limit.QuotaMax == 0 {
   514  			continue
   515  		}
   516  
   517  		quotaScope := ""
   518  		if access.AllowanceScope != "" {
   519  			quotaScope = access.AllowanceScope + "-"
   520  		}
   521  
   522  		limQuotaKey := QuotaKeyPrefix + quotaScope + storage.HashKey(sessionKey)
   523  		if byHash {
   524  			limQuotaKey = QuotaKeyPrefix + quotaScope + sessionKey
   525  		}
   526  
   527  		if usedQuota, err := sessionManager.Store().GetRawKey(limQuotaKey); err == nil {
   528  			qInt, _ := strconv.Atoi(usedQuota)
   529  			remaining := access.Limit.QuotaMax - int64(qInt)
   530  
   531  			if remaining < 0 {
   532  				access.Limit.QuotaRemaining = 0
   533  			} else {
   534  				access.Limit.QuotaRemaining = remaining
   535  			}
   536  			session.AccessRights[id] = access
   537  		} else {
   538  			access.Limit.QuotaRemaining = access.Limit.QuotaMax
   539  			session.AccessRights[id] = access
   540  
   541  			log.WithFields(logrus.Fields{
   542  				"prefix": "api",
   543  				"apiID":  id,
   544  				"key":    obfuscateKey(sessionKey),
   545  				"error":  err,
   546  			}).Info("Can't retrieve api limit quota")
   547  		}
   548  	}
   549  
   550  	log.WithFields(logrus.Fields{
   551  		"prefix": "api",
   552  		"key":    obfuscateKey(sessionKey),
   553  		"status": "ok",
   554  	}).Info("Retrieved key detail.")
   555  
   556  	return session, http.StatusOK
   557  }
   558  
   559  // apiAllKeys represents a list of keys in the memory store
   560  // swagger:model
   561  type apiAllKeys struct {
   562  	APIKeys []string `json:"keys"`
   563  }
   564  
   565  func handleGetAllKeys(filter, apiID string) (interface{}, int) {
   566  	sessionManager := FallbackKeySesionManager
   567  	if spec := getApiSpec(apiID); spec != nil {
   568  		sessionManager = spec.SessionManager
   569  	}
   570  
   571  	sessions := sessionManager.Sessions(filter)
   572  	if filter != "" {
   573  		filterB64 := base64.StdEncoding.WithPadding(base64.NoPadding).EncodeToString([]byte(fmt.Sprintf(`{"org":"%s"`, filter)))
   574  		// Remove last 2 digits to look exact match
   575  		filterB64 = filterB64[0 : len(filterB64)-2]
   576  		orgIDB64Sessions := sessionManager.Sessions(filterB64)
   577  		sessions = append(sessions, orgIDB64Sessions...)
   578  	}
   579  
   580  	fixedSessions := make([]string, 0)
   581  	for _, s := range sessions {
   582  		if !strings.HasPrefix(s, QuotaKeyPrefix) && !strings.HasPrefix(s, RateLimitKeyPrefix) {
   583  			fixedSessions = append(fixedSessions, s)
   584  		}
   585  	}
   586  
   587  	sessionsObj := apiAllKeys{fixedSessions}
   588  
   589  	log.WithFields(logrus.Fields{
   590  		"prefix": "api",
   591  		"status": "ok",
   592  	}).Info("Retrieved key list.")
   593  
   594  	return sessionsObj, http.StatusOK
   595  }
   596  
   597  func handleAddKey(keyName, hashedName, sessionString, apiID string) {
   598  	mw := BaseMiddleware{
   599  		Spec: &APISpec{
   600  			SessionManager: FallbackKeySesionManager,
   601  		},
   602  	}
   603  	sess := user.SessionState{
   604  		Mutex: &sync.RWMutex{},
   605  	}
   606  
   607  	json.Unmarshal([]byte(sessionString), &sess)
   608  	sess.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
   609  	var err error
   610  	if config.Global().HashKeys {
   611  		err = mw.Spec.SessionManager.UpdateSession(hashedName, &sess, 0, true)
   612  	} else {
   613  		err = mw.Spec.SessionManager.UpdateSession(keyName, &sess, 0, false)
   614  	}
   615  	if err != nil {
   616  		log.WithFields(logrus.Fields{
   617  			"prefix": "api",
   618  			"key":    obfuscateKey(keyName),
   619  			"status": "fail",
   620  			"err":    err,
   621  		}).Error("Failed to update key.")
   622  	}
   623  	log.WithFields(logrus.Fields{
   624  		"prefix": "RPC",
   625  		"key":    obfuscateKey(keyName),
   626  		"status": "ok",
   627  	}).Info("Updated hashed key in slave storage.")
   628  }
   629  
   630  func handleDeleteKey(keyName, apiID string, resetQuota bool) (interface{}, int) {
   631  	if apiID == "-1" {
   632  		// Go through ALL managed API's and delete the key
   633  		apisMu.RLock()
   634  
   635  		removed := false
   636  		for _, spec := range apisByID {
   637  			if spec.SessionManager.RemoveSession(keyName, false) {
   638  				removed = true
   639  			}
   640  			spec.SessionManager.ResetQuota(
   641  				keyName,
   642  				&user.SessionState{
   643  					Mutex: &sync.RWMutex{},
   644  				},
   645  				false)
   646  		}
   647  
   648  		apisMu.RUnlock()
   649  
   650  		if !removed {
   651  			log.WithFields(logrus.Fields{
   652  				"prefix": "api",
   653  				"key":    obfuscateKey(keyName),
   654  				"status": "fail",
   655  			}).Error("Failed to remove the key")
   656  			return apiError("Failed to remove the key"), http.StatusBadRequest
   657  		}
   658  
   659  		log.WithFields(logrus.Fields{
   660  			"prefix": "api",
   661  			"key":    keyName,
   662  			"status": "ok",
   663  		}).Info("Deleted key across all APIs.")
   664  
   665  		return nil, http.StatusOK
   666  	}
   667  
   668  	orgID := ""
   669  	sessionManager := FallbackKeySesionManager
   670  	if spec := getApiSpec(apiID); spec != nil {
   671  		orgID = spec.OrgID
   672  		sessionManager = spec.SessionManager
   673  	}
   674  
   675  	if !sessionManager.RemoveSession(keyName, false) {
   676  		log.WithFields(logrus.Fields{
   677  			"prefix": "api",
   678  			"key":    obfuscateKey(keyName),
   679  			"status": "fail",
   680  		}).Error("Failed to remove the key")
   681  		return apiError("Failed to remove the key"), http.StatusBadRequest
   682  	}
   683  
   684  	if resetQuota {
   685  		sessionManager.ResetQuota(keyName, &user.SessionState{Mutex: &sync.RWMutex{}}, false)
   686  	}
   687  
   688  	statusObj := apiModifyKeySuccess{
   689  		Key:    keyName,
   690  		Status: "ok",
   691  		Action: "deleted",
   692  	}
   693  
   694  	FireSystemEvent(EventTokenDeleted, EventTokenMeta{
   695  		EventMetaDefault: EventMetaDefault{Message: "Key deleted."},
   696  		Org:              orgID,
   697  		Key:              keyName,
   698  	})
   699  
   700  	log.WithFields(logrus.Fields{
   701  		"prefix": "api",
   702  		"key":    keyName,
   703  		"status": "ok",
   704  	}).Info("Deleted key.")
   705  
   706  	return statusObj, http.StatusOK
   707  }
   708  
   709  // handleDeleteHashedKeyWithLogs is a wrapper for handleDeleteHashedKey with logs
   710  func handleDeleteHashedKeyWithLogs(keyName, apiID string, resetQuota bool) (interface{}, int) {
   711  	res, code := handleDeleteHashedKey(keyName, apiID, resetQuota)
   712  
   713  	if code != http.StatusOK {
   714  		log.WithFields(logrus.Fields{
   715  			"prefix": "api",
   716  			"key":    obfuscateKey(keyName),
   717  			"status": "fail",
   718  		}).Error(res)
   719  	}
   720  
   721  	log.WithFields(logrus.Fields{
   722  		"prefix": "api",
   723  		"key":    keyName,
   724  		"status": "ok",
   725  	}).Info("Deleted hashed key across all APIs.")
   726  
   727  	return res, code
   728  }
   729  
   730  func handleDeleteHashedKey(keyName, apiID string, resetQuota bool) (interface{}, int) {
   731  	if apiID == "-1" {
   732  		// Go through ALL managed API's and delete the key
   733  		removed := false
   734  		apisMu.RLock()
   735  		for _, spec := range apisByID {
   736  			if spec.SessionManager.RemoveSession(keyName, true) {
   737  				removed = true
   738  			}
   739  		}
   740  		apisMu.RUnlock()
   741  
   742  		if !removed {
   743  			return apiError("Failed to remove the key"), http.StatusBadRequest
   744  		}
   745  
   746  		return nil, http.StatusOK
   747  	}
   748  
   749  	sessionManager := FallbackKeySesionManager
   750  	if spec := getApiSpec(apiID); spec != nil {
   751  		sessionManager = spec.SessionManager
   752  	}
   753  
   754  	if !sessionManager.RemoveSession(keyName, true) {
   755  		return apiError("Failed to remove the key"), http.StatusBadRequest
   756  	}
   757  
   758  	if resetQuota {
   759  		sessionManager.ResetQuota(keyName, &user.SessionState{Mutex: &sync.RWMutex{}}, true)
   760  	}
   761  
   762  	statusObj := apiModifyKeySuccess{
   763  		Key:    keyName,
   764  		Status: "ok",
   765  		Action: "deleted",
   766  	}
   767  
   768  	return statusObj, http.StatusOK
   769  }
   770  
   771  func handleGlobalAddToSortedSet(keyName, value string, score float64) {
   772  	log.Debug("handleRemoveSortedSetRange --> not implemented")
   773  }
   774  
   775  func handleGetSortedSetRange(keyName, scoreFrom, scoreTo string) ([]string, []float64, error) {
   776  	log.Debug("handleRemoveSortedSetRange --> not implemented")
   777  	return nil, nil, nil
   778  }
   779  
   780  func handleRemoveSortedSetRange(keyName, scoreFrom, scoreTo string) error {
   781  	log.Debug("handleRemoveSortedSetRange --> not implemented")
   782  	return nil
   783  }
   784  
   785  func handleGetAPIList() (interface{}, int) {
   786  	apisMu.RLock()
   787  	defer apisMu.RUnlock()
   788  	apiIDList := make([]*apidef.APIDefinition, len(apisByID))
   789  	c := 0
   790  	for _, apiSpec := range apisByID {
   791  		apiIDList[c] = apiSpec.APIDefinition
   792  		c++
   793  	}
   794  	return apiIDList, http.StatusOK
   795  }
   796  
   797  func handleGetAPI(apiID string) (interface{}, int) {
   798  	if spec := getApiSpec(apiID); spec != nil {
   799  		return spec.APIDefinition, http.StatusOK
   800  	}
   801  
   802  	log.WithFields(logrus.Fields{
   803  		"prefix": "api",
   804  		"apiID":  apiID,
   805  	}).Error("API doesn't exist.")
   806  	return apiError("API not found"), http.StatusNotFound
   807  }
   808  
   809  func handleAddOrUpdateApi(apiID string, r *http.Request) (interface{}, int) {
   810  	if config.Global().UseDBAppConfigs {
   811  		log.Error("Rejected new API Definition due to UseDBAppConfigs = true")
   812  		return apiError("Due to enabled use_db_app_configs, please use the Dashboard API"), http.StatusInternalServerError
   813  	}
   814  
   815  	newDef := &apidef.APIDefinition{}
   816  	if err := json.NewDecoder(r.Body).Decode(newDef); err != nil {
   817  		log.Error("Couldn't decode new API Definition object: ", err)
   818  		return apiError("Request malformed"), http.StatusBadRequest
   819  	}
   820  
   821  	if apiID != "" && newDef.APIID != apiID {
   822  		log.Error("PUT operation on different APIIDs")
   823  		return apiError("Request APIID does not match that in Definition! For Updtae operations these must match."), http.StatusBadRequest
   824  	}
   825  
   826  	// Create a filename
   827  	defFilePath := filepath.Join(config.Global().AppPath, newDef.APIID+".json")
   828  
   829  	// If it exists, delete it
   830  	if _, err := os.Stat(defFilePath); err == nil {
   831  		log.Warning("API Definition with this ID already exists, deleting file...")
   832  		os.Remove(defFilePath)
   833  	}
   834  
   835  	// unmarshal the object into the file
   836  	asByte, err := json.MarshalIndent(newDef, "", "  ")
   837  	if err != nil {
   838  		log.Error("Marshalling of API Definition failed: ", err)
   839  		return apiError("Marshalling failed"), http.StatusInternalServerError
   840  	}
   841  
   842  	if err := ioutil.WriteFile(defFilePath, asByte, 0644); err != nil {
   843  		log.Error("Failed to create file! - ", err)
   844  		return apiError("File object creation failed, write error"), http.StatusInternalServerError
   845  	}
   846  
   847  	action := "modified"
   848  	if r.Method == "POST" {
   849  		action = "added"
   850  	}
   851  
   852  	response := apiModifyKeySuccess{
   853  		Key:    newDef.APIID,
   854  		Status: "ok",
   855  		Action: action,
   856  	}
   857  
   858  	return response, http.StatusOK
   859  }
   860  
   861  func handleDeleteAPI(apiID string) (interface{}, int) {
   862  	// Generate a filename
   863  	defFilePath := filepath.Join(config.Global().AppPath, apiID+".json")
   864  
   865  	// If it exists, delete it
   866  	if _, err := os.Stat(defFilePath); err != nil {
   867  		log.Warning("File does not exist! ", err)
   868  		return apiError("Delete failed"), http.StatusInternalServerError
   869  	}
   870  
   871  	os.Remove(defFilePath)
   872  
   873  	response := apiModifyKeySuccess{
   874  		Key:    apiID,
   875  		Status: "ok",
   876  		Action: "deleted",
   877  	}
   878  
   879  	return response, http.StatusOK
   880  }
   881  
   882  func apiHandler(w http.ResponseWriter, r *http.Request) {
   883  	apiID := mux.Vars(r)["apiID"]
   884  
   885  	var obj interface{}
   886  	var code int
   887  
   888  	switch r.Method {
   889  	case "GET":
   890  		if apiID != "" {
   891  			log.Debug("Requesting API definition for", apiID)
   892  			obj, code = handleGetAPI(apiID)
   893  		} else {
   894  			log.Debug("Requesting API list")
   895  			obj, code = handleGetAPIList()
   896  		}
   897  	case "POST":
   898  		log.Debug("Creating new definition file")
   899  		obj, code = handleAddOrUpdateApi(apiID, r)
   900  	case "PUT":
   901  		if apiID != "" {
   902  			log.Debug("Updating existing API: ", apiID)
   903  			obj, code = handleAddOrUpdateApi(apiID, r)
   904  		} else {
   905  			obj, code = apiError("Must specify an apiID to update"), http.StatusBadRequest
   906  		}
   907  	case "DELETE":
   908  		if apiID != "" {
   909  			log.Debug("Deleting API definition for: ", apiID)
   910  			obj, code = handleDeleteAPI(apiID)
   911  		} else {
   912  			obj, code = apiError("Must specify an apiID to delete"), http.StatusBadRequest
   913  		}
   914  	}
   915  
   916  	doJSONWrite(w, code, obj)
   917  }
   918  
   919  func keyHandler(w http.ResponseWriter, r *http.Request) {
   920  	keyName := mux.Vars(r)["keyName"]
   921  	apiID := r.URL.Query().Get("api_id")
   922  	isHashed := r.URL.Query().Get("hashed") != ""
   923  	isUserName := r.URL.Query().Get("username") == "true"
   924  	orgID := r.URL.Query().Get("org_id")
   925  
   926  	// check if passed key is user name and convert it to real key with respect to current hashing algorithm
   927  	origKeyName := keyName
   928  	if r.Method != http.MethodPost && isUserName {
   929  		keyName = generateToken(orgID, keyName)
   930  	}
   931  
   932  	var obj interface{}
   933  	var code int
   934  	hashKeyFunction := config.Global().HashKeyFunction
   935  
   936  	switch r.Method {
   937  	case http.MethodPost:
   938  		obj, code = handleAddOrUpdate(keyName, r, isHashed)
   939  	case http.MethodPut:
   940  		obj, code = handleAddOrUpdate(keyName, r, isHashed)
   941  		if code != http.StatusOK && hashKeyFunction != "" {
   942  			// try to use legacy key format
   943  			obj, code = handleAddOrUpdate(origKeyName, r, isHashed)
   944  		}
   945  	case http.MethodGet:
   946  		if keyName != "" {
   947  			// Return single key detail
   948  			obj, code = handleGetDetail(keyName, apiID, isHashed)
   949  			if code != http.StatusOK && hashKeyFunction != "" {
   950  				// try to use legacy key format
   951  				obj, code = handleGetDetail(origKeyName, apiID, isHashed)
   952  			}
   953  		} else {
   954  			// Return list of keys
   955  			if config.Global().HashKeys {
   956  				// get all keys is disabled by default
   957  				if !config.Global().EnableHashedKeysListing {
   958  					doJSONWrite(
   959  						w,
   960  						http.StatusNotFound,
   961  						apiError("Hashed key listing is disabled in config (enable_hashed_keys_listing)"),
   962  					)
   963  					return
   964  				}
   965  
   966  				// we don't use filter for hashed keys
   967  				obj, code = handleGetAllKeys("", apiID)
   968  			} else {
   969  				filter := r.URL.Query().Get("filter")
   970  				obj, code = handleGetAllKeys(filter, apiID)
   971  			}
   972  		}
   973  
   974  	case http.MethodDelete:
   975  		// Remove a key
   976  		if !isHashed {
   977  			obj, code = handleDeleteKey(keyName, apiID, true)
   978  		} else {
   979  			obj, code = handleDeleteHashedKeyWithLogs(keyName, apiID, true)
   980  		}
   981  		if code != http.StatusOK && hashKeyFunction != "" {
   982  			// try to use legacy key format
   983  			if !isHashed {
   984  				obj, code = handleDeleteKey(origKeyName, apiID, true)
   985  			} else {
   986  				obj, code = handleDeleteHashedKeyWithLogs(origKeyName, apiID, true)
   987  			}
   988  		}
   989  	}
   990  
   991  	doJSONWrite(w, code, obj)
   992  }
   993  
   994  type PolicyUpdateObj struct {
   995  	Policy        string   `json:"policy"`
   996  	ApplyPolicies []string `json:"apply_policies"`
   997  }
   998  
   999  func policyUpdateHandler(w http.ResponseWriter, r *http.Request) {
  1000  	log.Warning("Hashed key change request detected!")
  1001  
  1002  	var policRecord PolicyUpdateObj
  1003  	if err := json.NewDecoder(r.Body).Decode(&policRecord); err != nil {
  1004  		doJSONWrite(w, http.StatusBadRequest, apiError("Couldn't decode instruction"))
  1005  		return
  1006  	}
  1007  
  1008  	if policRecord.Policy != "" {
  1009  		policRecord.ApplyPolicies = append(policRecord.ApplyPolicies, policRecord.Policy)
  1010  	}
  1011  
  1012  	keyName := mux.Vars(r)["keyName"]
  1013  	obj, code := handleUpdateHashedKey(keyName, policRecord.ApplyPolicies)
  1014  
  1015  	doJSONWrite(w, code, obj)
  1016  }
  1017  
  1018  func handleUpdateHashedKey(keyName string, applyPolicies []string) (interface{}, int) {
  1019  	sessionManager := FallbackKeySesionManager
  1020  
  1021  	sess, ok := sessionManager.SessionDetail(keyName, true)
  1022  	if !ok {
  1023  		log.WithFields(logrus.Fields{
  1024  			"prefix": "api",
  1025  			"key":    keyName,
  1026  			"status": "fail",
  1027  		}).Error("Failed to update hashed key.")
  1028  
  1029  		return apiError("Key not found"), http.StatusNotFound
  1030  	}
  1031  
  1032  	// Set the policy
  1033  	sess.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
  1034  	sess.SetPolicies(applyPolicies...)
  1035  
  1036  	err := sessionManager.UpdateSession(keyName, &sess, 0, true)
  1037  	if err != nil {
  1038  		log.WithFields(logrus.Fields{
  1039  			"prefix": "api",
  1040  			"key":    keyName,
  1041  			"status": "fail",
  1042  			"err":    err,
  1043  		}).Error("Failed to update hashed key.")
  1044  
  1045  		return apiError("Could not write key data"), http.StatusInternalServerError
  1046  	}
  1047  
  1048  	statusObj := apiModifyKeySuccess{
  1049  		Key:    keyName,
  1050  		Status: "ok",
  1051  		Action: "updated",
  1052  	}
  1053  
  1054  	log.WithFields(logrus.Fields{
  1055  		"prefix": "api",
  1056  		"key":    keyName,
  1057  		"status": "ok",
  1058  	}).Info("Updated hashed key.")
  1059  
  1060  	return statusObj, http.StatusOK
  1061  }
  1062  
  1063  func orgHandler(w http.ResponseWriter, r *http.Request) {
  1064  	keyName := mux.Vars(r)["keyName"]
  1065  	filter := r.URL.Query().Get("filter")
  1066  	var obj interface{}
  1067  	var code int
  1068  
  1069  	switch r.Method {
  1070  	case "POST", "PUT":
  1071  		obj, code = handleOrgAddOrUpdate(keyName, r)
  1072  
  1073  	case "GET":
  1074  		if keyName != "" {
  1075  			// Return single org detail
  1076  			obj, code = handleGetOrgDetail(keyName)
  1077  		} else {
  1078  			// Return list of keys
  1079  			obj, code = handleGetAllOrgKeys(filter)
  1080  		}
  1081  
  1082  	case "DELETE":
  1083  		// Remove a key
  1084  		obj, code = handleDeleteOrgKey(keyName)
  1085  	}
  1086  
  1087  	doJSONWrite(w, code, obj)
  1088  }
  1089  
  1090  func handleOrgAddOrUpdate(keyName string, r *http.Request) (interface{}, int) {
  1091  	newSession := new(user.SessionState)
  1092  	newSession.Mutex = &sync.RWMutex{}
  1093  
  1094  	if err := json.NewDecoder(r.Body).Decode(newSession); err != nil {
  1095  		log.Error("Couldn't decode new session object: ", err)
  1096  		return apiError("Request malformed"), http.StatusBadRequest
  1097  	}
  1098  	// Update our session object (create it)
  1099  
  1100  	spec := getSpecForOrg(keyName)
  1101  	var sessionManager SessionHandler
  1102  
  1103  	if spec == nil {
  1104  		log.Warning("Couldn't find org session store in active API list")
  1105  		if config.Global().SupressDefaultOrgStore {
  1106  			return apiError("No such organisation found in Active API list"), http.StatusNotFound
  1107  		}
  1108  		sessionManager = &DefaultOrgStore
  1109  	} else {
  1110  		sessionManager = spec.OrgSessionManager
  1111  	}
  1112  
  1113  	if r.URL.Query().Get("reset_quota") == "1" {
  1114  		sessionManager.ResetQuota(keyName, newSession, false)
  1115  		newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1116  		rawKey := QuotaKeyPrefix + storage.HashKey(keyName)
  1117  
  1118  		// manage quotas separately
  1119  		DefaultQuotaStore.RemoveSession(rawKey, false)
  1120  	}
  1121  
  1122  	err := sessionManager.UpdateSession(keyName, newSession, 0, false)
  1123  	if err != nil {
  1124  		return apiError("Error writing to key store " + err.Error()), http.StatusInternalServerError
  1125  	}
  1126  
  1127  	// identify that spec has org session
  1128  	if spec != nil {
  1129  		spec.Lock()
  1130  		spec.OrgHasNoSession = false
  1131  		spec.Unlock()
  1132  	}
  1133  
  1134  	log.WithFields(logrus.Fields{
  1135  		"prefix": "api",
  1136  		"org":    keyName,
  1137  		"status": "ok",
  1138  	}).Info("New organization key added or updated.")
  1139  
  1140  	action := "modified"
  1141  	if r.Method == "POST" {
  1142  		action = "added"
  1143  	}
  1144  
  1145  	response := apiModifyKeySuccess{
  1146  		Key:    keyName,
  1147  		Status: "ok",
  1148  		Action: action,
  1149  	}
  1150  
  1151  	return response, http.StatusOK
  1152  }
  1153  
  1154  func handleGetOrgDetail(orgID string) (interface{}, int) {
  1155  	spec := getSpecForOrg(orgID)
  1156  	if spec == nil {
  1157  		return apiError("Org not found"), http.StatusNotFound
  1158  	}
  1159  
  1160  	session, ok := spec.OrgSessionManager.SessionDetail(orgID, false)
  1161  	if !ok {
  1162  		log.WithFields(logrus.Fields{
  1163  			"prefix": "api",
  1164  			"org":    orgID,
  1165  			"status": "fail",
  1166  			"err":    "not found",
  1167  		}).Error("Failed retrieval of record for ORG ID.")
  1168  		return apiError("Org not found"), http.StatusNotFound
  1169  	}
  1170  	log.WithFields(logrus.Fields{
  1171  		"prefix": "api",
  1172  		"org":    orgID,
  1173  		"status": "ok",
  1174  	}).Info("Retrieved record for ORG ID.")
  1175  	return session, http.StatusOK
  1176  }
  1177  
  1178  func handleGetAllOrgKeys(filter string) (interface{}, int) {
  1179  	spec := getSpecForOrg("")
  1180  	if spec == nil {
  1181  		return apiError("ORG not found"), http.StatusNotFound
  1182  	}
  1183  
  1184  	sessions := spec.OrgSessionManager.Sessions(filter)
  1185  	fixed_sessions := make([]string, 0)
  1186  	for _, s := range sessions {
  1187  		if !strings.HasPrefix(s, QuotaKeyPrefix) && !strings.HasPrefix(s, RateLimitKeyPrefix) {
  1188  			fixed_sessions = append(fixed_sessions, s)
  1189  		}
  1190  	}
  1191  	sessionsObj := apiAllKeys{fixed_sessions}
  1192  	return sessionsObj, http.StatusOK
  1193  }
  1194  
  1195  func handleDeleteOrgKey(orgID string) (interface{}, int) {
  1196  	spec := getSpecForOrg(orgID)
  1197  	if spec == nil {
  1198  		log.WithFields(logrus.Fields{
  1199  			"prefix": "api",
  1200  			"key":    orgID,
  1201  			"status": "fail",
  1202  			"err":    "not found",
  1203  		}).Error("Failed to delete org key.")
  1204  
  1205  		return apiError("Org not found"), http.StatusNotFound
  1206  	}
  1207  
  1208  	if !spec.OrgSessionManager.RemoveSession(orgID, false) {
  1209  		return apiError("Failed to remove the key"), http.StatusBadRequest
  1210  	}
  1211  
  1212  	log.WithFields(logrus.Fields{
  1213  		"prefix": "api",
  1214  		"key":    orgID,
  1215  		"status": "ok",
  1216  	}).Info("Org key deleted.")
  1217  
  1218  	// identify that spec has no org session
  1219  	if spec != nil {
  1220  		spec.Lock()
  1221  		spec.OrgHasNoSession = true
  1222  		spec.Unlock()
  1223  	}
  1224  
  1225  	statusObj := apiModifyKeySuccess{
  1226  		Key:    orgID,
  1227  		Status: "ok",
  1228  		Action: "deleted",
  1229  	}
  1230  	return statusObj, http.StatusOK
  1231  }
  1232  
  1233  func groupResetHandler(w http.ResponseWriter, r *http.Request) {
  1234  	log.WithFields(logrus.Fields{
  1235  		"prefix": "api",
  1236  		"status": "ok",
  1237  	}).Info("Group reload accepted.")
  1238  
  1239  	// Signal to the group via redis
  1240  	MainNotifier.Notify(Notification{Command: NoticeGroupReload})
  1241  
  1242  	log.WithFields(logrus.Fields{
  1243  		"prefix": "api",
  1244  	}).Info("Reloaded URL Structure - Success")
  1245  
  1246  	doJSONWrite(w, http.StatusOK, apiOk(""))
  1247  }
  1248  
  1249  // resetHandler will try to queue a reload. If fn is nil and block=true
  1250  // was in the URL parameters, it will block until the reload is done.
  1251  // Otherwise, it won't block and fn will be called once the reload is
  1252  // finished.
  1253  //
  1254  func resetHandler(fn func()) http.HandlerFunc {
  1255  	return func(w http.ResponseWriter, r *http.Request) {
  1256  		var wg sync.WaitGroup
  1257  
  1258  		if fn == nil && r.URL.Query().Get("block") == "true" {
  1259  			wg.Add(1)
  1260  			reloadURLStructure(wg.Done)
  1261  		} else {
  1262  			reloadURLStructure(fn)
  1263  		}
  1264  
  1265  		log.WithFields(logrus.Fields{
  1266  			"prefix": "api",
  1267  		}).Info("Reload URL Structure - Scheduled")
  1268  
  1269  		wg.Wait()
  1270  		doJSONWrite(w, http.StatusOK, apiOk(""))
  1271  	}
  1272  }
  1273  
  1274  func createKeyHandler(w http.ResponseWriter, r *http.Request) {
  1275  	newSession := new(user.SessionState)
  1276  	newSession.Mutex = &sync.RWMutex{}
  1277  	if err := json.NewDecoder(r.Body).Decode(newSession); err != nil {
  1278  		log.WithFields(logrus.Fields{
  1279  			"prefix": "api",
  1280  			"status": "fail",
  1281  			"err":    err,
  1282  		}).Error("Key creation failed.")
  1283  		doJSONWrite(w, http.StatusInternalServerError, apiError("Unmarshalling failed"))
  1284  		return
  1285  	}
  1286  
  1287  	newKey := keyGen.GenerateAuthKey(newSession.OrgID)
  1288  	if newSession.HMACEnabled {
  1289  		newSession.HmacSecret = keyGen.GenerateHMACSecret()
  1290  	}
  1291  
  1292  	if newSession.Certificate != "" {
  1293  		newKey = generateToken(newSession.OrgID, newSession.Certificate)
  1294  		_, ok := FallbackKeySesionManager.SessionDetail(newKey, false)
  1295  		if ok {
  1296  			doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - Key with given certificate already found:"+newKey))
  1297  			return
  1298  		}
  1299  	}
  1300  
  1301  	newSession.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
  1302  	newSession.DateCreated = time.Now()
  1303  
  1304  	mw := BaseMiddleware{}
  1305  	mw.ApplyPolicies(newSession)
  1306  
  1307  	if len(newSession.GetAccessRights()) > 0 {
  1308  		// reset API-level limit to nil if any has a zero-value
  1309  		resetAPILimits(newSession.AccessRights)
  1310  		for apiID := range newSession.GetAccessRights() {
  1311  			apiSpec := getApiSpec(apiID)
  1312  			if apiSpec != nil {
  1313  				checkAndApplyTrialPeriod(newKey, apiID, newSession, false)
  1314  				// If we have enabled HMAC checking for keys, we need to generate a secret for the client to use
  1315  				if !apiSpec.DontSetQuotasOnCreate {
  1316  					// Reset quota by default
  1317  					apiSpec.SessionManager.ResetQuota(newKey, newSession, false)
  1318  					newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1319  				}
  1320  				// apply polices (if any) and save key
  1321  				if err := applyPoliciesAndSave(newKey, newSession, apiSpec, false); err != nil {
  1322  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error()))
  1323  					return
  1324  				}
  1325  			} else {
  1326  				// Use fallback
  1327  				sessionManager := FallbackKeySesionManager
  1328  				newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1329  				sessionManager.ResetQuota(newKey, newSession, false)
  1330  				err := sessionManager.UpdateSession(newKey, newSession, -1, false)
  1331  				if err != nil {
  1332  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error()))
  1333  					return
  1334  				}
  1335  			}
  1336  		}
  1337  	} else {
  1338  		if config.Global().AllowMasterKeys {
  1339  			// nothing defined, add key to ALL
  1340  			log.WithFields(logrus.Fields{
  1341  				"prefix":      "api",
  1342  				"status":      "warning",
  1343  				"org_id":      newSession.OrgID,
  1344  				"api_id":      "--",
  1345  				"user_id":     "system",
  1346  				"user_ip":     requestIPHops(r),
  1347  				"path":        "--",
  1348  				"server_name": "system",
  1349  			}).Warning("No API Access Rights set on key session, adding key to all APIs.")
  1350  
  1351  			apisMu.RLock()
  1352  			defer apisMu.RUnlock()
  1353  			for _, spec := range apisByID {
  1354  				checkAndApplyTrialPeriod(newKey, spec.APIID, newSession, false)
  1355  				if !spec.DontSetQuotasOnCreate {
  1356  					// Reset quote by default
  1357  					spec.SessionManager.ResetQuota(newKey, newSession, false)
  1358  					newSession.QuotaRenews = time.Now().Unix() + newSession.QuotaRenewalRate
  1359  				}
  1360  				// apply polices (if any) and save key
  1361  				if err := applyPoliciesAndSave(newKey, newSession, spec, false); err != nil {
  1362  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to create key - "+err.Error()))
  1363  					return
  1364  				}
  1365  			}
  1366  		} else {
  1367  			log.WithFields(logrus.Fields{
  1368  				"prefix":      "api",
  1369  				"status":      "error",
  1370  				"err":         "master keys disabled",
  1371  				"org_id":      newSession.OrgID,
  1372  				"api_id":      "--",
  1373  				"user_id":     "system",
  1374  				"user_ip":     requestIPHops(r),
  1375  				"path":        "--",
  1376  				"server_name": "system",
  1377  			}).Error("Master keys disallowed in configuration, key not added.")
  1378  
  1379  			doJSONWrite(w, http.StatusBadRequest, apiError("Failed to create key, keys must have at least one Access Rights record set."))
  1380  			return
  1381  		}
  1382  
  1383  	}
  1384  
  1385  	obj := apiModifyKeySuccess{
  1386  		Action: "added",
  1387  		Key:    newKey,
  1388  		Status: "ok",
  1389  	}
  1390  
  1391  	// add key hash to reply
  1392  	if config.Global().HashKeys {
  1393  		obj.KeyHash = storage.HashKey(newKey)
  1394  	}
  1395  
  1396  	FireSystemEvent(EventTokenCreated, EventTokenMeta{
  1397  		EventMetaDefault: EventMetaDefault{Message: "Key generated."},
  1398  		Org:              newSession.OrgID,
  1399  		Key:              newKey,
  1400  	})
  1401  
  1402  	log.WithFields(logrus.Fields{
  1403  		"prefix":      "api",
  1404  		"key":         obfuscateKey(newKey),
  1405  		"status":      "ok",
  1406  		"api_id":      "--",
  1407  		"org_id":      newSession.OrgID,
  1408  		"user_id":     "system",
  1409  		"user_ip":     requestIPHops(r),
  1410  		"path":        "--",
  1411  		"server_name": "system",
  1412  	}).Info("Generated new key: (", obfuscateKey(newKey), ")")
  1413  
  1414  	doJSONWrite(w, http.StatusOK, obj)
  1415  }
  1416  
  1417  func previewKeyHandler(w http.ResponseWriter, r *http.Request) {
  1418  	newSession := new(user.SessionState)
  1419  	newSession.Mutex = &sync.RWMutex{}
  1420  	if err := json.NewDecoder(r.Body).Decode(newSession); err != nil {
  1421  		log.WithFields(logrus.Fields{
  1422  			"prefix": "api",
  1423  			"status": "fail",
  1424  			"err":    err,
  1425  		}).Error("Key creation failed.")
  1426  		doJSONWrite(w, http.StatusInternalServerError, apiError("Unmarshalling failed"))
  1427  		return
  1428  	}
  1429  
  1430  	newSession.LastUpdated = strconv.Itoa(int(time.Now().Unix()))
  1431  	newSession.DateCreated = time.Now()
  1432  
  1433  	mw := BaseMiddleware{}
  1434  	mw.ApplyPolicies(newSession)
  1435  
  1436  	doJSONWrite(w, http.StatusOK, newSession)
  1437  }
  1438  
  1439  // NewClientRequest is an outward facing JSON object translated from osin OAuthClients
  1440  //
  1441  // swagger:model NewClientRequest
  1442  type NewClientRequest struct {
  1443  	ClientID          string      `json:"client_id"`
  1444  	ClientRedirectURI string      `json:"redirect_uri"`
  1445  	APIID             string      `json:"api_id,omitempty"`
  1446  	PolicyID          string      `json:"policy_id,omitempty"`
  1447  	ClientSecret      string      `json:"secret"`
  1448  	MetaData          interface{} `json:"meta_data"`
  1449  	Description       string      `json:"description"`
  1450  }
  1451  
  1452  func oauthClientStorageID(clientID string) string {
  1453  	return prefixClient + clientID
  1454  }
  1455  
  1456  func createOauthClient(w http.ResponseWriter, r *http.Request) {
  1457  	var newOauthClient NewClientRequest
  1458  	if err := json.NewDecoder(r.Body).Decode(&newOauthClient); err != nil {
  1459  		log.WithFields(logrus.Fields{
  1460  			"prefix": "api",
  1461  			"status": "fail",
  1462  			"err":    err,
  1463  		}).Error("Failed to create OAuth client")
  1464  		doJSONWrite(w, http.StatusInternalServerError, apiError("Unmarshalling failed"))
  1465  		return
  1466  	}
  1467  
  1468  	// Allow the client ID to be set
  1469  	cleanSting := newOauthClient.ClientID
  1470  
  1471  	if newOauthClient.ClientID == "" {
  1472  		u5 := uuid.NewV4()
  1473  		cleanSting = strings.Replace(u5.String(), "-", "", -1)
  1474  	}
  1475  
  1476  	// Allow the secret to be set
  1477  	secret := newOauthClient.ClientSecret
  1478  	if newOauthClient.ClientSecret == "" {
  1479  		u5Secret := uuid.NewV4()
  1480  		secret = base64.StdEncoding.EncodeToString([]byte(u5Secret.String()))
  1481  	}
  1482  
  1483  	newClient := OAuthClient{
  1484  		ClientID:          cleanSting,
  1485  		ClientRedirectURI: newOauthClient.ClientRedirectURI,
  1486  		ClientSecret:      secret,
  1487  		PolicyID:          newOauthClient.PolicyID,
  1488  		MetaData:          newOauthClient.MetaData,
  1489  		Description:       newOauthClient.Description,
  1490  	}
  1491  
  1492  	storageID := oauthClientStorageID(newClient.GetId())
  1493  	log.WithFields(logrus.Fields{
  1494  		"prefix": "api",
  1495  	}).Debug("Created storage ID: ", storageID)
  1496  
  1497  	if newOauthClient.APIID != "" {
  1498  		// set client only for passed API ID
  1499  		apiSpec := getApiSpec(newOauthClient.APIID)
  1500  		if apiSpec == nil {
  1501  			log.WithFields(logrus.Fields{
  1502  				"prefix": "api",
  1503  				"apiID":  newOauthClient.APIID,
  1504  				"status": "fail",
  1505  				"err":    "API doesn't exist",
  1506  			}).Error("Failed to create OAuth client")
  1507  			doJSONWrite(w, http.StatusBadRequest, apiError("API doesn't exist"))
  1508  			return
  1509  		}
  1510  
  1511  		if !apiSpec.UseOauth2 {
  1512  			doJSONWrite(w, http.StatusBadRequest,
  1513  				apiError("API is not OAuth2"))
  1514  			return
  1515  		}
  1516  
  1517  		err := apiSpec.OAuthManager.OsinServer.Storage.SetClient(storageID, apiSpec.OrgID, &newClient, true)
  1518  		if err != nil {
  1519  			log.WithFields(logrus.Fields{
  1520  				"prefix": "api",
  1521  				"apiID":  newOauthClient.APIID,
  1522  				"status": "fail",
  1523  				"err":    err,
  1524  			}).Error("Failed to create OAuth client")
  1525  			doJSONWrite(w, http.StatusInternalServerError, apiError("Failure in storing client data."))
  1526  			return
  1527  		}
  1528  	} else {
  1529  		// set client for all APIs from the given policy
  1530  		policiesMu.RLock()
  1531  		policy, ok := policiesByID[newClient.PolicyID]
  1532  		policiesMu.RUnlock()
  1533  		if !ok {
  1534  			log.WithFields(logrus.Fields{
  1535  				"prefix":   "api",
  1536  				"policyID": newClient.PolicyID,
  1537  				"status":   "fail",
  1538  				"err":      "Policy doesn't exist",
  1539  			}).Error("Failed to create OAuth client")
  1540  			doJSONWrite(w, http.StatusBadRequest, apiError("Policy doesn't exist"))
  1541  			return
  1542  		}
  1543  
  1544  		oauth2 := false
  1545  		// iterate over APIs and set client for each of them
  1546  		for apiID := range policy.AccessRights {
  1547  			apiSpec := getApiSpec(apiID)
  1548  			if apiSpec == nil {
  1549  				log.WithFields(logrus.Fields{
  1550  					"prefix": "api",
  1551  					"apiID":  apiID,
  1552  					"status": "fail",
  1553  					"err":    "API doesn't exist",
  1554  				}).Error("Failed to create OAuth client")
  1555  				doJSONWrite(w, http.StatusBadRequest, apiError("API doesn't exist"))
  1556  				return
  1557  			}
  1558  			// set oauth client if it is oauth API
  1559  			if apiSpec.UseOauth2 {
  1560  				oauth2 = true
  1561  				err := apiSpec.OAuthManager.OsinServer.Storage.SetClient(storageID, apiSpec.OrgID, &newClient, true)
  1562  				if err != nil {
  1563  					log.WithFields(logrus.Fields{
  1564  						"prefix": "api",
  1565  						"apiID":  apiID,
  1566  						"status": "fail",
  1567  						"err":    err,
  1568  					}).Error("Failed to create OAuth client")
  1569  					doJSONWrite(w, http.StatusInternalServerError, apiError("Failure in storing client data."))
  1570  					return
  1571  				}
  1572  			}
  1573  		}
  1574  
  1575  		if !oauth2 {
  1576  			doJSONWrite(w, http.StatusBadRequest,
  1577  				apiError("API is not OAuth2"))
  1578  			return
  1579  		}
  1580  	}
  1581  
  1582  	clientData := NewClientRequest{
  1583  		ClientID:          newClient.GetId(),
  1584  		ClientSecret:      newClient.GetSecret(),
  1585  		ClientRedirectURI: newClient.GetRedirectUri(),
  1586  		PolicyID:          newClient.GetPolicyID(),
  1587  		MetaData:          newClient.GetUserData(),
  1588  		Description:       newClient.GetDescription(),
  1589  	}
  1590  
  1591  	log.WithFields(logrus.Fields{
  1592  		"prefix":            "api",
  1593  		"apiID":             newOauthClient.APIID,
  1594  		"clientID":          clientData.ClientID,
  1595  		"clientRedirectURI": clientData.ClientRedirectURI,
  1596  		"policyID":          clientData.PolicyID,
  1597  		"description":       clientData.Description,
  1598  		"status":            "ok",
  1599  	}).Info("Created OAuth client")
  1600  
  1601  	doJSONWrite(w, http.StatusOK, clientData)
  1602  }
  1603  
  1604  // Update Client
  1605  func updateOauthClient(keyName, apiID string, r *http.Request) (interface{}, int) {
  1606  	// read payload
  1607  	var updateClientData NewClientRequest
  1608  	if err := json.NewDecoder(r.Body).Decode(&updateClientData); err != nil {
  1609  		log.WithFields(logrus.Fields{
  1610  			"prefix": "api",
  1611  			"status": "fail",
  1612  			"err":    err,
  1613  		}).Error("Failed to update OAuth client")
  1614  		return apiError("Unmarshalling failed"), http.StatusInternalServerError
  1615  	}
  1616  
  1617  	// check API
  1618  	apiSpec := getApiSpec(apiID)
  1619  	if apiSpec == nil {
  1620  		return apiError("API doesn't exist"), http.StatusNotFound
  1621  	}
  1622  
  1623  	// check policy
  1624  	if updateClientData.PolicyID != "" {
  1625  		policiesMu.RLock()
  1626  		policy, ok := policiesByID[updateClientData.PolicyID]
  1627  		policiesMu.RUnlock()
  1628  		if !ok {
  1629  			return apiError("Policy doesn't exist"), http.StatusNotFound
  1630  		}
  1631  		if _, ok := policy.AccessRights[apiID]; !ok {
  1632  			return apiError("Policy access rights doesn't contain API this OAuth client belongs to"),
  1633  				http.StatusBadRequest
  1634  		}
  1635  	}
  1636  
  1637  	// get existing version of oauth-client
  1638  	storageID := oauthClientStorageID(keyName)
  1639  	client, err := apiSpec.OAuthManager.OsinServer.Storage.GetExtendedClientNoPrefix(storageID)
  1640  	if err != nil {
  1641  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1642  	}
  1643  
  1644  	// update client
  1645  	updatedClient := OAuthClient{
  1646  		ClientID:          client.GetId(),
  1647  		ClientSecret:      client.GetSecret(),                 // DO NOT update
  1648  		ClientRedirectURI: updateClientData.ClientRedirectURI, // update
  1649  		PolicyID:          updateClientData.PolicyID,          // update
  1650  		MetaData:          updateClientData.MetaData,          // update
  1651  		Description:       updateClientData.Description,       // update
  1652  	}
  1653  
  1654  	err = apiSpec.OAuthManager.OsinServer.Storage.SetClient(storageID, apiSpec.OrgID, &updatedClient, true)
  1655  	if err != nil {
  1656  		log.WithFields(logrus.Fields{
  1657  			"prefix": "api",
  1658  			"apiID":  apiID,
  1659  			"status": "fail",
  1660  			"err":    err,
  1661  		}).Error("Failed to update OAuth client")
  1662  		return apiError("Failure in storing client data"), http.StatusInternalServerError
  1663  	}
  1664  
  1665  	// invalidate tokens if we had a new policy
  1666  	if prevPolicy := client.GetPolicyID(); prevPolicy != "" && prevPolicy != updatedClient.PolicyID {
  1667  		tokenList, err := apiSpec.OAuthManager.OsinServer.Storage.GetClientTokens(updatedClient.ClientID)
  1668  		if err != nil {
  1669  			log.WithError(err).Warning("Could not get list of tokens for updated OAuth client")
  1670  		}
  1671  		for _, token := range tokenList {
  1672  			if err := apiSpec.OAuthManager.OsinServer.Storage.RemoveAccess(token.Token); err != nil {
  1673  				log.WithError(err).Warning("Could not remove token for updated OAuth client policy")
  1674  			}
  1675  		}
  1676  	}
  1677  
  1678  	// convert to outbound format
  1679  	replyData := NewClientRequest{
  1680  		ClientID:          updatedClient.GetId(),
  1681  		ClientSecret:      updatedClient.GetSecret(),
  1682  		ClientRedirectURI: updatedClient.GetRedirectUri(),
  1683  		PolicyID:          updatedClient.GetPolicyID(),
  1684  		MetaData:          updatedClient.GetUserData(),
  1685  		Description:       updatedClient.GetDescription(),
  1686  	}
  1687  
  1688  	return replyData, http.StatusOK
  1689  }
  1690  
  1691  func invalidateOauthRefresh(w http.ResponseWriter, r *http.Request) {
  1692  	apiID := r.URL.Query().Get("api_id")
  1693  	if apiID == "" {
  1694  		doJSONWrite(w, http.StatusBadRequest, apiError("Missing parameter api_id"))
  1695  		return
  1696  	}
  1697  	apiSpec := getApiSpec(apiID)
  1698  
  1699  	log.WithFields(logrus.Fields{
  1700  		"prefix": "api",
  1701  		"apiID":  apiID,
  1702  	}).Debug("Looking for refresh token in API Register")
  1703  
  1704  	if apiSpec == nil {
  1705  		log.WithFields(logrus.Fields{
  1706  			"prefix": "api",
  1707  			"apiID":  apiID,
  1708  			"status": "fail",
  1709  			"err":    "API not found",
  1710  		}).Error("Failed to invalidate refresh token")
  1711  
  1712  		doJSONWrite(w, http.StatusNotFound, apiError("API for this refresh token not found"))
  1713  		return
  1714  	}
  1715  
  1716  	if apiSpec.OAuthManager == nil {
  1717  		log.WithFields(logrus.Fields{
  1718  			"prefix": "api",
  1719  			"apiID":  apiID,
  1720  			"status": "fail",
  1721  			"err":    "API is not OAuth",
  1722  		}).Error("Failed to invalidate refresh token")
  1723  
  1724  		doJSONWrite(w, http.StatusBadRequest, apiError("OAuth is not enabled on this API"))
  1725  		return
  1726  	}
  1727  
  1728  	keyName := mux.Vars(r)["keyName"]
  1729  	err := apiSpec.OAuthManager.OsinServer.Storage.RemoveRefresh(keyName)
  1730  	if err != nil {
  1731  		log.WithFields(logrus.Fields{
  1732  			"prefix": "api",
  1733  			"apiID":  apiID,
  1734  			"status": "fail",
  1735  			"err":    err,
  1736  		}).Error("Failed to invalidate refresh token")
  1737  
  1738  		doJSONWrite(w, http.StatusInternalServerError, apiError("Failed to invalidate refresh token"))
  1739  		return
  1740  	}
  1741  
  1742  	success := apiModifyKeySuccess{
  1743  		Key:    keyName,
  1744  		Status: "ok",
  1745  		Action: "deleted",
  1746  	}
  1747  
  1748  	log.WithFields(logrus.Fields{
  1749  		"prefix": "api",
  1750  		"apiID":  apiID,
  1751  		"token":  keyName,
  1752  		"status": "ok",
  1753  	}).Info("Invalidated refresh token")
  1754  
  1755  	doJSONWrite(w, http.StatusOK, success)
  1756  }
  1757  
  1758  func getApisForOauthApp(w http.ResponseWriter, r *http.Request) {
  1759  	apis := []string{}
  1760  	appID := mux.Vars(r)["appID"]
  1761  	orgID := r.FormValue("orgID")
  1762  
  1763  	//get all organization apis
  1764  	apisIds := getApisIdsForOrg(orgID)
  1765  
  1766  	for index := range apisIds {
  1767  		if api := getApiSpec(apisIds[index]); api != nil {
  1768  			if api.UseOauth2 {
  1769  				clients, _, code := getApiClients(apisIds[index])
  1770  				if code == http.StatusOK {
  1771  					for _, client := range clients {
  1772  						if client.GetId() == appID {
  1773  							apis = append(apis, apisIds[index])
  1774  						}
  1775  					}
  1776  				}
  1777  			}
  1778  		}
  1779  	}
  1780  
  1781  	doJSONWrite(w, http.StatusOK, apis)
  1782  }
  1783  
  1784  func oAuthClientHandler(w http.ResponseWriter, r *http.Request) {
  1785  	apiID := mux.Vars(r)["apiID"]
  1786  	keyName := mux.Vars(r)["keyName"]
  1787  
  1788  	var obj interface{}
  1789  	var code int
  1790  	switch r.Method {
  1791  	case http.MethodGet:
  1792  		if keyName != "" {
  1793  			// Return single client detail
  1794  			obj, code = getOauthClientDetails(keyName, apiID)
  1795  		} else {
  1796  			// Return list of keys
  1797  			obj, code = getOauthClients(apiID)
  1798  		}
  1799  	case http.MethodPut:
  1800  		// Update client
  1801  		obj, code = updateOauthClient(keyName, apiID, r)
  1802  	case http.MethodDelete:
  1803  		// Remove a key
  1804  		obj, code = handleDeleteOAuthClient(keyName, apiID)
  1805  	}
  1806  
  1807  	doJSONWrite(w, code, obj)
  1808  }
  1809  
  1810  func oAuthClientTokensHandler(w http.ResponseWriter, r *http.Request) {
  1811  	apiID := mux.Vars(r)["apiID"]
  1812  	keyName := mux.Vars(r)["keyName"]
  1813  
  1814  	apiSpec := getApiSpec(apiID)
  1815  	if apiSpec == nil {
  1816  		log.WithFields(logrus.Fields{
  1817  			"prefix": "api",
  1818  			"apiID":  apiID,
  1819  			"status": "fail",
  1820  			"client": keyName,
  1821  			"err":    "not found",
  1822  		}).Error("Failed to retrieve OAuth tokens")
  1823  		doJSONWrite(w, http.StatusNotFound, apiError("OAuth Client ID not found"))
  1824  		return
  1825  	}
  1826  
  1827  	if p := r.URL.Query().Get("page"); p != "" {
  1828  		page := 1
  1829  
  1830  		queryPage, err := strconv.Atoi(p)
  1831  		if err == nil {
  1832  			page = queryPage
  1833  		}
  1834  
  1835  		if page <= 0 {
  1836  			page = 1
  1837  		}
  1838  
  1839  		tokens, totalPages, err := apiSpec.OAuthManager.OsinServer.Storage.GetPaginatedClientTokens(keyName, page)
  1840  		if err != nil {
  1841  			doJSONWrite(w, http.StatusInternalServerError, apiError("Get client tokens failed"))
  1842  			return
  1843  		}
  1844  
  1845  		doJSONWrite(w, http.StatusOK, paginatedOAuthClientTokens{
  1846  			Pagination: paginationStatus{
  1847  				PageSize:  100,
  1848  				PageNum:   page,
  1849  				PageTotal: totalPages,
  1850  			},
  1851  			Tokens: tokens,
  1852  		})
  1853  
  1854  		return
  1855  	}
  1856  
  1857  	tokens, err := apiSpec.OAuthManager.OsinServer.Storage.GetClientTokens(keyName)
  1858  	if err != nil {
  1859  		doJSONWrite(w, http.StatusInternalServerError, apiError("Get client tokens failed"))
  1860  		return
  1861  	}
  1862  
  1863  	doJSONWrite(w, http.StatusOK, tokens)
  1864  }
  1865  
  1866  // Get client details
  1867  func getOauthClientDetails(keyName, apiID string) (interface{}, int) {
  1868  	storageID := oauthClientStorageID(keyName)
  1869  	apiSpec := getApiSpec(apiID)
  1870  	if apiSpec == nil {
  1871  		log.WithFields(logrus.Fields{
  1872  			"prefix": "api",
  1873  			"apiID":  apiID,
  1874  			"status": "fail",
  1875  			"client": keyName,
  1876  			"err":    "not found",
  1877  		}).Error("Failed to retrieve OAuth client details")
  1878  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1879  	}
  1880  
  1881  	clientData, err := apiSpec.OAuthManager.OsinServer.Storage.GetExtendedClientNoPrefix(storageID)
  1882  	if err != nil {
  1883  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1884  	}
  1885  	reportableClientData := NewClientRequest{
  1886  		ClientID:          clientData.GetId(),
  1887  		ClientSecret:      clientData.GetSecret(),
  1888  		ClientRedirectURI: clientData.GetRedirectUri(),
  1889  		PolicyID:          clientData.GetPolicyID(),
  1890  		MetaData:          clientData.GetUserData(),
  1891  		Description:       clientData.GetDescription(),
  1892  	}
  1893  
  1894  	log.WithFields(logrus.Fields{
  1895  		"prefix": "api",
  1896  		"apiID":  apiID,
  1897  		"status": "ok",
  1898  		"client": keyName,
  1899  	}).Info("Retrieved OAuth client ID")
  1900  
  1901  	return reportableClientData, http.StatusOK
  1902  }
  1903  
  1904  // Delete Client
  1905  func handleDeleteOAuthClient(keyName, apiID string) (interface{}, int) {
  1906  	storageID := oauthClientStorageID(keyName)
  1907  
  1908  	apiSpec := getApiSpec(apiID)
  1909  	if apiSpec == nil {
  1910  		log.WithFields(logrus.Fields{
  1911  			"prefix": "api",
  1912  			"apiID":  apiID,
  1913  			"status": "fail",
  1914  			"client": keyName,
  1915  			"err":    "not found",
  1916  		}).Error("Failed to delete OAuth client")
  1917  
  1918  		return apiError("OAuth Client ID not found"), http.StatusNotFound
  1919  	}
  1920  
  1921  	if apiSpec.OAuthManager != nil {
  1922  		err := apiSpec.OAuthManager.OsinServer.Storage.DeleteClient(storageID, apiSpec.OrgID, true)
  1923  		if err != nil {
  1924  			return apiError("Delete failed"), http.StatusInternalServerError
  1925  		}
  1926  
  1927  		statusObj := apiModifyKeySuccess{
  1928  			Key:    keyName,
  1929  			Status: "ok",
  1930  			Action: "deleted",
  1931  		}
  1932  
  1933  		log.WithFields(logrus.Fields{
  1934  			"prefix": "api",
  1935  			"apiID":  apiID,
  1936  			"status": "ok",
  1937  			"client": keyName,
  1938  		}).Info("Deleted OAuth client")
  1939  
  1940  		return statusObj, http.StatusOK
  1941  	}
  1942  
  1943  	return apiError("OAuth Client ID not found"), http.StatusNotFound
  1944  }
  1945  
  1946  const oAuthNotPropagatedErr = "OAuth client list isn't available or hasn't been propagated yet."
  1947  const oAuthClientNotFound = "OAuth client not found"
  1948  const oauthClientIdEmpty = "client_id is required"
  1949  const oauthClientSecretEmpty = "client_secret is required"
  1950  const oauthClientSecretWrong = "client secret is wrong"
  1951  const oauthTokenEmpty = "token is required"
  1952  
  1953  func getApiClients(apiID string) ([]ExtendedOsinClientInterface, apiStatusMessage, int) {
  1954  	var err error
  1955  	filterID := prefixClient
  1956  	apiSpec := getApiSpec(apiID)
  1957  
  1958  	if apiSpec == nil {
  1959  		log.WithFields(logrus.Fields{
  1960  			"prefix": "api",
  1961  			"apiID":  apiID,
  1962  			"status": "fail",
  1963  			"err":    "API not found",
  1964  		}).Error("Failed to retrieve OAuth client list.")
  1965  		return nil, apiError(oAuthClientNotFound), http.StatusNotFound
  1966  	}
  1967  
  1968  	clientData := []ExtendedOsinClientInterface{}
  1969  	if apiSpec.UseOauth2 {
  1970  		clientData, err = apiSpec.OAuthManager.OsinServer.Storage.GetClients(filterID, apiSpec.OrgID, true)
  1971  		if err != nil {
  1972  			log.WithFields(logrus.Fields{
  1973  				"prefix": "api",
  1974  				"apiID":  apiID,
  1975  				"status": "fail",
  1976  				"err":    err,
  1977  			}).Error("Failed to report OAuth client list")
  1978  
  1979  			return nil, apiError(oAuthClientNotFound), http.StatusNotFound
  1980  		}
  1981  	}
  1982  
  1983  	return clientData, apiStatusMessage{}, http.StatusOK
  1984  }
  1985  
  1986  // List Clients
  1987  func getOauthClients(apiID string) (interface{}, int) {
  1988  
  1989  	clientData, _, apiStatusCode := getApiClients(apiID)
  1990  
  1991  	if apiStatusCode != 200 {
  1992  		return clientData, apiStatusCode
  1993  	}
  1994  
  1995  	clients := []NewClientRequest{}
  1996  	for _, osinClient := range clientData {
  1997  		reportableClientData := NewClientRequest{
  1998  			ClientID:          osinClient.GetId(),
  1999  			ClientSecret:      osinClient.GetSecret(),
  2000  			ClientRedirectURI: osinClient.GetRedirectUri(),
  2001  			PolicyID:          osinClient.GetPolicyID(),
  2002  			MetaData:          osinClient.GetUserData(),
  2003  			Description:       osinClient.GetDescription(),
  2004  		}
  2005  
  2006  		clients = append(clients, reportableClientData)
  2007  	}
  2008  	log.WithFields(logrus.Fields{
  2009  		"prefix": "api",
  2010  		"apiID":  apiID,
  2011  		"status": "ok",
  2012  	}).Info("Retrieved OAuth client list")
  2013  
  2014  	return clients, http.StatusOK
  2015  }
  2016  
  2017  func getApisForOauthClientId(oauthClientId string, orgId string) []string {
  2018  	apis := []string{}
  2019  	orgApis := getApisIdsForOrg(orgId)
  2020  
  2021  	for index := range orgApis {
  2022  		clientsData, _, status := getApiClients(orgApis[index])
  2023  		if status == http.StatusOK {
  2024  			for _, client := range clientsData {
  2025  				if client.GetId() == oauthClientId {
  2026  					apis = append(apis, orgApis[index])
  2027  				}
  2028  			}
  2029  		}
  2030  	}
  2031  
  2032  	return apis
  2033  }
  2034  
  2035  func healthCheckhandler(w http.ResponseWriter, r *http.Request) {
  2036  	if !config.Global().HealthCheck.EnableHealthChecks {
  2037  		doJSONWrite(w, http.StatusBadRequest, apiError("Health checks are not enabled for this node"))
  2038  		return
  2039  	}
  2040  	apiID := r.URL.Query().Get("api_id")
  2041  	if apiID == "" {
  2042  		doJSONWrite(w, http.StatusBadRequest, apiError("missing api_id parameter"))
  2043  		return
  2044  	}
  2045  	apiSpec := getApiSpec(apiID)
  2046  	if apiSpec == nil {
  2047  		doJSONWrite(w, http.StatusNotFound, apiError("API ID not found"))
  2048  		return
  2049  	}
  2050  	health, _ := apiSpec.Health.ApiHealthValues()
  2051  	doJSONWrite(w, http.StatusOK, health)
  2052  }
  2053  
  2054  func userRatesCheck(w http.ResponseWriter, r *http.Request) {
  2055  	session := ctxGetSession(r)
  2056  	if session == nil {
  2057  		doJSONWrite(w, http.StatusBadRequest, apiError("Health checks are not enabled for this node"))
  2058  		return
  2059  	}
  2060  
  2061  	returnSession := PublicSession{}
  2062  	returnSession.Quota.QuotaRenews = session.QuotaRenews
  2063  	returnSession.Quota.QuotaRemaining = session.QuotaRemaining
  2064  	returnSession.Quota.QuotaMax = session.QuotaMax
  2065  	returnSession.RateLimit.Rate = session.Rate
  2066  	returnSession.RateLimit.Per = session.Per
  2067  
  2068  	doJSONWrite(w, http.StatusOK, returnSession)
  2069  }
  2070  
  2071  func invalidateCacheHandler(w http.ResponseWriter, r *http.Request) {
  2072  	apiID := mux.Vars(r)["apiID"]
  2073  
  2074  	keyPrefix := "cache-" + apiID
  2075  	matchPattern := keyPrefix + "*"
  2076  	store := storage.RedisCluster{KeyPrefix: keyPrefix, IsCache: true}
  2077  
  2078  	if ok := store.DeleteScanMatch(matchPattern); !ok {
  2079  		err := errors.New("scan/delete failed")
  2080  		var orgid string
  2081  		if spec := getApiSpec(apiID); spec != nil {
  2082  			orgid = spec.OrgID
  2083  		}
  2084  		log.WithFields(logrus.Fields{
  2085  			"prefix":      "api",
  2086  			"api_id":      apiID,
  2087  			"status":      "fail",
  2088  			"err":         err,
  2089  			"org_id":      orgid,
  2090  			"user_id":     "system",
  2091  			"user_ip":     requestIPHops(r),
  2092  			"path":        "--",
  2093  			"server_name": "system",
  2094  		}).Error("Failed to delete cache: ", err)
  2095  
  2096  		doJSONWrite(w, http.StatusInternalServerError, apiError("Cache invalidation failed"))
  2097  		return
  2098  	}
  2099  
  2100  	doJSONWrite(w, http.StatusOK, apiOk("cache invalidated"))
  2101  }
  2102  
  2103  func RevokeTokenHandler(w http.ResponseWriter, r *http.Request) {
  2104  	err := r.ParseForm()
  2105  
  2106  	if err != nil {
  2107  		doJSONWrite(w, http.StatusBadRequest, apiError("cannot parse form. Form malformed"))
  2108  		return
  2109  	}
  2110  
  2111  	tokenTypeHint := r.PostFormValue("token_type_hint")
  2112  	token := r.PostFormValue("token")
  2113  	clientID := r.PostFormValue("client_id")
  2114  	orgID := r.PostFormValue("org_id")
  2115  
  2116  	if token == "" {
  2117  		doJSONWrite(w, http.StatusBadRequest, apiError(oauthTokenEmpty))
  2118  		return
  2119  	}
  2120  
  2121  	if clientID == "" {
  2122  		doJSONWrite(w, http.StatusBadRequest, apiError(oauthClientIdEmpty))
  2123  		return
  2124  	}
  2125  
  2126  	apis := getApisForOauthClientId(clientID, orgID)
  2127  	if len(apis) == 0 {
  2128  		doJSONWrite(w, http.StatusBadRequest, apiError("oauth client doesn't exist"))
  2129  		return
  2130  	}
  2131  
  2132  	for _, apiID := range apis {
  2133  		storage, _, err := GetStorageForApi(apiID)
  2134  		if err == nil {
  2135  			RevokeToken(storage, token, tokenTypeHint)
  2136  		}
  2137  	}
  2138  	doJSONWrite(w, http.StatusOK, apiOk("token revoked successfully"))
  2139  }
  2140  
  2141  func GetStorageForApi(apiID string) (ExtendedOsinStorageInterface, int, error) {
  2142  	apiSpec := getApiSpec(apiID)
  2143  	if apiSpec == nil {
  2144  		log.WithFields(logrus.Fields{
  2145  			"prefix": "api",
  2146  			"apiID":  apiID,
  2147  			"status": "fail",
  2148  			"err":    "API not found",
  2149  		}).Error("Failed to retrieve OAuth client list.")
  2150  
  2151  		return nil, http.StatusNotFound, errors.New(oAuthClientNotFound)
  2152  	}
  2153  
  2154  	if apiSpec.OAuthManager == nil {
  2155  		log.WithFields(logrus.Fields{
  2156  			"prefix": "api",
  2157  			"apiID":  apiID,
  2158  			"status": "fail",
  2159  			"err":    "API not found",
  2160  		}).Error("Failed to revoke client tokens.")
  2161  
  2162  		return nil, http.StatusNotFound, errors.New(oAuthNotPropagatedErr)
  2163  	}
  2164  
  2165  	return apiSpec.OAuthManager.OsinServer.Storage, http.StatusOK, nil
  2166  }
  2167  
  2168  func RevokeAllTokensHandler(w http.ResponseWriter, r *http.Request) {
  2169  	err := r.ParseForm()
  2170  
  2171  	if err != nil {
  2172  		doJSONWrite(w, http.StatusBadRequest, apiError("cannot parse form. Form malformed"))
  2173  		return
  2174  	}
  2175  
  2176  	clientId := r.PostFormValue("client_id")
  2177  	clientSecret := r.PostFormValue("client_secret")
  2178  	orgId := r.PostFormValue("org_id")
  2179  
  2180  	if clientId == "" {
  2181  		doJSONWrite(w, http.StatusUnauthorized, apiError(oauthClientIdEmpty))
  2182  		return
  2183  	}
  2184  
  2185  	if clientSecret == "" {
  2186  		doJSONWrite(w, http.StatusUnauthorized, apiError(oauthClientSecretEmpty))
  2187  		return
  2188  	}
  2189  
  2190  	apis := getApisForOauthClientId(clientId, orgId)
  2191  	if len(apis) == 0 {
  2192  		//if api is 0 is because the client wasn't found
  2193  		doJSONWrite(w, http.StatusNotFound, apiError("oauth client doesn't exist"))
  2194  		return
  2195  	}
  2196  
  2197  	tokens := []string{}
  2198  	for _, apiId := range apis {
  2199  		storage, _, err := GetStorageForApi(apiId)
  2200  		if err == nil {
  2201  			_, tokensRevoked, _ := RevokeAllTokens(storage, clientId, clientSecret)
  2202  			tokens = append(tokens, tokensRevoked...)
  2203  		}
  2204  	}
  2205  
  2206  	n := Notification{
  2207  		Command: KeySpaceUpdateNotification,
  2208  		Payload: strings.Join(tokens, ","),
  2209  	}
  2210  	MainNotifier.Notify(n)
  2211  
  2212  	doJSONWrite(w, http.StatusOK, apiOk("tokens revoked successfully"))
  2213  }
  2214  
  2215  // TODO: Don't modify http.Request values in-place. We must right now
  2216  // because our middleware design doesn't pass around http.Request
  2217  // pointers, so we have no way to modify the pointer in a middleware.
  2218  //
  2219  // If we ever redesign middlewares - or if we find another workaround -
  2220  // revisit this.
  2221  func setContext(r *http.Request, ctx context.Context) {
  2222  	r2 := r.WithContext(ctx)
  2223  	*r = *r2
  2224  }
  2225  func setCtxValue(r *http.Request, key, val interface{}) {
  2226  	setContext(r, context.WithValue(r.Context(), key, val))
  2227  }
  2228  
  2229  func ctxGetData(r *http.Request) map[string]interface{} {
  2230  	if v := r.Context().Value(ctx.ContextData); v != nil {
  2231  		return v.(map[string]interface{})
  2232  	}
  2233  	return nil
  2234  }
  2235  
  2236  func ctxSetData(r *http.Request, m map[string]interface{}) {
  2237  	if m == nil {
  2238  		panic("setting a nil context ContextData")
  2239  	}
  2240  	setCtxValue(r, ctx.ContextData, m)
  2241  }
  2242  
  2243  func ctxGetSession(r *http.Request) *user.SessionState {
  2244  	return ctx.GetSession(r)
  2245  }
  2246  
  2247  func ctxSetSession(r *http.Request, s *user.SessionState, token string, scheduleUpdate bool) {
  2248  	ctx.SetSession(r, s, token, scheduleUpdate)
  2249  }
  2250  
  2251  func ctxScheduleSessionUpdate(r *http.Request) {
  2252  	setCtxValue(r, ctx.UpdateSession, true)
  2253  }
  2254  
  2255  func ctxDisableSessionUpdate(r *http.Request) {
  2256  	setCtxValue(r, ctx.UpdateSession, false)
  2257  }
  2258  
  2259  func ctxSessionUpdateScheduled(r *http.Request) bool {
  2260  	if v := r.Context().Value(ctx.UpdateSession); v != nil {
  2261  		return v.(bool)
  2262  	}
  2263  	return false
  2264  }
  2265  
  2266  func ctxGetAuthToken(r *http.Request) string {
  2267  	return ctx.GetAuthToken(r)
  2268  }
  2269  
  2270  func ctxGetTrackedPath(r *http.Request) string {
  2271  	if v := r.Context().Value(ctx.TrackThisEndpoint); v != nil {
  2272  		return v.(string)
  2273  	}
  2274  	return ""
  2275  }
  2276  
  2277  func ctxSetTrackedPath(r *http.Request, p string) {
  2278  	if p == "" {
  2279  		panic("setting a nil context TrackThisEndpoint")
  2280  	}
  2281  	setCtxValue(r, ctx.TrackThisEndpoint, p)
  2282  }
  2283  
  2284  func ctxGetDoNotTrack(r *http.Request) bool {
  2285  	return r.Context().Value(ctx.DoNotTrackThisEndpoint) == true
  2286  }
  2287  
  2288  func ctxSetDoNotTrack(r *http.Request, b bool) {
  2289  	setCtxValue(r, ctx.DoNotTrackThisEndpoint, b)
  2290  }
  2291  
  2292  func ctxGetVersionInfo(r *http.Request) *apidef.VersionInfo {
  2293  	if v := r.Context().Value(ctx.VersionData); v != nil {
  2294  		return v.(*apidef.VersionInfo)
  2295  	}
  2296  	return nil
  2297  }
  2298  
  2299  func ctxSetVersionInfo(r *http.Request, v *apidef.VersionInfo) {
  2300  	setCtxValue(r, ctx.VersionData, v)
  2301  }
  2302  
  2303  func ctxSetOrigRequestURL(r *http.Request, url *url.URL) {
  2304  	setCtxValue(r, ctx.OrigRequestURL, url)
  2305  }
  2306  
  2307  func ctxGetOrigRequestURL(r *http.Request) *url.URL {
  2308  	if v := r.Context().Value(ctx.OrigRequestURL); v != nil {
  2309  		if urlVal, ok := v.(*url.URL); ok {
  2310  			return urlVal
  2311  		}
  2312  	}
  2313  
  2314  	return nil
  2315  }
  2316  
  2317  func ctxSetURLRewriteTarget(r *http.Request, url *url.URL) {
  2318  	setCtxValue(r, ctx.UrlRewriteTarget, url)
  2319  }
  2320  
  2321  func ctxGetURLRewriteTarget(r *http.Request) *url.URL {
  2322  	if v := r.Context().Value(ctx.UrlRewriteTarget); v != nil {
  2323  		if urlVal, ok := v.(*url.URL); ok {
  2324  			return urlVal
  2325  		}
  2326  	}
  2327  
  2328  	return nil
  2329  }
  2330  
  2331  func ctxSetUrlRewritePath(r *http.Request, path string) {
  2332  	setCtxValue(r, ctx.UrlRewritePath, path)
  2333  }
  2334  
  2335  func ctxGetUrlRewritePath(r *http.Request) string {
  2336  	if v := r.Context().Value(ctx.UrlRewritePath); v != nil {
  2337  		if strVal, ok := v.(string); ok {
  2338  			return strVal
  2339  		}
  2340  	}
  2341  	return ""
  2342  }
  2343  
  2344  func ctxSetCheckLoopLimits(r *http.Request, b bool) {
  2345  	setCtxValue(r, ctx.CheckLoopLimits, b)
  2346  }
  2347  
  2348  // Should we check Rate limits and Quotas?
  2349  func ctxCheckLimits(r *http.Request) bool {
  2350  	// If looping disabled, allow all
  2351  	if !ctxLoopingEnabled(r) {
  2352  		return true
  2353  	}
  2354  
  2355  	if v := r.Context().Value(ctx.CheckLoopLimits); v != nil {
  2356  		return v.(bool)
  2357  	}
  2358  
  2359  	return false
  2360  }
  2361  
  2362  func ctxSetRequestMethod(r *http.Request, path string) {
  2363  	setCtxValue(r, ctx.RequestMethod, path)
  2364  }
  2365  
  2366  func ctxGetRequestMethod(r *http.Request) string {
  2367  	if v := r.Context().Value(ctx.RequestMethod); v != nil {
  2368  		if strVal, ok := v.(string); ok {
  2369  			return strVal
  2370  		}
  2371  	}
  2372  	return r.Method
  2373  }
  2374  
  2375  func ctxSetTransformRequestMethod(r *http.Request, path string) {
  2376  	setCtxValue(r, ctx.TransformedRequestMethod, path)
  2377  }
  2378  
  2379  func ctxGetTransformRequestMethod(r *http.Request) string {
  2380  	if v := r.Context().Value(ctx.TransformedRequestMethod); v != nil {
  2381  		if strVal, ok := v.(string); ok {
  2382  			return strVal
  2383  		}
  2384  	}
  2385  	return r.Method
  2386  }
  2387  
  2388  func ctxGetDefaultVersion(r *http.Request) bool {
  2389  	return r.Context().Value(ctx.VersionDefault) != nil
  2390  }
  2391  
  2392  func ctxSetDefaultVersion(r *http.Request) {
  2393  	setCtxValue(r, ctx.VersionDefault, true)
  2394  }
  2395  
  2396  func ctxLoopingEnabled(r *http.Request) bool {
  2397  	return ctxLoopLevel(r) > 0
  2398  }
  2399  
  2400  func ctxLoopLevel(r *http.Request) int {
  2401  	if v := r.Context().Value(ctx.LoopLevel); v != nil {
  2402  		if intVal, ok := v.(int); ok {
  2403  			return intVal
  2404  		}
  2405  	}
  2406  
  2407  	return 0
  2408  }
  2409  
  2410  func ctxSetLoopLevel(r *http.Request, value int) {
  2411  	setCtxValue(r, ctx.LoopLevel, value)
  2412  }
  2413  
  2414  func ctxIncLoopLevel(r *http.Request, loopLimit int) {
  2415  	ctxSetLoopLimit(r, loopLimit)
  2416  	ctxSetLoopLevel(r, ctxLoopLevel(r)+1)
  2417  }
  2418  
  2419  func ctxLoopLevelLimit(r *http.Request) int {
  2420  	if v := r.Context().Value(ctx.LoopLevelLimit); v != nil {
  2421  		if intVal, ok := v.(int); ok {
  2422  			return intVal
  2423  		}
  2424  	}
  2425  
  2426  	return 0
  2427  }
  2428  
  2429  func ctxSetLoopLimit(r *http.Request, limit int) {
  2430  	// Can be set only one time per request
  2431  	if ctxLoopLevelLimit(r) == 0 && limit > 0 {
  2432  		setCtxValue(r, ctx.LoopLevelLimit, limit)
  2433  	}
  2434  }
  2435  
  2436  func ctxThrottleLevelLimit(r *http.Request) int {
  2437  	if v := r.Context().Value(ctx.ThrottleLevelLimit); v != nil {
  2438  		if intVal, ok := v.(int); ok {
  2439  			return intVal
  2440  		}
  2441  	}
  2442  
  2443  	return 0
  2444  }
  2445  
  2446  func ctxThrottleLevel(r *http.Request) int {
  2447  	if v := r.Context().Value(ctx.ThrottleLevel); v != nil {
  2448  		if intVal, ok := v.(int); ok {
  2449  			return intVal
  2450  		}
  2451  	}
  2452  
  2453  	return 0
  2454  }
  2455  
  2456  func ctxSetThrottleLimit(r *http.Request, limit int) {
  2457  	// Can be set only one time per request
  2458  	if ctxThrottleLevelLimit(r) == 0 && limit > 0 {
  2459  		setCtxValue(r, ctx.ThrottleLevelLimit, limit)
  2460  	}
  2461  }
  2462  
  2463  func ctxSetThrottleLevel(r *http.Request, value int) {
  2464  	setCtxValue(r, ctx.ThrottleLevel, value)
  2465  }
  2466  
  2467  func ctxIncThrottleLevel(r *http.Request, throttleLimit int) {
  2468  	ctxSetThrottleLimit(r, throttleLimit)
  2469  	ctxSetThrottleLevel(r, ctxThrottleLevel(r)+1)
  2470  }
  2471  
  2472  func ctxTraceEnabled(r *http.Request) bool {
  2473  	return r.Context().Value(ctx.Trace) != nil
  2474  }
  2475  
  2476  func ctxSetTrace(r *http.Request) {
  2477  	setCtxValue(r, ctx.Trace, true)
  2478  }
  2479  
  2480  func ctxSetRequestStatus(r *http.Request, stat RequestStatus) {
  2481  	setCtxValue(r, ctx.RequestStatus, stat)
  2482  }
  2483  
  2484  func ctxGetRequestStatus(r *http.Request) (stat RequestStatus) {
  2485  	if v := r.Context().Value(ctx.RequestStatus); v != nil {
  2486  		stat = v.(RequestStatus)
  2487  	}
  2488  	return
  2489  }