| package apidAnalytics |
| |
| import ( |
| "database/sql" |
| "fmt" |
| "sync" |
| ) |
| |
| var tenantCache map[string]tenant |
| var developerInfoCache map[string]developerInfo |
| var tenantCachelock = sync.RWMutex{} |
| var developerInfoCacheLock = sync.RWMutex{} |
| |
| |
| func createTenantCache() error { |
| tenantCache = make(map[string]tenant) |
| var org, env, tenantId, id string |
| db := getDB() |
| |
| rows, error := db.Query("SELECT env, org, scope, id FROM DATA_SCOPE") |
| |
| if error != nil { |
| return fmt.Errorf("Count not get datascope from DB due to : %s", error.Error()) |
| } else { |
| defer rows.Close() |
| // Lock before writing to the map as it has multiple readers |
| tenantCachelock.Lock() |
| defer tenantCachelock.Unlock() |
| for rows.Next() { |
| rows.Scan(&env, &org, &tenantId, &id); |
| tenantCache[id] = tenant{Org: org, Env: env, TenantId: tenantId} |
| } |
| } |
| log.Debugf("Count of data scopes in the cache: %d", len(tenantCache)) |
| return nil |
| } |
| |
| func createDeveloperInfoCache() error { |
| developerInfoCache = make(map[string]developerInfo) |
| |
| var apiProduct, developerApp, developerEmail, developer sql.NullString |
| var tenantId, apiKey string |
| |
| db := getDB() |
| |
| sSql := "SELECT mp.tenant_id, mp.appcred_id, ap.name, a.name, d.username, d.email " + |
| "FROM APP_CREDENTIAL_APIPRODUCT_MAPPER as mp " + |
| "INNER JOIN API_PRODUCT as ap ON ap.id = mp.apiprdt_id " + |
| "INNER JOIN APP AS a ON a.id = mp.app_id " + |
| "INNER JOIN DEVELOPER as d ON d.id = a.developer_id ;" |
| rows, error := db.Query(sSql) |
| |
| if error != nil { |
| return fmt.Errorf("Count not get developerInfo from DB due to : %s", error.Error()) |
| } else { |
| defer rows.Close() |
| // Lock before writing to the map as it has multiple readers |
| developerInfoCacheLock.Lock() |
| defer developerInfoCacheLock.Unlock() |
| for rows.Next() { |
| rows.Scan(&tenantId,&apiKey,&apiProduct, &developerApp, &developer, &developerEmail) |
| |
| keyForMap := getKeyForDeveloperInfoCache(tenantId, apiKey) |
| apiPrd := getValuesIgnoringNull(apiProduct) |
| devApp := getValuesIgnoringNull(developerApp) |
| dev := getValuesIgnoringNull(developer) |
| devEmail := getValuesIgnoringNull(developerEmail) |
| |
| developerInfoCache[keyForMap] = developerInfo{ApiProduct: apiPrd, DeveloperApp: devApp, DeveloperEmail: devEmail, Developer: dev} |
| } |
| } |
| log.Debugf("Count of apiKey~tenantId combinations in the cache: %d", len(developerInfoCache)) |
| return nil |
| } |
| |
| func getTenantForScope(scopeuuid string) (tenant, dbError) { |
| if (config.GetBool(useCaching)) { |
| _, exists := tenantCache[scopeuuid] |
| if !exists { |
| reason := "No tenant found for this scopeuuid: " + scopeuuid |
| errorCode := "UNKNOWN_SCOPE" |
| return tenant{}, dbError{errorCode, reason} |
| } else { |
| // acquire a read lock as this cache has 1 writer as well |
| tenantCachelock.RLock() |
| defer tenantCachelock.RUnlock() |
| return tenantCache[scopeuuid], dbError{} |
| } |
| } else { |
| var org, env, tenantId string |
| db, err := data.DB() |
| if err != nil { |
| reason := "DB not initialized" |
| errorCode := "INTERNAL_SEARCH_ERROR" |
| return tenant{}, dbError{errorCode, reason} |
| } |
| |
| error := db.QueryRow("SELECT env, org, scope FROM DATA_SCOPE where id = ?", scopeuuid).Scan(&env, &org, &tenantId) |
| |
| switch { |
| case error == sql.ErrNoRows: |
| reason := "No tenant found for this scopeuuid: " + scopeuuid |
| errorCode := "UNKNOWN_SCOPE" |
| return tenant{}, dbError{errorCode, reason} |
| case error != nil: |
| reason := error.Error() |
| errorCode := "INTERNAL_SEARCH_ERROR" |
| return tenant{}, dbError{errorCode, reason} |
| } |
| |
| return tenant{Org: org, Env:env, TenantId: tenantId}, dbError{} |
| } |
| // TODO: localTesting |
| //return tenant{Org: "testorg", Env:"testenv", TenantId: "tenantid"}, dbError{} |
| } |
| |
| func getDeveloperInfo(tenantId string, apiKey string) developerInfo { |
| if (config.GetBool(useCaching)) { |
| keyForMap := getKeyForDeveloperInfoCache(tenantId, apiKey) |
| _, exists := developerInfoCache[keyForMap] |
| if !exists { |
| log.Debugf("No data found for for tenantId = %s and apiKey = %s", tenantId, apiKey) |
| return developerInfo{} |
| } else { |
| // acquire a read lock as this cache has 1 writer as well |
| developerInfoCacheLock.RLock() |
| defer developerInfoCacheLock.RUnlock() |
| return developerInfoCache[keyForMap] |
| } |
| } else { |
| var apiProduct, developerApp, developerEmail, developer sql.NullString |
| |
| db := getDB() |
| sSql := "SELECT ap.name, a.name, d.username, d.email " + |
| "FROM APP_CREDENTIAL_APIPRODUCT_MAPPER as mp " + |
| "INNER JOIN API_PRODUCT as ap ON ap.id = mp.apiprdt_id " + |
| "INNER JOIN APP AS a ON a.id = mp.app_id " + |
| "INNER JOIN DEVELOPER as d ON d.id = a.developer_id " + |
| "where mp.tenant_id = ? and mp.appcred_id = ?;" |
| error := db.QueryRow(sSql,tenantId, apiKey).Scan(&apiProduct, &developerApp, &developer, &developerEmail) |
| |
| switch { |
| case error == sql.ErrNoRows: |
| log.Debug("No info found for tenantId : " + tenantId + " and apikey : " + apiKey) |
| return developerInfo{} |
| case error != nil: |
| log.Debug("No info found for tenantId : " + tenantId + " and apikey : " + apiKey + " due to " + error.Error()) |
| return developerInfo{} |
| } |
| |
| apiPrd := getValuesIgnoringNull(apiProduct) |
| devApp := getValuesIgnoringNull(developerApp) |
| dev := getValuesIgnoringNull(developer) |
| devEmail := getValuesIgnoringNull(developerEmail) |
| |
| return developerInfo{ApiProduct: apiPrd, DeveloperApp: devApp, DeveloperEmail: devEmail, Developer: dev} |
| } |
| // TODO: localTesting |
| // return developerInfo{ApiProduct: "testproduct", DeveloperApp: "testapp", DeveloperEmail: "testdeveloper@test.com", Developer: "testdeveloper"} |
| |
| } |
| |
| func getValuesIgnoringNull(sqlValue sql.NullString) string { |
| if sqlValue.Valid { |
| return sqlValue.String |
| } else { |
| return "" |
| } |
| } |
| |
| func getKeyForDeveloperInfoCache(tenantId string, apiKey string) string { |
| return tenantId + "~" + apiKey |
| } |