Skip to content

Commit 29693dd

Browse files
committed
fix: disable caching for slack management api
1 parent 446ec33 commit 29693dd

2 files changed

Lines changed: 51 additions & 14 deletions

File tree

integrations/slack-gateway/gateway_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,38 @@ func TestWorkspaceManagementRendersManagedInstallations(t *testing.T) {
398398
}
399399
}
400400

401+
func TestWorkspaceManagementAPIWritesNoStore(t *testing.T) {
402+
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
403+
if r.URL.Path != "/internal/v2/spritz/channel-installations/list" {
404+
t.Fatalf("unexpected backend path %s", r.URL.Path)
405+
}
406+
writeJSON(w, http.StatusOK, map[string]any{
407+
"status": "resolved",
408+
"installations": []map[string]any{},
409+
})
410+
}))
411+
defer backend.Close()
412+
413+
gateway := newSlackGateway(config{
414+
BackendFastAPIBaseURL: backend.URL,
415+
BackendInternalToken: "backend-internal-token",
416+
PrincipalID: "shared-slack-gateway",
417+
HTTPTimeout: 5 * time.Second,
418+
}, slog.New(slog.NewTextHandler(io.Discard, nil)))
419+
420+
req := httptest.NewRequest(http.MethodGet, "/api/slack/workspaces", nil)
421+
req.Header.Set("X-Spritz-User-Id", "user-1")
422+
rec := httptest.NewRecorder()
423+
gateway.routes().ServeHTTP(rec, req)
424+
425+
if rec.Code != http.StatusOK {
426+
t.Fatalf("expected 200, got %d: %s", rec.Code, rec.Body.String())
427+
}
428+
if cacheControl := rec.Header().Get("Cache-Control"); cacheControl != "no-store" {
429+
t.Fatalf("expected no-store cache policy, got %q", cacheControl)
430+
}
431+
}
432+
401433
func TestChannelSettingsRendersManagedConnections(t *testing.T) {
402434
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
403435
if r.URL.Path != "/internal/v2/spritz/channel-installations/list" {

integrations/slack-gateway/management_api.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,17 @@ type channelRoutesUpdateRequest struct {
5757
}
5858

5959
func writeAPIError(w http.ResponseWriter, status int, message string) {
60-
writeJSON(w, status, slackGatewayErrorResponse{
60+
writeAPIJSON(w, status, slackGatewayErrorResponse{
6161
Status: "error",
6262
Message: strings.TrimSpace(message),
6363
})
6464
}
6565

66+
func writeAPIJSON(w http.ResponseWriter, status int, payload any) {
67+
w.Header().Set("Cache-Control", "no-store")
68+
writeJSON(w, status, payload)
69+
}
70+
6671
func decodeJSONRequest(r *http.Request, target any) error {
6772
decoder := json.NewDecoder(r.Body)
6873
decoder.DisallowUnknownFields()
@@ -100,7 +105,7 @@ func (g *slackGateway) handleInstallTargetSelectionAPIGet(w http.ResponseWriter,
100105
writeAPIError(w, http.StatusBadGateway, "install targets unavailable")
101106
return
102107
}
103-
writeJSON(w, http.StatusOK, installSelectionResponse{
108+
writeAPIJSON(w, http.StatusOK, installSelectionResponse{
104109
Status: "resolved",
105110
RequestID: pendingInstall.RequestID,
106111
TeamID: pendingInstall.Installation.TeamID,
@@ -152,7 +157,7 @@ func (g *slackGateway) handleInstallTargetSelectionAPIPost(w http.ResponseWriter
152157
return
153158
}
154159
g.clearPendingInstallCookie(w, r)
155-
writeJSON(w, http.StatusOK, map[string]any{
160+
writeAPIJSON(w, http.StatusOK, map[string]any{
156161
"status": "installed",
157162
"requestId": requestID,
158163
"teamId": installation.TeamID,
@@ -177,7 +182,7 @@ func (g *slackGateway) writeInstallResultAPI(w http.ResponseWriter, status int,
177182
if result.Status == installResultStatusSuccess && result.Code == installResultCodeInternalError {
178183
descriptor = installResultDescriptorFor(installResultCodeInstalled, g.installRedirectPath())
179184
}
180-
writeJSON(w, status, map[string]any{
185+
writeAPIJSON(w, status, map[string]any{
181186
"status": result.Status,
182187
"code": result.Code,
183188
"operation": result.Operation,
@@ -212,7 +217,7 @@ func (g *slackGateway) handleWorkspaceManagementAPI(w http.ResponseWriter, r *ht
212217
writeAPIError(w, http.StatusBadGateway, "workspace list unavailable")
213218
return
214219
}
215-
writeJSON(w, http.StatusOK, map[string]any{
220+
writeAPIJSON(w, http.StatusOK, map[string]any{
216221
"status": "resolved",
217222
"installations": installations,
218223
})
@@ -253,7 +258,7 @@ func (g *slackGateway) handleWorkspaceTargetAPIGet(w http.ResponseWriter, r *htt
253258
writeAPIError(w, http.StatusBadGateway, "workspace targets unavailable")
254259
return
255260
}
256-
writeJSON(w, http.StatusOK, map[string]any{
261+
writeAPIJSON(w, http.StatusOK, map[string]any{
257262
"status": "resolved",
258263
"teamId": teamID,
259264
"requestId": requestID,
@@ -293,7 +298,7 @@ func (g *slackGateway) handleWorkspaceTargetAPIPost(w http.ResponseWriter, r *ht
293298
writeAPIError(w, http.StatusBadGateway, "workspace target update failed")
294299
return
295300
}
296-
writeJSON(w, http.StatusOK, map[string]any{
301+
writeAPIJSON(w, http.StatusOK, map[string]any{
297302
"status": "updated",
298303
"teamId": teamID,
299304
"requestId": requestID,
@@ -330,7 +335,7 @@ func (g *slackGateway) handleWorkspaceDisconnectAPI(w http.ResponseWriter, r *ht
330335
writeAPIError(w, http.StatusBadGateway, "workspace disconnect failed")
331336
return
332337
}
333-
writeJSON(w, http.StatusOK, map[string]any{
338+
writeAPIJSON(w, http.StatusOK, map[string]any{
334339
"status": "disconnected",
335340
"teamId": teamID,
336341
})
@@ -383,7 +388,7 @@ func (g *slackGateway) handleWorkspaceTestAPI(w http.ResponseWriter, r *http.Req
383388
return
384389
}
385390
if !process {
386-
writeJSON(w, http.StatusOK, workspaceTestResponse{
391+
writeAPIJSON(w, http.StatusOK, workspaceTestResponse{
387392
Status: "resolved",
388393
Outcome: messageEventOutcomeIgnored,
389394
})
@@ -406,7 +411,7 @@ func (g *slackGateway) handleWorkspaceTestAPI(w http.ResponseWriter, r *http.Req
406411
writeAPIError(w, http.StatusBadGateway, err.Error())
407412
return
408413
}
409-
writeJSON(w, http.StatusOK, workspaceTestResponse{
414+
writeAPIJSON(w, http.StatusOK, workspaceTestResponse{
410415
Status: "resolved",
411416
Outcome: result.Outcome,
412417
Reply: result.Reply,
@@ -439,7 +444,7 @@ func (g *slackGateway) handleChannelSettingsAPI(w http.ResponseWriter, r *http.R
439444
writeAPIError(w, http.StatusMethodNotAllowed, "method not allowed")
440445
return
441446
}
442-
writeJSON(w, http.StatusOK, map[string]any{
447+
writeAPIJSON(w, http.StatusOK, map[string]any{
443448
"status": "resolved",
444449
"installations": installations,
445450
})
@@ -453,7 +458,7 @@ func (g *slackGateway) handleChannelSettingsAPI(w http.ResponseWriter, r *http.R
453458
}
454459
for _, installation := range installations {
455460
if strings.TrimSpace(installation.ID) == installationID {
456-
writeJSON(w, http.StatusOK, map[string]any{
461+
writeAPIJSON(w, http.StatusOK, map[string]any{
457462
"status": "resolved",
458463
"installation": installation,
459464
})
@@ -475,7 +480,7 @@ func (g *slackGateway) handleChannelSettingsAPI(w http.ResponseWriter, r *http.R
475480
}
476481
switch r.Method {
477482
case http.MethodGet:
478-
writeJSON(w, http.StatusOK, map[string]any{
483+
writeAPIJSON(w, http.StatusOK, map[string]any{
479484
"status": "resolved",
480485
"installation": installation,
481486
"connection": connection,
@@ -544,7 +549,7 @@ func (g *slackGateway) handleChannelSettingsAPIUpdate(
544549
return
545550
}
546551
g.policies.forget(installation.Route.ExternalTenantID)
547-
writeJSON(w, http.StatusOK, map[string]any{
552+
writeAPIJSON(w, http.StatusOK, map[string]any{
548553
"status": "updated",
549554
"installation": installation.ID,
550555
"connection": connection.ID,

0 commit comments

Comments
 (0)