Small fixes for access cache in nb

pull/787/head
kompotkot 2023-05-25 11:19:46 +00:00
rodzic bfdc2eb718
commit 43d7e4a807
4 zmienionych plików z 91 dodań i 28 usunięć

Wyświetl plik

@ -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()
}
}
}

Wyświetl plik

@ -1,4 +1,3 @@
// TODO(kompotkot): Re-write tests for client
package main
import (
@ -7,7 +6,7 @@ import (
"time"
)
func setupSuit(t *testing.T) func(t *testing.T) {
func clientsSetupSuit(t *testing.T) func(t *testing.T) {
t.Log("Setup suit")
supportedBlockchains = map[string]bool{"ethereum": true}
@ -18,7 +17,7 @@ func setupSuit(t *testing.T) func(t *testing.T) {
}
func TestAddClientNode(t *testing.T) {
teardownSuit := setupSuit(t)
teardownSuit := clientsSetupSuit(t)
defer teardownSuit(t)
var cases = []struct {
@ -44,7 +43,7 @@ func TestAddClientNode(t *testing.T) {
}
func TestGetClientNode(t *testing.T) {
teardownSuit := setupSuit(t)
teardownSuit := clientsSetupSuit(t)
defer teardownSuit(t)
ts := time.Now().Unix()
@ -75,7 +74,7 @@ func TestGetClientNode(t *testing.T) {
}
func TestCleanInactiveClientNodes(t *testing.T) {
teardownSuit := setupSuit(t)
teardownSuit := clientsSetupSuit(t)
defer teardownSuit(t)
ts := time.Now().Unix()

Wyświetl plik

@ -103,7 +103,13 @@ func (ac *AccessCache) UpdateAccessAtCache(accessId, authorizationToken, request
}
// 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()
access := &ClientAccess{
ResourceID: clientAccess.ResourceID,
@ -137,6 +143,8 @@ func (ac *AccessCache) AddAccessToCache(clientAccess ClientAccess, tsNow int64)
ac.authorizationTokens[clientAccess.authorizationToken] = access
}
ac.mux.Unlock()
return nil
}
// 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
func fetchResource(accessID, authorizationToken string, tsNow int64) (*brood.Resource, error) {
// fetchClientAccessFromResources get resources with access ID or authorization token and generate new one if there no one
func fetchClientAccessFromResources(accessID, authorizationToken string, tsNow int64) (*ClientAccess, error) {
var err error
var resources brood.Resources
queryParameters := map[string]string{"type": BUGOUT_RESOURCE_TYPE_NODEBALANCER_ACCESS}
if accessID != "" {
@ -215,6 +222,7 @@ func fetchResource(accessID, authorizationToken string, tsNow int64) (*brood.Res
token = authorizationToken
}
var resources brood.Resources
resources, err = bugoutClient.Brood.GetResources(
token,
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 &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.
@ -445,13 +466,13 @@ func accessMiddleware(next http.Handler) http.Handler {
authorizationToken = authorizationTokenSlice[1]
}
tsNow := time.Now().Unix()
if accessID == "" && authorizationToken == "" {
http.Error(w, "No access ID or authorization header passed with request", http.StatusForbidden)
return
}
tsNow := time.Now().Unix()
// 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 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")
}
resource, err := fetchResource(accessID, authorizationToken, tsNow)
clientAccessRaw, err := fetchClientAccessFromResources(accessID, authorizationToken, tsNow)
if err != nil {
http.Error(w, fmt.Sprintf("%v", err), http.StatusForbidden)
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)
if !isClientAllowedToGetAccess {
http.Error(w, "User exceeded limit of calls per period", http.StatusForbidden)
return
}
currentClientAccess = ClientAccess(clientAccessRaw)
currentClientAccess.ResourceID = resource.Id
currentClientAccess = ClientAccess(*clientAccessRaw)
currentClientAccess.authorizationToken = authorizationToken
currentClientAccess.requestedDataSource = requestedDataSource
@ -525,7 +533,11 @@ func accessMiddleware(next http.Handler) http.Handler {
if stateCLI.enableDebugFlag {
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
}
}
}

Wyświetl plik

@ -6,3 +6,6 @@ export NB_CONTROLLER_ACCESS_ID="<controller_access_id_for_internal_usage>"
# Error humbug reporter
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>"