Merge branch 'main' into issue-65-password-change
All checks were successful
check / check (push) Successful in 2m45s
All checks were successful
check / check (push) Successful in 2m45s
This commit is contained in:
@@ -22,3 +22,13 @@ func (s *Handlers) BuildSlackTargetConfigForTest(
|
||||
) (string, error) {
|
||||
return s.buildSlackTargetConfig(w, r, targetURL)
|
||||
}
|
||||
|
||||
// BuildDatabaseTargetConfigForTest exposes
|
||||
// buildDatabaseTargetConfig for use in the handlers_test
|
||||
// package.
|
||||
func (s *Handlers) BuildDatabaseTargetConfigForTest(
|
||||
w http.ResponseWriter,
|
||||
expiry string,
|
||||
) (string, error) {
|
||||
return s.buildDatabaseTargetConfig(w, expiry)
|
||||
}
|
||||
|
||||
@@ -186,3 +186,57 @@ func TestRenderTemplate(t *testing.T) {
|
||||
t, http.StatusInternalServerError, w.Code,
|
||||
)
|
||||
}
|
||||
|
||||
func TestBuildDatabaseTargetConfig_Valid(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var h *handlers.Handlers
|
||||
|
||||
app := newTestApp(t, &h)
|
||||
app.RequireStart()
|
||||
|
||||
t.Cleanup(app.RequireStop)
|
||||
|
||||
// Empty expiry: the keep-forever default, empty config.
|
||||
w := httptest.NewRecorder()
|
||||
cfg, err := h.BuildDatabaseTargetConfigForTest(w, "")
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, cfg)
|
||||
|
||||
// Explicit never is stored as config.
|
||||
w = httptest.NewRecorder()
|
||||
cfg, err = h.BuildDatabaseTargetConfigForTest(w, "never")
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, `{"expiry":"never"}`, cfg)
|
||||
|
||||
// A positive duration is stored as config.
|
||||
w = httptest.NewRecorder()
|
||||
cfg, err = h.BuildDatabaseTargetConfigForTest(w, "720h")
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, `{"expiry":"720h"}`, cfg)
|
||||
}
|
||||
|
||||
func TestBuildDatabaseTargetConfig_RejectsBadExpiry(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
var h *handlers.Handlers
|
||||
|
||||
app := newTestApp(t, &h)
|
||||
app.RequireStart()
|
||||
|
||||
t.Cleanup(app.RequireStop)
|
||||
|
||||
for _, bad := range []string{"nonsense", "7d", "-5h"} {
|
||||
w := httptest.NewRecorder()
|
||||
cfg, err := h.BuildDatabaseTargetConfigForTest(w, bad)
|
||||
|
||||
require.Error(t, err, "expiry %q", bad)
|
||||
assert.Empty(t, cfg)
|
||||
assert.Equal(
|
||||
t, http.StatusBadRequest, w.Code,
|
||||
"expiry %q should be rejected with 400", bad,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/google/uuid"
|
||||
@@ -815,6 +816,7 @@ func (h *Handlers) processTargetCreate(
|
||||
targetType := database.TargetType(r.FormValue("type"))
|
||||
targetURL := r.FormValue("url")
|
||||
maxRetriesStr := r.FormValue("max_retries")
|
||||
expiry := r.FormValue("expiry")
|
||||
|
||||
if name == "" {
|
||||
http.Error(
|
||||
@@ -834,7 +836,7 @@ func (h *Handlers) processTargetCreate(
|
||||
}
|
||||
|
||||
configJSON, err := h.buildTargetConfig(
|
||||
w, r, targetType, targetURL,
|
||||
w, r, targetType, targetURL, expiry,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -892,18 +894,22 @@ func parseNonNegativeInt(s string) int {
|
||||
}
|
||||
|
||||
// buildTargetConfig builds the JSON config string for a target.
|
||||
// The expiry form value is read by the caller (which bounds the
|
||||
// request body) and applies to database targets only.
|
||||
func (h *Handlers) buildTargetConfig(
|
||||
w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
targetType database.TargetType,
|
||||
targetURL string,
|
||||
targetURL, expiry string,
|
||||
) (string, error) {
|
||||
switch targetType {
|
||||
case database.TargetTypeHTTP:
|
||||
return h.buildHTTPTargetConfig(w, r, targetURL)
|
||||
case database.TargetTypeSlack:
|
||||
return h.buildSlackTargetConfig(w, r, targetURL)
|
||||
case database.TargetTypeDatabase, database.TargetTypeLog:
|
||||
case database.TargetTypeDatabase:
|
||||
return h.buildDatabaseTargetConfig(w, expiry)
|
||||
case database.TargetTypeLog:
|
||||
return "", nil
|
||||
default:
|
||||
http.Error(
|
||||
@@ -1013,6 +1019,47 @@ func (h *Handlers) buildSlackTargetConfig(
|
||||
return string(configBytes), nil
|
||||
}
|
||||
|
||||
// buildDatabaseTargetConfig builds config JSON for a database
|
||||
// (archive) target. The optional expiry (a form value read by
|
||||
// the caller, which bounds the request body) is validated here,
|
||||
// at creation time, so an unparseable value is rejected with a
|
||||
// 400 instead of failing every subsequent delivery. An empty
|
||||
// expiry yields an empty config (the keep-forever default).
|
||||
func (h *Handlers) buildDatabaseTargetConfig(
|
||||
w http.ResponseWriter,
|
||||
expiry string,
|
||||
) (string, error) {
|
||||
expiry = strings.TrimSpace(expiry)
|
||||
if expiry == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
err := delivery.ValidateArchiveExpiry(expiry)
|
||||
if err != nil {
|
||||
http.Error(
|
||||
w,
|
||||
"Invalid archive expiry: "+err.Error(),
|
||||
http.StatusBadRequest,
|
||||
)
|
||||
|
||||
return "", err
|
||||
}
|
||||
|
||||
cfg := map[string]any{"expiry": expiry}
|
||||
|
||||
configBytes, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
http.Error(
|
||||
w, "Internal server error",
|
||||
http.StatusInternalServerError,
|
||||
)
|
||||
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(configBytes), nil
|
||||
}
|
||||
|
||||
// HandleEntrypointDelete handles deleting an entrypoint.
|
||||
func (h *Handlers) HandleEntrypointDelete() http.HandlerFunc {
|
||||
return h.deleteChildResource(
|
||||
|
||||
Reference in New Issue
Block a user