Skip to content

Commit 0984be8

Browse files
committed
fix cache key; change ttl
Signed-off-by: Sylwester Piskozub <sylwesterpiskozub@gmail.com>
1 parent 580a095 commit 0984be8

2 files changed

Lines changed: 38 additions & 3 deletions

File tree

app/controlplane/internal/usercontext/operation_authorization_middleware.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ func WithOperationAuthorizationMiddleware(conf *conf.OperationAuthorizationProvi
6161
client := &http.Client{Timeout: 5 * time.Second}
6262
url := conf.GetUrl()
6363

64-
// LRU cache with 30s TTL keyed by "user_id:operation"
64+
// LRU cache with 10s TTL keyed by "user_id:org_id:operation"
6565
authCache, err := cache.New[*operationAuthResponse](
66-
cache.WithTTL(30*time.Second),
66+
cache.WithTTL(10*time.Second),
6767
cache.WithDescription("Operation authorization cache"),
6868
)
6969
if err != nil {
@@ -93,7 +93,7 @@ func WithOperationAuthorizationMiddleware(conf *conf.OperationAuthorizationProvi
9393
orgID = org.ID
9494
}
9595

96-
cacheKey := fmt.Sprintf("%s:%s", user.ID, operation)
96+
cacheKey := fmt.Sprintf("%s:%s:%s", user.ID, orgID, operation)
9797

9898
// Check cache
9999
if authCache != nil {

app/controlplane/internal/usercontext/operation_authorization_middleware_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,41 @@ func TestWithOperationAuthorizationMiddleware(t *testing.T) {
154154
assert.Contains(t, err.Error(), "unable to verify operation authorization")
155155
})
156156

157+
t.Run("cache key includes orgID so different orgs are not conflated", func(t *testing.T) {
158+
var callCount atomic.Int32
159+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
160+
callCount.Add(1)
161+
var req operationAuthRequest
162+
require.NoError(t, json.NewDecoder(r.Body).Decode(&req))
163+
164+
allowed := req.OrganizationID == "org-allowed"
165+
w.Header().Set("Content-Type", "application/json")
166+
json.NewEncoder(w).Encode(operationAuthResponse{Allowed: allowed, Reason: "denied for this org"}) //nolint:errcheck
167+
}))
168+
defer srv.Close()
169+
170+
cfg := &conf.OperationAuthorizationProvider{Enabled: true, Url: srv.URL}
171+
m := WithOperationAuthorizationMiddleware(cfg, logHelper)
172+
173+
baseCtx := ctxWithOperation(context.Background(), "/controlplane.v1.OrganizationService/Create")
174+
baseCtx = entities.WithCurrentUser(baseCtx, &entities.User{ID: "user-org-test"})
175+
176+
// Call with org-allowed -> should succeed and be cached
177+
ctxAllowed := entities.WithCurrentOrg(baseCtx, &entities.Org{ID: "org-allowed"})
178+
result, err := m(passHandler)(ctxAllowed, nil)
179+
require.NoError(t, err)
180+
assert.Equal(t, "ok", result)
181+
assert.Equal(t, int32(1), callCount.Load())
182+
183+
// Call with org-denied -> must NOT reuse the cached "allowed" result
184+
ctxDenied := entities.WithCurrentOrg(baseCtx, &entities.Org{ID: "org-denied"})
185+
result, err = m(passHandler)(ctxDenied, nil)
186+
require.Error(t, err)
187+
assert.Nil(t, result)
188+
assert.Contains(t, err.Error(), "denied for this org")
189+
assert.Equal(t, int32(2), callCount.Load(), "expected a second HTTP call for a different org")
190+
})
191+
157192
t.Run("cache hit skips HTTP call", func(t *testing.T) {
158193
var callCount atomic.Int32
159194
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {

0 commit comments

Comments
 (0)