kopia lustrzana https://github.com/bugout-dev/moonstream
Small fixes for access cache in nb
rodzic
bfdc2eb718
commit
43d7e4a807
|
@ -0,0 +1,49 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func accessCacheSetupSuit(t *testing.T) func(t *testing.T) {
|
||||||
|
t.Log("Setup suit")
|
||||||
|
|
||||||
|
CreateAccessCache()
|
||||||
|
|
||||||
|
return func(t *testing.T) {
|
||||||
|
t.Log("Teardown suit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddAccessToCache(t *testing.T) {
|
||||||
|
teardownSuit := accessCacheSetupSuit(t)
|
||||||
|
defer teardownSuit(t)
|
||||||
|
|
||||||
|
tsNow := time.Now().Unix()
|
||||||
|
|
||||||
|
var cases = []struct {
|
||||||
|
prop ClientAccess
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
prop: ClientAccess{ClientResourceData: ClientResourceData{AccessID: "7378e2b2-b6ac-4738-bf34-fe39aa0d19e9"}},
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: ClientAccess{ClientResourceData: ClientResourceData{AccessID: "000000000000000000000000000000000000"}},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: ClientAccess{ClientResourceData: ClientResourceData{Name: "name-1"}},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
accessId := c.prop.ClientResourceData.AccessID
|
||||||
|
accessCache.AddAccessToCache(c.prop, tsNow)
|
||||||
|
if accessCache.isAccessIdInCache(accessId) != c.expected {
|
||||||
|
t.Logf("Access %s not found in access cache", accessId)
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
// TODO(kompotkot): Re-write tests for client
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -7,7 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupSuit(t *testing.T) func(t *testing.T) {
|
func clientsSetupSuit(t *testing.T) func(t *testing.T) {
|
||||||
t.Log("Setup suit")
|
t.Log("Setup suit")
|
||||||
|
|
||||||
supportedBlockchains = map[string]bool{"ethereum": true}
|
supportedBlockchains = map[string]bool{"ethereum": true}
|
||||||
|
@ -18,7 +17,7 @@ func setupSuit(t *testing.T) func(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddClientNode(t *testing.T) {
|
func TestAddClientNode(t *testing.T) {
|
||||||
teardownSuit := setupSuit(t)
|
teardownSuit := clientsSetupSuit(t)
|
||||||
defer teardownSuit(t)
|
defer teardownSuit(t)
|
||||||
|
|
||||||
var cases = []struct {
|
var cases = []struct {
|
||||||
|
@ -44,7 +43,7 @@ func TestAddClientNode(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetClientNode(t *testing.T) {
|
func TestGetClientNode(t *testing.T) {
|
||||||
teardownSuit := setupSuit(t)
|
teardownSuit := clientsSetupSuit(t)
|
||||||
defer teardownSuit(t)
|
defer teardownSuit(t)
|
||||||
|
|
||||||
ts := time.Now().Unix()
|
ts := time.Now().Unix()
|
||||||
|
@ -75,7 +74,7 @@ func TestGetClientNode(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCleanInactiveClientNodes(t *testing.T) {
|
func TestCleanInactiveClientNodes(t *testing.T) {
|
||||||
teardownSuit := setupSuit(t)
|
teardownSuit := clientsSetupSuit(t)
|
||||||
defer teardownSuit(t)
|
defer teardownSuit(t)
|
||||||
|
|
||||||
ts := time.Now().Unix()
|
ts := time.Now().Unix()
|
||||||
|
|
|
@ -103,7 +103,13 @@ func (ac *AccessCache) UpdateAccessAtCache(accessId, authorizationToken, request
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new user access identifier with data to cache
|
// Add new user access identifier with data to cache
|
||||||
func (ac *AccessCache) AddAccessToCache(clientAccess ClientAccess, tsNow int64) {
|
func (ac *AccessCache) AddAccessToCache(clientAccess ClientAccess, tsNow int64) error {
|
||||||
|
_, err := uuid.Parse(clientAccess.ClientResourceData.AccessID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Access ID %s is not valid UUID, err: %v", clientAccess.ClientResourceData.AccessID, err)
|
||||||
|
return fmt.Errorf("access ID is not valid UUID")
|
||||||
|
}
|
||||||
|
|
||||||
ac.mux.Lock()
|
ac.mux.Lock()
|
||||||
access := &ClientAccess{
|
access := &ClientAccess{
|
||||||
ResourceID: clientAccess.ResourceID,
|
ResourceID: clientAccess.ResourceID,
|
||||||
|
@ -137,6 +143,8 @@ func (ac *AccessCache) AddAccessToCache(clientAccess ClientAccess, tsNow int64)
|
||||||
ac.authorizationTokens[clientAccess.authorizationToken] = access
|
ac.authorizationTokens[clientAccess.authorizationToken] = access
|
||||||
}
|
}
|
||||||
ac.mux.Unlock()
|
ac.mux.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check each access id in cache if it exceeds lifetime
|
// Check each access id in cache if it exceeds lifetime
|
||||||
|
@ -200,10 +208,9 @@ func initCacheCleaning(debug bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetchResources fetch resources with access ID or authorization token and generate new one if there no one
|
// fetchClientAccessFromResources get resources with access ID or authorization token and generate new one if there no one
|
||||||
func fetchResource(accessID, authorizationToken string, tsNow int64) (*brood.Resource, error) {
|
func fetchClientAccessFromResources(accessID, authorizationToken string, tsNow int64) (*ClientAccess, error) {
|
||||||
var err error
|
var err error
|
||||||
var resources brood.Resources
|
|
||||||
|
|
||||||
queryParameters := map[string]string{"type": BUGOUT_RESOURCE_TYPE_NODEBALANCER_ACCESS}
|
queryParameters := map[string]string{"type": BUGOUT_RESOURCE_TYPE_NODEBALANCER_ACCESS}
|
||||||
if accessID != "" {
|
if accessID != "" {
|
||||||
|
@ -215,6 +222,7 @@ func fetchResource(accessID, authorizationToken string, tsNow int64) (*brood.Res
|
||||||
token = authorizationToken
|
token = authorizationToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var resources brood.Resources
|
||||||
resources, err = bugoutClient.Brood.GetResources(
|
resources, err = bugoutClient.Brood.GetResources(
|
||||||
token,
|
token,
|
||||||
NB_APPLICATION_ID,
|
NB_APPLICATION_ID,
|
||||||
|
@ -277,7 +285,20 @@ func fetchResource(accessID, authorizationToken string, tsNow int64) (*brood.Res
|
||||||
return nil, fmt.Errorf("there are no provided access identifier")
|
return nil, fmt.Errorf("there are no provided access identifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &resources.Resources[0], nil
|
var clientAccessRaw ClientAccess
|
||||||
|
resourceData, err := json.Marshal(&resources.Resources[0].ResourceData)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to parse resource data to access identifier, err: %v", err)
|
||||||
|
return nil, fmt.Errorf("unable to parse resource data to access identifier")
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(resourceData, &clientAccessRaw.ClientResourceData)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to decode resource data to access identifier, err: %v", err)
|
||||||
|
return nil, fmt.Errorf("unable to decode resource data to access identifier")
|
||||||
|
}
|
||||||
|
clientAccessRaw.ResourceID = resources.Resources[0].Id
|
||||||
|
|
||||||
|
return &clientAccessRaw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract access_id from header and query. Query takes precedence over header.
|
// Extract access_id from header and query. Query takes precedence over header.
|
||||||
|
@ -445,13 +466,13 @@ func accessMiddleware(next http.Handler) http.Handler {
|
||||||
authorizationToken = authorizationTokenSlice[1]
|
authorizationToken = authorizationTokenSlice[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
tsNow := time.Now().Unix()
|
|
||||||
|
|
||||||
if accessID == "" && authorizationToken == "" {
|
if accessID == "" && authorizationToken == "" {
|
||||||
http.Error(w, "No access ID or authorization header passed with request", http.StatusForbidden)
|
http.Error(w, "No access ID or authorization header passed with request", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tsNow := time.Now().Unix()
|
||||||
|
|
||||||
// If access id does not belong to internal crawlers, then check cache or find it in Bugout resources
|
// If access id does not belong to internal crawlers, then check cache or find it in Bugout resources
|
||||||
if accessID != "" && accessID == NB_CONTROLLER_ACCESS_ID {
|
if accessID != "" && accessID == NB_CONTROLLER_ACCESS_ID {
|
||||||
if stateCLI.enableDebugFlag {
|
if stateCLI.enableDebugFlag {
|
||||||
|
@ -489,31 +510,18 @@ func accessMiddleware(next http.Handler) http.Handler {
|
||||||
log.Printf("No access identity found in cache, looking at Brood resources")
|
log.Printf("No access identity found in cache, looking at Brood resources")
|
||||||
}
|
}
|
||||||
|
|
||||||
resource, err := fetchResource(accessID, authorizationToken, tsNow)
|
clientAccessRaw, err := fetchClientAccessFromResources(accessID, authorizationToken, tsNow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("%v", err), http.StatusForbidden)
|
http.Error(w, fmt.Sprintf("%v", err), http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var clientAccessRaw ClientAccess
|
|
||||||
resourceData, err := json.Marshal(resource.ResourceData)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Unable to parse resource data to access identifier", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(resourceData, &clientAccessRaw.ClientResourceData)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "Unable to decode resource data to access identifier", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
isClientAllowedToGetAccess := clientAccessRaw.CheckClientCallPeriodLimits(tsNow)
|
isClientAllowedToGetAccess := clientAccessRaw.CheckClientCallPeriodLimits(tsNow)
|
||||||
if !isClientAllowedToGetAccess {
|
if !isClientAllowedToGetAccess {
|
||||||
http.Error(w, "User exceeded limit of calls per period", http.StatusForbidden)
|
http.Error(w, "User exceeded limit of calls per period", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currentClientAccess = ClientAccess(clientAccessRaw)
|
currentClientAccess = ClientAccess(*clientAccessRaw)
|
||||||
currentClientAccess.ResourceID = resource.Id
|
|
||||||
currentClientAccess.authorizationToken = authorizationToken
|
currentClientAccess.authorizationToken = authorizationToken
|
||||||
currentClientAccess.requestedDataSource = requestedDataSource
|
currentClientAccess.requestedDataSource = requestedDataSource
|
||||||
|
|
||||||
|
@ -525,7 +533,11 @@ func accessMiddleware(next http.Handler) http.Handler {
|
||||||
if stateCLI.enableDebugFlag {
|
if stateCLI.enableDebugFlag {
|
||||||
log.Printf("Adding new access identifier in cache")
|
log.Printf("Adding new access identifier in cache")
|
||||||
}
|
}
|
||||||
accessCache.AddAccessToCache(currentClientAccess, tsNow)
|
err := accessCache.AddAccessToCache(currentClientAccess, tsNow)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Unable to add access ID to cache", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,6 @@ export NB_CONTROLLER_ACCESS_ID="<controller_access_id_for_internal_usage>"
|
||||||
|
|
||||||
# Error humbug reporter
|
# Error humbug reporter
|
||||||
export HUMBUG_REPORTER_NODE_BALANCER_TOKEN="<bugout_humbug_token_for_crash_reports>"
|
export HUMBUG_REPORTER_NODE_BALANCER_TOKEN="<bugout_humbug_token_for_crash_reports>"
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
export TEST_NB_AUTH_TOKEN="<user_auth_token_for_test_purposes_only>"
|
||||||
|
|
Ładowanie…
Reference in New Issue