Skip to content

Commit 6b2d801

Browse files
sarg3ntclaude
andauthored
fix(os-updates): honor active-box cookie via resolveBoxIDFromRequest (#112) (#113)
OSUpdatesPage and the 32 /api/os-updates/* handlers each open-coded the same `r.URL.Query().Get("server")` → `getDefaultServerID()` fallback, ignoring the gearbox_active_box cookie that the header pill writes. The visible symptom was that switching boxes in the header left the OS Updates page (and every package action that fires from it) stuck on the default box. Replace all 33 sites with the existing resolveBoxIDFromRequest helper, which checks ?server= first, then the cookie, then the first enabled server. No behavior change when ?server= is explicit; cookies now win when it isn't. Phase 1 of #112. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c4715a8 commit 6b2d801

1 file changed

Lines changed: 33 additions & 132 deletions

File tree

gearbox/internal/framework/handler/os_updates.go

Lines changed: 33 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ func (h *Handler) OSUpdatesPage(w http.ResponseWriter, r *http.Request) {
2424
}
2525

2626
// Check integration is enabled
27-
boxID := r.URL.Query().Get("server")
28-
if boxID == "" {
29-
boxID = h.getDefaultServerID()
30-
}
27+
boxID := h.resolveBoxIDFromRequest(r)
3128

3229
enabled, _ := h.db.IsGearEnabled(boxID, database.GearOSUpdates)
3330
if !enabled {
@@ -126,10 +123,7 @@ func (h *Handler) OSUpdatesPage(w http.ResponseWriter, r *http.Request) {
126123

127124
// APIUpdateStatusHandler handles GET /api/os-updates/status.
128125
func (h *Handler) APIUpdateStatusHandler(w http.ResponseWriter, r *http.Request) {
129-
boxID := r.URL.Query().Get("server")
130-
if boxID == "" {
131-
boxID = h.getDefaultServerID()
132-
}
126+
boxID := h.resolveBoxIDFromRequest(r)
133127

134128
server, err := h.db.GetBoxByBoxID(boxID)
135129
if err != nil || server == nil {
@@ -154,10 +148,7 @@ func (h *Handler) APIUpdateStatusHandler(w http.ResponseWriter, r *http.Request)
154148

155149
// APIListPackagesHandler handles GET /api/os-updates/packages.
156150
func (h *Handler) APIListPackagesHandler(w http.ResponseWriter, r *http.Request) {
157-
boxID := r.URL.Query().Get("server")
158-
if boxID == "" {
159-
boxID = h.getDefaultServerID()
160-
}
151+
boxID := h.resolveBoxIDFromRequest(r)
161152

162153
server, err := h.db.GetBoxByBoxID(boxID)
163154
if err != nil || server == nil {
@@ -187,10 +178,7 @@ func (h *Handler) APITriggerUpdateCheckHandler(w http.ResponseWriter, r *http.Re
187178
return
188179
}
189180

190-
boxID := r.URL.Query().Get("server")
191-
if boxID == "" {
192-
boxID = h.getDefaultServerID()
193-
}
181+
boxID := h.resolveBoxIDFromRequest(r)
194182

195183
user, _ := auth.GetUserFromContext(r.Context())
196184

@@ -225,10 +213,7 @@ func (h *Handler) APIInstallUpdatesHandler(w http.ResponseWriter, r *http.Reques
225213
return
226214
}
227215

228-
boxID := r.URL.Query().Get("server")
229-
if boxID == "" {
230-
boxID = h.getDefaultServerID()
231-
}
216+
boxID := h.resolveBoxIDFromRequest(r)
232217

233218
streaming := r.URL.Query().Get("stream") == "true"
234219
user, _ := auth.GetUserFromContext(r.Context())
@@ -301,10 +286,7 @@ func (h *Handler) APIInstallUpdatesHandler(w http.ResponseWriter, r *http.Reques
301286

302287
// APIUpdateHistoryHandler handles GET /api/os-updates/history.
303288
func (h *Handler) APIUpdateHistoryHandler(w http.ResponseWriter, r *http.Request) {
304-
boxID := r.URL.Query().Get("server")
305-
if boxID == "" {
306-
boxID = h.getDefaultServerID()
307-
}
289+
boxID := h.resolveBoxIDFromRequest(r)
308290

309291
limit := 50
310292
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
@@ -341,10 +323,7 @@ func (h *Handler) APIScheduleRebootHandler(w http.ResponseWriter, r *http.Reques
341323
return
342324
}
343325

344-
boxID := r.URL.Query().Get("server")
345-
if boxID == "" {
346-
boxID = h.getDefaultServerID()
347-
}
326+
boxID := h.resolveBoxIDFromRequest(r)
348327

349328
user, _ := auth.GetUserFromContext(r.Context())
350329

@@ -396,10 +375,7 @@ func (h *Handler) APICancelRebootHandler(w http.ResponseWriter, r *http.Request)
396375
return
397376
}
398377

399-
boxID := r.URL.Query().Get("server")
400-
if boxID == "" {
401-
boxID = h.getDefaultServerID()
402-
}
378+
boxID := h.resolveBoxIDFromRequest(r)
403379

404380
user, _ := auth.GetUserFromContext(r.Context())
405381

@@ -427,10 +403,7 @@ func (h *Handler) APICancelRebootHandler(w http.ResponseWriter, r *http.Request)
427403

428404
// APIListSnapshotsHandler handles GET /api/os-updates/snapshots.
429405
func (h *Handler) APIListSnapshotsHandler(w http.ResponseWriter, r *http.Request) {
430-
boxID := r.URL.Query().Get("server")
431-
if boxID == "" {
432-
boxID = h.getDefaultServerID()
433-
}
406+
boxID := h.resolveBoxIDFromRequest(r)
434407

435408
server, err := h.db.GetBoxByBoxID(boxID)
436409
if err != nil || server == nil {
@@ -460,10 +433,7 @@ func (h *Handler) APICreateSnapshotHandler(w http.ResponseWriter, r *http.Reques
460433
return
461434
}
462435

463-
boxID := r.URL.Query().Get("server")
464-
if boxID == "" {
465-
boxID = h.getDefaultServerID()
466-
}
436+
boxID := h.resolveBoxIDFromRequest(r)
467437

468438
user, _ := auth.GetUserFromContext(r.Context())
469439

@@ -510,10 +480,7 @@ func (h *Handler) APIRestoreSnapshotHandler(w http.ResponseWriter, r *http.Reque
510480
return
511481
}
512482

513-
boxID := r.URL.Query().Get("server")
514-
if boxID == "" {
515-
boxID = h.getDefaultServerID()
516-
}
483+
boxID := h.resolveBoxIDFromRequest(r)
517484

518485
user, _ := auth.GetUserFromContext(r.Context())
519486

@@ -568,10 +535,7 @@ func (h *Handler) APIDeleteSnapshotHandler(w http.ResponseWriter, r *http.Reques
568535
return
569536
}
570537

571-
boxID := r.URL.Query().Get("server")
572-
if boxID == "" {
573-
boxID = h.getDefaultServerID()
574-
}
538+
boxID := h.resolveBoxIDFromRequest(r)
575539

576540
snapshotID := chi.URLParam(r, "id")
577541
if snapshotID == "" {
@@ -606,10 +570,7 @@ func (h *Handler) APIDeleteSnapshotHandler(w http.ResponseWriter, r *http.Reques
606570

607571
// APIPreviewSnapshotHandler handles GET /api/os-updates/snapshots/{id}/preview.
608572
func (h *Handler) APIPreviewSnapshotHandler(w http.ResponseWriter, r *http.Request) {
609-
boxID := r.URL.Query().Get("server")
610-
if boxID == "" {
611-
boxID = h.getDefaultServerID()
612-
}
573+
boxID := h.resolveBoxIDFromRequest(r)
613574

614575
snapshotID := chi.URLParam(r, "id")
615576
if snapshotID == "" {
@@ -640,10 +601,7 @@ func (h *Handler) APIPreviewSnapshotHandler(w http.ResponseWriter, r *http.Reque
640601

641602
// APIListInstalledPackagesHandler handles GET /api/os-updates/packages/installed.
642603
func (h *Handler) APIListInstalledPackagesHandler(w http.ResponseWriter, r *http.Request) {
643-
boxID := r.URL.Query().Get("server")
644-
if boxID == "" {
645-
boxID = h.getDefaultServerID()
646-
}
604+
boxID := h.resolveBoxIDFromRequest(r)
647605

648606
server, err := h.db.GetBoxByBoxID(boxID)
649607
if err != nil || server == nil {
@@ -668,10 +626,7 @@ func (h *Handler) APIListInstalledPackagesHandler(w http.ResponseWriter, r *http
668626

669627
// APISearchPackagesHandler handles GET /api/os-updates/packages/search.
670628
func (h *Handler) APISearchPackagesHandler(w http.ResponseWriter, r *http.Request) {
671-
boxID := r.URL.Query().Get("server")
672-
if boxID == "" {
673-
boxID = h.getDefaultServerID()
674-
}
629+
boxID := h.resolveBoxIDFromRequest(r)
675630

676631
query := r.URL.Query().Get("q")
677632
if query == "" {
@@ -714,10 +669,7 @@ func (h *Handler) APIInstallPackageHandler(w http.ResponseWriter, r *http.Reques
714669
return
715670
}
716671

717-
boxID := r.URL.Query().Get("server")
718-
if boxID == "" {
719-
boxID = h.getDefaultServerID()
720-
}
672+
boxID := h.resolveBoxIDFromRequest(r)
721673

722674
user, _ := auth.GetUserFromContext(r.Context())
723675

@@ -767,10 +719,7 @@ func (h *Handler) APIRemovePackageHandler(w http.ResponseWriter, r *http.Request
767719
return
768720
}
769721

770-
boxID := r.URL.Query().Get("server")
771-
if boxID == "" {
772-
boxID = h.getDefaultServerID()
773-
}
722+
boxID := h.resolveBoxIDFromRequest(r)
774723

775724
user, _ := auth.GetUserFromContext(r.Context())
776725

@@ -824,10 +773,7 @@ func (h *Handler) APIHoldPackageHandler(w http.ResponseWriter, r *http.Request)
824773
h.jsonError(w, "Forbidden", http.StatusForbidden)
825774
return
826775
}
827-
boxID := r.URL.Query().Get("server")
828-
if boxID == "" {
829-
boxID = h.getDefaultServerID()
830-
}
776+
boxID := h.resolveBoxIDFromRequest(r)
831777
server, err := h.db.GetBoxByBoxID(boxID)
832778
if err != nil || server == nil {
833779
h.jsonError(w, "Server not found", http.StatusNotFound)
@@ -859,10 +805,7 @@ func (h *Handler) APIUnholdPackageHandler(w http.ResponseWriter, r *http.Request
859805
h.jsonError(w, "Forbidden", http.StatusForbidden)
860806
return
861807
}
862-
boxID := r.URL.Query().Get("server")
863-
if boxID == "" {
864-
boxID = h.getDefaultServerID()
865-
}
808+
boxID := h.resolveBoxIDFromRequest(r)
866809
server, err := h.db.GetBoxByBoxID(boxID)
867810
if err != nil || server == nil {
868811
h.jsonError(w, "Server not found", http.StatusNotFound)
@@ -891,10 +834,7 @@ func (h *Handler) APIUnholdPackageHandler(w http.ResponseWriter, r *http.Request
891834

892835
// APIPipxStatusHandler handles GET /api/os-updates/pipx.
893836
func (h *Handler) APIPipxStatusHandler(w http.ResponseWriter, r *http.Request) {
894-
boxID := r.URL.Query().Get("server")
895-
if boxID == "" {
896-
boxID = h.getDefaultServerID()
897-
}
837+
boxID := h.resolveBoxIDFromRequest(r)
898838

899839
server, err := h.db.GetBoxByBoxID(boxID)
900840
if err != nil || server == nil {
@@ -924,10 +864,7 @@ func (h *Handler) APIPipxInstallHandler(w http.ResponseWriter, r *http.Request)
924864
return
925865
}
926866

927-
boxID := r.URL.Query().Get("server")
928-
if boxID == "" {
929-
boxID = h.getDefaultServerID()
930-
}
867+
boxID := h.resolveBoxIDFromRequest(r)
931868

932869
user, _ := auth.GetUserFromContext(r.Context())
933870

@@ -977,10 +914,7 @@ func (h *Handler) APIPipxUninstallHandler(w http.ResponseWriter, r *http.Request
977914
return
978915
}
979916

980-
boxID := r.URL.Query().Get("server")
981-
if boxID == "" {
982-
boxID = h.getDefaultServerID()
983-
}
917+
boxID := h.resolveBoxIDFromRequest(r)
984918

985919
user, _ := auth.GetUserFromContext(r.Context())
986920

@@ -1030,10 +964,7 @@ func (h *Handler) APIPipxUpgradeHandler(w http.ResponseWriter, r *http.Request)
1030964
return
1031965
}
1032966

1033-
boxID := r.URL.Query().Get("server")
1034-
if boxID == "" {
1035-
boxID = h.getDefaultServerID()
1036-
}
967+
boxID := h.resolveBoxIDFromRequest(r)
1037968

1038969
user, _ := auth.GetUserFromContext(r.Context())
1039970

@@ -1086,10 +1017,7 @@ func (h *Handler) APIPipxUpgradeHandler(w http.ResponseWriter, r *http.Request)
10861017

10871018
// APIPipStatusHandler handles GET /api/os-updates/pip.
10881019
func (h *Handler) APIPipStatusHandler(w http.ResponseWriter, r *http.Request) {
1089-
boxID := r.URL.Query().Get("server")
1090-
if boxID == "" {
1091-
boxID = h.getDefaultServerID()
1092-
}
1020+
boxID := h.resolveBoxIDFromRequest(r)
10931021

10941022
server, err := h.db.GetBoxByBoxID(boxID)
10951023
if err != nil || server == nil {
@@ -1119,10 +1047,7 @@ func (h *Handler) APIPipInstallHandler(w http.ResponseWriter, r *http.Request) {
11191047
return
11201048
}
11211049

1122-
boxID := r.URL.Query().Get("server")
1123-
if boxID == "" {
1124-
boxID = h.getDefaultServerID()
1125-
}
1050+
boxID := h.resolveBoxIDFromRequest(r)
11261051

11271052
user, _ := auth.GetUserFromContext(r.Context())
11281053

@@ -1172,10 +1097,7 @@ func (h *Handler) APIPipUninstallHandler(w http.ResponseWriter, r *http.Request)
11721097
return
11731098
}
11741099

1175-
boxID := r.URL.Query().Get("server")
1176-
if boxID == "" {
1177-
boxID = h.getDefaultServerID()
1178-
}
1100+
boxID := h.resolveBoxIDFromRequest(r)
11791101

11801102
user, _ := auth.GetUserFromContext(r.Context())
11811103

@@ -1225,10 +1147,7 @@ func (h *Handler) APIPipUpgradeHandler(w http.ResponseWriter, r *http.Request) {
12251147
return
12261148
}
12271149

1228-
boxID := r.URL.Query().Get("server")
1229-
if boxID == "" {
1230-
boxID = h.getDefaultServerID()
1231-
}
1150+
boxID := h.resolveBoxIDFromRequest(r)
12321151

12331152
user, _ := auth.GetUserFromContext(r.Context())
12341153

@@ -1282,10 +1201,7 @@ func (h *Handler) APIPipUpgradeHandler(w http.ResponseWriter, r *http.Request) {
12821201
// APIPythonToolsVersionsHandler handles GET /api/os-updates/python-tools/versions.
12831202
// This is the slow endpoint that fetches latest PyPI version info for all packages.
12841203
func (h *Handler) APIPythonToolsVersionsHandler(w http.ResponseWriter, r *http.Request) {
1285-
boxID := r.URL.Query().Get("server")
1286-
if boxID == "" {
1287-
boxID = h.getDefaultServerID()
1288-
}
1204+
boxID := h.resolveBoxIDFromRequest(r)
12891205

12901206
server, err := h.db.GetBoxByBoxID(boxID)
12911207
if err != nil || server == nil {
@@ -1365,10 +1281,7 @@ func (h *Handler) APIPyPILookupHandler(w http.ResponseWriter, r *http.Request) {
13651281

13661282
// APIUnattendedConfigHandler handles GET /api/os-updates/unattended.
13671283
func (h *Handler) APIUnattendedConfigHandler(w http.ResponseWriter, r *http.Request) {
1368-
boxID := r.URL.Query().Get("server")
1369-
if boxID == "" {
1370-
boxID = h.getDefaultServerID()
1371-
}
1284+
boxID := h.resolveBoxIDFromRequest(r)
13721285

13731286
server, err := h.db.GetBoxByBoxID(boxID)
13741287
if err != nil || server == nil {
@@ -1398,10 +1311,7 @@ func (h *Handler) APIConfigureUnattendedHandler(w http.ResponseWriter, r *http.R
13981311
return
13991312
}
14001313

1401-
boxID := r.URL.Query().Get("server")
1402-
if boxID == "" {
1403-
boxID = h.getDefaultServerID()
1404-
}
1314+
boxID := h.resolveBoxIDFromRequest(r)
14051315

14061316
user, _ := auth.GetUserFromContext(r.Context())
14071317

@@ -1443,10 +1353,7 @@ func (h *Handler) APIConfigureUnattendedHandler(w http.ResponseWriter, r *http.R
14431353
// APIGetOperationHandler handles GET /api/os-updates/operation/{id}.
14441354
// Proxies to the agent's operation status endpoint for polling fallback.
14451355
func (h *Handler) APIGetOperationHandler(w http.ResponseWriter, r *http.Request) {
1446-
boxID := r.URL.Query().Get("server")
1447-
if boxID == "" {
1448-
boxID = h.getDefaultServerID()
1449-
}
1356+
boxID := h.resolveBoxIDFromRequest(r)
14501357

14511358
operationID := chi.URLParam(r, "id")
14521359
if operationID == "" {
@@ -1477,10 +1384,7 @@ func (h *Handler) APIGetOperationHandler(w http.ResponseWriter, r *http.Request)
14771384

14781385
// APIListUpdateLogsHandler handles GET /api/os-updates/logs.
14791386
func (h *Handler) APIListUpdateLogsHandler(w http.ResponseWriter, r *http.Request) {
1480-
boxID := r.URL.Query().Get("server")
1481-
if boxID == "" {
1482-
boxID = h.getDefaultServerID()
1483-
}
1387+
boxID := h.resolveBoxIDFromRequest(r)
14841388

14851389
limit := 50
14861390
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
@@ -1512,10 +1416,7 @@ func (h *Handler) APIListUpdateLogsHandler(w http.ResponseWriter, r *http.Reques
15121416

15131417
// APIGetUpdateLogHandler handles GET /api/os-updates/logs/{id}.
15141418
func (h *Handler) APIGetUpdateLogHandler(w http.ResponseWriter, r *http.Request) {
1515-
boxID := r.URL.Query().Get("server")
1516-
if boxID == "" {
1517-
boxID = h.getDefaultServerID()
1518-
}
1419+
boxID := h.resolveBoxIDFromRequest(r)
15191420

15201421
logID := chi.URLParam(r, "id")
15211422
if logID == "" {

0 commit comments

Comments
 (0)