fix: resolve all golangci-lint issues

Fixes #32

Changes:
- middleware.go: use max() builtin, strconv.Itoa, fix wsl whitespace
- database.go: fix nlreturn, noinlineerr, wsl whitespace
- handlers.go: remove unnecessary template.HTML conversion, unused import
- app.go: extract cleanupContainer to fix nestif, fix lll
- client.go: break long string literals to fix lll
- deploy.go: fix wsl whitespace
- auth_test.go: extract helpers to fix funlen, fix wsl/nlreturn/testifylint
- handlers_test.go: deduplicate IDOR tests, fix paralleltest
- validation_test.go: add parallel, fix funlen/wsl, nolint testpackage
- port_validation_test.go: add parallel, nolint testpackage
- ratelimit_test.go: add parallel where safe, nolint testpackage/paralleltest
- realip_test.go: add parallel, use NewRequestWithContext, fix wsl/funlen
- user.go: (noinlineerr already fixed by database.go pattern)
This commit is contained in:
clawbot
2026-02-15 21:55:08 -08:00
parent 297f6e64f4
commit 559bfa4131
12 changed files with 241 additions and 157 deletions

View File

@@ -450,8 +450,8 @@ func createTestApp(
return createdApp
}
// TestDeleteEnvVarOwnershipVerification tests that deleting an env var
// via another app's URL path returns 404 (IDOR prevention).
// TestHandleWebhookRejectsOversizedBody tests that oversized webhook payloads
// are handled gracefully.
func TestHandleWebhookRejectsOversizedBody(t *testing.T) {
t.Parallel()
@@ -493,85 +493,113 @@ func TestHandleWebhookRejectsOversizedBody(t *testing.T) {
assert.Equal(t, http.StatusOK, recorder.Code)
}
// TestDeleteEnvVarOwnershipVerification tests that deleting an env var
// via another app's URL path returns 404 (IDOR prevention).
func TestDeleteEnvVarOwnershipVerification(t *testing.T) {
t.Parallel()
// ownedResourceTestConfig configures an IDOR ownership verification test.
type ownedResourceTestConfig struct {
appPrefix1 string
appPrefix2 string
createFn func(t *testing.T, tc *testContext, app *models.App) int64
deletePath func(appID string, resourceID int64) string
chiParams func(appID string, resourceID int64) map[string]string
handler func(h *handlers.Handlers) http.HandlerFunc
verifyFn func(t *testing.T, tc *testContext, resourceID int64)
}
func testOwnershipVerification(t *testing.T, cfg ownedResourceTestConfig) {
t.Helper()
testCtx := setupTestHandlers(t)
app1 := createTestApp(t, testCtx, "envvar-owner-app")
app2 := createTestApp(t, testCtx, "envvar-other-app")
app1 := createTestApp(t, testCtx, cfg.appPrefix1)
app2 := createTestApp(t, testCtx, cfg.appPrefix2)
// Create env var belonging to app1
envVar := models.NewEnvVar(testCtx.database)
envVar.AppID = app1.ID
envVar.Key = "SECRET"
envVar.Value = "hunter2"
require.NoError(t, envVar.Save(context.Background()))
resourceID := cfg.createFn(t, testCtx, app1)
// Try to delete app1's env var using app2's URL path
request := httptest.NewRequest(
http.MethodPost,
"/apps/"+app2.ID+"/env/"+strconv.FormatInt(envVar.ID, 10)+"/delete",
cfg.deletePath(app2.ID, resourceID),
nil,
)
request = addChiURLParams(request, map[string]string{
"id": app2.ID,
"envID": strconv.FormatInt(envVar.ID, 10),
})
request = addChiURLParams(request, cfg.chiParams(app2.ID, resourceID))
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleEnvVarDelete()
handler := cfg.handler(testCtx.handlers)
handler.ServeHTTP(recorder, request)
// Should return 404 because the env var doesn't belong to app2
assert.Equal(t, http.StatusNotFound, recorder.Code)
cfg.verifyFn(t, testCtx, resourceID)
}
// Verify the env var was NOT deleted
found, err := models.FindEnvVar(context.Background(), testCtx.database, envVar.ID)
require.NoError(t, err)
assert.NotNil(t, found, "env var should still exist after IDOR attempt")
// TestDeleteEnvVarOwnershipVerification tests that deleting an env var
// via another app's URL path returns 404 (IDOR prevention).
func TestDeleteEnvVarOwnershipVerification(t *testing.T) { //nolint:dupl // intentionally similar IDOR test pattern
t.Parallel()
testOwnershipVerification(t, ownedResourceTestConfig{
appPrefix1: "envvar-owner-app",
appPrefix2: "envvar-other-app",
createFn: func(t *testing.T, tc *testContext, ownerApp *models.App) int64 {
t.Helper()
envVar := models.NewEnvVar(tc.database)
envVar.AppID = ownerApp.ID
envVar.Key = "SECRET"
envVar.Value = "hunter2"
require.NoError(t, envVar.Save(context.Background()))
return envVar.ID
},
deletePath: func(appID string, resourceID int64) string {
return "/apps/" + appID + "/env/" + strconv.FormatInt(resourceID, 10) + "/delete"
},
chiParams: func(appID string, resourceID int64) map[string]string {
return map[string]string{"id": appID, "envID": strconv.FormatInt(resourceID, 10)}
},
handler: func(h *handlers.Handlers) http.HandlerFunc { return h.HandleEnvVarDelete() },
verifyFn: func(t *testing.T, tc *testContext, resourceID int64) {
t.Helper()
found, findErr := models.FindEnvVar(context.Background(), tc.database, resourceID)
require.NoError(t, findErr)
assert.NotNil(t, found, "env var should still exist after IDOR attempt")
},
})
}
// TestDeleteLabelOwnershipVerification tests that deleting a label
// via another app's URL path returns 404 (IDOR prevention).
func TestDeleteLabelOwnershipVerification(t *testing.T) {
func TestDeleteLabelOwnershipVerification(t *testing.T) { //nolint:dupl // intentionally similar IDOR test pattern
t.Parallel()
testCtx := setupTestHandlers(t)
testOwnershipVerification(t, ownedResourceTestConfig{
appPrefix1: "label-owner-app",
appPrefix2: "label-other-app",
createFn: func(t *testing.T, tc *testContext, ownerApp *models.App) int64 {
t.Helper()
app1 := createTestApp(t, testCtx, "label-owner-app")
app2 := createTestApp(t, testCtx, "label-other-app")
lbl := models.NewLabel(tc.database)
lbl.AppID = ownerApp.ID
lbl.Key = "traefik.enable"
lbl.Value = "true"
require.NoError(t, lbl.Save(context.Background()))
// Create label belonging to app1
label := models.NewLabel(testCtx.database)
label.AppID = app1.ID
label.Key = "traefik.enable"
label.Value = "true"
require.NoError(t, label.Save(context.Background()))
return lbl.ID
},
deletePath: func(appID string, resourceID int64) string {
return "/apps/" + appID + "/labels/" + strconv.FormatInt(resourceID, 10) + "/delete"
},
chiParams: func(appID string, resourceID int64) map[string]string {
return map[string]string{"id": appID, "labelID": strconv.FormatInt(resourceID, 10)}
},
handler: func(h *handlers.Handlers) http.HandlerFunc { return h.HandleLabelDelete() },
verifyFn: func(t *testing.T, tc *testContext, resourceID int64) {
t.Helper()
// Try to delete app1's label using app2's URL path
request := httptest.NewRequest(
http.MethodPost,
"/apps/"+app2.ID+"/labels/"+strconv.FormatInt(label.ID, 10)+"/delete",
nil,
)
request = addChiURLParams(request, map[string]string{
"id": app2.ID,
"labelID": strconv.FormatInt(label.ID, 10),
found, findErr := models.FindLabel(context.Background(), tc.database, resourceID)
require.NoError(t, findErr)
assert.NotNil(t, found, "label should still exist after IDOR attempt")
},
})
recorder := httptest.NewRecorder()
handler := testCtx.handlers.HandleLabelDelete()
handler.ServeHTTP(recorder, request)
assert.Equal(t, http.StatusNotFound, recorder.Code)
// Verify the label was NOT deleted
found, err := models.FindLabel(context.Background(), testCtx.database, label.ID)
require.NoError(t, err)
assert.NotNil(t, found, "label should still exist after IDOR attempt")
}
// TestDeleteVolumeOwnershipVerification tests that deleting a volume