diff --git a/Dockerfile b/Dockerfile index 5a6f00ea..2a3ed76f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,10 +31,10 @@ COPY . ./ # Regenerate the swagger RUN make swag -# Build it -RUN GOOS=linux go build -o /api +# Build it: a static binary, since the production image has no libc. +RUN CGO_ENABLED=0 GOOS=linux go build -o /api -FROM gcr.io/distroless/base-debian12@sha256:fabbf1c0c357a3d42550111351daed089b20a2c954df13ee2fcff60602515e84 AS production +FROM gcr.io/distroless/static-debian13@sha256:15f8637509792e05b97d83451b0b6ccfa4abd548f997e406ac1e72c87fe1fa78 AS production # The release and preview workflows pass VERSION (X.Y.Z, X.Y.Z-rcN, main- or # pr--) and set the source and revision labels themselves. diff --git a/go.mod b/go.mod index bc0d2ba0..4a479f34 100644 --- a/go.mod +++ b/go.mod @@ -21,8 +21,8 @@ require ( github.com/google/uuid v1.6.0 github.com/jackc/pgx/v5 v5.11.0 github.com/joho/godotenv v1.5.1 - github.com/labstack/echo-contrib v0.50.1 - github.com/labstack/echo/v4 v4.16.1 + github.com/labstack/echo-contrib/v5 v5.0.1 + github.com/labstack/echo/v5 v5.4.2 github.com/moby/moby/api v1.56.1 github.com/open-policy-agent/opa v1.21.3 github.com/prometheus/client_golang v1.25.0 @@ -35,7 +35,7 @@ require ( github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.12.1 - github.com/swaggo/echo-swagger v1.5.2 + github.com/swaggo/echo-swagger/v2 v2.0.1 github.com/swaggo/swag v1.16.6 github.com/testcontainers/testcontainers-go v0.44.0 github.com/testcontainers/testcontainers-go/modules/postgres v0.44.0 @@ -122,7 +122,6 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/klauspost/compress v1.20.1 // indirect - github.com/labstack/gommon v0.5.0 // indirect github.com/leodido/go-urn v1.5.0 // indirect github.com/lestrrat-go/blackmagic v1.0.4 // indirect github.com/lestrrat-go/dsig v1.4.0 // indirect @@ -184,9 +183,7 @@ require ( github.com/tklauser/go-sysconf v0.4.0 // indirect github.com/tklauser/numcpus v0.12.0 // indirect github.com/urfave/cli/v2 v2.27.7 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fastjson v1.6.10 // indirect - github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vektah/gqlparser/v2 v2.5.37 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect diff --git a/go.sum b/go.sum index 7368dba4..400fbb44 100644 --- a/go.sum +++ b/go.sum @@ -325,12 +325,10 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyokomi/emoji/v2 v2.2.13 h1:GhTfQa67venUUvmleTNFnb+bi7S3aocF7ZCXU9fSO7U= github.com/kyokomi/emoji/v2 v2.2.13/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= -github.com/labstack/echo-contrib v0.50.1 h1:W9cZZ9viA4TDdFtm8cuA+XGFwOcnfbjJpl7VgfsRLHE= -github.com/labstack/echo-contrib v0.50.1/go.mod h1:8r/++U/Fw/QniApFnzunLanKaviPfBX7fX7/2QX0qOk= -github.com/labstack/echo/v4 v4.16.1 h1:h05NuF1GvNu6jSAZxOv++AdjD/NJK+mZdGy0thiiuns= -github.com/labstack/echo/v4 v4.16.1/go.mod h1:V/EQaTVHYJH92QhbQe7kFQ4mjgcjxLQQUQtAN87zZdw= -github.com/labstack/gommon v0.5.0 h1:6VSQ2NOzsnEJ5W6+84E0RbcaDDmgB6NIAzWCczTEe6c= -github.com/labstack/gommon v0.5.0/go.mod h1:Rzlg7HHy1maLfzBYGg9NZcVuz1sA68HHhLjhcEllYE0= +github.com/labstack/echo-contrib/v5 v5.0.1 h1:Z23m8p1F9Doax+pa8ek8ll5d6wvzCbvrAn25ZWmSgrE= +github.com/labstack/echo-contrib/v5 v5.0.1/go.mod h1:ajrqEwSloW0vQSTfJ4j9u4tHoS+dg4umCDPxuTvChZs= +github.com/labstack/echo/v5 v5.4.2 h1:6Jk4ur2Sc7R6vH3DflrvfWmyrf9xX0yosFKBn+/8nZA= +github.com/labstack/echo/v5 v5.4.2/go.mod h1:4iEGNQiPPZnkfYpNR/L6fINd3NLiGWUD5+eBotFALas= github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0= github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE= github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA= @@ -503,8 +501,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/sv-tools/openapi v0.2.1 h1:ES1tMQMJFGibWndMagvdoo34T1Vllxr1Nlm5wz6b1aA= github.com/sv-tools/openapi v0.2.1/go.mod h1:k5VuZamTw1HuiS9p2Wl5YIDWzYnHG6/FgPOSFXLAhGg= -github.com/swaggo/echo-swagger v1.5.2 h1:KUM4QuEO1r/maky6Ybb9wS5MFEkJUpXwPbK4wwBe5Uk= -github.com/swaggo/echo-swagger v1.5.2/go.mod h1:nt3Z+SlyzXNIQ4odFNlPzRdcNOFvkPJHf+t4sMLhNu4= +github.com/swaggo/echo-swagger/v2 v2.0.1 h1:jKR3QiK+ciGjxE0+7qZ/azjtlx/pTVls7pJFJqdJoJI= +github.com/swaggo/echo-swagger/v2 v2.0.1/go.mod h1:BbgiO9XKX6yYU5Rq4ejqVlQI0mVRv6ziFKd0XgdztnQ= github.com/swaggo/files/v2 v2.0.2 h1:Bq4tgS/yxLB/3nwOMcul5oLEUKa877Ykgz3CJMVbQKU= github.com/swaggo/files/v2 v2.0.2/go.mod h1:TVqetIzZsO9OhHX1Am9sRf9LdrFZqoK49N37KON/jr0= github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI= @@ -543,12 +541,8 @@ github.com/tklauser/numcpus v0.12.0 h1:NR85qdvHA9pFse3x3weVZ0r0ST8R6l5RHbZrlRaqo github.com/tklauser/numcpus v0.12.0/go.mod h1:ABHeXzJnr/qqwguhClkZKT1/8VABcYrsyUiUGobwWJg= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4= github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE= -github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= -github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vektah/gqlparser/v2 v2.5.37 h1:jbb1Ilv+xBklV6653tKb4oVUupPNTLb5LmrnBKVI12Y= github.com/vektah/gqlparser/v2 v2.5.37/go.mod h1:9O4Ox6Ngd3Y12bMD3w6i3CRQXh8W1oC1q0m6olCymDM= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= diff --git a/internal/api/authcontext/signer_context.go b/internal/api/authcontext/signer_context.go index 7d420550..f4fe5dfb 100644 --- a/internal/api/authcontext/signer_context.go +++ b/internal/api/authcontext/signer_context.go @@ -4,10 +4,10 @@ import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/authn" evidencesvc "github.com/compliance-framework/api/internal/service/relational/evidence" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) -func SignerContextFromEcho(ctx echo.Context) *evidencesvc.SignerContext { +func SignerContextFromEcho(ctx *echo.Context) *evidencesvc.SignerContext { if claims, ok := ctx.Get("user").(*authn.UserClaims); ok && claims != nil { return evidencesvc.NewUserSignerContextFromClaims(claims) } diff --git a/internal/api/binders/custom_binder.go b/internal/api/binders/custom_binder.go index 272f97c0..8bb32fc2 100644 --- a/internal/api/binders/custom_binder.go +++ b/internal/api/binders/custom_binder.go @@ -4,7 +4,7 @@ import ( "io" "net/http" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gopkg.in/yaml.v2" ) @@ -15,17 +15,17 @@ const ( type CustomBinder struct{} -func (cb *CustomBinder) Bind(i any, c echo.Context) error { +func (cb *CustomBinder) Bind(c *echo.Context, i any) error { req := c.Request() contentType := req.Header.Get(echo.HeaderContentType) switch contentType { case MIMEApplicationYAML: if err := yaml.NewDecoder(req.Body).Decode(i); err != nil && err != io.EOF { - return echo.NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err) + return echo.NewHTTPError(http.StatusBadRequest, err.Error()).Wrap(err) } case MIMEApplicationJSON: defaultBinder := new(echo.DefaultBinder) - if err := defaultBinder.Bind(i, c); err != nil { + if err := defaultBinder.Bind(c, i); err != nil { return err } default: diff --git a/internal/api/error.go b/internal/api/error.go index 7d95c30b..015e8be7 100644 --- a/internal/api/error.go +++ b/internal/api/error.go @@ -7,7 +7,7 @@ import ( "github.com/go-playground/validator/v10" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) type Error struct { @@ -21,6 +21,11 @@ func NewError(err error) Error { switch { case errors.As(err, &v): e.Errors["body"] = v.Message + // Echo's binders return a generic 400 wrapping the decode error; that error says + // what was wrong with the request, as echo v4's message did. + if wrapped := v.Unwrap(); wrapped != nil { + e.Errors["body"] = wrapped.Error() + } default: e.Errors["body"] = err.Error() } diff --git a/internal/api/error_test.go b/internal/api/error_test.go new file mode 100644 index 00000000..4d858fae --- /dev/null +++ b/internal/api/error_test.go @@ -0,0 +1,32 @@ +package api + +import ( + "errors" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/labstack/echo/v5" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewErrorReportsWhyABindFailed(t *testing.T) { + req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(`{"name": 1}`)) + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + ctx := echo.New().NewContext(req, httptest.NewRecorder()) + + var body struct { + Name string `json:"name"` + } + err := ctx.Bind(&body) + require.Error(t, err) + + assert.Contains(t, NewError(err).Errors["body"], "cannot unmarshal number") +} + +func TestNewErrorUsesTheMessageOfAnUnwrappedHTTPError(t *testing.T) { + assert.Equal(t, "workflow_instance_id is required", NewError(echo.NewHTTPError(http.StatusBadRequest, "workflow_instance_id is required")).Errors["body"]) + assert.Equal(t, "plain", NewError(errors.New("plain")).Errors["body"]) +} diff --git a/internal/api/handler/agent_config.go b/internal/api/handler/agent_config.go index c7d92bf7..c86649b0 100644 --- a/internal/api/handler/agent_config.go +++ b/internal/api/handler/agent_config.go @@ -20,7 +20,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/agentcfg" "github.com/compliance-framework/api/pkg/agentconfig" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -204,7 +204,7 @@ type agentConfigPreviewRequest struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/config [get] -func (h *AgentConfigHandler) Get(ctx echo.Context) error { +func (h *AgentConfigHandler) Get(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -244,7 +244,7 @@ func (h *AgentConfigHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/config [put] -func (h *AgentConfigHandler) Put(ctx echo.Context) error { +func (h *AgentConfigHandler) Put(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -295,7 +295,7 @@ func (h *AgentConfigHandler) Put(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/config/revisions/{rev}/revert [post] -func (h *AgentConfigHandler) Revert(ctx echo.Context) error { +func (h *AgentConfigHandler) Revert(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -333,7 +333,7 @@ func (h *AgentConfigHandler) Revert(ctx echo.Context) error { } // save implements PUT/revert steps 3-7 (A4.3). -func (h *AgentConfigHandler) save(ctx echo.Context, agent *relational.Agent, expected int64, overlay json.RawMessage, comment *string, revertOf *int64) error { +func (h *AgentConfigHandler) save(ctx *echo.Context, agent *relational.Agent, expected int64, overlay json.RawMessage, comment *string, revertOf *int64) error { reqCtx := ctx.Request().Context() agentID := *agent.ID @@ -413,7 +413,7 @@ func (h *AgentConfigHandler) save(ctx echo.Context, agent *relational.Agent, exp // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/config/preview [post] -func (h *AgentConfigHandler) Preview(ctx echo.Context) error { +func (h *AgentConfigHandler) Preview(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -625,7 +625,7 @@ func mergeAndValidate(base agentconfig.Config, overlay json.RawMessage) (*agentc // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/config/revisions [get] -func (h *AgentConfigHandler) ListRevisions(ctx echo.Context) error { +func (h *AgentConfigHandler) ListRevisions(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -670,7 +670,7 @@ func (h *AgentConfigHandler) ListRevisions(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/config/revisions/{rev} [get] -func (h *AgentConfigHandler) GetRevision(ctx echo.Context) error { +func (h *AgentConfigHandler) GetRevision(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -709,7 +709,7 @@ func (h *AgentConfigHandler) GetRevision(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/instances [get] -func (h *AgentConfigHandler) ListInstances(ctx echo.Context) error { +func (h *AgentConfigHandler) ListInstances(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -763,7 +763,7 @@ func (h *AgentConfigHandler) ListInstances(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/agents/{id}/instances/{instanceId} [get] -func (h *AgentConfigHandler) GetInstance(ctx echo.Context) error { +func (h *AgentConfigHandler) GetInstance(ctx *echo.Context) error { agent, errResp := h.resolveAgent(ctx) if agent == nil { return errResp @@ -841,7 +841,7 @@ func (h *AgentConfigHandler) decodeColumn(inst *relational.AgentInstance, column } // resolveAgent loads :id. On failure it returns nil and the already-written error response. -func (h *AgentConfigHandler) resolveAgent(ctx echo.Context) (*relational.Agent, error) { +func (h *AgentConfigHandler) resolveAgent(ctx *echo.Context) (*relational.Agent, error) { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return nil, ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -859,7 +859,7 @@ func (h *AgentConfigHandler) resolveAgent(ctx echo.Context) (*relational.Agent, // canConfigure reports whether the caller holds agent:configure on the agent in :id, // evaluated against the PDP like the route guard does. It fails closed: no PDP, an // unavailable PDP or an evaluation error all count as no. -func (h *AgentConfigHandler) canConfigure(ctx echo.Context) bool { +func (h *AgentConfigHandler) canConfigure(ctx *echo.Context) bool { if h.pdp == nil { return false } @@ -877,7 +877,7 @@ func (h *AgentConfigHandler) canConfigure(ctx echo.Context) bool { // redactForReader redacts resp.Overlay (agentconfig.RedactDocument) unless the caller holds // agent:configure, so plain readers never see literal secrets typed into an overlay. // OverlaySize stays the stored size. -func (h *AgentConfigHandler) redactForReader(ctx echo.Context, resp *agentConfigRevisionResponse) error { +func (h *AgentConfigHandler) redactForReader(ctx *echo.Context, resp *agentConfigRevisionResponse) error { if len(resp.Overlay) == 0 || h.canConfigure(ctx) { return nil } @@ -889,7 +889,7 @@ func (h *AgentConfigHandler) redactForReader(ctx echo.Context, resp *agentConfig return nil } -func (h *AgentConfigHandler) internalError(ctx echo.Context, what string, err error) error { +func (h *AgentConfigHandler) internalError(ctx *echo.Context, what string, err error) error { h.sugar.Errorw("Agent configuration request failed", "operation", what, "path", ctx.Path(), "error", err) return ctx.JSON(http.StatusInternalServerError, api.InternalServerError()) } @@ -919,11 +919,11 @@ func revisionResponse(agentID uuid.UUID, rev *relational.AgentConfigRevision, wi return resp } -func preconditionRequired(ctx echo.Context) error { +func preconditionRequired(ctx *echo.Context) error { return ctx.JSON(http.StatusPreconditionRequired, api.NewError(errors.New("If-Match header with the current revision is required"))) } -func revisionConflict(ctx echo.Context, current int64) error { +func revisionConflict(ctx *echo.Context, current int64) error { return ctx.JSON(http.StatusConflict, api.Error{Errors: map[string]any{ "body": agentcfg.ErrRevisionConflict.Error(), "current-revision": current, @@ -931,7 +931,7 @@ func revisionConflict(ctx echo.Context, current int64) error { } // revisionAuthor returns the user subject (email) and user_uuid claim of the caller. -func revisionAuthor(ctx echo.Context) (string, *uuid.UUID) { +func revisionAuthor(ctx *echo.Context) (string, *uuid.UUID) { claims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || claims == nil { return "", nil diff --git a/internal/api/handler/agent_config_admin_integration_test.go b/internal/api/handler/agent_config_admin_integration_test.go index b965f2bb..4aa81522 100644 --- a/internal/api/handler/agent_config_admin_integration_test.go +++ b/internal/api/handler/agent_config_admin_integration_test.go @@ -24,7 +24,7 @@ import ( "github.com/compliance-framework/api/internal/tests" "github.com/compliance-framework/api/pkg/agentconfig" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/agent_config_body.go b/internal/api/handler/agent_config_body.go index 6316a58e..2d23d866 100644 --- a/internal/api/handler/agent_config_body.go +++ b/internal/api/handler/agent_config_body.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/compliance-framework/api/internal/api" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) // HTTP header names used by the agent-configuration routes. @@ -28,7 +28,7 @@ type bodyError struct { func (e *bodyError) Error() string { return e.msg } // respond writes the error as an api.Error body. -func (e *bodyError) respond(ctx echo.Context) error { +func (e *bodyError) respond(ctx *echo.Context) error { return ctx.JSON(e.status, api.NewError(errors.New(e.msg))) } @@ -36,7 +36,7 @@ func (e *bodyError) respond(ctx echo.Context) error { // not use ctx.Bind, because CustomBinder rejects "application/json; charset=utf-8". A missing // Content-Type or any application/json media type (with parameters) is accepted; any other // type is 415. More than limit bytes is 413. An empty body returns nil. -func readJSONBody(ctx echo.Context, limit int64) ([]byte, *bodyError) { +func readJSONBody(ctx *echo.Context, limit int64) ([]byte, *bodyError) { if ct := strings.TrimSpace(ctx.Request().Header.Get(echo.HeaderContentType)); ct != "" { mediaType, _, err := mime.ParseMediaType(ct) if err != nil || !strings.EqualFold(mediaType, echo.MIMEApplicationJSON) { diff --git a/internal/api/handler/agent_config_sync.go b/internal/api/handler/agent_config_sync.go index 81ef8991..3824271d 100644 --- a/internal/api/handler/agent_config_sync.go +++ b/internal/api/handler/agent_config_sync.go @@ -16,7 +16,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/agentcfg" "github.com/compliance-framework/api/pkg/agentconfig" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -92,7 +92,7 @@ func (h *AgentConfigSyncHandler) Register(g *echo.Group, middlewares ...echo.Mid // agentAuthFrom returns the authenticated agent, or nil. The handler requires it even though // the route middleware does too: Cedar grants the agent role to anonymous subjects when // public agent endpoints are on (defence in depth). -func agentAuthFrom(ctx echo.Context) *middleware.AgentAuthContext { +func agentAuthFrom(ctx *echo.Context) *middleware.AgentAuthContext { auth, _ := ctx.Get("agent_auth").(*middleware.AgentAuthContext) if auth == nil || auth.Agent == nil || auth.Agent.ID == nil { return nil @@ -100,7 +100,7 @@ func agentAuthFrom(ctx echo.Context) *middleware.AgentAuthContext { return auth } -func setRemoteConfigHeaders(ctx echo.Context) { +func setRemoteConfigHeaders(ctx *echo.Context) { ctx.Response().Header().Set(headerRemoteConfig, "1") ctx.Response().Header().Set(echo.HeaderCacheControl, "no-cache") } @@ -119,7 +119,7 @@ func setRemoteConfigHeaders(ctx echo.Context) { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /agent/config [get] -func (h *AgentConfigSyncHandler) GetConfig(ctx echo.Context) error { +func (h *AgentConfigSyncHandler) GetConfig(ctx *echo.Context) error { auth := agentAuthFrom(ctx) if auth == nil { return ctx.JSON(http.StatusUnauthorized, api.NewError(errors.New("agent authentication required"))) @@ -189,7 +189,7 @@ func (h *AgentConfigSyncHandler) GetConfig(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /agent/instances/{instanceId}/config-report [put] -func (h *AgentConfigSyncHandler) PutReport(ctx echo.Context) error { +func (h *AgentConfigSyncHandler) PutReport(ctx *echo.Context) error { auth := agentAuthFrom(ctx) if auth == nil { return ctx.JSON(http.StatusUnauthorized, api.NewError(errors.New("agent authentication required"))) diff --git a/internal/api/handler/agent_config_sync_integration_test.go b/internal/api/handler/agent_config_sync_integration_test.go index a7638a39..b2328f34 100644 --- a/internal/api/handler/agent_config_sync_integration_test.go +++ b/internal/api/handler/agent_config_sync_integration_test.go @@ -20,7 +20,7 @@ import ( "github.com/compliance-framework/api/internal/tests" "github.com/compliance-framework/api/pkg/agentconfig" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/agent_config_sync_test.go b/internal/api/handler/agent_config_sync_test.go index 2a3322f4..2475325f 100644 --- a/internal/api/handler/agent_config_sync_test.go +++ b/internal/api/handler/agent_config_sync_test.go @@ -11,7 +11,7 @@ import ( "unicode/utf8" "github.com/compliance-framework/api/pkg/agentconfig" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -294,7 +294,7 @@ func TestIsJSONObject(t *testing.T) { assert.False(t, isJSONObject(json.RawMessage(`1`))) } -func jsonBodyContext(contentType, body string) echo.Context { +func jsonBodyContext(contentType, body string) *echo.Context { req := httptest.NewRequest(http.MethodPut, "/", strings.NewReader(body)) if contentType != "" { req.Header.Set(echo.HeaderContentType, contentType) @@ -344,7 +344,9 @@ func TestReadJSONBody(t *testing.T) { assert.Equal(t, http.StatusRequestEntityTooLarge, err.status) assert.Equal(t, "request body exceeds 16 bytes", err.msg) require.NoError(t, err.respond(ctx)) - assert.Equal(t, http.StatusRequestEntityTooLarge, ctx.Response().Status) + resp, unwrapErr := echo.UnwrapResponse(ctx.Response()) + require.NoError(t, unwrapErr) + assert.Equal(t, http.StatusRequestEntityTooLarge, resp.Status) }) t.Run("413 from a MaxBytesReader", func(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/", strings.NewReader(strings.Repeat("a", 64))) diff --git a/internal/api/handler/agents.go b/internal/api/handler/agents.go index 4bac302e..5fddc7d8 100644 --- a/internal/api/handler/agents.go +++ b/internal/api/handler/agents.go @@ -12,7 +12,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/agentcfg" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -86,7 +86,7 @@ func (h *AgentHandler) Register(api *echo.Group, readGuard, adminGuard echo.Midd api.DELETE("/:id/keys/:keyId", h.DeleteAgentKey, adminGuard) } -func (h *AgentHandler) ListAgents(ctx echo.Context) error { +func (h *AgentHandler) ListAgents(ctx *echo.Context) error { var agents []relational.Agent if err := h.db.Order("created_at asc").Find(&agents).Error; err != nil { return ctx.JSON(http.StatusInternalServerError, api.NewError(err)) @@ -106,7 +106,7 @@ func (h *AgentHandler) ListAgents(ctx echo.Context) error { return ctx.JSON(http.StatusOK, GenericDataListResponse[agentResponse]{Data: resp}) } -func (h *AgentHandler) GetAgent(ctx echo.Context) error { +func (h *AgentHandler) GetAgent(ctx *echo.Context) error { agent, err := h.getAgentByParam(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -122,7 +122,7 @@ func (h *AgentHandler) GetAgent(ctx echo.Context) error { return ctx.JSON(http.StatusOK, GenericDataResponse[agentResponse]{Data: resp}) } -func (h *AgentHandler) CreateAgent(ctx echo.Context) error { +func (h *AgentHandler) CreateAgent(ctx *echo.Context) error { var req createAgentRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -151,7 +151,7 @@ func (h *AgentHandler) CreateAgent(ctx echo.Context) error { return ctx.JSON(http.StatusCreated, GenericDataResponse[agentResponse]{Data: resp}) } -func (h *AgentHandler) UpdateAgent(ctx echo.Context) error { +func (h *AgentHandler) UpdateAgent(ctx *echo.Context) error { agent, err := h.getAgentByParam(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -186,7 +186,7 @@ func (h *AgentHandler) UpdateAgent(ctx echo.Context) error { return ctx.JSON(http.StatusOK, GenericDataResponse[agentResponse]{Data: resp}) } -func (h *AgentHandler) DeleteAgent(ctx echo.Context) error { +func (h *AgentHandler) DeleteAgent(ctx *echo.Context) error { agent, err := h.getAgentByParam(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -227,7 +227,7 @@ func (h *AgentHandler) DeleteAgent(ctx echo.Context) error { return ctx.NoContent(http.StatusNoContent) } -func (h *AgentHandler) CreateAgentKey(ctx echo.Context) error { +func (h *AgentHandler) CreateAgentKey(ctx *echo.Context) error { agent, err := h.getAgentByParam(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -272,7 +272,7 @@ func (h *AgentHandler) CreateAgentKey(ctx echo.Context) error { }) } -func (h *AgentHandler) ListAgentKeys(ctx echo.Context) error { +func (h *AgentHandler) ListAgentKeys(ctx *echo.Context) error { agent, err := h.getAgentByParam(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -293,7 +293,7 @@ func (h *AgentHandler) ListAgentKeys(ctx echo.Context) error { return ctx.JSON(http.StatusOK, GenericDataListResponse[agentKeyResponse]{Data: resp}) } -func (h *AgentHandler) GetAgentKey(ctx echo.Context) error { +func (h *AgentHandler) GetAgentKey(ctx *echo.Context) error { key, status, err := h.getAgentKey(ctx.Param("id"), ctx.Param("keyId")) if err != nil { return ctx.JSON(status, api.NewError(err)) @@ -301,7 +301,7 @@ func (h *AgentHandler) GetAgentKey(ctx echo.Context) error { return ctx.JSON(http.StatusOK, GenericDataResponse[agentKeyResponse]{Data: buildAgentKeyResponse(key)}) } -func (h *AgentHandler) DeleteAgentKey(ctx echo.Context) error { +func (h *AgentHandler) DeleteAgentKey(ctx *echo.Context) error { key, status, err := h.getAgentKey(ctx.Param("id"), ctx.Param("keyId")) if err != nil { return ctx.JSON(status, api.NewError(err)) diff --git a/internal/api/handler/agents_integration_test.go b/internal/api/handler/agents_integration_test.go index c5fd1e1b..5a2ba84f 100644 --- a/internal/api/handler/agents_integration_test.go +++ b/internal/api/handler/agents_integration_test.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/tests" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/api.go b/internal/api/handler/api.go index 8223a629..1e98f9fa 100644 --- a/internal/api/handler/api.go +++ b/internal/api/handler/api.go @@ -19,8 +19,8 @@ import ( "github.com/compliance-framework/api/internal/service/relational/sspscope" workflowsvc "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/compliance-framework/api/internal/workflow" - "github.com/labstack/echo/v4" - echomiddleware "github.com/labstack/echo/v4/middleware" + "github.com/labstack/echo/v5" + echomiddleware "github.com/labstack/echo/v5/middleware" "go.uber.org/zap" "gorm.io/gorm" ) diff --git a/internal/api/handler/artifacts.go b/internal/api/handler/artifacts.go index d031d6f8..15945251 100644 --- a/internal/api/handler/artifacts.go +++ b/internal/api/handler/artifacts.go @@ -16,7 +16,7 @@ import ( "github.com/compliance-framework/api/internal/config" artifactsvc "github.com/compliance-framework/api/internal/service/relational/artifacts" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -102,7 +102,7 @@ func (h *ArtifactHandler) RegisterRead(e *echo.Group, middlewares ...echo.Middle // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /agent/artifacts [post] -func (h *ArtifactHandler) Upload(ctx echo.Context) error { +func (h *ArtifactHandler) Upload(ctx *echo.Context) error { // Read the whole body before any other work, so a slow upload holds nothing but its // own connection. content, err := io.ReadAll(http.MaxBytesReader(ctx.Response(), ctx.Request().Body, h.maxBytes)) @@ -161,7 +161,7 @@ func (h *ArtifactHandler) Upload(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /artifacts/{digest} [get] -func (h *ArtifactHandler) Get(ctx echo.Context) error { +func (h *ArtifactHandler) Get(ctx *echo.Context) error { digest := ctx.Param("digest") if !artifact.ValidDigest(digest) { return ctx.JSON(http.StatusBadRequest, api.NewError(fmt.Errorf("invalid digest %q", digest))) @@ -182,7 +182,7 @@ func (h *ArtifactHandler) Get(ctx echo.Context) error { return ctx.Blob(http.StatusOK, stored.MediaType, stored.Content) } -func uploaderAgentID(ctx echo.Context) *uuid.UUID { +func uploaderAgentID(ctx *echo.Context) *uuid.UUID { auth, ok := ctx.Get("agent_auth").(*middleware.AgentAuthContext) if !ok || auth == nil || auth.Agent == nil { return nil diff --git a/internal/api/handler/artifacts_integration_test.go b/internal/api/handler/artifacts_integration_test.go index 3d7c9cc2..87eca701 100644 --- a/internal/api/handler/artifacts_integration_test.go +++ b/internal/api/handler/artifacts_integration_test.go @@ -27,7 +27,7 @@ import ( "github.com/compliance-framework/api/sdk" "github.com/compliance-framework/api/sdk/types" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/artifacts_test.go b/internal/api/handler/artifacts_test.go index fd273bf5..63e4c9db 100644 --- a/internal/api/handler/artifacts_test.go +++ b/internal/api/handler/artifacts_test.go @@ -10,7 +10,7 @@ import ( "github.com/compliance-framework/api/internal/artifact" "github.com/compliance-framework/api/internal/config" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" diff --git a/internal/api/handler/auth/agent.go b/internal/api/handler/auth/agent.go index 0fe25fde..ff2a9ff7 100644 --- a/internal/api/handler/auth/agent.go +++ b/internal/api/handler/auth/agent.go @@ -9,7 +9,7 @@ import ( "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/authn" "github.com/compliance-framework/api/internal/service/relational" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" ) @@ -19,7 +19,7 @@ type agentTokenResponse struct { ExpiresIn int `json:"expires_in"` } -func (h *AuthHandler) GetAgentToken(ctx echo.Context) error { +func (h *AuthHandler) GetAgentToken(ctx *echo.Context) error { clientID, clientSecret, err := getAgentCredentials(ctx) if err != nil { return ctx.JSON(http.StatusUnauthorized, api.NewError(err)) @@ -95,7 +95,7 @@ func (h *AuthHandler) GetAgentToken(ctx echo.Context) error { }) } -func getAgentCredentials(ctx echo.Context) (string, string, error) { +func getAgentCredentials(ctx *echo.Context) (string, string, error) { if clientID, clientSecret, ok := ctx.Request().BasicAuth(); ok { clientID = strings.TrimSpace(clientID) clientSecret = strings.TrimSpace(clientSecret) @@ -112,14 +112,14 @@ func getAgentCredentials(ctx echo.Context) (string, string, error) { return clientID, clientSecret, nil } -func (h *AuthHandler) logAgentAuthEvent(agent *relational.Agent, key *relational.AgentServiceAccountKey, principal string, outcome string, reason string, ctx echo.Context) { +func (h *AuthHandler) logAgentAuthEvent(agent *relational.Agent, key *relational.AgentServiceAccountKey, principal string, outcome string, reason string, ctx *echo.Context) { event := h.newAgentAuthEvent(agent, key, principal, outcome, &reason, ctx) if err := h.db.Create(event).Error; err != nil { h.sugar.Warnw("Failed to log agent auth event", "error", err) } } -func (h *AuthHandler) newAgentAuthEvent(agent *relational.Agent, key *relational.AgentServiceAccountKey, principal string, outcome string, reason *string, ctx echo.Context) *relational.AgentAuthEvent { +func (h *AuthHandler) newAgentAuthEvent(agent *relational.Agent, key *relational.AgentServiceAccountKey, principal string, outcome string, reason *string, ctx *echo.Context) *relational.AgentAuthEvent { event := &relational.AgentAuthEvent{ AuthMethod: relational.AgentAuthMethodServiceAccount, Outcome: outcome, diff --git a/internal/api/handler/auth/auth.go b/internal/api/handler/auth/auth.go index 0051a095..04fe83ab 100644 --- a/internal/api/handler/auth/auth.go +++ b/internal/api/handler/auth/auth.go @@ -15,7 +15,7 @@ import ( emailtypes "github.com/compliance-framework/api/internal/service/email/types" "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/worker" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -65,7 +65,7 @@ func (h *AuthHandler) Register(api *echo.Group) { // @Failure 401 {object} handler.GenericDataResponse[auth.AuthHandler.LoginUser.errorResponse] // @Failure 500 {object} api.Error // @Router /auth/login [post] -func (h *AuthHandler) LoginUser(ctx echo.Context) error { +func (h *AuthHandler) LoginUser(ctx *echo.Context) error { type loginRequest struct { Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"required"` @@ -147,7 +147,7 @@ func isDevelopmentEnvironment(env string) bool { // @Failure 401 {object} api.Error // @Failure 500 {object} api.Error // @Router /auth/token [post] -func (h *AuthHandler) GetOAuth2Token(ctx echo.Context) error { +func (h *AuthHandler) GetOAuth2Token(ctx *echo.Context) error { type response struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` @@ -241,7 +241,7 @@ func (h *AuthHandler) CheckUser(username, password string) (*relational.User, bo } // GetPublicKeyPEM returns a plaintext representation of the JWT public key in PEM format. -func (h *AuthHandler) GetPublicKeyPEM(ctx echo.Context) error { +func (h *AuthHandler) GetPublicKeyPEM(ctx *echo.Context) error { pubPem, err := authn.PublicKeyToPEM(h.config.JWTPublicKey) if err != nil { @@ -262,7 +262,7 @@ func (h *AuthHandler) GetPublicKeyPEM(ctx echo.Context) error { // @Success 200 {object} authn.JWK // @Failure 500 {object} api.Error // @Router /auth/publickey [get] -func (h *AuthHandler) GetJWK(ctx echo.Context) error { +func (h *AuthHandler) GetJWK(ctx *echo.Context) error { jwk := &authn.JWK{} jwk, err := jwk.UnmarshalPublicKey(h.config.JWTPublicKey) if err != nil { @@ -285,7 +285,7 @@ func (h *AuthHandler) GetJWK(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /auth/forgot-password [post] -func (h *AuthHandler) ForgotPassword(ctx echo.Context) error { +func (h *AuthHandler) ForgotPassword(ctx *echo.Context) error { type request struct { Email string `json:"email" validate:"required,email"` } @@ -400,7 +400,7 @@ func (h *AuthHandler) ForgotPassword(ctx echo.Context) error { // @Failure 401 {object} api.Error // @Failure 500 {object} api.Error // @Router /auth/password-reset [post] -func (h *AuthHandler) PasswordReset(ctx echo.Context) error { +func (h *AuthHandler) PasswordReset(ctx *echo.Context) error { type request struct { Token string `json:"token" validate:"required"` Password string `json:"password" validate:"required,min=8"` diff --git a/internal/api/handler/auth/password_reset_test.go b/internal/api/handler/auth/password_reset_test.go index 0a2fd8cf..7925501f 100644 --- a/internal/api/handler/auth/password_reset_test.go +++ b/internal/api/handler/auth/password_reset_test.go @@ -11,7 +11,7 @@ import ( "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/config" "github.com/compliance-framework/api/internal/service/relational" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" diff --git a/internal/api/handler/auth/slack_link.go b/internal/api/handler/auth/slack_link.go index 29bab58d..dcf2c516 100644 --- a/internal/api/handler/auth/slack_link.go +++ b/internal/api/handler/auth/slack_link.go @@ -19,7 +19,7 @@ import ( "github.com/compliance-framework/api/internal/config" "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "golang.org/x/oauth2" "gorm.io/gorm" @@ -101,7 +101,7 @@ func (h *SlackLinkHandler) Register(api *echo.Group, jwtMiddleware echo.Middlewa api.GET("/slack/link/callback", h.Callback) } -func (h *SlackLinkHandler) StartLink(ctx echo.Context) error { +func (h *SlackLinkHandler) StartLink(ctx *echo.Context) error { if !h.isLinkingConfigured() { h.sugar.Error("Slack linking attempted but Slack integration is not configured") @@ -132,7 +132,7 @@ func (h *SlackLinkHandler) StartLink(ctx echo.Context) error { return ctx.Redirect(http.StatusTemporaryRedirect, authURL) } -func (h *SlackLinkHandler) Callback(ctx echo.Context) error { +func (h *SlackLinkHandler) Callback(ctx *echo.Context) error { if !h.isLinkingConfigured() { return h.respondCallbackError(ctx, "not_configured") } @@ -201,7 +201,7 @@ func (h *SlackLinkHandler) Callback(ctx echo.Context) error { return h.respondCallbackSuccess(ctx) } -func (h *SlackLinkHandler) GetStatus(ctx echo.Context) error { +func (h *SlackLinkHandler) GetStatus(ctx *echo.Context) error { if !h.isLinkingConfigured() { return ctx.JSON(http.StatusNotFound, api.NewError(fmt.Errorf("slack account linking is not configured"))) } @@ -239,7 +239,7 @@ func (h *SlackLinkHandler) GetStatus(ctx echo.Context) error { }) } -func (h *SlackLinkHandler) Unlink(ctx echo.Context) error { +func (h *SlackLinkHandler) Unlink(ctx *echo.Context) error { if !h.isLinkingConfigured() { return ctx.JSON(http.StatusNotFound, api.NewError(fmt.Errorf("slack account linking is not configured"))) } @@ -451,7 +451,7 @@ func (h *SlackLinkHandler) consumeLinkAttempt(ctx context.Context, state string) return userID, nil } -func (h *SlackLinkHandler) getCurrentUser(ctx echo.Context) (*relational.User, error) { +func (h *SlackLinkHandler) getCurrentUser(ctx *echo.Context) (*relational.User, error) { userClaims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || userClaims == nil { return nil, fmt.Errorf("missing user claims") @@ -476,7 +476,7 @@ func (h *SlackLinkHandler) getCurrentUser(ctx echo.Context) (*relational.User, e return &user, nil } -func (h *SlackLinkHandler) setLinkCookie(ctx echo.Context, name, value string, ttl time.Duration) { +func (h *SlackLinkHandler) setLinkCookie(ctx *echo.Context, name, value string, ttl time.Duration) { cookie := new(http.Cookie) cookie.Name = name cookie.Value = value @@ -493,7 +493,7 @@ func (h *SlackLinkHandler) setLinkCookie(ctx echo.Context, name, value string, t ctx.SetCookie(cookie) } -func (h *SlackLinkHandler) clearLinkCookie(ctx echo.Context, name string) { +func (h *SlackLinkHandler) clearLinkCookie(ctx *echo.Context, name string) { cookie := new(http.Cookie) cookie.Name = name cookie.Value = "" @@ -556,14 +556,14 @@ func generateStateToken() (string, error) { return base64.RawURLEncoding.EncodeToString(raw), nil } -func (h *SlackLinkHandler) respondCallbackSuccess(ctx echo.Context) error { +func (h *SlackLinkHandler) respondCallbackSuccess(ctx *echo.Context) error { query := url.Values{} query.Set("status", "success") return ctx.Redirect(http.StatusFound, h.webCallbackRedirectURL(query)) } -func (h *SlackLinkHandler) respondCallbackError(ctx echo.Context, errCode string) error { +func (h *SlackLinkHandler) respondCallbackError(ctx *echo.Context, errCode string) error { query := url.Values{} query.Set("status", "error") diff --git a/internal/api/handler/auth/sso.go b/internal/api/handler/auth/sso.go index 197d7bd8..04bee87d 100644 --- a/internal/api/handler/auth/sso.go +++ b/internal/api/handler/auth/sso.go @@ -16,7 +16,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/sso" "github.com/compliance-framework/api/internal/service/sso/types" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "golang.org/x/oauth2" "gorm.io/gorm" @@ -112,7 +112,7 @@ type ProviderInfo struct { IconURL string `json:"iconUrl,omitempty"` } -func (h *SSOHandler) ListProviders(ctx echo.Context) error { +func (h *SSOHandler) ListProviders(ctx *echo.Context) error { if !h.ssoService.IsEnabled() { return ctx.JSON(http.StatusOK, handler.GenericDataResponse[[]ProviderInfo]{ Data: []ProviderInfo{}, @@ -135,7 +135,7 @@ func (h *SSOHandler) ListProviders(ctx echo.Context) error { }) } -func (h *SSOHandler) InitiateLogin(ctx echo.Context) error { +func (h *SSOHandler) InitiateLogin(ctx *echo.Context) error { providerName := ctx.Param("provider") if !h.ssoService.IsEnabled() { @@ -179,7 +179,7 @@ func (h *SSOHandler) InitiateLogin(ctx echo.Context) error { return ctx.Redirect(http.StatusTemporaryRedirect, authURL) } -func (h *SSOHandler) Callback(ctx echo.Context) error { +func (h *SSOHandler) Callback(ctx *echo.Context) error { providerName := ctx.Param("provider") if !h.ssoService.IsEnabled() { diff --git a/internal/api/handler/auth/sso_test.go b/internal/api/handler/auth/sso_test.go index df4b5ac9..bb19b601 100644 --- a/internal/api/handler/auth/sso_test.go +++ b/internal/api/handler/auth/sso_test.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/sso" "github.com/compliance-framework/api/internal/service/sso/types" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "golang.org/x/oauth2" @@ -134,8 +134,7 @@ func TestSSOHandlerInitiateLogin_SetsStateCookie(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/api/auth/sso/google", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("provider") - ctx.SetParamValues("google") + ctx.SetPathValues(echo.PathValues{{Name: "provider", Value: "google"}}) err := h.InitiateLogin(ctx) require.NoError(t, err) @@ -183,8 +182,7 @@ func TestSSOHandlerCallback_NewUserCreated(t *testing.T) { rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("provider") - ctx.SetParamValues("google") + ctx.SetPathValues(echo.PathValues{{Name: "provider", Value: "google"}}) err := h.Callback(ctx) require.NoError(t, err) @@ -241,8 +239,7 @@ func TestSSOHandlerCallback_MaterializesNativeMemberships(t *testing.T) { req.AddCookie(&http.Cookie{Name: "oauth_state", Value: "state123"}) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("provider") - ctx.SetParamValues("google") + ctx.SetPathValues(echo.PathValues{{Name: "provider", Value: "google"}}) require.NoError(t, h.Callback(ctx)) require.Equal(t, http.StatusTemporaryRedirect, rec.Code) diff --git a/internal/api/handler/control_links.go b/internal/api/handler/control_links.go index da42ca17..fa01a210 100644 --- a/internal/api/handler/control_links.go +++ b/internal/api/handler/control_links.go @@ -10,7 +10,7 @@ import ( svc "github.com/compliance-framework/api/internal/service" "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -112,7 +112,7 @@ type catalogLinkSummary struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /control-links [get] -func (h *ControlLinkHandler) List(ctx echo.Context) error { +func (h *ControlLinkHandler) List(ctx *echo.Context) error { pagination, err := h.pagination.ParseParams(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -172,7 +172,7 @@ func (h *ControlLinkHandler) List(ctx echo.Context) error { // @Failure 422 {object} api.Error // @Security OAuth2Password // @Router /control-links [post] -func (h *ControlLinkHandler) Create(ctx echo.Context) error { +func (h *ControlLinkHandler) Create(ctx *echo.Context) error { var req createControlLinkRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -236,7 +236,7 @@ func (h *ControlLinkHandler) Create(ctx echo.Context) error { // @Failure 422 {object} api.Error // @Security OAuth2Password // @Router /control-links/bulk [post] -func (h *ControlLinkHandler) BulkCreate(ctx echo.Context) error { +func (h *ControlLinkHandler) BulkCreate(ctx *echo.Context) error { var req bulkControlLinkRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -313,7 +313,7 @@ func (h *ControlLinkHandler) BulkCreate(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Security OAuth2Password // @Router /control-links [delete] -func (h *ControlLinkHandler) Delete(ctx echo.Context) error { +func (h *ControlLinkHandler) Delete(ctx *echo.Context) error { sourceCatalogID, err := uuid.Parse(ctx.QueryParam("sourceCatalogId")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("valid sourceCatalogId is required"))) @@ -356,7 +356,7 @@ func (h *ControlLinkHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /control-links/catalog [get] -func (h *ControlLinkHandler) ListCatalogLinks(ctx echo.Context) error { +func (h *ControlLinkHandler) ListCatalogLinks(ctx *echo.Context) error { query := h.db.Model(&relational.ControlLink{}). Select("source_catalog_id, target_catalog_id, target_control_id, relationship_type, count(*) AS control_count"). Group("source_catalog_id, target_catalog_id, target_control_id, relationship_type"). @@ -396,7 +396,7 @@ func (h *ControlLinkHandler) ListCatalogLinks(ctx echo.Context) error { // @Failure 422 {object} api.Error // @Security OAuth2Password // @Router /control-links/catalog [post] -func (h *ControlLinkHandler) CreateCatalogLink(ctx echo.Context) error { +func (h *ControlLinkHandler) CreateCatalogLink(ctx *echo.Context) error { var req catalogLinkRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -429,7 +429,7 @@ func (h *ControlLinkHandler) CreateCatalogLink(ctx echo.Context) error { // @Failure 422 {object} api.Error // @Security OAuth2Password // @Router /control-links/catalog [put] -func (h *ControlLinkHandler) SyncCatalogLink(ctx echo.Context) error { +func (h *ControlLinkHandler) SyncCatalogLink(ctx *echo.Context) error { var req catalogLinkRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -481,7 +481,7 @@ func (h *ControlLinkHandler) SyncCatalogLink(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Security OAuth2Password // @Router /control-links/catalog [delete] -func (h *ControlLinkHandler) DeleteCatalogLink(ctx echo.Context) error { +func (h *ControlLinkHandler) DeleteCatalogLink(ctx *echo.Context) error { sourceCatalogID, err := uuid.Parse(ctx.QueryParam("sourceCatalogId")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("valid sourceCatalogId is required"))) @@ -668,7 +668,7 @@ func (h *ControlLinkHandler) loadEdges() ([]relational.ControlLink, error) { // actorUserID extracts the authenticated user's primary-key UUID from the JWT // claims for CreatedByID attribution; nil when unavailable. -func actorUserID(ctx echo.Context) *uuid.UUID { +func actorUserID(ctx *echo.Context) *uuid.UUID { claims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || claims == nil || claims.UserUUID == "" { return nil diff --git a/internal/api/handler/control_links_catalog_integration_test.go b/internal/api/handler/control_links_catalog_integration_test.go index 1c04bef9..17a5936e 100644 --- a/internal/api/handler/control_links_catalog_integration_test.go +++ b/internal/api/handler/control_links_catalog_integration_test.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) @@ -33,7 +33,7 @@ func (suite *CatalogControlLinksSuite) handler() *ControlLinkHandler { // call invokes a handler method with an optional JSON body and raw query string, // returning the recorder. Mirrors the direct-handler style used by the lineage // integration tests (no auth middleware; actorUserID tolerates absent claims). -func (suite *CatalogControlLinksSuite) call(method, query string, body any, fn func(echo.Context) error) *httptest.ResponseRecorder { +func (suite *CatalogControlLinksSuite) call(method, query string, body any, fn func(*echo.Context) error) *httptest.ResponseRecorder { var reader *bytes.Reader if body != nil { raw, err := json.Marshal(body) diff --git a/internal/api/handler/digest.go b/internal/api/handler/digest.go index 954aeb9f..ada7b673 100644 --- a/internal/api/handler/digest.go +++ b/internal/api/handler/digest.go @@ -6,7 +6,7 @@ import ( "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/service/digest" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -42,7 +42,7 @@ func (h *DigestHandler) Register(api *echo.Group) { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/digest/trigger [post] -func (h *DigestHandler) TriggerDigest(ctx echo.Context) error { +func (h *DigestHandler) TriggerDigest(ctx *echo.Context) error { jobName := ctx.QueryParam("job") if jobName == "" { jobName = "global-evidence-digest" @@ -72,7 +72,7 @@ func (h *DigestHandler) TriggerDigest(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/digest/preview [get] -func (h *DigestHandler) PreviewDigest(ctx echo.Context) error { +func (h *DigestHandler) PreviewDigest(ctx *echo.Context) error { summary, err := h.digestService.GetGlobalEvidenceSummary(ctx.Request().Context()) if err != nil { h.logger.Errorw("Failed to get evidence summary", "error", err) diff --git a/internal/api/handler/evidence.go b/internal/api/handler/evidence.go index f9cf3fb1..950e80cc 100644 --- a/internal/api/handler/evidence.go +++ b/internal/api/handler/evidence.go @@ -23,7 +23,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/sspscope" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -267,7 +267,7 @@ func implementedComponentLinkID(itemIdentifier, componentIdentifier string) (uui // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /evidence [post] -func (h *EvidenceHandler) Create(ctx echo.Context) error { +func (h *EvidenceHandler) Create(ctx *echo.Context) error { var input *EvidenceCreateRequest if err := ctx.Bind(&input); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -525,7 +525,7 @@ type evidenceConfigResponse struct { // @Produce json // @Success 200 {object} GenericDataResponse[evidenceConfigResponse] // @Router /evidence/config [get] -func (h *EvidenceHandler) Config(ctx echo.Context) error { +func (h *EvidenceHandler) Config(ctx *echo.Context) error { return ctx.JSON(http.StatusOK, GenericDataResponse[evidenceConfigResponse]{ Data: evidenceConfigResponse{ManualSubjectRequired: h.evidenceService.ManualEvidenceRequiresSubject()}, }) @@ -550,7 +550,7 @@ func (h *EvidenceHandler) Config(ctx echo.Context) error { // @Failure 422 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/search [post] -func (h *EvidenceHandler) Search(ctx echo.Context) error { +func (h *EvidenceHandler) Search(ctx *echo.Context) error { return h.search(ctx, nil) } @@ -558,7 +558,7 @@ func (h *EvidenceHandler) Search(ctx echo.Context) error { type scopeRestriction func(labelfilter.Filter) (filter labelfilter.Filter, ok bool) // search serves an evidence search, narrowed by restrict when it is not nil. -func (h *EvidenceHandler) search(ctx echo.Context, restrict scopeRestriction) error { +func (h *EvidenceHandler) search(ctx *echo.Context, restrict scopeRestriction) error { filter := &labelfilter.Filter{} req := filteredSearchRequest{} @@ -602,7 +602,7 @@ func (h *EvidenceHandler) search(ctx echo.Context, restrict scopeRestriction) er return ctx.JSON(http.StatusOK, svc.NewListResponse(output, total, pagination.Page, pagination.Limit)) } -func parseEvidenceSearchOptions(ctx echo.Context, pagination *svc.PaginationParams) (evidencesvc.SearchOptions, error) { +func parseEvidenceSearchOptions(ctx *echo.Context, pagination *svc.PaginationParams) (evidencesvc.SearchOptions, error) { sortBy := evidencesvc.SearchSortBy(ctx.QueryParam("sortBy")) if sortBy == "" { sortBy = evidencesvc.SearchSortByLastSeenAt @@ -794,7 +794,7 @@ func newCreatedEvidenceResponse(evidence *relational.Evidence) (*CreatedEvidence return response, nil } -func parseEvidenceID(ctx echo.Context) (uuid.UUID, error) { +func parseEvidenceID(ctx *echo.Context) (uuid.UUID, error) { return uuid.Parse(ctx.Param("id")) } @@ -810,7 +810,7 @@ func parseEvidenceID(ctx echo.Context) (uuid.UUID, error) { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/{id} [get] -func (h *EvidenceHandler) Get(ctx echo.Context) error { +func (h *EvidenceHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := parseEvidenceID(ctx) if err != nil { @@ -849,7 +849,7 @@ func (h *EvidenceHandler) Get(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/history/{id} [get] -func (h *EvidenceHandler) History(ctx echo.Context) error { +func (h *EvidenceHandler) History(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := parseEvidenceID(ctx) if err != nil { @@ -895,7 +895,7 @@ func (h *EvidenceHandler) History(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/latest/{id} [get] -func (h *EvidenceHandler) Latest(ctx echo.Context) error { +func (h *EvidenceHandler) Latest(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := parseEvidenceID(ctx) if err != nil { @@ -934,7 +934,7 @@ func (h *EvidenceHandler) Latest(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /evidence/{id}/signature [get] -func (h *EvidenceHandler) GetSignature(ctx echo.Context) error { +func (h *EvidenceHandler) GetSignature(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := parseEvidenceID(ctx) if err != nil { @@ -970,7 +970,7 @@ func (h *EvidenceHandler) GetSignature(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /evidence/{id}/verify [post] -func (h *EvidenceHandler) VerifySignature(ctx echo.Context) error { +func (h *EvidenceHandler) VerifySignature(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := parseEvidenceID(ctx) if err != nil { @@ -1016,7 +1016,7 @@ type EvidenceRiskResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /evidence/{id}/risks [get] -func (h *EvidenceHandler) Risks(ctx echo.Context) error { +func (h *EvidenceHandler) Risks(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := parseEvidenceID(ctx) if err != nil { @@ -1082,7 +1082,7 @@ func (h *EvidenceHandler) Risks(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/for-control/{id} [get] -func (h *EvidenceHandler) ForControl(ctx echo.Context) error { +func (h *EvidenceHandler) ForControl(ctx *echo.Context) error { type responseMetadata struct { Control *oscalTypes_1_1_3.Control `json:"control"` } @@ -1153,13 +1153,13 @@ type StatusInterval struct { // @Failure 422 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/status-over-time [post] -func (h *EvidenceHandler) StatusOverTime(ctx echo.Context) error { +func (h *EvidenceHandler) StatusOverTime(ctx *echo.Context) error { return h.statusOverTime(ctx, nil) } // statusOverTime serves status counts over intervals, narrowed by restrict when it is // not nil. -func (h *EvidenceHandler) statusOverTime(ctx echo.Context, restrict scopeRestriction) error { +func (h *EvidenceHandler) statusOverTime(ctx *echo.Context, restrict scopeRestriction) error { filter := &labelfilter.Filter{} req := filteredSearchRequest{} @@ -1247,7 +1247,7 @@ func (h *EvidenceHandler) statusOverTime(ctx echo.Context, restrict scopeRestric // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/evidence/search [post] -func (h *EvidenceHandler) SSPScopedSearch(ctx echo.Context) error { +func (h *EvidenceHandler) SSPScopedSearch(ctx *echo.Context) error { restrict, ok := h.sspScopeRestriction(ctx) if !ok { return nil @@ -1273,7 +1273,7 @@ func (h *EvidenceHandler) SSPScopedSearch(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/evidence/status-over-time [post] -func (h *EvidenceHandler) SSPScopedStatusOverTime(ctx echo.Context) error { +func (h *EvidenceHandler) SSPScopedStatusOverTime(ctx *echo.Context) error { restrict, ok := h.sspScopeRestriction(ctx) if !ok { return nil @@ -1294,7 +1294,7 @@ func (h *EvidenceHandler) SSPScopedStatusOverTime(ctx echo.Context) error { // @Failure 422 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/status-over-time/{id} [get] -func (h *EvidenceHandler) StatusOverTimeByUUID(ctx echo.Context) error { +func (h *EvidenceHandler) StatusOverTimeByUUID(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1360,7 +1360,7 @@ func (h *EvidenceHandler) StatusOverTimeByUUID(ctx echo.Context) error { // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/compliance-by-control/{id} [get] -func (h *EvidenceHandler) ComplianceByControl(ctx echo.Context) error { +func (h *EvidenceHandler) ComplianceByControl(ctx *echo.Context) error { id := ctx.Param("id") control, err := h.evidenceService.GetControlByID(id) if err != nil { @@ -1387,7 +1387,7 @@ func (h *EvidenceHandler) ComplianceByControl(ctx echo.Context) error { return ctx.JSON(http.StatusOK, GenericDataListResponse[evidencesvc.StatusCount]{Data: rows}) } -func visibleControlFilters(ctx echo.Context, filterModels []relational.Filter) ([]labelfilter.Filter, error) { +func visibleControlFilters(ctx *echo.Context, filterModels []relational.Filter) ([]labelfilter.Filter, error) { sspIDParam := strings.TrimSpace(ctx.QueryParam("sspId")) var sspID *uuid.UUID if sspIDParam != "" { @@ -1419,7 +1419,7 @@ func visibleControlFilters(ctx echo.Context, filterModels []relational.Filter) ( // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /evidence/compliance-by-filter/{id} [get] -func (h *EvidenceHandler) ComplianceByFilter(ctx echo.Context) error { +func (h *EvidenceHandler) ComplianceByFilter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/evidence_batch.go b/internal/api/handler/evidence_batch.go index 7d3b566b..c289b993 100644 --- a/internal/api/handler/evidence_batch.go +++ b/internal/api/handler/evidence_batch.go @@ -19,14 +19,14 @@ import ( evidencesvc "github.com/compliance-framework/api/internal/service/relational/evidence" "github.com/compliance-framework/api/internal/service/worker" "github.com/google/uuid" - "github.com/labstack/echo/v4" - echomiddleware "github.com/labstack/echo/v4/middleware" + "github.com/labstack/echo/v5" + echomiddleware "github.com/labstack/echo/v5/middleware" "gorm.io/gorm" ) const ( // evidenceBatchBodyLimit bounds a batch request body. - evidenceBatchBodyLimit = "64M" + evidenceBatchBodyLimit = 64 * echomiddleware.MB // evidenceBatchRouteName names GET /evidence/batches/:id, the Location of a new batch. evidenceBatchRouteName = "evidence-batch" ) @@ -99,7 +99,7 @@ func (h *EvidenceHandler) WithBatchService(service *evidencesvc.BatchService, ma // canInspectBatches reports whether the caller holds evidence:inspect, evaluated against // the PDP like a route guard. It fails closed: no PDP, an unavailable PDP or an evaluation // error all count as no. -func (h *EvidenceHandler) canInspectBatches(ctx echo.Context) bool { +func (h *EvidenceHandler) canInspectBatches(ctx *echo.Context) bool { if h.batchPDP == nil { return false } @@ -118,7 +118,15 @@ func (h *EvidenceHandler) canInspectBatches(ctx echo.Context) bool { func (h *EvidenceHandler) RegisterBatchRoutes(api *echo.Group, middlewares ...echo.MiddlewareFunc) { createMiddlewares := append([]echo.MiddlewareFunc{echomiddleware.BodyLimit(evidenceBatchBodyLimit)}, middlewares...) api.POST("", h.CreateBatch, createMiddlewares...) - api.GET("/:id", h.GetBatch, middlewares...).Name = evidenceBatchRouteName + if _, err := api.AddRoute(echo.Route{ + Method: http.MethodGet, + Path: "/:id", + Name: evidenceBatchRouteName, + Handler: h.GetBatch, + Middlewares: middlewares, + }); err != nil { + panic(err) // as echo's GET does: a route that can't be registered is a programming error + } } // CreateBatch godoc @@ -137,7 +145,7 @@ func (h *EvidenceHandler) RegisterBatchRoutes(api *echo.Group, middlewares ...ec // @Failure 503 {object} api.Error // @Security OAuth2Password // @Router /evidence/batches [post] -func (h *EvidenceHandler) CreateBatch(ctx echo.Context) error { +func (h *EvidenceHandler) CreateBatch(ctx *echo.Context) error { if h.batchService == nil { return ctx.JSON(http.StatusServiceUnavailable, api.NewError(errors.New("evidence batches are not available"))) } @@ -169,14 +177,16 @@ func (h *EvidenceHandler) CreateBatch(ctx echo.Context) error { return ctx.JSON(http.StatusInternalServerError, api.InternalServerError()) } - ctx.Response().Header().Set(echo.HeaderLocation, ctx.Echo().Reverse(evidenceBatchRouteName, summary.ID.String())) + if location, err := ctx.Echo().Router().Routes().Reverse(evidenceBatchRouteName, summary.ID.String()); err == nil { + ctx.Response().Header().Set(echo.HeaderLocation, location) + } return ctx.JSON(http.StatusAccepted, GenericDataResponse[EvidenceBatchResponse]{Data: newEvidenceBatchResponse(summary)}) } // checkBatchItems checks what can be checked without the database: each item decodes, // validates, sets no reserved prop and doesn't start or end in the future. Problems are // keyed by the item's position, "evidence[i]". -func (h *EvidenceHandler) checkBatchItems(ctx echo.Context, items []json.RawMessage, now time.Time) api.Error { +func (h *EvidenceHandler) checkBatchItems(ctx *echo.Context, items []json.RawMessage, now time.Time) api.Error { invalid := api.Error{Errors: map[string]any{}} for i, raw := range items { key := fmt.Sprintf("evidence[%d]", i) @@ -253,7 +263,7 @@ func (h *EvidenceHandler) storeBatchItem(ctx context.Context, payload json.RawMe // @Failure 503 {object} api.Error // @Security OAuth2Password // @Router /evidence/batches/{id} [get] -func (h *EvidenceHandler) GetBatch(ctx echo.Context) error { +func (h *EvidenceHandler) GetBatch(ctx *echo.Context) error { if h.batchService == nil { return ctx.JSON(http.StatusServiceUnavailable, api.NewError(errors.New("evidence batches are not available"))) } diff --git a/internal/api/handler/evidence_batch_integration_test.go b/internal/api/handler/evidence_batch_integration_test.go index 418e0f84..f97ea954 100644 --- a/internal/api/handler/evidence_batch_integration_test.go +++ b/internal/api/handler/evidence_batch_integration_test.go @@ -25,7 +25,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/evidence_create_links_integration_test.go b/internal/api/handler/evidence_create_links_integration_test.go index 8aaf1c78..a5143f52 100644 --- a/internal/api/handler/evidence_create_links_integration_test.go +++ b/internal/api/handler/evidence_create_links_integration_test.go @@ -17,7 +17,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/evidence_integration_test.go b/internal/api/handler/evidence_integration_test.go index 58a4b959..04deafa7 100644 --- a/internal/api/handler/evidence_integration_test.go +++ b/internal/api/handler/evidence_integration_test.go @@ -24,7 +24,7 @@ import ( sdktypes "github.com/compliance-framework/api/sdk/types" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" diff --git a/internal/api/handler/evidence_playback.go b/internal/api/handler/evidence_playback.go index 7653b2c6..62d25099 100644 --- a/internal/api/handler/evidence_playback.go +++ b/internal/api/handler/evidence_playback.go @@ -18,7 +18,7 @@ import ( evidencesvc "github.com/compliance-framework/api/internal/service/relational/evidence" "github.com/compliance-framework/api/pkg/policyeval" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" ) @@ -133,7 +133,7 @@ func (h *PlaybackHandler) RegisterEvidence(api *echo.Group, middlewares ...echo. // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /evidence/{id}/playback [get] -func (h *PlaybackHandler) EvidencePlayback(ctx echo.Context) error { +func (h *PlaybackHandler) EvidencePlayback(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(fmt.Errorf("invalid evidence id: %w", err))) diff --git a/internal/api/handler/evidence_playback_integration_test.go b/internal/api/handler/evidence_playback_integration_test.go index 7c3d74f7..50c51631 100644 --- a/internal/api/handler/evidence_playback_integration_test.go +++ b/internal/api/handler/evidence_playback_integration_test.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/pkg/policyeval" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) const playbackTestPackage = "compliance_framework.ports" diff --git a/internal/api/handler/evidence_ssp_scope.go b/internal/api/handler/evidence_ssp_scope.go index 2ca6aa03..5a7831ce 100644 --- a/internal/api/handler/evidence_ssp_scope.go +++ b/internal/api/handler/evidence_ssp_scope.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/converters/labelfilter" "github.com/compliance-framework/api/internal/service/relational/sspscope" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) // RegisterSSPScopedRoutes mounts the SSP-scoped evidence reads, which read scopes through @@ -23,7 +23,7 @@ func (h *EvidenceHandler) RegisterSSPScopedRoutes(api *echo.Group, scope *sspsco // sspScopeRestriction loads the scope of the SSP named by the id path parameter. On // failure it has already written the response and returns ok=false. -func (h *EvidenceHandler) sspScopeRestriction(ctx echo.Context) (scopeRestriction, bool) { +func (h *EvidenceHandler) sspScopeRestriction(ctx *echo.Context) (scopeRestriction, bool) { sspID, err := uuid.Parse(ctx.Param("id")) if err != nil { _ = ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/evidence_ssp_scope_integration_test.go b/internal/api/handler/evidence_ssp_scope_integration_test.go index 21aaad04..13ac33a6 100644 --- a/internal/api/handler/evidence_ssp_scope_integration_test.go +++ b/internal/api/handler/evidence_ssp_scope_integration_test.go @@ -21,7 +21,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/sspscope" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/evidence_test.go b/internal/api/handler/evidence_test.go index bb620848..3b42285d 100644 --- a/internal/api/handler/evidence_test.go +++ b/internal/api/handler/evidence_test.go @@ -11,7 +11,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" ) diff --git a/internal/api/handler/filter.go b/internal/api/handler/filter.go index 21cf449d..807963a6 100644 --- a/internal/api/handler/filter.go +++ b/internal/api/handler/filter.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/sspscope" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -66,7 +66,7 @@ type FilterWithAssociations struct { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /filters/{id} [get] -func (h *FilterHandler) Get(ctx echo.Context) error { +func (h *FilterHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -118,7 +118,7 @@ func (h *FilterHandler) Get(ctx echo.Context) error { // @Failure 401 {object} api.Error // @Failure 500 {object} api.Error // @Router /filters [get] -func (h *FilterHandler) List(ctx echo.Context) error { +func (h *FilterHandler) List(ctx *echo.Context) error { controlID := ctx.QueryParam("controlId") componentID := ctx.QueryParam("componentId") scope := strings.TrimSpace(ctx.QueryParam("scope")) @@ -204,7 +204,7 @@ func (h *FilterHandler) List(ctx echo.Context) error { // @Failure 422 {object} api.Error // @Failure 500 {object} api.Error // @Router /filters [post] -func (h *FilterHandler) Create(ctx echo.Context) error { +func (h *FilterHandler) Create(ctx *echo.Context) error { var req createFilterRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -291,7 +291,7 @@ func (h *FilterHandler) Create(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /filters/{id} [put] -func (h *FilterHandler) Update(ctx echo.Context) error { +func (h *FilterHandler) Update(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -433,7 +433,7 @@ func (h *FilterHandler) Update(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /filters/{id} [delete] -func (h *FilterHandler) Delete(ctx echo.Context) error { +func (h *FilterHandler) Delete(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -476,7 +476,7 @@ func (h *FilterHandler) Delete(ctx echo.Context) error { // @Failure 409 {object} api.Error // @Failure 500 {object} api.Error // @Router /filters/{id}/responsibilities [post] -func (h *FilterHandler) AttachResponsibility(ctx echo.Context) error { +func (h *FilterHandler) AttachResponsibility(ctx *echo.Context) error { idParam := ctx.Param("id") filterID, err := uuid.Parse(idParam) if err != nil { @@ -772,7 +772,7 @@ func (h *FilterHandler) resolveCatalogIDForSSPControl(sspID uuid.UUID, controlID } } -func (h *FilterHandler) DetachResponsibility(ctx echo.Context) error { +func (h *FilterHandler) DetachResponsibility(ctx *echo.Context) error { filterID, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -862,7 +862,7 @@ func followSSPScope(tx *gorm.DB, filter *relational.Filter, base labelfilter.Fil return nil } -func (h *FilterHandler) filterWriteError(ctx echo.Context, err error) error { +func (h *FilterHandler) filterWriteError(ctx *echo.Context, err error) error { switch { case errors.Is(err, errFollowNeedsSSP), errors.Is(err, sspscope.ErrScopeEmpty), errors.Is(err, sspscope.ErrSSPNotFound): return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/filter_follow_scope_integration_test.go b/internal/api/handler/filter_follow_scope_integration_test.go index 7b405ecf..887a2a1c 100644 --- a/internal/api/handler/filter_follow_scope_integration_test.go +++ b/internal/api/handler/filter_follow_scope_integration_test.go @@ -20,7 +20,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/sspscope" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/filter_import.go b/internal/api/handler/filter_import.go index d473e213..6be47c48 100644 --- a/internal/api/handler/filter_import.go +++ b/internal/api/handler/filter_import.go @@ -11,7 +11,7 @@ import ( "github.com/compliance-framework/api/internal/converters/labelfilter" "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/datatypes" "gorm.io/gorm/clause" ) @@ -55,7 +55,7 @@ type controlRef struct { // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /filters/import [post] -func (h *FilterHandler) ImportFilters(ctx echo.Context) error { +func (h *FilterHandler) ImportFilters(ctx *echo.Context) error { form, err := ctx.MultipartForm() if err != nil { h.sugar.Errorw("Failed to parse multipart form", "error", err) diff --git a/internal/api/handler/filter_integration_test.go b/internal/api/handler/filter_integration_test.go index 8d8eada8..e8d748f5 100644 --- a/internal/api/handler/filter_integration_test.go +++ b/internal/api/handler/filter_integration_test.go @@ -16,7 +16,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/groups.go b/internal/api/handler/groups.go index 7dd1d687..78bb8de9 100644 --- a/internal/api/handler/groups.go +++ b/internal/api/handler/groups.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgconn" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -65,7 +65,7 @@ type groupResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups [get] -func (h *GroupsHandler) ListGroups(ctx echo.Context) error { +func (h *GroupsHandler) ListGroups(ctx *echo.Context) error { var groups []relational.UserGroup if err := h.db.Order("name ASC").Find(&groups).Error; err != nil { h.sugar.Errorw("Failed to list groups", "error", err) @@ -102,7 +102,7 @@ func (h *GroupsHandler) ListGroups(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id} [get] -func (h *GroupsHandler) GetGroup(ctx echo.Context) error { +func (h *GroupsHandler) GetGroup(ctx *echo.Context) error { group, err := h.loadGroup(ctx.Param("id")) if err != nil { return h.groupError(ctx, err) @@ -135,7 +135,7 @@ func (h *GroupsHandler) GetGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups [post] -func (h *GroupsHandler) CreateGroup(ctx echo.Context) error { +func (h *GroupsHandler) CreateGroup(ctx *echo.Context) error { type createGroupRequest struct { Name string `json:"name" validate:"required"` Description string `json:"description"` @@ -180,7 +180,7 @@ func (h *GroupsHandler) CreateGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id} [put] -func (h *GroupsHandler) UpdateGroup(ctx echo.Context) error { +func (h *GroupsHandler) UpdateGroup(ctx *echo.Context) error { type updateGroupRequest struct { Name *string `json:"name"` Description *string `json:"description"` @@ -232,7 +232,7 @@ func (h *GroupsHandler) UpdateGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id} [delete] -func (h *GroupsHandler) DeleteGroup(ctx echo.Context) error { +func (h *GroupsHandler) DeleteGroup(ctx *echo.Context) error { group, err := h.loadGroup(ctx.Param("id")) if err != nil { return h.groupError(ctx, err) @@ -286,7 +286,7 @@ func (h *GroupsHandler) DeleteGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id}/members [get] -func (h *GroupsHandler) ListMembers(ctx echo.Context) error { +func (h *GroupsHandler) ListMembers(ctx *echo.Context) error { group, err := h.loadGroup(ctx.Param("id")) if err != nil { return h.groupError(ctx, err) @@ -353,7 +353,7 @@ func (h *GroupsHandler) ListMembers(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id}/members [post] -func (h *GroupsHandler) AddMember(ctx echo.Context) error { +func (h *GroupsHandler) AddMember(ctx *echo.Context) error { type addMemberRequest struct { UserID string `json:"userId" validate:"required"` } @@ -418,7 +418,7 @@ func (h *GroupsHandler) AddMember(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id}/members/{userId} [delete] -func (h *GroupsHandler) RemoveMember(ctx echo.Context) error { +func (h *GroupsHandler) RemoveMember(ctx *echo.Context) error { group, err := h.loadGroup(ctx.Param("id")) if err != nil { return h.groupError(ctx, err) @@ -470,7 +470,7 @@ func (h *GroupsHandler) RemoveMember(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id}/sso-mappings [get] -func (h *GroupsHandler) ListSSOMappings(ctx echo.Context) error { +func (h *GroupsHandler) ListSSOMappings(ctx *echo.Context) error { group, err := h.loadGroup(ctx.Param("id")) if err != nil { return h.groupError(ctx, err) @@ -504,7 +504,7 @@ func (h *GroupsHandler) ListSSOMappings(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id}/sso-mappings [post] -func (h *GroupsHandler) AddSSOMapping(ctx echo.Context) error { +func (h *GroupsHandler) AddSSOMapping(ctx *echo.Context) error { type addMappingRequest struct { Provider string `json:"provider" validate:"required"` ExternalGroup string `json:"externalGroup" validate:"required"` @@ -558,7 +558,7 @@ func (h *GroupsHandler) AddSSOMapping(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id}/sso-mappings/{mappingId} [delete] -func (h *GroupsHandler) RemoveSSOMapping(ctx echo.Context) error { +func (h *GroupsHandler) RemoveSSOMapping(ctx *echo.Context) error { group, err := h.loadGroup(ctx.Param("id")) if err != nil { return h.groupError(ctx, err) @@ -601,7 +601,7 @@ var errGroupNotEmpty = errors.New("group still has members") // groupError maps a loadGroup error to the right status: 400 for a malformed id, 404 for a // missing group, 500 otherwise. -func (h *GroupsHandler) groupError(ctx echo.Context, err error) error { +func (h *GroupsHandler) groupError(ctx *echo.Context, err error) error { switch { case errors.Is(err, errInvalidGroupID): return ctx.JSON(400, api.NewError(err)) diff --git a/internal/api/handler/health.go b/internal/api/handler/health.go index 0451a9a5..1efc79d8 100644 --- a/internal/api/handler/health.go +++ b/internal/api/handler/health.go @@ -7,7 +7,7 @@ import ( "time" "github.com/compliance-framework/api/internal/authz" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -46,11 +46,11 @@ func (h *HealthHandler) Register(api *echo.Group) { api.GET("/ready", h.Ready) } -func (h *HealthHandler) Health(ctx echo.Context) error { +func (h *HealthHandler) Health(ctx *echo.Context) error { return ctx.JSON(http.StatusOK, healthResponse{Status: "ok"}) } -func (h *HealthHandler) Ready(ctx echo.Context) error { +func (h *HealthHandler) Ready(ctx *echo.Context) error { sqlDB, err := h.sqlDB() if err != nil { h.sugar.Errorw("failed to retrieve sql DB", "err", err) diff --git a/internal/api/handler/health_integration_test.go b/internal/api/handler/health_integration_test.go index b08aa436..7548c5bd 100644 --- a/internal/api/handler/health_integration_test.go +++ b/internal/api/handler/health_integration_test.go @@ -11,7 +11,7 @@ import ( "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/tests" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/heartbeat.go b/internal/api/handler/heartbeat.go index 54121c09..00b85733 100644 --- a/internal/api/handler/heartbeat.go +++ b/internal/api/handler/heartbeat.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/service" "github.com/compliance-framework/api/internal/service/relational/agentcfg" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -70,7 +70,7 @@ type HeartbeatCreateRequest struct { // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /agent/heartbeat [post] -func (h *HeartbeatHandler) Create(ctx echo.Context) error { +func (h *HeartbeatHandler) Create(ctx *echo.Context) error { // Bind the incoming JSON payload into a slice of SDK findings. var heartbeat HeartbeatCreateRequest if err := ctx.Bind(&heartbeat); err != nil { @@ -97,7 +97,7 @@ func (h *HeartbeatHandler) Create(ctx echo.Context) error { // touchAgentInstance records an authenticated heartbeat against the agent-instance registry. // Failures are logged and never change the 201; anonymous heartbeats are ignored. -func (h *HeartbeatHandler) touchAgentInstance(ctx echo.Context, heartbeat HeartbeatCreateRequest) { +func (h *HeartbeatHandler) touchAgentInstance(ctx *echo.Context, heartbeat HeartbeatCreateRequest) { if h.instances == nil { return } @@ -135,7 +135,7 @@ func (h *HeartbeatHandler) touchAgentInstance(ctx echo.Context, heartbeat Heartb // @Success 200 {object} handler.GenericDataListResponse[handler.OverTime.HeartbeatInterval] // @Failure 500 {object} api.Error // @Router /agent/heartbeat/over-time [get] -func (h *HeartbeatHandler) OverTime(ctx echo.Context) error { +func (h *HeartbeatHandler) OverTime(ctx *echo.Context) error { type HeartbeatInterval struct { Interval time.Time `json:"interval"` diff --git a/internal/api/handler/heartbeat_integration_test.go b/internal/api/handler/heartbeat_integration_test.go index 5dbf962a..c804768d 100644 --- a/internal/api/handler/heartbeat_integration_test.go +++ b/internal/api/handler/heartbeat_integration_test.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/service" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "github.com/compliance-framework/api/internal/tests" diff --git a/internal/api/handler/lineage.go b/internal/api/handler/lineage.go index 38f6ff9a..cd553d2f 100644 --- a/internal/api/handler/lineage.go +++ b/internal/api/handler/lineage.go @@ -20,7 +20,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" riskrel "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -56,7 +56,7 @@ func (h *LineageHandler) WithEngineCache(cfg *config.LineageConfig) *LineageHand // engine returns the lineage engine for the scope, rebuilt when the request sets // refresh=true, and stamps the response with when its data was loaded. -func (h *LineageHandler) engine(ctx echo.Context, sspID, componentID *uuid.UUID) (*lineageEngine, error) { +func (h *LineageHandler) engine(ctx *echo.Context, sspID, componentID *uuid.UUID) (*lineageEngine, error) { refresh := false if raw := ctx.QueryParam("refresh"); raw != "" { parsed, err := strconv.ParseBool(raw) @@ -77,7 +77,7 @@ var errLineageRefreshParam = errors.New("refresh must be true or false") // engineError writes the response for an engine() failure: 400 for a bad refresh // parameter, otherwise a logged 500. -func (h *LineageHandler) engineError(ctx echo.Context, err error) error { +func (h *LineageHandler) engineError(ctx *echo.Context, err error) error { if errors.Is(err, errLineageRefreshParam) { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) } @@ -295,7 +295,7 @@ type LineageNode struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /lineage/roots [get] -func (h *LineageHandler) Roots(ctx echo.Context) error { +func (h *LineageHandler) Roots(ctx *echo.Context) error { sspID, componentID, err := parseScope(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -359,7 +359,7 @@ func (h *LineageHandler) Roots(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /lineage/nodes/{key}/children [get] -func (h *LineageHandler) Children(ctx echo.Context) error { +func (h *LineageHandler) Children(ctx *echo.Context) error { sspID, componentID, err := parseScope(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -419,7 +419,7 @@ func (h *LineageHandler) Children(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /lineage/nodes/{key}/ssps [get] -func (h *LineageHandler) SSPDetail(ctx echo.Context) error { +func (h *LineageHandler) SSPDetail(ctx *echo.Context) error { // This table is inherently multi-SSP, so it ignores any sspId scope and always // walks every plan; componentId still narrows the evidence. _, componentID, err := parseScope(ctx) @@ -2152,7 +2152,7 @@ func sortNodes(nodes []LineageNode) { } // parseScope parses the shared sspId/componentId query params. -func parseScope(ctx echo.Context) (*uuid.UUID, *uuid.UUID, error) { +func parseScope(ctx *echo.Context) (*uuid.UUID, *uuid.UUID, error) { var sspID, componentID *uuid.UUID if v := strings.TrimSpace(ctx.QueryParam("sspId")); v != "" { id, err := uuid.Parse(v) diff --git a/internal/api/handler/lineage_cache_integration_test.go b/internal/api/handler/lineage_cache_integration_test.go index 0d05e5e9..4aff889a 100644 --- a/internal/api/handler/lineage_cache_integration_test.go +++ b/internal/api/handler/lineage_cache_integration_test.go @@ -14,7 +14,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) @@ -74,8 +74,7 @@ func (suite *LineageCacheSuite) TestCachedDataIsReusedUntilRefresh() { childReq := httptest.NewRequest(http.MethodGet, "/x", nil) childRec := httptest.NewRecorder() ctx := echo.New().NewContext(childReq, childRec) - ctx.SetParamNames("key") - ctx.SetParamValues("catalog:" + second.String()) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: "catalog:" + second.String()}}) suite.Require().NoError(h.Children(ctx)) suite.Equal(http.StatusNotFound, childRec.Code, "the new catalog is not in the cached data") diff --git a/internal/api/handler/lineage_compliant_evidence_integration_test.go b/internal/api/handler/lineage_compliant_evidence_integration_test.go index 485590bf..e40ba011 100644 --- a/internal/api/handler/lineage_compliant_evidence_integration_test.go +++ b/internal/api/handler/lineage_compliant_evidence_integration_test.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" @@ -34,8 +34,7 @@ func (suite *LineageCompliantEvidenceSuite) childrenOf(key string) []LineageNode req := httptest.NewRequest(http.MethodGet, "/x", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).Children(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/lineage_grouping_integration_test.go b/internal/api/handler/lineage_grouping_integration_test.go index f9d8926b..9a8bee35 100644 --- a/internal/api/handler/lineage_grouping_integration_test.go +++ b/internal/api/handler/lineage_grouping_integration_test.go @@ -12,7 +12,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) @@ -30,8 +30,7 @@ func (suite *LineageGroupingSuite) childrenOf(key string) []LineageNode { req := httptest.NewRequest(http.MethodGet, "/x", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).Children(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/lineage_hierarchy_integration_test.go b/internal/api/handler/lineage_hierarchy_integration_test.go index 05bac8b0..7e094c83 100644 --- a/internal/api/handler/lineage_hierarchy_integration_test.go +++ b/internal/api/handler/lineage_hierarchy_integration_test.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) @@ -31,8 +31,7 @@ func (suite *LineageHierarchySuite) children(key string) []LineageNode { req := httptest.NewRequest(http.MethodGet, "/x", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).Children(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/lineage_leverage.go b/internal/api/handler/lineage_leverage.go index 1d10b665..a3607e3b 100644 --- a/internal/api/handler/lineage_leverage.go +++ b/internal/api/handler/lineage_leverage.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" "github.com/compliance-framework/api/internal/api" @@ -73,7 +73,7 @@ type LineageLeverageRow struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /lineage/nodes/{key}/leverage [get] -func (h *LineageHandler) LeverageDetail(ctx echo.Context) error { +func (h *LineageHandler) LeverageDetail(ctx *echo.Context) error { // sspId here is a row filter (which downstream SSP), not a metric scope; componentId // is irrelevant to leverage and is ignored. var sspFilter *uuid.UUID diff --git a/internal/api/handler/lineage_leverage_integration_test.go b/internal/api/handler/lineage_leverage_integration_test.go index bc4ecb36..ebdef094 100644 --- a/internal/api/handler/lineage_leverage_integration_test.go +++ b/internal/api/handler/lineage_leverage_integration_test.go @@ -16,7 +16,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" @@ -157,7 +157,7 @@ func (suite *LineageLeverageSuite) seedInherited() inheritedSeed { } } -func (suite *LineageLeverageSuite) get(handlerCall func(echo.Context) error, path, key, sspID string, out any) { +func (suite *LineageLeverageSuite) get(handlerCall func(*echo.Context) error, path, key, sspID string, out any) { url := path if sspID != "" { url += "?sspId=" + sspID @@ -167,8 +167,7 @@ func (suite *LineageLeverageSuite) get(handlerCall func(echo.Context) error, pat rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) if key != "" { - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) } suite.Require().NoError(handlerCall(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) diff --git a/internal/api/handler/lineage_link_compliance_integration_test.go b/internal/api/handler/lineage_link_compliance_integration_test.go index 80558ea1..f2d722c3 100644 --- a/internal/api/handler/lineage_link_compliance_integration_test.go +++ b/internal/api/handler/lineage_link_compliance_integration_test.go @@ -14,7 +14,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" @@ -33,8 +33,7 @@ func (suite *LineageLinkComplianceSuite) childrenOf(key string) []LineageNode { req := httptest.NewRequest(http.MethodGet, "/x", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).Children(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { @@ -49,8 +48,7 @@ func (suite *LineageLinkComplianceSuite) ssps(key string) []LineageSSPRow { req := httptest.NewRequest(http.MethodGet, "/x", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).SSPDetail(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/lineage_linkcat_integration_test.go b/internal/api/handler/lineage_linkcat_integration_test.go index 6b4561e5..e0089468 100644 --- a/internal/api/handler/lineage_linkcat_integration_test.go +++ b/internal/api/handler/lineage_linkcat_integration_test.go @@ -12,7 +12,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) @@ -30,8 +30,7 @@ func (suite *LineageLinkCatSuite) childrenOf(key string) []LineageNode { req := httptest.NewRequest(http.MethodGet, "/x", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).Children(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/lineage_perf_integration_test.go b/internal/api/handler/lineage_perf_integration_test.go index 59497199..1f6a67d5 100644 --- a/internal/api/handler/lineage_perf_integration_test.go +++ b/internal/api/handler/lineage_perf_integration_test.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" diff --git a/internal/api/handler/lineage_posture_integration_test.go b/internal/api/handler/lineage_posture_integration_test.go index 1716d64c..4524cbb3 100644 --- a/internal/api/handler/lineage_posture_integration_test.go +++ b/internal/api/handler/lineage_posture_integration_test.go @@ -14,7 +14,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" @@ -38,8 +38,7 @@ func (suite *LineagePostureSuite) childrenOf(key, sspID string) []LineageNode { req := httptest.NewRequest(http.MethodGet, url, nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).Children(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/lineage_risk_evidence_integration_test.go b/internal/api/handler/lineage_risk_evidence_integration_test.go index 7aca7aed..96b4ffd4 100644 --- a/internal/api/handler/lineage_risk_evidence_integration_test.go +++ b/internal/api/handler/lineage_risk_evidence_integration_test.go @@ -14,7 +14,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" @@ -33,8 +33,7 @@ func (suite *LineageRiskEvidenceSuite) childrenOf(key string) []LineageNode { req := httptest.NewRequest(http.MethodGet, "/x", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("key") - ctx.SetParamValues(key) + ctx.SetPathValues(echo.PathValues{{Name: "key", Value: key}}) suite.Require().NoError(NewLineageHandler(zap.NewNop().Sugar(), suite.DB).Children(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/notifications.go b/internal/api/handler/notifications.go index abd654a0..f48ac411 100644 --- a/internal/api/handler/notifications.go +++ b/internal/api/handler/notifications.go @@ -21,7 +21,7 @@ import ( slackprovider "github.com/compliance-framework/api/internal/service/notification/providers/slack" notificationtroubleshooting "github.com/compliance-framework/api/internal/service/notificationtroubleshooting" "github.com/compliance-framework/api/internal/service/relational" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -143,7 +143,7 @@ func (h *NotificationsHandler) RegisterPublic(api *echo.Group, guard middleware. // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/health [get] -func (h *NotificationsHandler) GetTroubleshootingHealth(ctx echo.Context) error { +func (h *NotificationsHandler) GetTroubleshootingHealth(ctx *echo.Context) error { response, err := h.troubleshooting.Health(ctx.Request().Context()) if err != nil { h.sugar.Errorw("Failed to get notification troubleshooting health", "error", err) @@ -171,7 +171,7 @@ func (h *NotificationsHandler) GetTroubleshootingHealth(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/jobs [get] -func (h *NotificationsHandler) ListTroubleshootingJobs(ctx echo.Context) error { +func (h *NotificationsHandler) ListTroubleshootingJobs(ctx *echo.Context) error { query, err := parseTroubleshootingJobsQuery(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -201,7 +201,7 @@ func (h *NotificationsHandler) ListTroubleshootingJobs(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/jobs/{id} [get] -func (h *NotificationsHandler) GetTroubleshootingJob(ctx echo.Context) error { +func (h *NotificationsHandler) GetTroubleshootingJob(ctx *echo.Context) error { id, err := strconv.ParseInt(ctx.Param("id"), 10, 64) if err != nil || id <= 0 { return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("invalid job id"))) @@ -231,7 +231,7 @@ func (h *NotificationsHandler) GetTroubleshootingJob(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/{notificationName}/diagnostics [get] -func (h *NotificationsHandler) GetNotificationDiagnostics(ctx echo.Context) error { +func (h *NotificationsHandler) GetNotificationDiagnostics(ctx *echo.Context) error { response, err := h.troubleshooting.Diagnostics(ctx.Request().Context(), ctx.Param("notificationName")) if err != nil { if notificationtroubleshooting.IsUnsupportedNotificationName(err) { @@ -258,7 +258,7 @@ func (h *NotificationsHandler) GetNotificationDiagnostics(ctx echo.Context) erro // @Failure 503 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/test [post] -func (h *NotificationsHandler) SendTestNotification(ctx echo.Context) error { +func (h *NotificationsHandler) SendTestNotification(ctx *echo.Context) error { if h.enqueuer == nil || !h.enqueuer.IsStarted() { return ctx.JSON(http.StatusServiceUnavailable, api.NewError(errors.New("notification worker enqueuer is not available"))) } @@ -345,7 +345,7 @@ func (h *NotificationsHandler) SendTestNotification(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/providers [get] -func (h *NotificationsHandler) ListNotificationProviders(ctx echo.Context) error { +func (h *NotificationsHandler) ListNotificationProviders(ctx *echo.Context) error { catalog, ok := h.providers.(notification.ProviderCatalog) if !ok { err := errors.New("notification provider catalog is not configured") @@ -380,7 +380,7 @@ func (h *NotificationsHandler) ListNotificationProviders(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /notifications/providers [get] -func (h *NotificationsHandler) ListNotificationProviderStatus(ctx echo.Context) error { +func (h *NotificationsHandler) ListNotificationProviderStatus(ctx *echo.Context) error { catalog, ok := h.providers.(notification.ProviderCatalog) if !ok { err := errors.New("notification provider catalog is not configured") @@ -411,7 +411,7 @@ func (h *NotificationsHandler) ListNotificationProviderStatus(ctx echo.Context) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications [get] -func (h *NotificationsHandler) ListSystemNotifications(ctx echo.Context) error { +func (h *NotificationsHandler) ListSystemNotifications(ctx *echo.Context) error { var rows []relational.SystemNotificationDestination if err := h.db.WithContext(ctx.Request().Context()). Order("notification_type ASC, provider ASC, created_at ASC"). @@ -492,7 +492,7 @@ func (h *NotificationsHandler) ListSystemNotifications(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/{notificationName}/destinations [post] -func (h *NotificationsHandler) CreateSystemNotificationDestination(ctx echo.Context) error { +func (h *NotificationsHandler) CreateSystemNotificationDestination(ctx *echo.Context) error { notificationName := ctx.Param("notificationName") canonicalType, ok := notification.NormalizeSystemNotificationName(notificationName) if !ok { @@ -592,7 +592,7 @@ func (h *NotificationsHandler) CreateSystemNotificationDestination(ctx echo.Cont // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/notifications/{notificationName}/destinations [delete] -func (h *NotificationsHandler) DeleteSystemNotificationDestination(ctx echo.Context) error { +func (h *NotificationsHandler) DeleteSystemNotificationDestination(ctx *echo.Context) error { notificationName := ctx.Param("notificationName") canonicalType, ok := notification.NormalizeSystemNotificationName(notificationName) if !ok { @@ -786,7 +786,7 @@ func (h *NotificationsHandler) targetsMatch(left notification.Target, right noti return strings.EqualFold(leftResponse.DestinationTarget, rightResponse.DestinationTarget), nil } -func parseTroubleshootingJobsQuery(ctx echo.Context) (notificationtroubleshooting.JobsQuery, error) { +func parseTroubleshootingJobsQuery(ctx *echo.Context) (notificationtroubleshooting.JobsQuery, error) { query := notificationtroubleshooting.JobsQuery{ Queues: ctx.QueryParams()["queue"], Provider: strings.TrimSpace(ctx.QueryParam("provider")), diff --git a/internal/api/handler/notifications_test.go b/internal/api/handler/notifications_test.go index 0389608f..06add69f 100644 --- a/internal/api/handler/notifications_test.go +++ b/internal/api/handler/notifications_test.go @@ -14,7 +14,7 @@ import ( notificationproviders "github.com/compliance-framework/api/internal/service/notification/providers" emailprovider "github.com/compliance-framework/api/internal/service/notification/providers/email" slackprovider "github.com/compliance-framework/api/internal/service/notification/providers/slack" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/activity.go b/internal/api/handler/oscal/activity.go index 36c7d08b..4338e56f 100644 --- a/internal/api/handler/oscal/activity.go +++ b/internal/api/handler/oscal/activity.go @@ -7,7 +7,7 @@ import ( "go.uber.org/zap" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" "github.com/compliance-framework/api/internal/api" @@ -65,7 +65,7 @@ func (h *ActivityHandler) validateActivityInput(activity *oscalTypes_1_1_3.Activ // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/activities [post] -func (h *ActivityHandler) CreateActivity(ctx echo.Context) error { +func (h *ActivityHandler) CreateActivity(ctx *echo.Context) error { var activity oscalTypes_1_1_3.Activity if err := ctx.Bind(&activity); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -103,7 +103,7 @@ func (h *ActivityHandler) CreateActivity(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/activities/{id} [get] -func (h *ActivityHandler) GetActivity(ctx echo.Context) error { +func (h *ActivityHandler) GetActivity(ctx *echo.Context) error { fmt.Println("Trying to GET activity") idParam := ctx.Param("id") id, err := uuid.Parse(idParam) @@ -139,7 +139,7 @@ func (h *ActivityHandler) GetActivity(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/activities/{id} [put] -func (h *ActivityHandler) UpdateActivity(ctx echo.Context) error { +func (h *ActivityHandler) UpdateActivity(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -207,7 +207,7 @@ func (h *ActivityHandler) UpdateActivity(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/activities/{id} [delete] -func (h *ActivityHandler) DeleteActivity(ctx echo.Context) error { +func (h *ActivityHandler) DeleteActivity(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/activity_integration_test.go b/internal/api/handler/oscal/activity_integration_test.go index a8081ecc..e9a71358 100644 --- a/internal/api/handler/oscal/activity_integration_test.go +++ b/internal/api/handler/oscal/activity_integration_test.go @@ -16,7 +16,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/assessment_results.go b/internal/api/handler/oscal/assessment_results.go index 65784253..ef9f8c3a 100644 --- a/internal/api/handler/oscal/assessment_results.go +++ b/internal/api/handler/oscal/assessment_results.go @@ -8,7 +8,7 @@ import ( "github.com/defenseunicorns/go-oscal/src/pkg/versioning" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -39,7 +39,7 @@ func NewAssessmentResultsHandler(sugar *zap.SugaredLogger, db *gorm.DB) *Assessm } // verifyAssessmentResultsExists checks if an Assessment Results exists by ID and returns appropriate HTTP error if not -func (h *AssessmentResultsHandler) verifyAssessmentResultsExists(ctx echo.Context, arID uuid.UUID) error { +func (h *AssessmentResultsHandler) verifyAssessmentResultsExists(ctx *echo.Context, arID uuid.UUID) error { var ar relational.AssessmentResult if err := h.db.First(&ar, "id = ?", arID).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -254,7 +254,7 @@ func (h *AssessmentResultsHandler) validateAttestationInput(attestation *oscalTy // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results [get] -func (h *AssessmentResultsHandler) List(ctx echo.Context) error { +func (h *AssessmentResultsHandler) List(ctx *echo.Context) error { var assessmentResults []relational.AssessmentResult if err := h.db.Preload("Metadata").Preload("Metadata.Revisions").Find(&assessmentResults).Error; err != nil { h.sugar.Errorw("failed to list assessment results", "error", err) @@ -281,7 +281,7 @@ func (h *AssessmentResultsHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id} [get] -func (h *AssessmentResultsHandler) Get(ctx echo.Context) error { +func (h *AssessmentResultsHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -313,7 +313,7 @@ func (h *AssessmentResultsHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/full [get] -func (h *AssessmentResultsHandler) Full(ctx echo.Context) error { +func (h *AssessmentResultsHandler) Full(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -353,7 +353,7 @@ func (h *AssessmentResultsHandler) Full(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results [post] -func (h *AssessmentResultsHandler) Create(ctx echo.Context) error { +func (h *AssessmentResultsHandler) Create(ctx *echo.Context) error { var oscalAR oscalTypes_1_1_3.AssessmentResults if err := ctx.Bind(&oscalAR); err != nil { h.sugar.Warnw("Invalid create assessment results request", "error", err) @@ -395,7 +395,7 @@ func (h *AssessmentResultsHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id} [put] -func (h *AssessmentResultsHandler) Update(ctx echo.Context) error { +func (h *AssessmentResultsHandler) Update(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -521,7 +521,7 @@ func (h *AssessmentResultsHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id} [delete] -func (h *AssessmentResultsHandler) Delete(ctx echo.Context) error { +func (h *AssessmentResultsHandler) Delete(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -555,7 +555,7 @@ func (h *AssessmentResultsHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/metadata [get] -func (h *AssessmentResultsHandler) GetMetadata(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetMetadata(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -585,7 +585,7 @@ func (h *AssessmentResultsHandler) GetMetadata(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/metadata [put] -func (h *AssessmentResultsHandler) UpdateMetadata(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateMetadata(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -649,7 +649,7 @@ func (h *AssessmentResultsHandler) UpdateMetadata(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/import-ap [get] -func (h *AssessmentResultsHandler) GetImportAp(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetImportAp(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -680,7 +680,7 @@ func (h *AssessmentResultsHandler) GetImportAp(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/import-ap [put] -func (h *AssessmentResultsHandler) UpdateImportAp(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateImportAp(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -746,7 +746,7 @@ func (h *AssessmentResultsHandler) UpdateImportAp(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/local-definitions [get] -func (h *AssessmentResultsHandler) GetLocalDefinitions(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetLocalDefinitions(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -780,7 +780,7 @@ func (h *AssessmentResultsHandler) GetLocalDefinitions(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/local-definitions [put] -func (h *AssessmentResultsHandler) UpdateLocalDefinitions(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateLocalDefinitions(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -858,7 +858,7 @@ func (h *AssessmentResultsHandler) UpdateLocalDefinitions(ctx echo.Context) erro // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results [get] -func (h *AssessmentResultsHandler) GetResults(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResults(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -895,7 +895,7 @@ func (h *AssessmentResultsHandler) GetResults(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results [post] -func (h *AssessmentResultsHandler) CreateResult(ctx echo.Context) error { +func (h *AssessmentResultsHandler) CreateResult(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -955,7 +955,7 @@ func (h *AssessmentResultsHandler) CreateResult(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId} [get] -func (h *AssessmentResultsHandler) GetResult(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResult(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1002,7 +1002,7 @@ func (h *AssessmentResultsHandler) GetResult(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId} [put] -func (h *AssessmentResultsHandler) UpdateResult(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateResult(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1075,7 +1075,7 @@ func (h *AssessmentResultsHandler) UpdateResult(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId} [delete] -func (h *AssessmentResultsHandler) DeleteResult(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DeleteResult(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1138,7 +1138,7 @@ func (h *AssessmentResultsHandler) DeleteResult(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/observations [get] -func (h *AssessmentResultsHandler) GetResultObservations(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResultObservations(ctx *echo.Context) error { idParam := ctx.Param("id") _, err := uuid.Parse(idParam) if err != nil { @@ -1185,7 +1185,7 @@ func (h *AssessmentResultsHandler) GetResultObservations(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/observations [post] -func (h *AssessmentResultsHandler) CreateResultObservation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) CreateResultObservation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1258,7 +1258,7 @@ func (h *AssessmentResultsHandler) CreateResultObservation(ctx echo.Context) err // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/observations/{obsId} [put] -func (h *AssessmentResultsHandler) UpdateResultObservation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateResultObservation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1353,7 +1353,7 @@ func (h *AssessmentResultsHandler) UpdateResultObservation(ctx echo.Context) err // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/observations/{obsId} [delete] -func (h *AssessmentResultsHandler) DeleteResultObservation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DeleteResultObservation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1415,7 +1415,7 @@ func (h *AssessmentResultsHandler) DeleteResultObservation(ctx echo.Context) err // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/risks [get] -func (h *AssessmentResultsHandler) GetResultRisks(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResultRisks(ctx *echo.Context) error { idParam := ctx.Param("id") _, err := uuid.Parse(idParam) if err != nil { @@ -1462,7 +1462,7 @@ func (h *AssessmentResultsHandler) GetResultRisks(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/risks [post] -func (h *AssessmentResultsHandler) CreateResultRisk(ctx echo.Context) error { +func (h *AssessmentResultsHandler) CreateResultRisk(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1535,7 +1535,7 @@ func (h *AssessmentResultsHandler) CreateResultRisk(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/risks/{riskId} [put] -func (h *AssessmentResultsHandler) UpdateResultRisk(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateResultRisk(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1630,7 +1630,7 @@ func (h *AssessmentResultsHandler) UpdateResultRisk(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/risks/{riskId} [delete] -func (h *AssessmentResultsHandler) DeleteResultRisk(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DeleteResultRisk(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1692,7 +1692,7 @@ func (h *AssessmentResultsHandler) DeleteResultRisk(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/findings [get] -func (h *AssessmentResultsHandler) GetResultFindings(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResultFindings(ctx *echo.Context) error { idParam := ctx.Param("id") _, err := uuid.Parse(idParam) if err != nil { @@ -1739,7 +1739,7 @@ func (h *AssessmentResultsHandler) GetResultFindings(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/findings [post] -func (h *AssessmentResultsHandler) CreateResultFinding(ctx echo.Context) error { +func (h *AssessmentResultsHandler) CreateResultFinding(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1812,7 +1812,7 @@ func (h *AssessmentResultsHandler) CreateResultFinding(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/findings/{findingId} [put] -func (h *AssessmentResultsHandler) UpdateResultFinding(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateResultFinding(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1907,7 +1907,7 @@ func (h *AssessmentResultsHandler) UpdateResultFinding(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/findings/{findingId} [delete] -func (h *AssessmentResultsHandler) DeleteResultFinding(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DeleteResultFinding(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1969,7 +1969,7 @@ func (h *AssessmentResultsHandler) DeleteResultFinding(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/attestations [get] -func (h *AssessmentResultsHandler) GetResultAttestations(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResultAttestations(ctx *echo.Context) error { idParam := ctx.Param("id") _, err := uuid.Parse(idParam) if err != nil { @@ -2016,7 +2016,7 @@ func (h *AssessmentResultsHandler) GetResultAttestations(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/attestations [post] -func (h *AssessmentResultsHandler) CreateResultAttestation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) CreateResultAttestation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2090,7 +2090,7 @@ func (h *AssessmentResultsHandler) CreateResultAttestation(ctx echo.Context) err // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/attestations/{attestationId} [put] -func (h *AssessmentResultsHandler) UpdateResultAttestation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateResultAttestation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2179,7 +2179,7 @@ func (h *AssessmentResultsHandler) UpdateResultAttestation(ctx echo.Context) err // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/attestations/{attestationId} [delete] -func (h *AssessmentResultsHandler) DeleteResultAttestation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DeleteResultAttestation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2251,7 +2251,7 @@ func (h *AssessmentResultsHandler) DeleteResultAttestation(ctx echo.Context) err // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-observations [get] -func (h *AssessmentResultsHandler) GetResultAssociatedObservations(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResultAssociatedObservations(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2307,7 +2307,7 @@ func (h *AssessmentResultsHandler) GetResultAssociatedObservations(ctx echo.Cont // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-observations/{observationId} [post] -func (h *AssessmentResultsHandler) AssociateResultObservation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) AssociateResultObservation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2386,7 +2386,7 @@ func (h *AssessmentResultsHandler) AssociateResultObservation(ctx echo.Context) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-observations/{observationId} [delete] -func (h *AssessmentResultsHandler) DisassociateResultObservation(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DisassociateResultObservation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2454,7 +2454,7 @@ func (h *AssessmentResultsHandler) DisassociateResultObservation(ctx echo.Contex // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-risks [get] -func (h *AssessmentResultsHandler) GetResultAssociatedRisks(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResultAssociatedRisks(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2510,7 +2510,7 @@ func (h *AssessmentResultsHandler) GetResultAssociatedRisks(ctx echo.Context) er // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-risks/{riskId} [post] -func (h *AssessmentResultsHandler) AssociateResultRisk(ctx echo.Context) error { +func (h *AssessmentResultsHandler) AssociateResultRisk(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2589,7 +2589,7 @@ func (h *AssessmentResultsHandler) AssociateResultRisk(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-risks/{riskId} [delete] -func (h *AssessmentResultsHandler) DisassociateResultRisk(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DisassociateResultRisk(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2657,7 +2657,7 @@ func (h *AssessmentResultsHandler) DisassociateResultRisk(ctx echo.Context) erro // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-findings [get] -func (h *AssessmentResultsHandler) GetResultAssociatedFindings(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetResultAssociatedFindings(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2713,7 +2713,7 @@ func (h *AssessmentResultsHandler) GetResultAssociatedFindings(ctx echo.Context) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-findings/{findingId} [post] -func (h *AssessmentResultsHandler) AssociateResultFinding(ctx echo.Context) error { +func (h *AssessmentResultsHandler) AssociateResultFinding(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2792,7 +2792,7 @@ func (h *AssessmentResultsHandler) AssociateResultFinding(ctx echo.Context) erro // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/results/{resultId}/associated-findings/{findingId} [delete] -func (h *AssessmentResultsHandler) DisassociateResultFinding(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DisassociateResultFinding(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2859,7 +2859,7 @@ func (h *AssessmentResultsHandler) DisassociateResultFinding(ctx echo.Context) e // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/observations [get] -func (h *AssessmentResultsHandler) GetAllObservations(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetAllObservations(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2900,7 +2900,7 @@ func (h *AssessmentResultsHandler) GetAllObservations(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/risks [get] -func (h *AssessmentResultsHandler) GetAllRisks(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetAllRisks(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2941,7 +2941,7 @@ func (h *AssessmentResultsHandler) GetAllRisks(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/findings [get] -func (h *AssessmentResultsHandler) GetAllFindings(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetAllFindings(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2982,7 +2982,7 @@ func (h *AssessmentResultsHandler) GetAllFindings(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter [get] -func (h *AssessmentResultsHandler) GetBackMatter(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3025,7 +3025,7 @@ func (h *AssessmentResultsHandler) GetBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter [post] -func (h *AssessmentResultsHandler) CreateBackMatter(ctx echo.Context) error { +func (h *AssessmentResultsHandler) CreateBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3120,7 +3120,7 @@ func (h *AssessmentResultsHandler) CreateBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter [put] -func (h *AssessmentResultsHandler) UpdateBackMatter(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3211,7 +3211,7 @@ func (h *AssessmentResultsHandler) UpdateBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter [delete] -func (h *AssessmentResultsHandler) DeleteBackMatter(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DeleteBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3260,7 +3260,7 @@ func (h *AssessmentResultsHandler) DeleteBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter/resources [get] -func (h *AssessmentResultsHandler) GetBackMatterResources(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetBackMatterResources(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3306,7 +3306,7 @@ func (h *AssessmentResultsHandler) GetBackMatterResources(ctx echo.Context) erro // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter/resources [post] -func (h *AssessmentResultsHandler) CreateBackMatterResource(ctx echo.Context) error { +func (h *AssessmentResultsHandler) CreateBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3386,7 +3386,7 @@ func (h *AssessmentResultsHandler) CreateBackMatterResource(ctx echo.Context) er // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter/resources/{resourceId} [put] -func (h *AssessmentResultsHandler) UpdateBackMatterResource(ctx echo.Context) error { +func (h *AssessmentResultsHandler) UpdateBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3468,7 +3468,7 @@ func (h *AssessmentResultsHandler) UpdateBackMatterResource(ctx echo.Context) er // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/back-matter/resources/{resourceId} [delete] -func (h *AssessmentResultsHandler) DeleteBackMatterResource(ctx echo.Context) error { +func (h *AssessmentResultsHandler) DeleteBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3544,7 +3544,7 @@ func (h *AssessmentResultsHandler) validateResourceInput(r *oscalTypes_1_1_3.Res // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/available-controls [get] -func (h *AssessmentResultsHandler) GetAvailableControls(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetAvailableControls(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3594,7 +3594,7 @@ func (h *AssessmentResultsHandler) GetAvailableControls(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-results/{id}/control/{controlId} [get] -func (h *AssessmentResultsHandler) GetControlDetails(ctx echo.Context) error { +func (h *AssessmentResultsHandler) GetControlDetails(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/assessment_results_integration_test.go b/internal/api/handler/oscal/assessment_results_integration_test.go index 9ea16159..9c393921 100644 --- a/internal/api/handler/oscal/assessment_results_integration_test.go +++ b/internal/api/handler/oscal/assessment_results_integration_test.go @@ -19,7 +19,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscaltypes "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/assessmentplan.go b/internal/api/handler/oscal/assessmentplan.go index fae7c3fe..b21b5c22 100644 --- a/internal/api/handler/oscal/assessmentplan.go +++ b/internal/api/handler/oscal/assessmentplan.go @@ -7,7 +7,7 @@ import ( "github.com/defenseunicorns/go-oscal/src/pkg/versioning" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" @@ -71,7 +71,7 @@ func (h *AssessmentPlanHandler) Register(api *echo.Group, guard middleware.Resou } // verifyAssessmentPlanExists checks if an assessment plan exists in the database -func (h *AssessmentPlanHandler) verifyAssessmentPlanExists(ctx echo.Context, planID uuid.UUID) error { +func (h *AssessmentPlanHandler) verifyAssessmentPlanExists(ctx *echo.Context, planID uuid.UUID) error { var count int64 if err := h.db.Model(&relational.AssessmentPlan{}).Where("id = ?", planID).Count(&count).Error; err != nil { h.sugar.Errorw("failed to count assessment plans", "err", err) @@ -94,7 +94,7 @@ func (h *AssessmentPlanHandler) verifyAssessmentPlanExists(ctx echo.Context, pla // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans [get] -func (h *AssessmentPlanHandler) List(ctx echo.Context) error { +func (h *AssessmentPlanHandler) List(ctx *echo.Context) error { var plans []relational.AssessmentPlan if err := h.db. Preload("Metadata"). @@ -124,7 +124,7 @@ func (h *AssessmentPlanHandler) List(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id} [get] -func (h *AssessmentPlanHandler) Get(ctx echo.Context) error { +func (h *AssessmentPlanHandler) Get(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -160,7 +160,7 @@ func (h *AssessmentPlanHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error "Internal server error" // @Security OAuth2Password // @Router /oscal/assessment-plans [post] -func (h *AssessmentPlanHandler) Create(ctx echo.Context) error { +func (h *AssessmentPlanHandler) Create(ctx *echo.Context) error { var request AssessmentPlanCreateRequest err := ctx.Bind(&request.Data) if err != nil { @@ -205,7 +205,7 @@ func (h *AssessmentPlanHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id} [put] -func (h *AssessmentPlanHandler) Update(ctx echo.Context) error { +func (h *AssessmentPlanHandler) Update(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -258,7 +258,7 @@ func (h *AssessmentPlanHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id} [delete] -func (h *AssessmentPlanHandler) Delete(ctx echo.Context) error { +func (h *AssessmentPlanHandler) Delete(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -291,7 +291,7 @@ func (h *AssessmentPlanHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/metadata [get] -func (h *AssessmentPlanHandler) GetMetadata(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetMetadata(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -322,7 +322,7 @@ func (h *AssessmentPlanHandler) GetMetadata(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/import-ssp [get] -func (h *AssessmentPlanHandler) GetImportSsp(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetImportSsp(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -354,7 +354,7 @@ func (h *AssessmentPlanHandler) GetImportSsp(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/local-definitions [get] -func (h *AssessmentPlanHandler) GetLocalDefinitions(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetLocalDefinitions(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -389,7 +389,7 @@ func (h *AssessmentPlanHandler) GetLocalDefinitions(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/terms-and-conditions [get] -func (h *AssessmentPlanHandler) GetTermsAndConditions(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetTermsAndConditions(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -424,7 +424,7 @@ func (h *AssessmentPlanHandler) GetTermsAndConditions(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/back-matter [get] -func (h *AssessmentPlanHandler) GetBackMatter(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetBackMatter(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) @@ -459,7 +459,7 @@ func (h *AssessmentPlanHandler) GetBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/full [get] -func (h *AssessmentPlanHandler) Full(ctx echo.Context) error { +func (h *AssessmentPlanHandler) Full(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.InvalidUUID()) diff --git a/internal/api/handler/oscal/assessmentplan_integration_test.go b/internal/api/handler/oscal/assessmentplan_integration_test.go index ed8c0f34..f272ad89 100644 --- a/internal/api/handler/oscal/assessmentplan_integration_test.go +++ b/internal/api/handler/oscal/assessmentplan_integration_test.go @@ -18,7 +18,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/asset.go b/internal/api/handler/oscal/asset.go index a4b2b7b4..509cb2c5 100644 --- a/internal/api/handler/oscal/asset.go +++ b/internal/api/handler/oscal/asset.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/api/handler" @@ -35,7 +35,7 @@ func (h *AssessmentPlanHandler) validateAssessmentAssetInput(asset *oscalTypes_1 // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-assets [get] -func (h *AssessmentPlanHandler) GetAssessmentAssets(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetAssessmentAssets(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -77,7 +77,7 @@ func (h *AssessmentPlanHandler) GetAssessmentAssets(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-assets [post] -func (h *AssessmentPlanHandler) CreateAssessmentAsset(ctx echo.Context) error { +func (h *AssessmentPlanHandler) CreateAssessmentAsset(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -140,7 +140,7 @@ func (h *AssessmentPlanHandler) CreateAssessmentAsset(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-assets/{assetId} [put] -func (h *AssessmentPlanHandler) UpdateAssessmentAsset(ctx echo.Context) error { +func (h *AssessmentPlanHandler) UpdateAssessmentAsset(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -215,7 +215,7 @@ func (h *AssessmentPlanHandler) UpdateAssessmentAsset(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-assets/{assetId} [delete] -func (h *AssessmentPlanHandler) DeleteAssessmentAsset(ctx echo.Context) error { +func (h *AssessmentPlanHandler) DeleteAssessmentAsset(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/asset_integration_test.go b/internal/api/handler/oscal/asset_integration_test.go index 48d5ce41..057bdee8 100644 --- a/internal/api/handler/oscal/asset_integration_test.go +++ b/internal/api/handler/oscal/asset_integration_test.go @@ -17,7 +17,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/catalogs.go b/internal/api/handler/oscal/catalogs.go index cf947615..a342cbea 100644 --- a/internal/api/handler/oscal/catalogs.go +++ b/internal/api/handler/oscal/catalogs.go @@ -12,7 +12,7 @@ import ( oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" @@ -73,7 +73,7 @@ func (h *CatalogHandler) Register(api *echo.Group, guard middleware.ResourceGuar // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs [get] -func (h *CatalogHandler) List(ctx echo.Context) error { +func (h *CatalogHandler) List(ctx *echo.Context) error { query := h.db. Preload("Metadata"). Preload("Metadata.Revisions") @@ -115,7 +115,7 @@ func (h *CatalogHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id} [get] -func (h *CatalogHandler) Get(ctx echo.Context) error { +func (h *CatalogHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -150,7 +150,7 @@ func (h *CatalogHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id} [delete] -func (h *CatalogHandler) Delete(ctx echo.Context) error { +func (h *CatalogHandler) Delete(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -328,7 +328,7 @@ func (h *CatalogHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups/{group} [delete] -func (h *CatalogHandler) DeleteGroup(ctx echo.Context) error { +func (h *CatalogHandler) DeleteGroup(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -409,7 +409,7 @@ func (h *CatalogHandler) DeleteGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/controls/{control} [delete] -func (h *CatalogHandler) DeleteControl(ctx echo.Context) error { +func (h *CatalogHandler) DeleteControl(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -468,7 +468,7 @@ func (h *CatalogHandler) DeleteControl(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs [post] -func (h *CatalogHandler) Create(ctx echo.Context) error { +func (h *CatalogHandler) Create(ctx *echo.Context) error { now := time.Now() var oscalCat oscalTypes_1_1_3.Catalog @@ -510,7 +510,7 @@ func (h *CatalogHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id} [put] -func (h *CatalogHandler) Update(ctx echo.Context) error { +func (h *CatalogHandler) Update(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -555,7 +555,7 @@ func (h *CatalogHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/active [put] -func (h *CatalogHandler) SetActive(ctx echo.Context) error { +func (h *CatalogHandler) SetActive(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -618,7 +618,7 @@ func (h *CatalogHandler) SetActive(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/back-matter [get] -func (h *CatalogHandler) GetBackMatter(ctx echo.Context) error { +func (h *CatalogHandler) GetBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -660,7 +660,7 @@ func (h *CatalogHandler) GetBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups/{group} [get] -func (h *CatalogHandler) GetGroup(ctx echo.Context) error { +func (h *CatalogHandler) GetGroup(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -695,7 +695,7 @@ func (h *CatalogHandler) GetGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups [get] -func (h *CatalogHandler) GetGroups(ctx echo.Context) error { +func (h *CatalogHandler) GetGroups(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -733,7 +733,7 @@ func (h *CatalogHandler) GetGroups(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups/{group}/groups [get] -func (h *CatalogHandler) GetGroupSubGroups(ctx echo.Context) error { +func (h *CatalogHandler) GetGroupSubGroups(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -773,7 +773,7 @@ func (h *CatalogHandler) GetGroupSubGroups(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups/{group}/controls [get] -func (h *CatalogHandler) GetGroupControls(ctx echo.Context) error { +func (h *CatalogHandler) GetGroupControls(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -813,7 +813,7 @@ func (h *CatalogHandler) GetGroupControls(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups [post] -func (h *CatalogHandler) CreateGroup(ctx echo.Context) error { +func (h *CatalogHandler) CreateGroup(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -863,7 +863,7 @@ func (h *CatalogHandler) CreateGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups/{group} [put] -func (h *CatalogHandler) UpdateGroup(ctx echo.Context) error { +func (h *CatalogHandler) UpdateGroup(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -906,7 +906,7 @@ func (h *CatalogHandler) UpdateGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups/{group}/groups [post] -func (h *CatalogHandler) CreateGroupSubGroup(ctx echo.Context) error { +func (h *CatalogHandler) CreateGroupSubGroup(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -958,7 +958,7 @@ func (h *CatalogHandler) CreateGroupSubGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/groups/{group}/controls [post] -func (h *CatalogHandler) CreateGroupControl(ctx echo.Context) error { +func (h *CatalogHandler) CreateGroupControl(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -1009,7 +1009,7 @@ func (h *CatalogHandler) CreateGroupControl(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/controls/{control} [get] -func (h *CatalogHandler) GetControl(ctx echo.Context) error { +func (h *CatalogHandler) GetControl(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1044,7 +1044,7 @@ func (h *CatalogHandler) GetControl(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/controls [get] -func (h *CatalogHandler) GetControls(ctx echo.Context) error { +func (h *CatalogHandler) GetControls(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1082,7 +1082,7 @@ func (h *CatalogHandler) GetControls(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/all-controls [get] -func (h *CatalogHandler) GetAllControls(ctx echo.Context) error { +func (h *CatalogHandler) GetAllControls(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1120,7 +1120,7 @@ func (h *CatalogHandler) GetAllControls(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/controls/{control}/controls [get] -func (h *CatalogHandler) GetControlSubControls(ctx echo.Context) error { +func (h *CatalogHandler) GetControlSubControls(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1162,7 +1162,7 @@ func (h *CatalogHandler) GetControlSubControls(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/controls [post] -func (h *CatalogHandler) CreateControl(ctx echo.Context) error { +func (h *CatalogHandler) CreateControl(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -1211,7 +1211,7 @@ func (h *CatalogHandler) CreateControl(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/controls/{control} [put] -func (h *CatalogHandler) UpdateControl(ctx echo.Context) error { +func (h *CatalogHandler) UpdateControl(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -1254,7 +1254,7 @@ func (h *CatalogHandler) UpdateControl(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/catalogs/{id}/controls/{control}/controls [post] -func (h *CatalogHandler) CreateControlSubControl(ctx echo.Context) error { +func (h *CatalogHandler) CreateControlSubControl(ctx *echo.Context) error { idParam := ctx.Param("id") catalogID, err := uuid.Parse(idParam) if err != nil { @@ -1292,7 +1292,7 @@ func (h *CatalogHandler) CreateControlSubControl(ctx echo.Context) error { return ctx.JSON(http.StatusCreated, handler.GenericDataResponse[oscalTypes_1_1_3.Control]{Data: *relCtl.MarshalOscal()}) } -func (h *CatalogHandler) Full(ctx echo.Context) error { +func (h *CatalogHandler) Full(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/catalogs_integration_test.go b/internal/api/handler/oscal/catalogs_integration_test.go index 54a111d7..cc1d534d 100644 --- a/internal/api/handler/oscal/catalogs_integration_test.go +++ b/internal/api/handler/oscal/catalogs_integration_test.go @@ -18,7 +18,7 @@ import ( evidencesvc "github.com/compliance-framework/api/internal/service/relational/evidence" "github.com/compliance-framework/api/internal/tests" oscaltypes "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "go.uber.org/zap" "gorm.io/datatypes" diff --git a/internal/api/handler/oscal/component_definition.go b/internal/api/handler/oscal/component_definition.go index b8fc93b4..5de07911 100644 --- a/internal/api/handler/oscal/component_definition.go +++ b/internal/api/handler/oscal/component_definition.go @@ -11,7 +11,7 @@ import ( oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -79,7 +79,7 @@ func (h *ComponentDefinitionHandler) Register(api *echo.Group, guard middleware. // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions [get] -func (h *ComponentDefinitionHandler) List(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) List(ctx *echo.Context) error { var componentDefinitions []relational.ComponentDefinition if err := h.db. Preload("Metadata"). @@ -111,7 +111,7 @@ func (h *ComponentDefinitionHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id} [get] -func (h *ComponentDefinitionHandler) Get(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -149,7 +149,7 @@ func (h *ComponentDefinitionHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions [post] -func (h *ComponentDefinitionHandler) Create(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) Create(ctx *echo.Context) error { now := time.Now() var oscalCat oscalTypes_1_1_3.ComponentDefinition @@ -184,7 +184,7 @@ func (h *ComponentDefinitionHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id} [put] -func (h *ComponentDefinitionHandler) Update(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) Update(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -277,7 +277,7 @@ func (h *ComponentDefinitionHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/full [get] -func (h *ComponentDefinitionHandler) Full(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) Full(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -332,7 +332,7 @@ func (h *ComponentDefinitionHandler) Full(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/import-component-definitions [get] -func (h *ComponentDefinitionHandler) GetImportComponentDefinitions(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetImportComponentDefinitions(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -371,7 +371,7 @@ func (h *ComponentDefinitionHandler) GetImportComponentDefinitions(ctx echo.Cont // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/import-component-definitions [post] -func (h *ComponentDefinitionHandler) CreateImportComponentDefinitions(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) CreateImportComponentDefinitions(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -458,7 +458,7 @@ func (h *ComponentDefinitionHandler) CreateImportComponentDefinitions(ctx echo.C // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/import-component-definitions [put] -func (h *ComponentDefinitionHandler) UpdateImportComponentDefinitions(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) UpdateImportComponentDefinitions(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -543,7 +543,7 @@ func (h *ComponentDefinitionHandler) UpdateImportComponentDefinitions(ctx echo.C // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components [get] -func (h *ComponentDefinitionHandler) GetComponents(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetComponents(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -585,7 +585,7 @@ func (h *ComponentDefinitionHandler) GetComponents(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components [post] -func (h *ComponentDefinitionHandler) CreateComponents(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) CreateComponents(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -688,7 +688,7 @@ func (h *ComponentDefinitionHandler) CreateComponents(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components [put] -func (h *ComponentDefinitionHandler) UpdateComponents(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) UpdateComponents(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -812,7 +812,7 @@ func (h *ComponentDefinitionHandler) UpdateComponents(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component} [get] -func (h *ComponentDefinitionHandler) GetDefinedComponent(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetDefinedComponent(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -862,7 +862,7 @@ func (h *ComponentDefinitionHandler) GetDefinedComponent(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component} [post] -func (h *ComponentDefinitionHandler) CreateDefinedComponent(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) CreateDefinedComponent(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -949,7 +949,7 @@ func (h *ComponentDefinitionHandler) CreateDefinedComponent(ctx echo.Context) er // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component} [put] -func (h *ComponentDefinitionHandler) UpdateDefinedComponent(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) UpdateDefinedComponent(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1060,7 +1060,7 @@ func (h *ComponentDefinitionHandler) UpdateDefinedComponent(ctx echo.Context) er // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations [get] -func (h *ComponentDefinitionHandler) GetControlImplementations(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetControlImplementations(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1147,7 +1147,7 @@ func (h *ComponentDefinitionHandler) GetControlImplementations(ctx echo.Context) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations [post] -func (h *ComponentDefinitionHandler) CreateControlImplementations(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) CreateControlImplementations(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1228,7 +1228,7 @@ func (h *ComponentDefinitionHandler) CreateControlImplementations(ctx echo.Conte // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations/implemented-requirements [get] -func (h *ComponentDefinitionHandler) GetImplementedRequirements(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetImplementedRequirements(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1284,7 +1284,7 @@ func (h *ComponentDefinitionHandler) GetImplementedRequirements(ctx echo.Context // // @Failure 500 {object} api.Error // // @Security OAuth2Password // // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations/implemented-requirements [post] -// func (h *ComponentDefinitionHandler) CreateImplementedRequirements(ctx echo.Context) error { +// func (h *ComponentDefinitionHandler) CreateImplementedRequirements(ctx *echo.Context) error { // idParam := ctx.Param("id") // id, err := uuid.Parse(idParam) // if err != nil { @@ -1367,7 +1367,7 @@ func (h *ComponentDefinitionHandler) GetImplementedRequirements(ctx echo.Context // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations/implemented-requirements/statements [get] -func (h *ComponentDefinitionHandler) GetStatements(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetStatements(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1428,7 +1428,7 @@ func (h *ComponentDefinitionHandler) GetStatements(ctx echo.Context) error { // // @Failure 500 {object} api.Error // // @Security OAuth2Password // // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations/statements [post] -// func (h *ComponentDefinitionHandler) CreateStatements(ctx echo.Context) error { +// func (h *ComponentDefinitionHandler) CreateStatements(ctx *echo.Context) error { // idParam := ctx.Param("id") // id, err := uuid.Parse(idParam) // if err != nil { @@ -1531,7 +1531,7 @@ func (h *ComponentDefinitionHandler) GetStatements(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/capabilities [get] -func (h *ComponentDefinitionHandler) GetCapabilities(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetCapabilities(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1573,7 +1573,7 @@ func (h *ComponentDefinitionHandler) GetCapabilities(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/capabilities [post] -func (h *ComponentDefinitionHandler) CreateCapabilities(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) CreateCapabilities(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1678,7 +1678,7 @@ func (h *ComponentDefinitionHandler) CreateCapabilities(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/capabilities/incorporates-components [get] -func (h *ComponentDefinitionHandler) GetIncorporatesComponents(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetIncorporatesComponents(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1737,7 +1737,7 @@ func (h *ComponentDefinitionHandler) GetIncorporatesComponents(ctx echo.Context) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/capabilities/incorporates-components [post] -func (h *ComponentDefinitionHandler) CreateIncorporatesComponents(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) CreateIncorporatesComponents(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1808,7 +1808,7 @@ func (h *ComponentDefinitionHandler) CreateIncorporatesComponents(ctx echo.Conte // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/back-matter [get] -func (h *ComponentDefinitionHandler) GetBackMatter(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) GetBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1852,7 +1852,7 @@ func (h *ComponentDefinitionHandler) GetBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/back-matter [post] -func (h *ComponentDefinitionHandler) CreateBackMatter(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) CreateBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1950,7 +1950,7 @@ func (h *ComponentDefinitionHandler) CreateBackMatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations [put] -func (h *ComponentDefinitionHandler) UpdateControlImplementations(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) UpdateControlImplementations(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2052,7 +2052,7 @@ func (h *ComponentDefinitionHandler) UpdateControlImplementations(ctx echo.Conte // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/components/{defined-component}/control-implementations/{control-implementation} [put] -func (h *ComponentDefinitionHandler) UpdateSingleControlImplementation(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) UpdateSingleControlImplementation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2160,7 +2160,7 @@ func (h *ComponentDefinitionHandler) UpdateSingleControlImplementation(ctx echo. // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/component-definitions/{id}/capabilities/{capability} [put] -func (h *ComponentDefinitionHandler) UpdateCapability(ctx echo.Context) error { +func (h *ComponentDefinitionHandler) UpdateCapability(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/component_definition_integration_test.go b/internal/api/handler/oscal/component_definition_integration_test.go index 6e6b48e0..3dfc5514 100644 --- a/internal/api/handler/oscal/component_definition_integration_test.go +++ b/internal/api/handler/oscal/component_definition_integration_test.go @@ -18,7 +18,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscaltypes "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/dashboard_suggestion_diagnostics.go b/internal/api/handler/oscal/dashboard_suggestion_diagnostics.go index de54168f..d4096187 100644 --- a/internal/api/handler/oscal/dashboard_suggestion_diagnostics.go +++ b/internal/api/handler/oscal/dashboard_suggestion_diagnostics.go @@ -18,7 +18,7 @@ import ( suggestionrel "github.com/compliance-framework/api/internal/service/relational/suggestions" workersvc "github.com/compliance-framework/api/internal/service/worker" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -175,7 +175,7 @@ func (h *AiDiagnosticsHandler) Register(apiGroup *echo.Group) { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ai-diagnostics/summary [get] -func (h *AiDiagnosticsHandler) Summary(ctx echo.Context) error { +func (h *AiDiagnosticsHandler) Summary(ctx *echo.Context) error { totals, recent, err := h.loadTotals(ctx.Request().Context()) if err != nil { return ctx.JSON(http.StatusInternalServerError, api.NewError(err)) @@ -210,7 +210,7 @@ func (h *AiDiagnosticsHandler) Summary(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ai-diagnostics/runs [get] -func (h *AiDiagnosticsHandler) Runs(ctx echo.Context) error { +func (h *AiDiagnosticsHandler) Runs(ctx *echo.Context) error { query, err := parseAiDiagnosticsRunsQuery(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -239,7 +239,7 @@ func (h *AiDiagnosticsHandler) Runs(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ai-diagnostics/runs/{runId} [get] -func (h *AiDiagnosticsHandler) RunDetail(ctx echo.Context) error { +func (h *AiDiagnosticsHandler) RunDetail(ctx *echo.Context) error { runID, err := uuid.Parse(ctx.Param("runId")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -303,7 +303,7 @@ type aiDiagnosticsRunsQuery struct { runID *uuid.UUID } -func parseAiDiagnosticsRunsQuery(ctx echo.Context) (aiDiagnosticsRunsQuery, error) { +func parseAiDiagnosticsRunsQuery(ctx *echo.Context) (aiDiagnosticsRunsQuery, error) { limit := 25 if raw := strings.TrimSpace(ctx.QueryParam("limit")); raw != "" { parsed, err := strconv.Atoi(raw) diff --git a/internal/api/handler/oscal/dashboard_suggestions.go b/internal/api/handler/oscal/dashboard_suggestions.go index 55c8efd3..f7270811 100644 --- a/internal/api/handler/oscal/dashboard_suggestions.go +++ b/internal/api/handler/oscal/dashboard_suggestions.go @@ -22,7 +22,7 @@ import ( workersvc "github.com/compliance-framework/api/internal/service/worker" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgconn" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -185,7 +185,7 @@ func (h *DashboardSuggestionHandler) Register(apiGroup *echo.Group, auth echo.Mi // @Produce json // @Success 200 {object} handler.GenericDataResponse[oscal.dashboardSuggestionConfigResponse] // @Router /dashboard-suggestions/config [get] -func (h *DashboardSuggestionHandler) Config(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) Config(ctx *echo.Context) error { return ctx.JSON(http.StatusOK, handler.GenericDataResponse[dashboardSuggestionConfigResponse]{ Data: dashboardSuggestionConfigResponse{Enabled: h.aiEnabled()}, }) @@ -209,7 +209,7 @@ func (h *DashboardSuggestionHandler) Config(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/generate [post] -func (h *DashboardSuggestionHandler) Generate(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) Generate(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -319,7 +319,7 @@ type generalizeDashboardSuggestionsResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/generalize [post] -func (h *DashboardSuggestionHandler) Generalize(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) Generalize(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -364,7 +364,7 @@ func (h *DashboardSuggestionHandler) Generalize(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/preview [post] -func (h *DashboardSuggestionHandler) Preview(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) Preview(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -406,7 +406,7 @@ func (h *DashboardSuggestionHandler) Preview(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/label-sets [get] -func (h *DashboardSuggestionHandler) LabelSets(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) LabelSets(ctx *echo.Context) error { filter, ok := h.labelPickerFilter(ctx, false) if !ok { return nil @@ -433,7 +433,7 @@ func (h *DashboardSuggestionHandler) LabelSets(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/label-keys [get] -func (h *DashboardSuggestionHandler) LabelKeys(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) LabelKeys(ctx *echo.Context) error { filter, ok := h.labelPickerFilter(ctx, true) if !ok { return nil @@ -462,7 +462,7 @@ func (h *DashboardSuggestionHandler) LabelKeys(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/label-values [get] -func (h *DashboardSuggestionHandler) LabelValues(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) LabelValues(ctx *echo.Context) error { filter, ok := h.labelPickerFilter(ctx, true) if !ok { return nil @@ -490,7 +490,7 @@ func (h *DashboardSuggestionHandler) LabelValues(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestion-runs/latest [get] -func (h *DashboardSuggestionHandler) LatestRun(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) LatestRun(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -517,7 +517,7 @@ func (h *DashboardSuggestionHandler) LatestRun(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestion-runs/{runId} [get] -func (h *DashboardSuggestionHandler) GetRun(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) GetRun(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -547,7 +547,7 @@ func (h *DashboardSuggestionHandler) GetRun(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions [get] -func (h *DashboardSuggestionHandler) ListSuggestions(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) ListSuggestions(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -576,7 +576,7 @@ func (h *DashboardSuggestionHandler) ListSuggestions(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/control-results [get] -func (h *DashboardSuggestionHandler) ControlResults(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) ControlResults(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -619,7 +619,7 @@ func (h *DashboardSuggestionHandler) ControlResults(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/accept [post] -func (h *DashboardSuggestionHandler) Accept(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) Accept(ctx *echo.Context) error { sspID, req, actorID, ok := h.bindDecision(ctx) if !ok { return nil @@ -663,7 +663,7 @@ func (h *DashboardSuggestionHandler) Accept(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/reject [post] -func (h *DashboardSuggestionHandler) Reject(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) Reject(ctx *echo.Context) error { sspID, req, actorID, ok := h.bindDecision(ctx) if !ok { return nil @@ -694,7 +694,7 @@ func (h *DashboardSuggestionHandler) Reject(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/edit-group [post] -func (h *DashboardSuggestionHandler) EditGroup(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) EditGroup(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -747,7 +747,7 @@ func (h *DashboardSuggestionHandler) EditGroup(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/dashboard-suggestions/{suggestionId}/events [get] -func (h *DashboardSuggestionHandler) Events(ctx echo.Context) error { +func (h *DashboardSuggestionHandler) Events(ctx *echo.Context) error { sspID, err := parseUUIDParam(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -945,11 +945,11 @@ func snapshotJSON(snapshot suggestionrel.Snapshot) datatypes.JSONMap { } } -func parseUUIDParam(ctx echo.Context, name string) (uuid.UUID, error) { +func parseUUIDParam(ctx *echo.Context, name string) (uuid.UUID, error) { return uuid.Parse(ctx.Param(name)) } -func (h *DashboardSuggestionHandler) actorUserID(ctx echo.Context) (*uuid.UUID, error) { +func (h *DashboardSuggestionHandler) actorUserID(ctx *echo.Context) (*uuid.UUID, error) { claims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || claims == nil { return nil, ctx.JSON(http.StatusUnauthorized, api.NewError(fmt.Errorf("missing authentication claims"))) @@ -964,7 +964,7 @@ func (h *DashboardSuggestionHandler) actorUserID(ctx echo.Context) (*uuid.UUID, return user.ID, nil } -func (h *DashboardSuggestionHandler) bindDecision(ctx echo.Context) (uuid.UUID, dashboardSuggestionDecisionRequest, *uuid.UUID, bool) { +func (h *DashboardSuggestionHandler) bindDecision(ctx *echo.Context) (uuid.UUID, dashboardSuggestionDecisionRequest, *uuid.UUID, bool) { sspID, err := parseUUIDParam(ctx, "id") if err != nil { _ = ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1081,7 +1081,7 @@ func jsonMapFrom(value any) (datatypes.JSONMap, error) { return out, nil } -func (h *DashboardSuggestionHandler) respondRun(ctx echo.Context, run suggestionrel.DashboardSuggestionRun) error { +func (h *DashboardSuggestionHandler) respondRun(ctx *echo.Context, run suggestionrel.DashboardSuggestionRun) error { completed, failed, err := h.cellProgress(*run.ID) if err != nil { return ctx.JSON(http.StatusInternalServerError, api.NewError(err)) @@ -1163,7 +1163,7 @@ func (e *emptyDashboardSuggestionScopeError) Error() string { return e.message } -func (h *DashboardSuggestionHandler) generateError(ctx echo.Context, err error) error { +func (h *DashboardSuggestionHandler) generateError(ctx *echo.Context, err error) error { if errors.Is(err, sspscope.ErrSSPNotFound) { return ctx.JSON(http.StatusNotFound, api.NewError(err)) } @@ -1198,7 +1198,7 @@ func (h *DashboardSuggestionHandler) generateError(ctx echo.Context, err error) return ctx.JSON(http.StatusInternalServerError, api.NewError(err)) } -func (h *DashboardSuggestionHandler) decisionError(ctx echo.Context, err error) error { +func (h *DashboardSuggestionHandler) decisionError(ctx *echo.Context, err error) error { var conflict *suggestionrel.ConflictError if errors.As(err, &conflict) { return ctx.JSON(http.StatusConflict, api.NewError(err)) @@ -1210,7 +1210,7 @@ func (h *DashboardSuggestionHandler) decisionError(ctx echo.Context, err error) return ctx.JSON(http.StatusInternalServerError, api.NewError(err)) } -func (h *DashboardSuggestionHandler) notFoundOrInternal(ctx echo.Context, err error) error { +func (h *DashboardSuggestionHandler) notFoundOrInternal(ctx *echo.Context, err error) error { if errors.Is(err, gorm.ErrRecordNotFound) { return ctx.JSON(http.StatusNotFound, api.NewError(err)) } @@ -1241,7 +1241,7 @@ func scopedLabelFilter(db *gorm.DB, sspID uuid.UUID, requested *labelfilter.Filt // ?ignoreScope=true returns nil (all evidence): the scope editor needs labels that are // not in the scope yet. On failure it has already written the response and returns // ok=false. -func (h *DashboardSuggestionHandler) labelPickerFilter(ctx echo.Context, allowIgnore bool) (*labelfilter.Filter, bool) { +func (h *DashboardSuggestionHandler) labelPickerFilter(ctx *echo.Context, allowIgnore bool) (*labelfilter.Filter, bool) { sspID, err := parseUUIDParam(ctx, "id") if err != nil { _ = ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/oscal/dashboard_suggestions_integration_test.go b/internal/api/handler/oscal/dashboard_suggestions_integration_test.go index fdf078cd..cb384d07 100644 --- a/internal/api/handler/oscal/dashboard_suggestions_integration_test.go +++ b/internal/api/handler/oscal/dashboard_suggestions_integration_test.go @@ -21,7 +21,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" diff --git a/internal/api/handler/oscal/import.go b/internal/api/handler/oscal/import.go index 913874b3..1af277ba 100644 --- a/internal/api/handler/oscal/import.go +++ b/internal/api/handler/oscal/import.go @@ -14,7 +14,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -62,7 +62,7 @@ type ImportResponse struct { // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/import [post] -func (h *ImportHandler) ImportOSCAL(ctx echo.Context) error { +func (h *ImportHandler) ImportOSCAL(ctx *echo.Context) error { form, err := ctx.MultipartForm() if err != nil { h.sugar.Errorw("Failed to parse multipart form", "error", err) diff --git a/internal/api/handler/oscal/import_integration_test.go b/internal/api/handler/oscal/import_integration_test.go index bb2eb0fa..b9f16154 100644 --- a/internal/api/handler/oscal/import_integration_test.go +++ b/internal/api/handler/oscal/import_integration_test.go @@ -13,7 +13,7 @@ import ( "testing" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/oscal/import_unit_test.go b/internal/api/handler/oscal/import_unit_test.go index 0e5d580b..d6e2a4b9 100644 --- a/internal/api/handler/oscal/import_unit_test.go +++ b/internal/api/handler/oscal/import_unit_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/datatypes" @@ -32,8 +32,9 @@ func registeredSSPRoutes(t *testing.T) []string { NewSystemSecurityPlanHandler(zap.NewNop().Sugar(), nil, nil, nil). Register(e.Group("/api/oscal/system-security-plans"), pep.For(authz.ResourceSSP)) - routes := make([]string, 0, len(e.Routes())) - for _, route := range e.Routes() { + registered := e.Router().Routes() + routes := make([]string, 0, len(registered)) + for _, route := range registered { routes = append(routes, route.Method+" "+route.Path) } return routes diff --git a/internal/api/handler/oscal/inventory.go b/internal/api/handler/oscal/inventory.go index 556ab5cf..7cc266e4 100644 --- a/internal/api/handler/oscal/inventory.go +++ b/internal/api/handler/oscal/inventory.go @@ -10,7 +10,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -101,7 +101,7 @@ type GetAllInventoryItemsRequest struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/inventory [get] -func (h *InventoryHandler) GetAllInventoryItems(ctx echo.Context) error { +func (h *InventoryHandler) GetAllInventoryItems(ctx *echo.Context) error { // Get query parameters directly req := GetAllInventoryItemsRequest{ IncludeSSP: ctx.QueryParam("include_ssp"), @@ -382,7 +382,7 @@ func (h *InventoryHandler) applyFilters(items []InventoryItemWithSource, req Get // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/inventory/{id} [get] -func (h *InventoryHandler) GetInventoryItem(ctx echo.Context) error { +func (h *InventoryHandler) GetInventoryItem(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -441,7 +441,7 @@ func (h *InventoryHandler) GetInventoryItem(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/inventory [post] -func (h *InventoryHandler) CreateInventoryItem(ctx echo.Context) error { +func (h *InventoryHandler) CreateInventoryItem(ctx *echo.Context) error { var req CreateInventoryItemRequest if err := ctx.Bind(&req); err != nil { h.sugar.Warnw("Invalid create inventory item request", "error", err) diff --git a/internal/api/handler/oscal/inventory_integration_test.go b/internal/api/handler/oscal/inventory_integration_test.go index 67f3374a..583f6705 100644 --- a/internal/api/handler/oscal/inventory_integration_test.go +++ b/internal/api/handler/oscal/inventory_integration_test.go @@ -13,7 +13,7 @@ import ( "time" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/oscal/parties.go b/internal/api/handler/oscal/parties.go index 23716bf2..34d49eef 100644 --- a/internal/api/handler/oscal/parties.go +++ b/internal/api/handler/oscal/parties.go @@ -7,7 +7,7 @@ import ( "github.com/compliance-framework/api/internal/api" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" @@ -45,7 +45,7 @@ func (h *PartyHandler) Register(api *echo.Group, guard middleware.ResourceGuard) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/parties [get] -func (h *PartyHandler) List(ctx echo.Context) error { +func (h *PartyHandler) List(ctx *echo.Context) error { var parties []relational.Party if err := h.db. Preload("Locations"). @@ -77,7 +77,7 @@ func (h *PartyHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/parties/{id} [get] -func (h *PartyHandler) Get(ctx echo.Context) error { +func (h *PartyHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/plan_of_action_and_milestones.go b/internal/api/handler/oscal/plan_of_action_and_milestones.go index c348ddac..be58af52 100644 --- a/internal/api/handler/oscal/plan_of_action_and_milestones.go +++ b/internal/api/handler/oscal/plan_of_action_and_milestones.go @@ -11,7 +11,7 @@ import ( "github.com/defenseunicorns/go-oscal/src/pkg/versioning" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -42,7 +42,7 @@ func NewPlanOfActionAndMilestonesHandler(sugar *zap.SugaredLogger, db *gorm.DB) } // verifyPoamExists checks if a POA&M exists by ID and returns appropriate HTTP error if not -func (h *PlanOfActionAndMilestonesHandler) verifyPoamExists(ctx echo.Context, poamID uuid.UUID) error { +func (h *PlanOfActionAndMilestonesHandler) verifyPoamExists(ctx *echo.Context, poamID uuid.UUID) error { var poam relational.PlanOfActionAndMilestones if err := h.db.First(&poam, "id = ?", poamID).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -205,7 +205,7 @@ func (h *PlanOfActionAndMilestonesHandler) validatePoamItemInput(item *oscalType // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones [get] -func (h *PlanOfActionAndMilestonesHandler) List(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) List(ctx *echo.Context) error { var poams []relational.PlanOfActionAndMilestones if err := h.db.Preload("Metadata").Preload("Metadata.Revisions").Find(&poams).Error; err != nil { h.sugar.Errorw("failed to list poams", "error", err) @@ -231,7 +231,7 @@ func (h *PlanOfActionAndMilestonesHandler) List(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id} [get] -func (h *PlanOfActionAndMilestonesHandler) Get(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -262,7 +262,7 @@ func (h *PlanOfActionAndMilestonesHandler) Get(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/full [get] -func (h *PlanOfActionAndMilestonesHandler) Full(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) Full(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -292,7 +292,7 @@ func (h *PlanOfActionAndMilestonesHandler) Full(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/observations [get] -func (h *PlanOfActionAndMilestonesHandler) GetObservations(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetObservations(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -326,7 +326,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetObservations(ctx echo.Context) err // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/risks [get] -func (h *PlanOfActionAndMilestonesHandler) GetRisks(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetRisks(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -361,7 +361,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetRisks(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/findings [get] -func (h *PlanOfActionAndMilestonesHandler) GetFindings(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetFindings(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -395,7 +395,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetFindings(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/poam-items [get] -func (h *PlanOfActionAndMilestonesHandler) GetPoamItems(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetPoamItems(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -429,7 +429,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetPoamItems(ctx echo.Context) error // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/metadata [get] -func (h *PlanOfActionAndMilestonesHandler) GetMetadata(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetMetadata(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -458,7 +458,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetMetadata(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/metadata [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateMetadata(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateMetadata(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -521,7 +521,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateMetadata(ctx echo.Context) erro // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/import-ssp [get] -func (h *PlanOfActionAndMilestonesHandler) GetImportSsp(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetImportSsp(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -554,7 +554,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetImportSsp(ctx echo.Context) error // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/import-ssp [post] -func (h *PlanOfActionAndMilestonesHandler) CreateImportSsp(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreateImportSsp(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -614,7 +614,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreateImportSsp(ctx echo.Context) err // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/import-ssp [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateImportSsp(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateImportSsp(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -672,7 +672,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateImportSsp(ctx echo.Context) err // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/system-id [get] -func (h *PlanOfActionAndMilestonesHandler) GetSystemId(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetSystemId(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -705,7 +705,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetSystemId(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/system-id [post] -func (h *PlanOfActionAndMilestonesHandler) CreateSystemId(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreateSystemId(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -765,7 +765,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreateSystemId(ctx echo.Context) erro // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/system-id [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateSystemId(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateSystemId(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -823,7 +823,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateSystemId(ctx echo.Context) erro // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/local-definitions [get] -func (h *PlanOfActionAndMilestonesHandler) GetLocalDefinitions(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetLocalDefinitions(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -860,7 +860,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetLocalDefinitions(ctx echo.Context) // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/local-definitions [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateLocalDefinitions(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateLocalDefinitions(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1024,7 +1024,7 @@ func hasAssessmentAssets(assets datatypes.JSONType[oscalTypes_1_1_3.AssessmentAs } // deleteLocalDefinitionsForPOAM handles the deletion of entire local-definitions when empty payload is sent -func (h *PlanOfActionAndMilestonesHandler) deleteLocalDefinitionsForPOAM(ctx echo.Context, existingPoam relational.PlanOfActionAndMilestones) error { +func (h *PlanOfActionAndMilestonesHandler) deleteLocalDefinitionsForPOAM(ctx *echo.Context, existingPoam relational.PlanOfActionAndMilestones) error { // Clear the local-definitions field emptyLocalDefs := relational.PlanOfActionAndMilestonesLocalDefinitions{} if err := h.db.Model(&existingPoam).Update("local_definitions", datatypes.NewJSONType(emptyLocalDefs)).Error; err != nil { @@ -1047,7 +1047,7 @@ func (h *PlanOfActionAndMilestonesHandler) deleteLocalDefinitionsForPOAM(ctx ech // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/back-matter [get] -func (h *PlanOfActionAndMilestonesHandler) GetBackMatter(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1079,7 +1079,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetBackMatter(ctx echo.Context) error } // CreateBackMatter creates back-matter for a POA&M -func (h *PlanOfActionAndMilestonesHandler) CreateBackMatter(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreateBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1124,7 +1124,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreateBackMatter(ctx echo.Context) er } // UpdateBackMatter updates back-matter for a POA&M -func (h *PlanOfActionAndMilestonesHandler) UpdateBackMatter(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1164,7 +1164,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateBackMatter(ctx echo.Context) er } // DeleteBackMatter deletes back-matter for a POA&M -func (h *PlanOfActionAndMilestonesHandler) DeleteBackMatter(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) DeleteBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1215,7 +1215,7 @@ func (h *PlanOfActionAndMilestonesHandler) DeleteBackMatter(ctx echo.Context) er // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones [post] -func (h *PlanOfActionAndMilestonesHandler) Create(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) Create(ctx *echo.Context) error { now := time.Now() var oscalPoam oscalTypes_1_1_3.PlanOfActionAndMilestones @@ -1257,7 +1257,7 @@ func (h *PlanOfActionAndMilestonesHandler) Create(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/observations [post] -func (h *PlanOfActionAndMilestonesHandler) CreateObservation(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreateObservation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1310,7 +1310,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreateObservation(ctx echo.Context) e // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/risks [post] -func (h *PlanOfActionAndMilestonesHandler) CreateRisk(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreateRisk(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1363,7 +1363,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreateRisk(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/findings [post] -func (h *PlanOfActionAndMilestonesHandler) CreateFinding(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreateFinding(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1416,7 +1416,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreateFinding(ctx echo.Context) error // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/poam-items [post] -func (h *PlanOfActionAndMilestonesHandler) CreatePoamItem(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreatePoamItem(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1466,7 +1466,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreatePoamItem(ctx echo.Context) erro // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id} [put] -func (h *PlanOfActionAndMilestonesHandler) Update(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) Update(ctx *echo.Context) error { // Parse and validate ID parameter idParam := ctx.Param("id") id, err := uuid.Parse(idParam) @@ -1531,7 +1531,7 @@ func (h *PlanOfActionAndMilestonesHandler) Update(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/observations/{obsId} [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateObservation(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateObservation(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -1603,7 +1603,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateObservation(ctx echo.Context) e // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/risks/{riskId} [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateRisk(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateRisk(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -1675,7 +1675,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateRisk(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/findings/{findingId} [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateFinding(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateFinding(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -1747,7 +1747,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateFinding(ctx echo.Context) error // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/poam-items/{itemId} [put] -func (h *PlanOfActionAndMilestonesHandler) UpdatePoamItem(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdatePoamItem(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -1856,7 +1856,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdatePoamItem(ctx echo.Context) erro // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id} [delete] -func (h *PlanOfActionAndMilestonesHandler) Delete(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) Delete(ctx *echo.Context) error { // Parse and validate ID parameter idParam := ctx.Param("id") id, err := uuid.Parse(idParam) @@ -1922,7 +1922,7 @@ func (h *PlanOfActionAndMilestonesHandler) Delete(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/observations/{obsId} [delete] -func (h *PlanOfActionAndMilestonesHandler) DeleteObservation(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) DeleteObservation(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -1972,7 +1972,7 @@ func (h *PlanOfActionAndMilestonesHandler) DeleteObservation(ctx echo.Context) e // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/risks/{riskId} [delete] -func (h *PlanOfActionAndMilestonesHandler) DeleteRisk(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) DeleteRisk(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -2022,7 +2022,7 @@ func (h *PlanOfActionAndMilestonesHandler) DeleteRisk(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/findings/{findingId} [delete] -func (h *PlanOfActionAndMilestonesHandler) DeleteFinding(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) DeleteFinding(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -2073,7 +2073,7 @@ func (h *PlanOfActionAndMilestonesHandler) DeleteFinding(ctx echo.Context) error // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/poam-items/{itemId} [delete] -func (h *PlanOfActionAndMilestonesHandler) DeletePoamItem(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) DeletePoamItem(ctx *echo.Context) error { // Parse and validate ID parameters idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) @@ -2124,7 +2124,7 @@ func (h *PlanOfActionAndMilestonesHandler) DeletePoamItem(ctx echo.Context) erro // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/back-matter/resources [get] -func (h *PlanOfActionAndMilestonesHandler) GetBackMatterResources(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) GetBackMatterResources(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2163,7 +2163,7 @@ func (h *PlanOfActionAndMilestonesHandler) GetBackMatterResources(ctx echo.Conte // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/back-matter/resources [post] -func (h *PlanOfActionAndMilestonesHandler) CreateBackMatterResource(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) CreateBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2225,7 +2225,7 @@ func (h *PlanOfActionAndMilestonesHandler) CreateBackMatterResource(ctx echo.Con // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/back-matter/resources/{resourceId} [put] -func (h *PlanOfActionAndMilestonesHandler) UpdateBackMatterResource(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) UpdateBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) if err != nil { @@ -2292,7 +2292,7 @@ func (h *PlanOfActionAndMilestonesHandler) UpdateBackMatterResource(ctx echo.Con // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/plan-of-action-and-milestones/{id}/back-matter/resources/{resourceId} [delete] -func (h *PlanOfActionAndMilestonesHandler) DeleteBackMatterResource(ctx echo.Context) error { +func (h *PlanOfActionAndMilestonesHandler) DeleteBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") poamID, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/plan_of_action_and_milestones_integration_test.go b/internal/api/handler/oscal/plan_of_action_and_milestones_integration_test.go index d5b75dc2..0858b5fa 100644 --- a/internal/api/handler/oscal/plan_of_action_and_milestones_integration_test.go +++ b/internal/api/handler/oscal/plan_of_action_and_milestones_integration_test.go @@ -18,7 +18,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscaltypes "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/profile_compliance.go b/internal/api/handler/oscal/profile_compliance.go index 110c4605..5e0bfeb1 100644 --- a/internal/api/handler/oscal/profile_compliance.go +++ b/internal/api/handler/oscal/profile_compliance.go @@ -14,7 +14,7 @@ import ( "github.com/compliance-framework/api/internal/service/leverage" "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" ) @@ -150,7 +150,7 @@ type profileComplianceGroupAccumulator struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/compliance-progress [get] -func (h *ProfileHandler) ComplianceProgress(ctx echo.Context) error { +func (h *ProfileHandler) ComplianceProgress(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/profile_compliance_leverage_integration_test.go b/internal/api/handler/oscal/profile_compliance_leverage_integration_test.go index e11b3b92..ea928a7a 100644 --- a/internal/api/handler/oscal/profile_compliance_leverage_integration_test.go +++ b/internal/api/handler/oscal/profile_compliance_leverage_integration_test.go @@ -10,7 +10,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -128,8 +128,7 @@ func (suite *ProfileIntegrationSuite) complianceProgress(profileID, sspID string req := httptest.NewRequest(http.MethodGet, url, nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(profileID) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: profileID}}) suite.Require().NoError(NewProfileHandler(zap.NewNop().Sugar(), suite.DB).ComplianceProgress(ctx)) suite.Require().Equal(http.StatusOK, rec.Code, rec.Body.String()) var resp struct { diff --git a/internal/api/handler/oscal/profile_compliance_workflow_integration_test.go b/internal/api/handler/oscal/profile_compliance_workflow_integration_test.go index 64d77f56..a6f1864a 100644 --- a/internal/api/handler/oscal/profile_compliance_workflow_integration_test.go +++ b/internal/api/handler/oscal/profile_compliance_workflow_integration_test.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/workflows" workflowevidence "github.com/compliance-framework/api/internal/workflow" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -85,8 +85,7 @@ func (suite *ProfileIntegrationSuite) TestComplianceProgressIncludesWorkflowComp req := httptest.NewRequest(http.MethodGet, "/profiles/"+profileID.String()+"/compliance-progress", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(profileID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: profileID.String()}}) suite.Require().NoError(NewProfileHandler(zap.NewNop().Sugar(), suite.DB).ComplianceProgress(ctx)) suite.Require().Equal(http.StatusOK, rec.Code) @@ -113,8 +112,7 @@ func (suite *ProfileIntegrationSuite) TestComplianceProgressIncludesWorkflowComp req = httptest.NewRequest(http.MethodGet, "/profiles/"+profileID.String()+"/compliance-progress", nil) rec = httptest.NewRecorder() ctx = e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(profileID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: profileID.String()}}) suite.Require().NoError(NewProfileHandler(zap.NewNop().Sugar(), suite.DB).ComplianceProgress(ctx)) suite.Require().Equal(http.StatusOK, rec.Code) diff --git a/internal/api/handler/oscal/profiles.go b/internal/api/handler/oscal/profiles.go index daf2668a..f02a0bea 100644 --- a/internal/api/handler/oscal/profiles.go +++ b/internal/api/handler/oscal/profiles.go @@ -16,7 +16,7 @@ import ( "github.com/defenseunicorns/go-oscal/src/pkg/versioning" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -105,7 +105,7 @@ func (h *ProfileHandler) Register(api *echo.Group, guard middleware.ResourceGuar // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/build-props [post] -func (h *ProfileHandler) BuildByProps(ctx echo.Context) error { +func (h *ProfileHandler) BuildByProps(ctx *echo.Context) error { var req BuildByPropsRequest var raw map[string]any if err := json.NewDecoder(ctx.Request().Body).Decode(&raw); err != nil { @@ -340,7 +340,7 @@ func matchControlByProps(ctl *relational.Control, rules []rule, matchAll bool) b // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles [get] -func (h *ProfileHandler) List(ctx echo.Context) error { +func (h *ProfileHandler) List(ctx *echo.Context) error { type response struct { UUID uuid.UUID `json:"uuid"` Metadata oscalTypes_1_1_3.Metadata `json:"metadata"` @@ -381,7 +381,7 @@ func (h *ProfileHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id} [get] -func (h *ProfileHandler) Get(ctx echo.Context) error { +func (h *ProfileHandler) Get(ctx *echo.Context) error { type response struct { UUID uuid.UUID `json:"uuid"` Metadata oscalTypes_1_1_3.Metadata `json:"metadata"` @@ -429,7 +429,7 @@ func (h *ProfileHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/resolved [get] -func (h *ProfileHandler) Resolved(ctx echo.Context) error { +func (h *ProfileHandler) Resolved(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -472,7 +472,7 @@ func (h *ProfileHandler) Resolved(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/resolved-with-catalogs [get] -func (h *ProfileHandler) ResolvedWithCatalogs(ctx echo.Context) error { +func (h *ProfileHandler) ResolvedWithCatalogs(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -533,7 +533,7 @@ func (h *ProfileHandler) ResolvedWithCatalogs(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/imports [get] -func (h *ProfileHandler) ListImports(ctx echo.Context) error { +func (h *ProfileHandler) ListImports(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -575,7 +575,7 @@ func (h *ProfileHandler) ListImports(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/imports/{href} [get] -func (h *ProfileHandler) GetImport(ctx echo.Context) error { +func (h *ProfileHandler) GetImport(ctx *echo.Context) error { profileId := ctx.Param("id") importHref := ctx.Param("href") @@ -616,7 +616,7 @@ func (h *ProfileHandler) GetImport(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/imports/add [post] -func (h *ProfileHandler) AddImport(ctx echo.Context) error { +func (h *ProfileHandler) AddImport(ctx *echo.Context) error { type request struct { Type string `json:"type"` // catalog / profile UUID string `json:"uuid"` @@ -715,7 +715,7 @@ func (h *ProfileHandler) AddImport(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/imports/{href} [put] -func (h *ProfileHandler) UpdateImport(ctx echo.Context) error { +func (h *ProfileHandler) UpdateImport(ctx *echo.Context) error { profileId := ctx.Param("id") id, err := uuid.Parse(profileId) if err != nil { @@ -795,7 +795,7 @@ func (h *ProfileHandler) UpdateImport(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/imports/{href} [delete] -func (h *ProfileHandler) DeleteImport(ctx echo.Context) error { +func (h *ProfileHandler) DeleteImport(ctx *echo.Context) error { profileId := ctx.Param("id") href := ctx.Param("href") @@ -868,7 +868,7 @@ func (h *ProfileHandler) DeleteImport(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/merge [get] -func (h *ProfileHandler) GetMerge(ctx echo.Context) error { +func (h *ProfileHandler) GetMerge(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -907,7 +907,7 @@ func (h *ProfileHandler) GetMerge(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/merge [put] -func (h *ProfileHandler) UpdateMerge(ctx echo.Context) error { +func (h *ProfileHandler) UpdateMerge(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -985,7 +985,7 @@ func (h *ProfileHandler) UpdateMerge(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/back-matter [get] -func (h *ProfileHandler) GetBackmatter(ctx echo.Context) error { +func (h *ProfileHandler) GetBackmatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1020,7 +1020,7 @@ func (h *ProfileHandler) GetBackmatter(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/resolve [post] -func (h *ProfileHandler) Resolve(ctx echo.Context) error { +func (h *ProfileHandler) Resolve(ctx *echo.Context) error { type response struct { ID string `json:"id"` } @@ -1121,7 +1121,7 @@ func updateCatalogID(controls []relational.Control, newCatalogID uuid.UUID) []re // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles [post] -func (h *ProfileHandler) Create(ctx echo.Context) error { +func (h *ProfileHandler) Create(ctx *echo.Context) error { now := time.Now() var oscalProfile oscalTypes_1_1_3.Profile @@ -1171,7 +1171,7 @@ func (h *ProfileHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/full [get] -func (h *ProfileHandler) GetFull(ctx echo.Context) error { +func (h *ProfileHandler) GetFull(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1204,7 +1204,7 @@ func (h *ProfileHandler) GetFull(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/profiles/{id}/modify [get] -func (h *ProfileHandler) GetModify(ctx echo.Context) error { +func (h *ProfileHandler) GetModify(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/profiles_integration_test.go b/internal/api/handler/oscal/profiles_integration_test.go index f6e32f26..0d1013ed 100644 --- a/internal/api/handler/oscal/profiles_integration_test.go +++ b/internal/api/handler/oscal/profiles_integration_test.go @@ -18,7 +18,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/response.go b/internal/api/handler/oscal/response.go index 9fc59c2d..6ff158ae 100644 --- a/internal/api/handler/oscal/response.go +++ b/internal/api/handler/oscal/response.go @@ -1,12 +1,30 @@ package oscal import ( + "encoding/json" "net/http" - - "github.com/labstack/echo/v4" ) -func NewValidationErrorResponse(errors []ValidationError) *echo.HTTPError { +// ValidationErrorResponse is a 400 whose body is {"errors": {"": ["", ...]}}. +// Echo's error handler writes it as is: it reports its own status and marshals itself. +type ValidationErrorResponse struct { + Errors map[string][]string `json:"errors"` +} + +func (e *ValidationErrorResponse) Error() string { + return "validation failed" +} + +func (e *ValidationErrorResponse) StatusCode() int { + return http.StatusBadRequest +} + +func (e *ValidationErrorResponse) MarshalJSON() ([]byte, error) { + type body ValidationErrorResponse // drops MarshalJSON, so this doesn't recurse + return json.Marshal((*body)(e)) +} + +func NewValidationErrorResponse(errors []ValidationError) *ValidationErrorResponse { validationErrors := make(map[string][]string) for _, ve := range errors { if _, ok := validationErrors[ve.Field]; !ok { @@ -15,5 +33,5 @@ func NewValidationErrorResponse(errors []ValidationError) *echo.HTTPError { validationErrors[ve.Field] = append(validationErrors[ve.Field], ve.Message) } - return echo.NewHTTPError(http.StatusBadRequest, map[string]any{"errors": validationErrors}) + return &ValidationErrorResponse{Errors: validationErrors} } diff --git a/internal/api/handler/oscal/response_unit_test.go b/internal/api/handler/oscal/response_unit_test.go new file mode 100644 index 00000000..f484a2ba --- /dev/null +++ b/internal/api/handler/oscal/response_unit_test.go @@ -0,0 +1,32 @@ +package oscal + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/labstack/echo/v5" + "github.com/stretchr/testify/assert" +) + +// A handler returning NewValidationErrorResponse gets a 400 whose body lists the messages per +// field, through echo's own error handler. +func TestValidationErrorResponseBody(t *testing.T) { + e := echo.New() + e.POST("/", func(c *echo.Context) error { + return NewValidationErrorResponse([]ValidationError{ + {Field: "metadata.title", Message: "title is required"}, + {Field: "metadata.title", Message: "title is too short"}, + {Field: "import-ssp.href", Message: "href is required"}, + }) + }) + + rec := httptest.NewRecorder() + e.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/", http.NoBody)) + + assert.Equal(t, http.StatusBadRequest, rec.Code) + assert.JSONEq(t, `{"errors": { + "metadata.title": ["title is required", "title is too short"], + "import-ssp.href": ["href is required"] + }}`, rec.Body.String()) +} diff --git a/internal/api/handler/oscal/roles.go b/internal/api/handler/oscal/roles.go index 307c2b50..aac8ddd2 100644 --- a/internal/api/handler/oscal/roles.go +++ b/internal/api/handler/oscal/roles.go @@ -7,7 +7,7 @@ import ( "github.com/compliance-framework/api/internal/api" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" @@ -45,7 +45,7 @@ func (h *RoleHandler) Register(api *echo.Group, guard middleware.ResourceGuard) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/roles [get] -func (h *RoleHandler) List(ctx echo.Context) error { +func (h *RoleHandler) List(ctx *echo.Context) error { var parties []relational.Role if err := h.db. Find(&parties).Error; err != nil { @@ -75,7 +75,7 @@ func (h *RoleHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/roles/{id} [get] -func (h *RoleHandler) Get(ctx echo.Context) error { +func (h *RoleHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/ssp_by_components.go b/internal/api/handler/oscal/ssp_by_components.go index cab15b63..cbab3f10 100644 --- a/internal/api/handler/oscal/ssp_by_components.go +++ b/internal/api/handler/oscal/ssp_by_components.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" "github.com/compliance-framework/api/internal/api" @@ -139,7 +139,7 @@ func assertInheritedNotSubscribed(tx *gorm.DB, inheritedIDs []uuid.UUID) error { // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId} [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponent(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -166,7 +166,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponent(ctx ech // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId} [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponent(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -175,7 +175,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponen } // getByComponent renders one already-resolved by-component with every subtree preloaded. -func (h *SystemSecurityPlanHandler) getByComponent(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) getByComponent(ctx *echo.Context, bc *relational.ByComponent) error { loaded, err := h.reloadByComponent(*bc.ID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -204,7 +204,7 @@ func (h *SystemSecurityPlanHandler) getByComponent(ctx echo.Context, bc *relatio // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponents(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponents(ctx *echo.Context) error { stmt, ok := h.resolveStatement(ctx) if !ok { return nil @@ -235,7 +235,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponen // in the path, writing the appropriate error response and returning ok=false on any failure — // the statement-level sibling of resolveByComponentForStatement, for routes that address a // statement rather than one by-component under it. -func (h *SystemSecurityPlanHandler) resolveStatement(ctx echo.Context) (stmt *relational.Statement, ok bool) { +func (h *SystemSecurityPlanHandler) resolveStatement(ctx *echo.Context) (stmt *relational.Statement, ok bool) { sspID, reqID, stmtID, err := parseSSPReqStmtIDs(ctx) if err != nil { h.sugar.Warnw("Invalid statement path params", "error", err) @@ -308,7 +308,7 @@ func (h *SystemSecurityPlanHandler) resolveStatement(ctx echo.Context) (stmt *re // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponent(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -328,7 +328,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponent(ctx // getByComponentExportProvided lists the Provided entries under an already-resolved // by-component's Export. -func (h *SystemSecurityPlanHandler) getByComponentExportProvided(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) getByComponentExportProvided(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -353,7 +353,7 @@ func (h *SystemSecurityPlanHandler) getByComponentExportProvided(ctx echo.Contex // getByComponentExportResponsibilities lists the ControlImplementationResponsibility entries // under an already-resolved by-component's Export. -func (h *SystemSecurityPlanHandler) getByComponentExportResponsibilities(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) getByComponentExportResponsibilities(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -392,7 +392,7 @@ func (h *SystemSecurityPlanHandler) getByComponentExportResponsibilities(ctx ech // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/provided [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -416,7 +416,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExportPr // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/responsibilities [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExportResponsibilities(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExportResponsibilities(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -440,7 +440,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExportRe // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/provided [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -464,7 +464,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponen // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/responsibilities [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentExportResponsibilities(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentExportResponsibilities(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -488,7 +488,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponen // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/inherited [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentInherited(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentInherited(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -532,7 +532,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponen // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/inherited [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentInherited(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentInherited(ctx *echo.Context) error { sspID, _, _, err := parseSSPReqStmtIDs(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -657,7 +657,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/inherited/{inheritedId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentInherited(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentInherited(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -747,7 +747,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/inherited/{inheritedId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentInherited(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentInherited(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -813,7 +813,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/satisfied [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentSatisfied(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentSatisfied(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -859,7 +859,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponen // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/satisfied [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentSatisfied(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentSatisfied(ctx *echo.Context) error { sspID, _, _, err := parseSSPReqStmtIDs(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -950,7 +950,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/satisfied/{satisfiedId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentSatisfied(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentSatisfied(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -1035,7 +1035,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/satisfied/{satisfiedId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentSatisfied(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentSatisfied(ctx *echo.Context) error { sspID, _, _, err := parseSSPReqStmtIDs(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/oscal/ssp_export_offering_allowlist_test.go b/internal/api/handler/oscal/ssp_export_offering_allowlist_test.go index 6832dd34..c7a96cb0 100644 --- a/internal/api/handler/oscal/ssp_export_offering_allowlist_test.go +++ b/internal/api/handler/oscal/ssp_export_offering_allowlist_test.go @@ -10,12 +10,12 @@ import ( "github.com/compliance-framework/api/internal/api/handler" "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" ) -func newAllowedDownstreamsRequestContext(method string, sspID, offeringID uuid.UUID, extraParam, extraValue string, body string) (echo.Context, *httptest.ResponseRecorder) { +func newAllowedDownstreamsRequestContext(method string, sspID, offeringID uuid.UUID, extraParam, extraValue string, body string) (*echo.Context, *httptest.ResponseRecorder) { e := echo.New() var reader *bytes.Reader if body != "" { @@ -28,11 +28,9 @@ func newAllowedDownstreamsRequestContext(method string, sspID, offeringID uuid.U rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) if extraParam != "" { - ctx.SetParamNames("id", "offeringId", extraParam) - ctx.SetParamValues(sspID.String(), offeringID.String(), extraValue) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}, {Name: "offeringId", Value: offeringID.String()}, {Name: extraParam, Value: extraValue}}) } else { - ctx.SetParamNames("id", "offeringId") - ctx.SetParamValues(sspID.String(), offeringID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}, {Name: "offeringId", Value: offeringID.String()}}) } return ctx, rec } diff --git a/internal/api/handler/oscal/ssp_export_offering_status_test.go b/internal/api/handler/oscal/ssp_export_offering_status_test.go index 4757e275..7ed35d18 100644 --- a/internal/api/handler/oscal/ssp_export_offering_status_test.go +++ b/internal/api/handler/oscal/ssp_export_offering_status_test.go @@ -9,20 +9,19 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/gorm" ) -func newOfferingStatusRequestContext(sspID, offeringID uuid.UUID, body string) (echo.Context, *httptest.ResponseRecorder) { +func newOfferingStatusRequestContext(sspID, offeringID uuid.UUID, body string) (*echo.Context, *httptest.ResponseRecorder) { e := echo.New() req := httptest.NewRequest(http.MethodPatch, "/", bytes.NewBufferString(body)) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id", "offeringId") - ctx.SetParamValues(sspID.String(), offeringID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}, {Name: "offeringId", Value: offeringID.String()}}) return ctx, rec } diff --git a/internal/api/handler/oscal/ssp_export_offerings.go b/internal/api/handler/oscal/ssp_export_offerings.go index ee24b516..223c818e 100644 --- a/internal/api/handler/oscal/ssp_export_offerings.go +++ b/internal/api/handler/oscal/ssp_export_offerings.go @@ -13,7 +13,7 @@ import ( "time" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -266,7 +266,7 @@ func (h *SSPExportOfferingHandler) Register(api *echo.Group, guard middleware.Re // actorUserID resolves the authenticated subject's own user UUID (set on the JWT at // login) for CreatedByID attribution. Returns nil (not an error) if the claim is // missing/invalid — attribution is best-effort, not a request precondition. -func actorUserID(ctx echo.Context) *uuid.UUID { +func actorUserID(ctx *echo.Context) *uuid.UUID { claims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || claims == nil || claims.UserUUID == "" { return nil @@ -281,7 +281,7 @@ func actorUserID(ctx echo.Context) *uuid.UUID { // resolveOfferingForSSP loads the offering (with its items) and verifies it belongs to // the SSP named in the :id path param, writing the appropriate error response and // returning ok=false if either lookup fails. -func (h *SSPExportOfferingHandler) resolveOfferingForSSP(ctx echo.Context) (offering *relational.SSPExportOffering, ok bool) { +func (h *SSPExportOfferingHandler) resolveOfferingForSSP(ctx *echo.Context) (offering *relational.SSPExportOffering, ok bool) { sspIdParam := ctx.Param("id") sspID, err := uuid.Parse(sspIdParam) if err != nil { @@ -324,7 +324,7 @@ func (h *SSPExportOfferingHandler) resolveOfferingForSSP(ctx echo.Context) (offe // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings [get] -func (h *SSPExportOfferingHandler) ListForSSP(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) ListForSSP(ctx *echo.Context) error { sspIdParam := ctx.Param("id") sspID, err := uuid.Parse(sspIdParam) if err != nil { @@ -361,7 +361,7 @@ type createExportOfferingRequest struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings [post] -func (h *SSPExportOfferingHandler) CreateOffering(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) CreateOffering(ctx *echo.Context) error { sspIdParam := ctx.Param("id") sspID, err := uuid.Parse(sspIdParam) if err != nil { @@ -414,7 +414,7 @@ func (h *SSPExportOfferingHandler) CreateOffering(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId} [get] -func (h *SSPExportOfferingHandler) GetOffering(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) GetOffering(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -438,7 +438,7 @@ func (h *SSPExportOfferingHandler) GetOffering(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId} [put] -func (h *SSPExportOfferingHandler) UpdateOffering(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) UpdateOffering(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -477,7 +477,7 @@ func (h *SSPExportOfferingHandler) UpdateOffering(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId} [delete] -func (h *SSPExportOfferingHandler) DeleteOffering(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) DeleteOffering(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -645,7 +645,7 @@ func (h *SSPExportOfferingHandler) validateOfferingItemCoherence(sspID uuid.UUID // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/items [post] -func (h *SSPExportOfferingHandler) CreateItem(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) CreateItem(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -703,7 +703,7 @@ func (h *SSPExportOfferingHandler) CreateItem(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/items/{itemId} [put] -func (h *SSPExportOfferingHandler) UpdateItem(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) UpdateItem(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -779,7 +779,7 @@ func (h *SSPExportOfferingHandler) UpdateItem(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/items/{itemId} [delete] -func (h *SSPExportOfferingHandler) DeleteItem(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) DeleteItem(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -845,7 +845,7 @@ func (r allowedDownstreamRequest) validate() error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/allowed-downstreams [get] -func (h *SSPExportOfferingHandler) ListAllowedDownstreams(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) ListAllowedDownstreams(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -878,7 +878,7 @@ func (h *SSPExportOfferingHandler) ListAllowedDownstreams(ctx echo.Context) erro // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/allowed-downstreams [post] -func (h *SSPExportOfferingHandler) AddAllowedDownstream(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) AddAllowedDownstream(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -925,7 +925,7 @@ func (h *SSPExportOfferingHandler) AddAllowedDownstream(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/allowed-downstreams/{downstreamSspId} [delete] -func (h *SSPExportOfferingHandler) RemoveAllowedDownstream(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) RemoveAllowedDownstream(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -967,7 +967,7 @@ func (h *SSPExportOfferingHandler) RemoveAllowedDownstream(ctx echo.Context) err // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/publish [post] -func (h *SSPExportOfferingHandler) Publish(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) Publish(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -1036,7 +1036,7 @@ func (r updateOfferingStatusRequest) validate() error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/export-offerings/{offeringId}/status [patch] -func (h *SSPExportOfferingHandler) UpdateOfferingStatus(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) UpdateOfferingStatus(ctx *echo.Context) error { offering, ok := h.resolveOfferingForSSP(ctx) if !ok { return nil @@ -1155,7 +1155,7 @@ func (h *SSPExportOfferingHandler) withResolvedResponsibilities(offerings []rela // parseExportOfferingPagination reads the shared limit/offset params for the export-offering // catalog reads, capping limit at maxExportOfferingCatalogLimit. Shared by ListAll and ByControl // so the two cannot drift into different bounds — or, as ByControl did, into none at all. -func parseExportOfferingPagination(ctx echo.Context) (limit int, offset int, err error) { +func parseExportOfferingPagination(ctx *echo.Context) (limit int, offset int, err error) { limit = defaultExportOfferingCatalogLimit if raw := strings.TrimSpace(ctx.QueryParam("limit")); raw != "" { parsed, convErr := strconv.Atoi(raw) @@ -1201,7 +1201,7 @@ const allowedDownstreamSQL = `( ) )` -func (h *SSPExportOfferingHandler) ListAll(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) ListAll(ctx *echo.Context) error { limit, offset, err := parseExportOfferingPagination(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1238,7 +1238,7 @@ func (h *SSPExportOfferingHandler) ListAll(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/ssp-export-offerings/{id} [get] -func (h *SSPExportOfferingHandler) GetByID(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) GetByID(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1339,7 +1339,7 @@ type ControlExportOffer struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/ssp-export-offerings/by-control/{controlId} [get] -func (h *SSPExportOfferingHandler) ByControl(ctx echo.Context) error { +func (h *SSPExportOfferingHandler) ByControl(ctx *echo.Context) error { controlID := strings.TrimSpace(ctx.Param("controlId")) if controlID == "" { return ctx.JSON(http.StatusBadRequest, api.NewError(fmt.Errorf("controlId is required"))) diff --git a/internal/api/handler/oscal/ssp_export_offerings_items_test.go b/internal/api/handler/oscal/ssp_export_offerings_items_test.go index ff9fcfb4..8bde71ca 100644 --- a/internal/api/handler/oscal/ssp_export_offerings_items_test.go +++ b/internal/api/handler/oscal/ssp_export_offerings_items_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/gorm" @@ -71,8 +71,7 @@ func byControlPage(t *testing.T, h *SSPExportOfferingHandler, downstream *uuid.U e := echo.New() rec := httptest.NewRecorder() ctx := e.NewContext(httptest.NewRequest(http.MethodGet, target, nil), rec) - ctx.SetParamNames("controlId") - ctx.SetParamValues("ac-2") + ctx.SetPathValues(echo.PathValues{{Name: "controlId", Value: "ac-2"}}) require.NoError(t, h.ByControl(ctx)) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) @@ -148,7 +147,7 @@ type offeringItemWriteCase struct { name string method string okStatus int - invoke func(h *SSPExportOfferingHandler, ctx echo.Context) error + invoke func(h *SSPExportOfferingHandler, ctx *echo.Context) error extraParam func(fx sharedResponsibilityFixture) (name, value string) } @@ -158,13 +157,13 @@ func offeringItemWriteCases() []offeringItemWriteCase { name: "CreateItem", method: http.MethodPost, okStatus: http.StatusCreated, - invoke: func(h *SSPExportOfferingHandler, ctx echo.Context) error { return h.CreateItem(ctx) }, + invoke: func(h *SSPExportOfferingHandler, ctx *echo.Context) error { return h.CreateItem(ctx) }, }, { name: "UpdateItem", method: http.MethodPut, okStatus: http.StatusOK, - invoke: func(h *SSPExportOfferingHandler, ctx echo.Context) error { return h.UpdateItem(ctx) }, + invoke: func(h *SSPExportOfferingHandler, ctx *echo.Context) error { return h.UpdateItem(ctx) }, extraParam: func(fx sharedResponsibilityFixture) (string, string) { return "itemId", fx.itemID.String() }, @@ -181,15 +180,15 @@ func (c offeringItemWriteCase) call(t *testing.T, h *SSPExportOfferingHandler, f rec := httptest.NewRecorder() ctx := e.NewContext(httpReq, rec) - names := []string{"id", "offeringId"} - values := []string{fx.upstreamSSPID.String(), fx.offeringID.String()} + pathValues := echo.PathValues{ + {Name: "id", Value: fx.upstreamSSPID.String()}, + {Name: "offeringId", Value: fx.offeringID.String()}, + } if c.extraParam != nil { n, v := c.extraParam(fx) - names = append(names, n) - values = append(values, v) + pathValues = append(pathValues, echo.PathValue{Name: n, Value: v}) } - ctx.SetParamNames(names...) - ctx.SetParamValues(values...) + ctx.SetPathValues(pathValues) require.NoError(t, c.invoke(h, ctx)) return rec @@ -301,8 +300,7 @@ func TestUpdateItemUnknownItemReturns404(t *testing.T) { httpReq.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() ctx := e.NewContext(httpReq, rec) - ctx.SetParamNames("id", "offeringId", "itemId") - ctx.SetParamValues(fx.upstreamSSPID.String(), fx.offeringID.String(), uuid.New().String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.upstreamSSPID.String()}, {Name: "offeringId", Value: fx.offeringID.String()}, {Name: "itemId", Value: uuid.New().String()}}) require.NoError(t, h.UpdateItem(ctx)) require.Equal(t, http.StatusNotFound, rec.Code, rec.Body.String()) diff --git a/internal/api/handler/oscal/ssp_export_offerings_test.go b/internal/api/handler/oscal/ssp_export_offerings_test.go index db84449d..118fc659 100644 --- a/internal/api/handler/oscal/ssp_export_offerings_test.go +++ b/internal/api/handler/oscal/ssp_export_offerings_test.go @@ -13,7 +13,7 @@ import ( "time" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/oscal/ssp_leverage.go b/internal/api/handler/oscal/ssp_leverage.go index dc028d40..4d6acd94 100644 --- a/internal/api/handler/oscal/ssp_leverage.go +++ b/internal/api/handler/oscal/ssp_leverage.go @@ -9,7 +9,7 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5/pgconn" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -147,7 +147,7 @@ func (h *SSPLeverageHandler) RegisterProjection(g *echo.Group, guard middleware. // handling. Critically, this is the only authorization check Subscribe performs against // the downstream SSP's own resource — ssp:read on the *upstream* SSP is never evaluated // anywhere in this path, which is the trust-boundary property AC #2 requires. -func (h *SSPLeverageHandler) authorizeDownstreamUpdate(ctx echo.Context, sspID uuid.UUID) (bool, error) { +func (h *SSPLeverageHandler) authorizeDownstreamUpdate(ctx *echo.Context, sspID uuid.UUID) (bool, error) { subject := middleware.SubjectFromContext(ctx) resource := authz.Resource{Type: authz.ResourceSSP, ID: sspID.String()} reqCtx := map[string]any{"method": ctx.Request().Method, "path": ctx.Path()} @@ -521,7 +521,7 @@ func (r subscribeRequest) validate() error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/ssp-export-offerings/{id}/subscribe [post] -func (h *SSPLeverageHandler) Subscribe(ctx echo.Context) error { +func (h *SSPLeverageHandler) Subscribe(ctx *echo.Context) error { offeringIdParam := ctx.Param("id") offeringID, err := uuid.Parse(offeringIdParam) if err != nil { @@ -913,7 +913,7 @@ type responsibilityFilterResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/responsibility-filters [get] -func (h *SSPLeverageHandler) ResponsibilityFilters(ctx echo.Context) error { +func (h *SSPLeverageHandler) ResponsibilityFilters(ctx *echo.Context) error { sspIdParam := ctx.Param("id") sspID, err := uuid.Parse(sspIdParam) if err != nil { @@ -985,7 +985,7 @@ func (h *SSPLeverageHandler) ResponsibilityFilters(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/leveraged-controls [get] -func (h *SSPLeverageHandler) LeveragedControls(ctx echo.Context) error { +func (h *SSPLeverageHandler) LeveragedControls(ctx *echo.Context) error { sspIdParam := ctx.Param("id") sspID, err := uuid.Parse(sspIdParam) if err != nil { @@ -1056,7 +1056,7 @@ func projectLeveragedControls(db *gorm.DB, sspID uuid.UUID) ([]leveragedControlP // responsibility set and downstream satisfied set, flips the link back to active, and // marks the associated drift risk remediated — all in one transaction. Human-in-the-loop // only: this is the sole path that clears drift, there is no automatic re-activation. -func (h *SSPLeverageHandler) ReAttest(ctx echo.Context) error { +func (h *SSPLeverageHandler) ReAttest(ctx *echo.Context) error { sspIdParam := ctx.Param("id") sspID, err := uuid.Parse(sspIdParam) if err != nil { diff --git a/internal/api/handler/oscal/ssp_leverage_allowlist_test.go b/internal/api/handler/oscal/ssp_leverage_allowlist_test.go index 15fd1824..70cace88 100644 --- a/internal/api/handler/oscal/ssp_leverage_allowlist_test.go +++ b/internal/api/handler/oscal/ssp_leverage_allowlist_test.go @@ -59,7 +59,7 @@ func TestSubscribeRejectsNonAllowListedDownstream(t *testing.T) { ctx, e, rec := newSubscribeRequestContext(fx.offeringID, body) err := h.Subscribe(ctx) require.Error(t, err) - e.HTTPErrorHandler(err, ctx) + e.HTTPErrorHandler(ctx, err) require.Equal(t, http.StatusForbidden, rec.Code) var count int64 diff --git a/internal/api/handler/oscal/ssp_leverage_drift.go b/internal/api/handler/oscal/ssp_leverage_drift.go index 40f6c9de..5f5a17fb 100644 --- a/internal/api/handler/oscal/ssp_leverage_drift.go +++ b/internal/api/handler/oscal/ssp_leverage_drift.go @@ -7,7 +7,7 @@ import ( "time" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -55,7 +55,7 @@ func enqueueLeverageDriftNotifications(ctx context.Context, sugar *zap.SugaredLo // drifted, otherwise a detached, timeout-bounded context (mirroring the // EnqueueOrphanedRiskCleanup call sites) so a slow/failed enqueue can't hang or be // cancelled by the already-completed request. -func enqueueLeverageDriftNotificationsAsync(ctx echo.Context, sugar *zap.SugaredLogger, jobEnqueuer SSPJobEnqueuer, links []driftedLinkInfo) { +func enqueueLeverageDriftNotificationsAsync(ctx *echo.Context, sugar *zap.SugaredLogger, jobEnqueuer SSPJobEnqueuer, links []driftedLinkInfo) { if len(links) == 0 { return } diff --git a/internal/api/handler/oscal/ssp_leverage_drift_enqueue_test.go b/internal/api/handler/oscal/ssp_leverage_drift_enqueue_test.go index 0ced7c62..7aa4f217 100644 --- a/internal/api/handler/oscal/ssp_leverage_drift_enqueue_test.go +++ b/internal/api/handler/oscal/ssp_leverage_drift_enqueue_test.go @@ -8,18 +8,17 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" ) -func newPublishRequestContext(sspID, offeringID uuid.UUID) (echo.Context, *httptest.ResponseRecorder) { +func newPublishRequestContext(sspID, offeringID uuid.UUID) (*echo.Context, *httptest.ResponseRecorder) { e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id", "offeringId") - ctx.SetParamValues(sspID.String(), offeringID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}, {Name: "offeringId", Value: offeringID.String()}}) return ctx, rec } diff --git a/internal/api/handler/oscal/ssp_leverage_drift_integration_test.go b/internal/api/handler/oscal/ssp_leverage_drift_integration_test.go index 53a6a019..5258eeb7 100644 --- a/internal/api/handler/oscal/ssp_leverage_drift_integration_test.go +++ b/internal/api/handler/oscal/ssp_leverage_drift_integration_test.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" @@ -273,8 +273,7 @@ func (suite *LeverageDriftIntegrationSuite) assertProjectionExposesNoUpstreamRis req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(downstreamSSPID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: downstreamSSPID.String()}}) suite.Require().NoError(h.LeveragedControls(ctx)) suite.Equal(http.StatusOK, rec.Code) diff --git a/internal/api/handler/oscal/ssp_leverage_reattest_test.go b/internal/api/handler/oscal/ssp_leverage_reattest_test.go index 7d994f49..9e6739b1 100644 --- a/internal/api/handler/oscal/ssp_leverage_reattest_test.go +++ b/internal/api/handler/oscal/ssp_leverage_reattest_test.go @@ -10,19 +10,18 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/gorm" ) -func newReAttestRequestContext(sspID, linkID uuid.UUID) (echo.Context, *httptest.ResponseRecorder) { +func newReAttestRequestContext(sspID, linkID uuid.UUID) (*echo.Context, *httptest.ResponseRecorder) { e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id", "linkId") - ctx.SetParamValues(sspID.String(), linkID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}, {Name: "linkId", Value: linkID.String()}}) return ctx, rec } @@ -93,8 +92,7 @@ func TestLeveragedControlsIncludesIdStatusAndDriftRiskId(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(fx.downstreamSSPID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.downstreamSSPID.String()}}) require.NoError(t, h.LeveragedControls(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -132,8 +130,7 @@ func TestLeveragedControlsActiveLinkHasNoDriftRiskId(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(fx.downstreamSSPID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.downstreamSSPID.String()}}) require.NoError(t, h.LeveragedControls(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -173,8 +170,7 @@ func TestLeveragedControlsRevokedLinkHasNoDriftRiskId(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(fx.downstreamSSPID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.downstreamSSPID.String()}}) require.NoError(t, h.LeveragedControls(ctx)) require.Equal(t, http.StatusOK, rec.Code) diff --git a/internal/api/handler/oscal/ssp_leverage_unit_test.go b/internal/api/handler/oscal/ssp_leverage_unit_test.go index ea0c4fbb..dde4e8d9 100644 --- a/internal/api/handler/oscal/ssp_leverage_unit_test.go +++ b/internal/api/handler/oscal/ssp_leverage_unit_test.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/driver/sqlite" @@ -145,14 +145,13 @@ func newLeverageFixture(t *testing.T, db *gorm.DB) leverageFixture { } } -func newSubscribeRequestContext(offeringID uuid.UUID, body string) (echo.Context, *echo.Echo, *httptest.ResponseRecorder) { +func newSubscribeRequestContext(offeringID uuid.UUID, body string) (*echo.Context, *echo.Echo, *httptest.ResponseRecorder) { e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBufferString(body)) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(offeringID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: offeringID.String()}}) ctx.Set("user", &authn.UserClaims{UserUUID: uuid.New().String()}) return ctx, e, rec } @@ -477,7 +476,7 @@ func TestSubscribeForbiddenWhenDownstreamUpdateDenied(t *testing.T) { err := h.Subscribe(ctx) require.Error(t, err) - e.HTTPErrorHandler(err, ctx) + e.HTTPErrorHandler(ctx, err) require.Equal(t, http.StatusForbidden, rec.Code) var count int64 @@ -586,8 +585,7 @@ func TestLeveragedControlsProjectionShowsPartialAndOutstanding(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(fx.downstreamSSPID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.downstreamSSPID.String()}}) require.NoError(t, h.LeveragedControls(ctx)) require.Equal(t, http.StatusOK, rec.Code) diff --git a/internal/api/handler/oscal/ssp_scope.go b/internal/api/handler/oscal/ssp_scope.go index 778ef54e..49e8fca5 100644 --- a/internal/api/handler/oscal/ssp_scope.go +++ b/internal/api/handler/oscal/ssp_scope.go @@ -12,7 +12,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/sspscope" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -98,7 +98,7 @@ func newSSPScopeExceptionResponse(exception relational.SSPScopeException) sspSco // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/scope [get] -func (h *SSPScopeHandler) Get(ctx echo.Context) error { +func (h *SSPScopeHandler) Get(ctx *echo.Context) error { sspID, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -122,7 +122,7 @@ func (h *SSPScopeHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/scope [put] -func (h *SSPScopeHandler) Update(ctx echo.Context) error { +func (h *SSPScopeHandler) Update(ctx *echo.Context) error { sspID, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -157,7 +157,7 @@ func (h *SSPScopeHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/scope/entries [post] -func (h *SSPScopeHandler) AddEntry(ctx echo.Context) error { +func (h *SSPScopeHandler) AddEntry(ctx *echo.Context) error { sspID, labels, actor, ok := h.bindLabels(ctx) if !ok { return nil @@ -186,7 +186,7 @@ func (h *SSPScopeHandler) AddEntry(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/scope/exceptions [post] -func (h *SSPScopeHandler) AddException(ctx echo.Context) error { +func (h *SSPScopeHandler) AddException(ctx *echo.Context) error { sspID, labels, actor, ok := h.bindLabels(ctx) if !ok { return nil @@ -212,7 +212,7 @@ func (h *SSPScopeHandler) AddException(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/scope/exceptions/{exceptionId} [delete] -func (h *SSPScopeHandler) DeleteException(ctx echo.Context) error { +func (h *SSPScopeHandler) DeleteException(ctx *echo.Context) error { sspID, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -227,7 +227,7 @@ func (h *SSPScopeHandler) DeleteException(ctx echo.Context) error { return ctx.NoContent(http.StatusNoContent) } -func (h *SSPScopeHandler) respondScope(ctx echo.Context, sspID uuid.UUID) error { +func (h *SSPScopeHandler) respondScope(ctx *echo.Context, sspID uuid.UUID) error { scope, err := h.scope.Get(sspID) if err != nil { return h.scopeError(ctx, err) @@ -248,7 +248,7 @@ func (h *SSPScopeHandler) respondScope(ctx echo.Context, sspID uuid.UUID) error // bindLabels parses the SSP id, the labels body and the acting user. On failure it has // already written the response and returns ok=false. -func (h *SSPScopeHandler) bindLabels(ctx echo.Context) (uuid.UUID, []relational.ScopeLabel, *uuid.UUID, bool) { +func (h *SSPScopeHandler) bindLabels(ctx *echo.Context) (uuid.UUID, []relational.ScopeLabel, *uuid.UUID, bool) { sspID, err := uuid.Parse(ctx.Param("id")) if err != nil { _ = ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -269,7 +269,7 @@ func (h *SSPScopeHandler) bindLabels(ctx echo.Context) (uuid.UUID, []relational. } // actor returns the id of the calling user, or nil when the caller is not a known user. -func (h *SSPScopeHandler) actor(ctx echo.Context) (*uuid.UUID, error) { +func (h *SSPScopeHandler) actor(ctx *echo.Context) (*uuid.UUID, error) { claims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || claims == nil { return nil, nil @@ -284,7 +284,7 @@ func (h *SSPScopeHandler) actor(ctx echo.Context) (*uuid.UUID, error) { return users[0].ID, nil } -func (h *SSPScopeHandler) scopeError(ctx echo.Context, err error) error { +func (h *SSPScopeHandler) scopeError(ctx *echo.Context, err error) error { switch { case errors.Is(err, sspscope.ErrSSPNotFound), errors.Is(err, sspscope.ErrExceptionNotFound): return ctx.JSON(http.StatusNotFound, api.NewError(err)) diff --git a/internal/api/handler/oscal/ssp_shared_responsibility.go b/internal/api/handler/oscal/ssp_shared_responsibility.go index fdbd82aa..9030a729 100644 --- a/internal/api/handler/oscal/ssp_shared_responsibility.go +++ b/internal/api/handler/oscal/ssp_shared_responsibility.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" "github.com/compliance-framework/api/internal/api" @@ -126,7 +126,7 @@ type SharedResponsibilityRollup struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/shared-responsibility [get] -func (h *SystemSecurityPlanHandler) SharedResponsibility(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) SharedResponsibility(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/ssp_shared_responsibility_test.go b/internal/api/handler/oscal/ssp_shared_responsibility_test.go index a9faf432..31e24a78 100644 --- a/internal/api/handler/oscal/ssp_shared_responsibility_test.go +++ b/internal/api/handler/oscal/ssp_shared_responsibility_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/datatypes" @@ -135,21 +135,23 @@ func newSharedResponsibilityFixture(t *testing.T, db *gorm.DB) sharedResponsibil // newByComponentContext builds an echo context addressed at one statement-level by-component, // with any extra path params (inheritedId/satisfiedId) appended. -func newByComponentContext(method, body string, sspID, reqID, stmtID, bcID uuid.UUID, extra ...[2]string) (echo.Context, *httptest.ResponseRecorder) { +func newByComponentContext(method, body string, sspID, reqID, stmtID, bcID uuid.UUID, extra ...[2]string) (*echo.Context, *httptest.ResponseRecorder) { e := echo.New() req := httptest.NewRequest(method, "/", bytes.NewBufferString(body)) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - names := []string{"id", "reqId", "stmtId", "byComponentId"} - values := []string{sspID.String(), reqID.String(), stmtID.String(), bcID.String()} + pathValues := echo.PathValues{ + {Name: "id", Value: sspID.String()}, + {Name: "reqId", Value: reqID.String()}, + {Name: "stmtId", Value: stmtID.String()}, + {Name: "byComponentId", Value: bcID.String()}, + } for _, pair := range extra { - names = append(names, pair[0]) - values = append(values, pair[1]) + pathValues = append(pathValues, echo.PathValue{Name: pair[0], Value: pair[1]}) } - ctx.SetParamNames(names...) - ctx.SetParamValues(values...) + ctx.SetPathValues(pathValues) return ctx, rec } @@ -498,8 +500,7 @@ func TestListStatementByComponentsReturnsAll(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id", "reqId", "stmtId") - ctx.SetParamValues(fx.upstreamSSPID.String(), fx.requirementID.String(), fx.statementID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.upstreamSSPID.String()}, {Name: "reqId", Value: fx.requirementID.String()}, {Name: "stmtId", Value: fx.statementID.String()}}) require.NoError(t, h.GetImplementedRequirementStatementByComponents(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -907,8 +908,7 @@ func TestDeleteRequirementByComponentCascades(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id", "reqId", "byComponentId") - ctx.SetParamValues(fx.upstreamSSPID.String(), fx.requirementID.String(), legacyBC.ID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.upstreamSSPID.String()}, {Name: "reqId", Value: fx.requirementID.String()}, {Name: "byComponentId", Value: legacyBC.ID.String()}}) require.NoError(t, h.DeleteImplementedRequirementByComponent(ctx)) require.Equal(t, http.StatusNoContent, rec.Code) @@ -957,8 +957,7 @@ func TestByControlResolvesEveryPointer(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("controlId") - ctx.SetParamValues("AC-2") // deliberately different casing from the stored "ac-2" + ctx.SetPathValues(echo.PathValues{{Name: "controlId", Value: "AC-2"}}) // deliberately different casing from the stored "ac-2" require.NoError(t, h.ByControl(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -998,8 +997,7 @@ func TestByControlExcludesUnpublishedOfferings(t *testing.T) { e := echo.New() rec := httptest.NewRecorder() ctx := e.NewContext(httptest.NewRequest(http.MethodGet, "/", nil), rec) - ctx.SetParamNames("controlId") - ctx.SetParamValues("ac-2") + ctx.SetPathValues(echo.PathValues{{Name: "controlId", Value: "ac-2"}}) require.NoError(t, h.ByControl(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -1021,8 +1019,7 @@ func TestByControlHonoursDownstreamAllowList(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodGet, "/?downstreamSspId="+downstream.String(), nil) ctx := e.NewContext(req, rec) - ctx.SetParamNames("controlId") - ctx.SetParamValues("ac-2") + ctx.SetPathValues(echo.PathValues{{Name: "controlId", Value: "ac-2"}}) require.NoError(t, h.ByControl(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -1072,8 +1069,7 @@ func TestSharedResponsibilityRollup(t *testing.T) { e := echo.New() rec := httptest.NewRecorder() ctx := e.NewContext(httptest.NewRequest(http.MethodGet, "/"+query, nil), rec) - ctx.SetParamNames("id") - ctx.SetParamValues(sspID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}}) require.NoError(t, h.SharedResponsibility(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -1138,8 +1134,7 @@ func TestSharedResponsibilityFiltersByControl(t *testing.T) { e := echo.New() rec := httptest.NewRecorder() ctx := e.NewContext(httptest.NewRequest(http.MethodGet, "/?controlId="+controlID, nil), rec) - ctx.SetParamNames("id") - ctx.SetParamValues(sspID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}}) require.NoError(t, h.SharedResponsibility(ctx)) // Without this, an error response still returns nil from the handler and its JSON body // unmarshals into a ZERO-VALUE rollup — so every "Empty" assertion below would pass just @@ -1456,8 +1451,7 @@ func TestSharedResponsibilityOfferedIsPublishedOnly(t *testing.T) { e := echo.New() rec := httptest.NewRecorder() ctx := e.NewContext(httptest.NewRequest(http.MethodGet, "/", nil), rec) - ctx.SetParamNames("id") - ctx.SetParamValues(fx.upstreamSSPID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.upstreamSSPID.String()}}) require.NoError(t, h.SharedResponsibility(ctx)) require.Equal(t, http.StatusOK, rec.Code) @@ -1559,8 +1553,7 @@ func TestDeletingByComponentWithSubscribedInheritedConflicts(t *testing.T) { e := echo.New() rec = httptest.NewRecorder() ctx = e.NewContext(httptest.NewRequest(http.MethodDelete, "/", nil), rec) - ctx.SetParamNames("id", "reqId") - ctx.SetParamValues(fx.downstreamSSPID.String(), reqID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.downstreamSSPID.String()}, {Name: "reqId", Value: reqID.String()}}) require.NoError(t, h.DeleteImplementedRequirement(ctx)) require.Equal(t, http.StatusConflict, rec.Code, rec.Body.String()) @@ -1626,8 +1619,7 @@ func TestOfferingItemStoresCanonicalControlIdCasing(t *testing.T) { httpReq.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() ctx := e.NewContext(httpReq, rec) - ctx.SetParamNames("id", "offeringId") - ctx.SetParamValues(fx.upstreamSSPID.String(), fx.offeringID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.upstreamSSPID.String()}, {Name: "offeringId", Value: fx.offeringID.String()}}) require.NoError(t, h.CreateItem(ctx)) require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) @@ -1698,8 +1690,7 @@ func TestSharedResponsibilityLegacyExcludesOrdinaryImplementations(t *testing.T) e := echo.New() rec := httptest.NewRecorder() ctx := e.NewContext(httptest.NewRequest(http.MethodGet, "/", nil), rec) - ctx.SetParamNames("id") - ctx.SetParamValues(fx.upstreamSSPID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: fx.upstreamSSPID.String()}}) require.NoError(t, h.SharedResponsibility(ctx)) require.Equal(t, http.StatusOK, rec.Code) diff --git a/internal/api/handler/oscal/subject.go b/internal/api/handler/oscal/subject.go index 6315af6d..90b2460d 100644 --- a/internal/api/handler/oscal/subject.go +++ b/internal/api/handler/oscal/subject.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/compliance-framework/api/internal/api" "github.com/compliance-framework/api/internal/api/handler" @@ -34,7 +34,7 @@ func (h *AssessmentPlanHandler) validateAssessmentSubjectInput(subject *oscalTyp // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-subjects [get] -func (h *AssessmentPlanHandler) GetAssessmentSubjects(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetAssessmentSubjects(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -78,7 +78,7 @@ func (h *AssessmentPlanHandler) GetAssessmentSubjects(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-subjects [post] -func (h *AssessmentPlanHandler) CreateAssessmentSubject(ctx echo.Context) error { +func (h *AssessmentPlanHandler) CreateAssessmentSubject(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -182,7 +182,7 @@ func (h *AssessmentPlanHandler) CreateAssessmentSubject(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-subjects/{subjectId} [put] -func (h *AssessmentPlanHandler) UpdateAssessmentSubject(ctx echo.Context) error { +func (h *AssessmentPlanHandler) UpdateAssessmentSubject(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -246,7 +246,7 @@ func (h *AssessmentPlanHandler) UpdateAssessmentSubject(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/assessment-subjects/{subjectId} [delete] -func (h *AssessmentPlanHandler) DeleteAssessmentSubject(ctx echo.Context) error { +func (h *AssessmentPlanHandler) DeleteAssessmentSubject(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/subject_integration_test.go b/internal/api/handler/oscal/subject_integration_test.go index 0e3cef4d..a7415c8a 100644 --- a/internal/api/handler/oscal/subject_integration_test.go +++ b/internal/api/handler/oscal/subject_integration_test.go @@ -17,7 +17,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/system_security_plan_profiles_integration_test.go b/internal/api/handler/oscal/system_security_plan_profiles_integration_test.go index 1bbb56ce..c7716ba9 100644 --- a/internal/api/handler/oscal/system_security_plan_profiles_integration_test.go +++ b/internal/api/handler/oscal/system_security_plan_profiles_integration_test.go @@ -19,7 +19,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/oscal/system_security_plan_suggestions_integration_test.go b/internal/api/handler/oscal/system_security_plan_suggestions_integration_test.go index 3125f0fe..578df6c6 100644 --- a/internal/api/handler/oscal/system_security_plan_suggestions_integration_test.go +++ b/internal/api/handler/oscal/system_security_plan_suggestions_integration_test.go @@ -20,7 +20,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" diff --git a/internal/api/handler/oscal/system_security_plans.go b/internal/api/handler/oscal/system_security_plans.go index 1c4f72b2..1059343a 100644 --- a/internal/api/handler/oscal/system_security_plans.go +++ b/internal/api/handler/oscal/system_security_plans.go @@ -26,7 +26,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/sspservice" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/datatypes" "gorm.io/gorm" @@ -551,7 +551,7 @@ func (h *SystemSecurityPlanHandler) Register(api *echo.Group, guard middleware.R // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans [get] -func (h *SystemSecurityPlanHandler) List(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) List(ctx *echo.Context) error { var ssps []relational.SystemSecurityPlan if err := h.db. @@ -584,7 +584,7 @@ func (h *SystemSecurityPlanHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id} [get] -func (h *SystemSecurityPlanHandler) Get(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) Get(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -622,7 +622,7 @@ func (h *SystemSecurityPlanHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans [post] -func (h *SystemSecurityPlanHandler) Create(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) Create(ctx *echo.Context) error { var oscalSSP oscalTypes_1_1_3.SystemSecurityPlan if err := ctx.Bind(&oscalSSP); err != nil { h.sugar.Warnw("Invalid create SSP request", "error", err) @@ -658,7 +658,7 @@ func (h *SystemSecurityPlanHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics [get] -func (h *SystemSecurityPlanHandler) GetCharacteristics(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetCharacteristics(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -694,7 +694,7 @@ func (h *SystemSecurityPlanHandler) GetCharacteristics(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/network-architecture [get] -func (h *SystemSecurityPlanHandler) GetCharacteristicsNetworkArchitecture(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetCharacteristicsNetworkArchitecture(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -735,7 +735,7 @@ func (h *SystemSecurityPlanHandler) GetCharacteristicsNetworkArchitecture(ctx ec // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/network-architecture/diagrams [post] -func (h *SystemSecurityPlanHandler) CreateCharacteristicsNetworkArchitectureDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateCharacteristicsNetworkArchitectureDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -815,7 +815,7 @@ func (h *SystemSecurityPlanHandler) CreateCharacteristicsNetworkArchitectureDiag // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/network-architecture/diagrams/{diagram} [put] -func (h *SystemSecurityPlanHandler) UpdateCharacteristicsNetworkArchitectureDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateCharacteristicsNetworkArchitectureDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") planID, err := uuid.Parse(idParam) if err != nil { @@ -887,7 +887,7 @@ func (h *SystemSecurityPlanHandler) UpdateCharacteristicsNetworkArchitectureDiag // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/network-architecture/diagrams/{diagram} [delete] -func (h *SystemSecurityPlanHandler) DeleteCharacteristicsNetworkArchitectureDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteCharacteristicsNetworkArchitectureDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") planID, err := uuid.Parse(idParam) if err != nil { @@ -939,7 +939,7 @@ func (h *SystemSecurityPlanHandler) DeleteCharacteristicsNetworkArchitectureDiag // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/data-flow [get] -func (h *SystemSecurityPlanHandler) GetCharacteristicsDataFlow(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetCharacteristicsDataFlow(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -980,7 +980,7 @@ func (h *SystemSecurityPlanHandler) GetCharacteristicsDataFlow(ctx echo.Context) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/data-flow/diagrams [post] -func (h *SystemSecurityPlanHandler) CreateCharacteristicsDataFlowDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateCharacteristicsDataFlowDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -1056,7 +1056,7 @@ func (h *SystemSecurityPlanHandler) CreateCharacteristicsDataFlowDiagram(ctx ech // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/data-flow/diagrams/{diagram} [put] -func (h *SystemSecurityPlanHandler) UpdateCharacteristicsDataFlowDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateCharacteristicsDataFlowDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") planID, err := uuid.Parse(idParam) if err != nil { @@ -1128,7 +1128,7 @@ func (h *SystemSecurityPlanHandler) UpdateCharacteristicsDataFlowDiagram(ctx ech // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/data-flow/diagrams/{diagram} [delete] -func (h *SystemSecurityPlanHandler) DeleteCharacteristicsDataFlowDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteCharacteristicsDataFlowDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") planID, err := uuid.Parse(idParam) if err != nil { @@ -1180,7 +1180,7 @@ func (h *SystemSecurityPlanHandler) DeleteCharacteristicsDataFlowDiagram(ctx ech // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/authorization-boundary [get] -func (h *SystemSecurityPlanHandler) GetCharacteristicsAuthorizationBoundary(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetCharacteristicsAuthorizationBoundary(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1221,7 +1221,7 @@ func (h *SystemSecurityPlanHandler) GetCharacteristicsAuthorizationBoundary(ctx // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/authorization-boundary/diagrams [post] -func (h *SystemSecurityPlanHandler) CreateCharacteristicsAuthorizationBoundaryDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateCharacteristicsAuthorizationBoundaryDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -1297,7 +1297,7 @@ func (h *SystemSecurityPlanHandler) CreateCharacteristicsAuthorizationBoundaryDi // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/authorization-boundary/diagrams/{diagram} [put] -func (h *SystemSecurityPlanHandler) UpdateCharacteristicsAuthorizationBoundaryDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateCharacteristicsAuthorizationBoundaryDiagram(ctx *echo.Context) error { // This is ugly for now, but it's safe and it works. idParam := ctx.Param("id") @@ -1373,7 +1373,7 @@ func (h *SystemSecurityPlanHandler) UpdateCharacteristicsAuthorizationBoundaryDi // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics/authorization-boundary/diagrams/{diagram} [delete] -func (h *SystemSecurityPlanHandler) DeleteCharacteristicsAuthorizationBoundaryDiagram(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteCharacteristicsAuthorizationBoundaryDiagram(ctx *echo.Context) error { idParam := ctx.Param("id") planID, err := uuid.Parse(idParam) if err != nil { @@ -1427,7 +1427,7 @@ func (h *SystemSecurityPlanHandler) DeleteCharacteristicsAuthorizationBoundaryDi // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-characteristics [put] -func (h *SystemSecurityPlanHandler) UpdateCharacteristics(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateCharacteristics(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1479,7 +1479,7 @@ func (h *SystemSecurityPlanHandler) UpdateCharacteristics(ctx echo.Context) erro // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-implementation [get] -func (h *SystemSecurityPlanHandler) GetSystemImplementation(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetSystemImplementation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1532,7 +1532,7 @@ func (h *SystemSecurityPlanHandler) GetSystemImplementation(ctx echo.Context) er // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-implementation/users [get] -func (h *SystemSecurityPlanHandler) GetSystemImplementationUsers(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetSystemImplementationUsers(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1570,7 +1570,7 @@ func (h *SystemSecurityPlanHandler) GetSystemImplementationUsers(ctx echo.Contex // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-implementation/components [get] -func (h *SystemSecurityPlanHandler) GetSystemImplementationComponents(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetSystemImplementationComponents(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1608,7 +1608,7 @@ func (h *SystemSecurityPlanHandler) GetSystemImplementationComponents(ctx echo.C // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-implementation/components/{componentId} [get] -func (h *SystemSecurityPlanHandler) GetSystemImplementationComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetSystemImplementationComponent(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1651,7 +1651,7 @@ func (h *SystemSecurityPlanHandler) GetSystemImplementationComponent(ctx echo.Co // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-implementation/inventory-items [get] -func (h *SystemSecurityPlanHandler) GetSystemImplementationInventoryItems(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetSystemImplementationInventoryItems(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1694,7 +1694,7 @@ func (h *SystemSecurityPlanHandler) GetSystemImplementationInventoryItems(ctx ec // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-implementation/leveraged-authorizations [get] -func (h *SystemSecurityPlanHandler) GetSystemImplementationLeveragedAuthorizations(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetSystemImplementationLeveragedAuthorizations(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1736,7 +1736,7 @@ func (h *SystemSecurityPlanHandler) GetSystemImplementationLeveragedAuthorizatio // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation [get] -func (h *SystemSecurityPlanHandler) GetControlImplementation(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetControlImplementation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1793,7 +1793,7 @@ func (h *SystemSecurityPlanHandler) GetControlImplementation(ctx echo.Context) e return ctx.JSON(http.StatusOK, handler.GenericDataResponse[oscalTypes_1_1_3.ControlImplementation]{Data: ssp.MarshalOscal().ControlImplementation}) } -func (h *SystemSecurityPlanHandler) Full(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) Full(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1923,7 +1923,7 @@ func (h *SystemSecurityPlanHandler) Full(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id} [put] -func (h *SystemSecurityPlanHandler) Update(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) Update(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -1977,7 +1977,7 @@ func (h *SystemSecurityPlanHandler) Update(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id} [delete] -func (h *SystemSecurityPlanHandler) Delete(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) Delete(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2014,7 +2014,7 @@ func (h *SystemSecurityPlanHandler) Delete(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/metadata [get] -func (h *SystemSecurityPlanHandler) GetMetadata(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetMetadata(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2050,7 +2050,7 @@ func (h *SystemSecurityPlanHandler) GetMetadata(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/metadata [put] -func (h *SystemSecurityPlanHandler) UpdateMetadata(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateMetadata(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2106,7 +2106,7 @@ func (h *SystemSecurityPlanHandler) UpdateMetadata(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/profile [get] -func (h *SystemSecurityPlanHandler) GetProfile(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetProfile(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2153,7 +2153,7 @@ func (h *SystemSecurityPlanHandler) GetProfile(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/profile [put] -func (h *SystemSecurityPlanHandler) AttachProfile(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) AttachProfile(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2305,7 +2305,7 @@ func (h *SystemSecurityPlanHandler) AttachProfile(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/profiles [get] -func (h *SystemSecurityPlanHandler) ListProfiles(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) ListProfiles(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2350,7 +2350,7 @@ func (h *SystemSecurityPlanHandler) ListProfiles(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/profiles [post] -func (h *SystemSecurityPlanHandler) AddProfile(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) AddProfile(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2423,7 +2423,7 @@ func (h *SystemSecurityPlanHandler) AddProfile(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/profiles/{profileId} [delete] -func (h *SystemSecurityPlanHandler) RemoveProfile(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) RemoveProfile(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2495,7 +2495,7 @@ func (h *SystemSecurityPlanHandler) RemoveProfile(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/import-profile [get] -func (h *SystemSecurityPlanHandler) GetImportProfile(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImportProfile(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2531,7 +2531,7 @@ func (h *SystemSecurityPlanHandler) GetImportProfile(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/import-profile [put] -func (h *SystemSecurityPlanHandler) UpdateImportProfile(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImportProfile(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2594,7 +2594,7 @@ func (h *SystemSecurityPlanHandler) UpdateImportProfile(ctx echo.Context) error // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/system-implementation [put] -func (h *SystemSecurityPlanHandler) UpdateSystemImplementation(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateSystemImplementation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2659,7 +2659,7 @@ func (h *SystemSecurityPlanHandler) UpdateSystemImplementation(ctx echo.Context) // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/users [post] -func (h *SystemSecurityPlanHandler) CreateSystemImplementationUser(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateSystemImplementationUser(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2721,7 +2721,7 @@ func (h *SystemSecurityPlanHandler) CreateSystemImplementationUser(ctx echo.Cont // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/users/{userId} [put] -func (h *SystemSecurityPlanHandler) UpdateSystemImplementationUser(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateSystemImplementationUser(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2792,7 +2792,7 @@ func (h *SystemSecurityPlanHandler) UpdateSystemImplementationUser(ctx echo.Cont // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/users/{userId} [delete] -func (h *SystemSecurityPlanHandler) DeleteSystemImplementationUser(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteSystemImplementationUser(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2850,7 +2850,7 @@ func (h *SystemSecurityPlanHandler) DeleteSystemImplementationUser(ctx echo.Cont // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/components [post] -func (h *SystemSecurityPlanHandler) CreateSystemImplementationComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateSystemImplementationComponent(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -2913,7 +2913,7 @@ func (h *SystemSecurityPlanHandler) CreateSystemImplementationComponent(ctx echo // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/components/{componentId} [put] -func (h *SystemSecurityPlanHandler) UpdateSystemImplementationComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateSystemImplementationComponent(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -2991,7 +2991,7 @@ func (h *SystemSecurityPlanHandler) UpdateSystemImplementationComponent(ctx echo // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/components/{componentId} [delete] -func (h *SystemSecurityPlanHandler) DeleteSystemImplementationComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteSystemImplementationComponent(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3066,7 +3066,7 @@ func (h *SystemSecurityPlanHandler) DeleteSystemImplementationComponent(ctx echo // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/inventory-items [post] -func (h *SystemSecurityPlanHandler) CreateSystemImplementationInventoryItem(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateSystemImplementationInventoryItem(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3128,7 +3128,7 @@ func (h *SystemSecurityPlanHandler) CreateSystemImplementationInventoryItem(ctx // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/inventory-items/{itemId} [put] -func (h *SystemSecurityPlanHandler) UpdateSystemImplementationInventoryItem(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateSystemImplementationInventoryItem(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3200,7 +3200,7 @@ func (h *SystemSecurityPlanHandler) UpdateSystemImplementationInventoryItem(ctx // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/inventory-items/{itemId} [delete] -func (h *SystemSecurityPlanHandler) DeleteSystemImplementationInventoryItem(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteSystemImplementationInventoryItem(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3258,7 +3258,7 @@ func (h *SystemSecurityPlanHandler) DeleteSystemImplementationInventoryItem(ctx // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/leveraged-authorizations [post] -func (h *SystemSecurityPlanHandler) CreateSystemImplementationLeveragedAuthorization(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateSystemImplementationLeveragedAuthorization(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3315,7 +3315,7 @@ func (h *SystemSecurityPlanHandler) CreateSystemImplementationLeveragedAuthoriza // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/leveraged-authorizations/{authId} [put] -func (h *SystemSecurityPlanHandler) UpdateSystemImplementationLeveragedAuthorization(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateSystemImplementationLeveragedAuthorization(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3386,7 +3386,7 @@ func (h *SystemSecurityPlanHandler) UpdateSystemImplementationLeveragedAuthoriza // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/system-implementation/leveraged-authorizations/{authId} [delete] -func (h *SystemSecurityPlanHandler) DeleteSystemImplementationLeveragedAuthorization(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteSystemImplementationLeveragedAuthorization(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3473,7 +3473,7 @@ func (h *SystemSecurityPlanHandler) DeleteSystemImplementationLeveragedAuthoriza // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation [put] -func (h *SystemSecurityPlanHandler) UpdateControlImplementation(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateControlImplementation(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3521,7 +3521,7 @@ func (h *SystemSecurityPlanHandler) UpdateControlImplementation(ctx echo.Context // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirements(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirements(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3579,7 +3579,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirements(ctx echo.Context) // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirement(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3642,7 +3642,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirement(ctx echo.Contex // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirement(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3725,7 +3725,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirement(ctx echo.Contex // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponent(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -3749,7 +3749,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponent(ctx // @Failure 409 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirement(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3839,7 +3839,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirement(ctx echo.Contex // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatement(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -3902,7 +3902,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatement(ctx ec // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/back-matter [get] -func (h *SystemSecurityPlanHandler) GetBackMatter(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3941,7 +3941,7 @@ func (h *SystemSecurityPlanHandler) GetBackMatter(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/back-matter [put] -func (h *SystemSecurityPlanHandler) UpdateBackMatter(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateBackMatter(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -3998,7 +3998,7 @@ func (h *SystemSecurityPlanHandler) UpdateBackMatter(ctx echo.Context) error { // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/back-matter/resources [get] -func (h *SystemSecurityPlanHandler) GetBackMatterResources(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetBackMatterResources(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -4037,7 +4037,7 @@ func (h *SystemSecurityPlanHandler) GetBackMatterResources(ctx echo.Context) err // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/back-matter/resources [post] -func (h *SystemSecurityPlanHandler) CreateBackMatterResource(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -4093,7 +4093,7 @@ func (h *SystemSecurityPlanHandler) CreateBackMatterResource(ctx echo.Context) e // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/back-matter/resources/{resourceId} [put] -func (h *SystemSecurityPlanHandler) UpdateBackMatterResource(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -4157,7 +4157,7 @@ func (h *SystemSecurityPlanHandler) UpdateBackMatterResource(ctx echo.Context) e // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/back-matter/resources/{resourceId} [delete] -func (h *SystemSecurityPlanHandler) DeleteBackMatterResource(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteBackMatterResource(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -4210,7 +4210,7 @@ func (h *SystemSecurityPlanHandler) DeleteBackMatterResource(ctx echo.Context) e // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatement(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -4302,7 +4302,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatement(ctx ec // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponent(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -4327,7 +4327,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByCompo // struct cannot distinguish "absent" from "present and empty", and GORM's map-form Updates writes // every key it is given unconditionally (the zero-value skipping people expect applies only to // struct-form Updates). So the update map is built from the keys the client actually sent. -func (h *SystemSecurityPlanHandler) updateByComponentMetadata(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) updateByComponentMetadata(ctx *echo.Context, bc *relational.ByComponent) error { // Read the body before Bind consumes it, then hand it back for binding. rawBody, err := io.ReadAll(ctx.Request().Body) if err != nil { @@ -4502,7 +4502,7 @@ func (h *SystemSecurityPlanHandler) reloadByComponent(byComponentID uuid.UUID) ( // @Failure 409 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponent(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -4600,7 +4600,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByCompo // @Failure 404 {object} api.Error // @Failure 500 {object} api.Error // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponent(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponent(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -4682,7 +4682,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByCompo // directly to an implemented requirement (control-level). On any failure it writes // the appropriate JSON error response to ctx and returns ok=false; callers should // return nil immediately when ok is false. -func (h *SystemSecurityPlanHandler) resolveByComponentForRequirement(ctx echo.Context) (bc *relational.ByComponent, ok bool) { +func (h *SystemSecurityPlanHandler) resolveByComponentForRequirement(ctx *echo.Context) (bc *relational.ByComponent, ok bool) { sspID, reqID, err := parseSSPReqIDs(ctx) if err != nil { h.sugar.Warnw("Invalid by-component path params", "error", err) @@ -4737,7 +4737,7 @@ func (h *SystemSecurityPlanHandler) resolveByComponentForRequirement(ctx echo.Co // resolveByComponentForStatement parses and verifies a by-component that belongs to // a statement within an implemented requirement (statement-level). Same contract as // resolveByComponentForRequirement. -func (h *SystemSecurityPlanHandler) resolveByComponentForStatement(ctx echo.Context) (bc *relational.ByComponent, ok bool) { +func (h *SystemSecurityPlanHandler) resolveByComponentForStatement(ctx *echo.Context) (bc *relational.ByComponent, ok bool) { sspID, reqID, stmtID, err := parseSSPReqStmtIDs(ctx) if err != nil { h.sugar.Warnw("Invalid by-component path params", "error", err) @@ -4818,7 +4818,7 @@ func (h *SystemSecurityPlanHandler) reloadByComponentExport(byComponentID uuid.U } // getByComponentExport reads the Export sub-resource for an already-resolved by-component. -func (h *SystemSecurityPlanHandler) getByComponentExport(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) getByComponentExport(ctx *echo.Context, bc *relational.ByComponent) error { export, err := h.reloadByComponentExport(*bc.ID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -4831,7 +4831,7 @@ func (h *SystemSecurityPlanHandler) getByComponentExport(ctx echo.Context, bc *r // createByComponentExport creates the (singleton) Export sub-resource for an // already-resolved by-component. A by-component may have at most one Export. -func (h *SystemSecurityPlanHandler) createByComponentExport(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) createByComponentExport(ctx *echo.Context, bc *relational.ByComponent) error { var oscalExport oscalTypes_1_1_3.Export if err := ctx.Bind(&oscalExport); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -4922,7 +4922,7 @@ func lockByComponentSubtreeWrite(tx *gorm.DB, byComponentID uuid.UUID) error { // updateByComponentExport updates the scalar fields (description, remarks, props, // links) of an existing Export. The Provided and Responsibilities entries are managed // individually via their own routes and are left untouched here. -func (h *SystemSecurityPlanHandler) updateByComponentExport(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) updateByComponentExport(ctx *echo.Context, bc *relational.ByComponent) error { var existing relational.Export if err := h.db.Where("by_component_id = ?", bc.ID).First(&existing).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -4966,7 +4966,7 @@ func (h *SystemSecurityPlanHandler) updateByComponentExport(ctx echo.Context, bc // Responsibilities entries, including their ResponsibleRoles and responsible_role_parties // join rows. Children are deleted explicitly rather than relying on a DB-level cascade, // since this ticket makes no schema change. -func (h *SystemSecurityPlanHandler) deleteByComponentExport(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) deleteByComponentExport(ctx *echo.Context, bc *relational.ByComponent) error { var existing relational.Export if err := h.db. Preload("Provided.ResponsibleRoles.Parties"). @@ -5138,7 +5138,7 @@ func deleteByComponentCascade(tx *gorm.DB, byComponentID uuid.UUID) error { // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5170,7 +5170,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementByComponentExport(c // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5201,7 +5201,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExpor // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5229,7 +5229,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExpor // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5253,7 +5253,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExpor // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export [get] -func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5280,7 +5280,7 @@ func (h *SystemSecurityPlanHandler) GetImplementedRequirementStatementByComponen // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5306,7 +5306,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5329,7 +5329,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentExport(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentExport(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5339,7 +5339,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByCompo // findExportForByComponent looks up the (singleton) Export belonging to an // already-resolved by-component, writing a 404 if none exists. -func (h *SystemSecurityPlanHandler) findExportForByComponent(ctx echo.Context, bc *relational.ByComponent) (*relational.Export, bool) { +func (h *SystemSecurityPlanHandler) findExportForByComponent(ctx *echo.Context, bc *relational.ByComponent) (*relational.Export, bool) { var export relational.Export if err := h.db.Where("by_component_id = ?", bc.ID).First(&export).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -5354,7 +5354,7 @@ func (h *SystemSecurityPlanHandler) findExportForByComponent(ctx echo.Context, b // createByComponentExportProvided creates a Provided entry under an already-resolved // by-component's Export. -func (h *SystemSecurityPlanHandler) createByComponentExportProvided(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) createByComponentExportProvided(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -5378,7 +5378,7 @@ func (h *SystemSecurityPlanHandler) createByComponentExportProvided(ctx echo.Con // updateByComponentExportProvided replaces an existing Provided entry under an // already-resolved by-component's Export. -func (h *SystemSecurityPlanHandler) updateByComponentExportProvided(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) updateByComponentExportProvided(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -5418,7 +5418,7 @@ func (h *SystemSecurityPlanHandler) updateByComponentExportProvided(ctx echo.Con // deleteByComponentExportProvided deletes an existing Provided entry under an // already-resolved by-component's Export. -func (h *SystemSecurityPlanHandler) deleteByComponentExportProvided(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) deleteByComponentExportProvided(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -5465,7 +5465,7 @@ func (h *SystemSecurityPlanHandler) deleteByComponentExportProvided(ctx echo.Con // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/provided [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5497,7 +5497,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExpor // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/provided/{providedId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5526,7 +5526,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExpor // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/provided/{providedId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5552,7 +5552,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExpor // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/provided [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5579,7 +5579,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/provided/{providedId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5603,7 +5603,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/provided/{providedId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentExportProvided(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentExportProvided(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5613,7 +5613,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByCompo // createByComponentExportResponsibility creates a Responsibility entry under an // already-resolved by-component's Export. -func (h *SystemSecurityPlanHandler) createByComponentExportResponsibility(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) createByComponentExportResponsibility(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -5637,7 +5637,7 @@ func (h *SystemSecurityPlanHandler) createByComponentExportResponsibility(ctx ec // updateByComponentExportResponsibility replaces an existing Responsibility entry // under an already-resolved by-component's Export. -func (h *SystemSecurityPlanHandler) updateByComponentExportResponsibility(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) updateByComponentExportResponsibility(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -5677,7 +5677,7 @@ func (h *SystemSecurityPlanHandler) updateByComponentExportResponsibility(ctx ec // deleteByComponentExportResponsibility deletes an existing Responsibility entry // under an already-resolved by-component's Export. -func (h *SystemSecurityPlanHandler) deleteByComponentExportResponsibility(ctx echo.Context, bc *relational.ByComponent) error { +func (h *SystemSecurityPlanHandler) deleteByComponentExportResponsibility(ctx *echo.Context, bc *relational.ByComponent) error { export, ok := h.findExportForByComponent(ctx, bc) if !ok { return nil @@ -5724,7 +5724,7 @@ func (h *SystemSecurityPlanHandler) deleteByComponentExportResponsibility(ctx ec // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/responsibilities [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExportResponsibility(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExportResponsibility(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5756,7 +5756,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementByComponentExpor // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/responsibilities/{responsibilityId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExportResponsibility(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExportResponsibility(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5785,7 +5785,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementByComponentExpor // @Deprecated // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/by-components/{byComponentId}/export/responsibilities/{responsibilityId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExportResponsibility(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExportResponsibility(ctx *echo.Context) error { bc, ok := h.resolveByComponentForRequirement(ctx) if !ok { return nil @@ -5811,7 +5811,7 @@ func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementByComponentExpor // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/responsibilities [post] -func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentExportResponsibility(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByComponentExportResponsibility(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5838,7 +5838,7 @@ func (h *SystemSecurityPlanHandler) CreateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/responsibilities/{responsibilityId} [put] -func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentExportResponsibility(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByComponentExportResponsibility(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5862,7 +5862,7 @@ func (h *SystemSecurityPlanHandler) UpdateImplementedRequirementStatementByCompo // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/by-components/{byComponentId}/export/responsibilities/{responsibilityId} [delete] -func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentExportResponsibility(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) DeleteImplementedRequirementStatementByComponentExportResponsibility(ctx *echo.Context) error { bc, ok := h.resolveByComponentForStatement(ctx) if !ok { return nil @@ -5923,7 +5923,7 @@ func (h *SystemSecurityPlanHandler) extractControlIDsFromProfile(profile *relati // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/suggest-components [post] -func (h *SystemSecurityPlanHandler) SuggestComponents(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) SuggestComponents(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -5965,7 +5965,7 @@ func (h *SystemSecurityPlanHandler) SuggestComponents(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/suggest-components [post] -func (h *SystemSecurityPlanHandler) SuggestComponentsForStatement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) SuggestComponentsForStatement(ctx *echo.Context) error { sspID, reqID, stmtID, err := parseSSPReqStmtIDs(ctx) if err != nil { h.sugar.Warnw("Invalid statement suggestion path params", "error", err) @@ -5999,7 +5999,7 @@ func (h *SystemSecurityPlanHandler) SuggestComponentsForStatement(ctx echo.Conte // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/apply-suggestion [post] -func (h *SystemSecurityPlanHandler) ApplySuggestion(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) ApplySuggestion(ctx *echo.Context) error { sspID, reqID, err := parseSSPReqIDs(ctx) if err != nil { h.sugar.Warnw("Invalid apply-suggestion path params", "error", err) @@ -6048,7 +6048,7 @@ func (h *SystemSecurityPlanHandler) ApplySuggestion(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/apply-suggestion [post] -func (h *SystemSecurityPlanHandler) ApplySuggestionForStatement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) ApplySuggestionForStatement(ctx *echo.Context) error { sspID, reqID, stmtID, err := parseSSPReqStmtIDs(ctx) if err != nil { h.sugar.Warnw("Invalid statement apply path params", "error", err) @@ -6096,7 +6096,7 @@ func (h *SystemSecurityPlanHandler) ApplySuggestionForStatement(ctx echo.Context // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/control-implementation/implemented-requirements/{reqId}/statements/{stmtId}/apply-suggestions [post] -func (h *SystemSecurityPlanHandler) ApplySuggestionsForStatement(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) ApplySuggestionsForStatement(ctx *echo.Context) error { sspID, reqID, stmtID, err := parseSSPReqStmtIDs(ctx) if err != nil { h.sugar.Warnw("Invalid statement apply-suggestions path params", "error", err) @@ -6136,7 +6136,7 @@ func (h *SystemSecurityPlanHandler) ApplySuggestionsForStatement(ctx echo.Contex // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{id}/bulk-apply-component-suggestions [post] -func (h *SystemSecurityPlanHandler) BulkApplyComponentSuggestions(ctx echo.Context) error { +func (h *SystemSecurityPlanHandler) BulkApplyComponentSuggestions(ctx *echo.Context) error { idParam := ctx.Param("id") sspID, err := uuid.Parse(idParam) if err != nil { @@ -6155,7 +6155,7 @@ func (h *SystemSecurityPlanHandler) BulkApplyComponentSuggestions(ctx echo.Conte return ctx.NoContent(http.StatusNoContent) } -func parseSSPReqStmtIDs(ctx echo.Context) (uuid.UUID, uuid.UUID, uuid.UUID, error) { +func parseSSPReqStmtIDs(ctx *echo.Context) (uuid.UUID, uuid.UUID, uuid.UUID, error) { sspID, reqID, err := parseSSPReqIDs(ctx) if err != nil { return uuid.Nil, uuid.Nil, uuid.Nil, err @@ -6167,7 +6167,7 @@ func parseSSPReqStmtIDs(ctx echo.Context) (uuid.UUID, uuid.UUID, uuid.UUID, erro return sspID, reqID, stmtID, nil } -func parseSSPReqIDs(ctx echo.Context) (uuid.UUID, uuid.UUID, error) { +func parseSSPReqIDs(ctx *echo.Context) (uuid.UUID, uuid.UUID, error) { sspID, err := uuid.Parse(ctx.Param("id")) if err != nil { return uuid.Nil, uuid.Nil, err diff --git a/internal/api/handler/oscal/system_security_plans_leveraged_auth_drift_test.go b/internal/api/handler/oscal/system_security_plans_leveraged_auth_drift_test.go index 9d8d8320..cfadb00a 100644 --- a/internal/api/handler/oscal/system_security_plans_leveraged_auth_drift_test.go +++ b/internal/api/handler/oscal/system_security_plans_leveraged_auth_drift_test.go @@ -8,18 +8,17 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" ) -func newDeleteLeveragedAuthRequestContext(sspID, authID uuid.UUID) (echo.Context, *httptest.ResponseRecorder) { +func newDeleteLeveragedAuthRequestContext(sspID, authID uuid.UUID) (*echo.Context, *httptest.ResponseRecorder) { e := echo.New() req := httptest.NewRequest(http.MethodDelete, "/", nil) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id", "authId") - ctx.SetParamValues(sspID.String(), authID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}, {Name: "authId", Value: authID.String()}}) return ctx, rec } diff --git a/internal/api/handler/oscal/system_security_plans_test.go b/internal/api/handler/oscal/system_security_plans_test.go index 6cd76aec..dd3d2e60 100644 --- a/internal/api/handler/oscal/system_security_plans_test.go +++ b/internal/api/handler/oscal/system_security_plans_test.go @@ -14,7 +14,7 @@ import ( "time" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/oscal/system_security_plans_unit_test.go b/internal/api/handler/oscal/system_security_plans_unit_test.go index ef443c23..d31c48e1 100644 --- a/internal/api/handler/oscal/system_security_plans_unit_test.go +++ b/internal/api/handler/oscal/system_security_plans_unit_test.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/driver/sqlite" @@ -196,14 +196,13 @@ func closedSQLiteDB(t *testing.T) *gorm.DB { return db } -func newSSPProfileRequestContext(method string, sspID, profileID uuid.UUID) (echo.Context, *httptest.ResponseRecorder) { +func newSSPProfileRequestContext(method string, sspID, profileID uuid.UUID) (*echo.Context, *httptest.ResponseRecorder) { e := echo.New() body := bytes.NewBufferString(`{"profileId":"` + profileID.String() + `"}`) req := httptest.NewRequest(method, "/", body) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() ctx := e.NewContext(req, rec) - ctx.SetParamNames("id") - ctx.SetParamValues(sspID.String()) + ctx.SetPathValues(echo.PathValues{{Name: "id", Value: sspID.String()}}) return ctx, rec } diff --git a/internal/api/handler/oscal/task.go b/internal/api/handler/oscal/task.go index 1f396bf8..c5f5aef9 100644 --- a/internal/api/handler/oscal/task.go +++ b/internal/api/handler/oscal/task.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" "github.com/compliance-framework/api/internal/api" @@ -49,7 +49,7 @@ func (h *AssessmentPlanHandler) validateTaskInput(task *oscalTypes_1_1_3.Task) e // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/tasks [get] -func (h *AssessmentPlanHandler) GetTasks(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetTasks(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -101,7 +101,7 @@ func (h *AssessmentPlanHandler) GetTasks(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/tasks [post] -func (h *AssessmentPlanHandler) CreateTask(ctx echo.Context) error { +func (h *AssessmentPlanHandler) CreateTask(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -155,7 +155,7 @@ func (h *AssessmentPlanHandler) CreateTask(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/tasks/{taskId} [put] -func (h *AssessmentPlanHandler) UpdateTask(ctx echo.Context) error { +func (h *AssessmentPlanHandler) UpdateTask(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -254,7 +254,7 @@ func (h *AssessmentPlanHandler) UpdateTask(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/tasks/{taskId} [delete] -func (h *AssessmentPlanHandler) DeleteTask(ctx echo.Context) error { +func (h *AssessmentPlanHandler) DeleteTask(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -304,7 +304,7 @@ func (h *AssessmentPlanHandler) DeleteTask(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/tasks/{taskId}/associated-activities [get] -func (h *AssessmentPlanHandler) GetTaskActivities(ctx echo.Context) error { +func (h *AssessmentPlanHandler) GetTaskActivities(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -356,7 +356,7 @@ func (h *AssessmentPlanHandler) GetTaskActivities(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/tasks/{taskId}/associated-activities/{activityId} [post] -func (h *AssessmentPlanHandler) AssociateTaskActivity(ctx echo.Context) error { +func (h *AssessmentPlanHandler) AssociateTaskActivity(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { @@ -422,7 +422,7 @@ func (h *AssessmentPlanHandler) AssociateTaskActivity(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/assessment-plans/{id}/tasks/{taskId}/associated-activities/{activityId} [delete] -func (h *AssessmentPlanHandler) DisassociateTaskActivity(ctx echo.Context) error { +func (h *AssessmentPlanHandler) DisassociateTaskActivity(ctx *echo.Context) error { idParam := ctx.Param("id") id, err := uuid.Parse(idParam) if err != nil { diff --git a/internal/api/handler/oscal/task_integration_test.go b/internal/api/handler/oscal/task_integration_test.go index 826bc77f..7c37fca0 100644 --- a/internal/api/handler/oscal/task_integration_test.go +++ b/internal/api/handler/oscal/task_integration_test.go @@ -17,7 +17,7 @@ import ( "github.com/compliance-framework/api/internal/tests" oscalTypes_1_1_3 "github.com/defenseunicorns/go-oscal/src/types/oscal-1-1-3" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/permissions.go b/internal/api/handler/permissions.go index 0175fbe2..ed3651e0 100644 --- a/internal/api/handler/permissions.go +++ b/internal/api/handler/permissions.go @@ -7,7 +7,7 @@ import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/authz" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -54,7 +54,7 @@ type permissionsResponse struct { // asks the PDP for all decisions in one batch, and returns the allowed map. Resources are // always present (so the UI knows the full vocabulary) with their allowed actions; ordering // is deterministic (resources sorted, actions in manifest order). -func (h *PermissionsHandler) GetPermissions(c echo.Context) error { +func (h *PermissionsHandler) GetPermissions(c *echo.Context) error { subject := middleware.SubjectFromContext(c) subjectView := permissionsSubject{Type: subject.Type, ID: subject.ID} diff --git a/internal/api/handler/permissions_test.go b/internal/api/handler/permissions_test.go index 68419591..770ce12f 100644 --- a/internal/api/handler/permissions_test.go +++ b/internal/api/handler/permissions_test.go @@ -11,7 +11,7 @@ import ( "github.com/compliance-framework/api/internal/authn" "github.com/compliance-framework/api/internal/authz" "github.com/golang-jwt/jwt/v5" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -40,7 +40,7 @@ func (s *stubPDP) Evaluations(_ context.Context, reqs []authz.EvalRequest) ([]au return out, nil } -func newPermissionsCtx(t *testing.T, subject string) (echo.Context, *httptest.ResponseRecorder) { +func newPermissionsCtx(t *testing.T, subject string) (*echo.Context, *httptest.ResponseRecorder) { t.Helper() e := echo.New() req := httptest.NewRequest(http.MethodGet, "/api/me/permissions", nil) diff --git a/internal/api/handler/playback.go b/internal/api/handler/playback.go index c83b04a1..ad598f35 100644 --- a/internal/api/handler/playback.go +++ b/internal/api/handler/playback.go @@ -16,7 +16,7 @@ import ( artifactsvc "github.com/compliance-framework/api/internal/service/relational/artifacts" evidencesvc "github.com/compliance-framework/api/internal/service/relational/evidence" "github.com/compliance-framework/api/pkg/policyeval" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -73,7 +73,7 @@ func (h *PlaybackHandler) Register(api *echo.Group, middlewares ...echo.Middlewa // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /playback/evaluate [post] -func (h *PlaybackHandler) Evaluate(ctx echo.Context) error { +func (h *PlaybackHandler) Evaluate(ctx *echo.Context) error { select { case h.slots <- struct{}{}: defer func() { <-h.slots }() diff --git a/internal/api/handler/playback_integration_test.go b/internal/api/handler/playback_integration_test.go index d2608c85..805d285a 100644 --- a/internal/api/handler/playback_integration_test.go +++ b/internal/api/handler/playback_integration_test.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/config" "github.com/compliance-framework/api/internal/tests" "github.com/compliance-framework/api/pkg/policyeval" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" ) diff --git a/internal/api/handler/playback_test.go b/internal/api/handler/playback_test.go index 81b519c7..46b77015 100644 --- a/internal/api/handler/playback_test.go +++ b/internal/api/handler/playback_test.go @@ -10,7 +10,7 @@ import ( "github.com/compliance-framework/api/internal/config" "github.com/compliance-framework/api/pkg/policyeval" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" diff --git a/internal/api/handler/poam_items.go b/internal/api/handler/poam_items.go index 77a3f643..5db16aa6 100644 --- a/internal/api/handler/poam_items.go +++ b/internal/api/handler/poam_items.go @@ -12,7 +12,7 @@ import ( poamsvc "github.com/compliance-framework/api/internal/service/relational/poam" riskrel "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -300,7 +300,7 @@ func toMilestoneResponse(m *poamsvc.PoamItemMilestone) milestoneResponse { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items [get] -func (h *PoamItemsHandler) List(c echo.Context) error { +func (h *PoamItemsHandler) List(c *echo.Context) error { filters, err := parsePoamListFilters(c) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -338,7 +338,7 @@ func (h *PoamItemsHandler) List(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items [post] -func (h *PoamItemsHandler) Create(c echo.Context) error { +func (h *PoamItemsHandler) Create(c *echo.Context) error { var in createPoamItemRequest if err := c.Bind(&in); err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -456,7 +456,7 @@ func (h *PoamItemsHandler) Create(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id} [get] -func (h *PoamItemsHandler) Get(c echo.Context) error { +func (h *PoamItemsHandler) Get(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -485,7 +485,7 @@ func (h *PoamItemsHandler) Get(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id} [put] -func (h *PoamItemsHandler) Update(c echo.Context) error { +func (h *PoamItemsHandler) Update(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -614,7 +614,7 @@ func (h *PoamItemsHandler) Update(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id} [delete] -func (h *PoamItemsHandler) Delete(c echo.Context) error { +func (h *PoamItemsHandler) Delete(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -644,7 +644,7 @@ func (h *PoamItemsHandler) Delete(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/milestones [get] -func (h *PoamItemsHandler) ListMilestones(c echo.Context) error { +func (h *PoamItemsHandler) ListMilestones(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -680,7 +680,7 @@ func (h *PoamItemsHandler) ListMilestones(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/milestones [post] -func (h *PoamItemsHandler) AddMilestone(c echo.Context) error { +func (h *PoamItemsHandler) AddMilestone(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -731,7 +731,7 @@ func (h *PoamItemsHandler) AddMilestone(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/milestones/{milestoneId} [put] -func (h *PoamItemsHandler) UpdateMilestone(c echo.Context) error { +func (h *PoamItemsHandler) UpdateMilestone(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -777,7 +777,7 @@ func (h *PoamItemsHandler) UpdateMilestone(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/milestones/{milestoneId} [delete] -func (h *PoamItemsHandler) DeleteMilestone(c echo.Context) error { +func (h *PoamItemsHandler) DeleteMilestone(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -811,7 +811,7 @@ func (h *PoamItemsHandler) DeleteMilestone(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/risks [get] -func (h *PoamItemsHandler) ListRisks(c echo.Context) error { +func (h *PoamItemsHandler) ListRisks(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -843,7 +843,7 @@ func (h *PoamItemsHandler) ListRisks(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/risks [post] -func (h *PoamItemsHandler) AddRiskLink(c echo.Context) error { +func (h *PoamItemsHandler) AddRiskLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -884,7 +884,7 @@ func (h *PoamItemsHandler) AddRiskLink(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/risks/{riskId} [delete] -func (h *PoamItemsHandler) DeleteRiskLink(c echo.Context) error { +func (h *PoamItemsHandler) DeleteRiskLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -918,7 +918,7 @@ func (h *PoamItemsHandler) DeleteRiskLink(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/evidence [get] -func (h *PoamItemsHandler) ListEvidence(c echo.Context) error { +func (h *PoamItemsHandler) ListEvidence(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -950,7 +950,7 @@ func (h *PoamItemsHandler) ListEvidence(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/evidence [post] -func (h *PoamItemsHandler) AddEvidenceLink(c echo.Context) error { +func (h *PoamItemsHandler) AddEvidenceLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -991,7 +991,7 @@ func (h *PoamItemsHandler) AddEvidenceLink(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/evidence/{evidenceId} [delete] -func (h *PoamItemsHandler) DeleteEvidenceLink(c echo.Context) error { +func (h *PoamItemsHandler) DeleteEvidenceLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1025,7 +1025,7 @@ func (h *PoamItemsHandler) DeleteEvidenceLink(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/controls [get] -func (h *PoamItemsHandler) ListControls(c echo.Context) error { +func (h *PoamItemsHandler) ListControls(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1057,7 +1057,7 @@ func (h *PoamItemsHandler) ListControls(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/controls [post] -func (h *PoamItemsHandler) AddControlLink(c echo.Context) error { +func (h *PoamItemsHandler) AddControlLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1099,7 +1099,7 @@ func (h *PoamItemsHandler) AddControlLink(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/controls/{catalogId}/{controlId} [delete] -func (h *PoamItemsHandler) DeleteControlLink(c echo.Context) error { +func (h *PoamItemsHandler) DeleteControlLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1137,7 +1137,7 @@ func (h *PoamItemsHandler) DeleteControlLink(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/findings [get] -func (h *PoamItemsHandler) ListFindings(c echo.Context) error { +func (h *PoamItemsHandler) ListFindings(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1169,7 +1169,7 @@ func (h *PoamItemsHandler) ListFindings(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/findings [post] -func (h *PoamItemsHandler) AddFindingLink(c echo.Context) error { +func (h *PoamItemsHandler) AddFindingLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1210,7 +1210,7 @@ func (h *PoamItemsHandler) AddFindingLink(c echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /poam-items/{id}/findings/{findingId} [delete] -func (h *PoamItemsHandler) DeleteFindingLink(c echo.Context) error { +func (h *PoamItemsHandler) DeleteFindingLink(c *echo.Context) error { id, err := uuid.Parse(c.Param("id")) if err != nil { return c.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1235,7 +1235,7 @@ func (h *PoamItemsHandler) DeleteFindingLink(c echo.Context) error { // parseListFilters parses and validates all query parameters for the List // endpoint. Returns 400-compatible errors for any malformed UUID or RFC3339 // value rather than silently ignoring them (Copilot item 12). -func parsePoamListFilters(c echo.Context) (poamsvc.ListFilters, error) { +func parsePoamListFilters(c *echo.Context) (poamsvc.ListFilters, error) { var f poamsvc.ListFilters if s := c.QueryParam("status"); s != "" { @@ -1319,7 +1319,7 @@ func parseControlRefs(raw []poamControlRefRequest) ([]poamsvc.ControlRef, error) return result, nil } -func (h *PoamItemsHandler) internalError(c echo.Context, msg string, err error) error { +func (h *PoamItemsHandler) internalError(c *echo.Context, msg string, err error) error { h.sugar.Errorw(msg, "error", err) return c.JSON(http.StatusInternalServerError, api.NewError(err)) } diff --git a/internal/api/handler/poam_items_integration_test.go b/internal/api/handler/poam_items_integration_test.go index 69871663..a86ceef9 100644 --- a/internal/api/handler/poam_items_integration_test.go +++ b/internal/api/handler/poam_items_integration_test.go @@ -17,7 +17,7 @@ import ( poamsvc "github.com/compliance-framework/api/internal/service/relational/poam" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/request.go b/internal/api/handler/request.go index 74f74b90..5483489e 100644 --- a/internal/api/handler/request.go +++ b/internal/api/handler/request.go @@ -7,7 +7,7 @@ import ( "github.com/compliance-framework/api/internal/converters/labelfilter" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) func ParseIntervalListQueryParam(intervalQuery string, def []time.Duration) ([]time.Duration, error) { @@ -100,7 +100,7 @@ type filteredSearchRequest struct { Filter labelfilter.Filter `json:"filter" yaml:"filter" validate:"required"` } -func (r *filteredSearchRequest) bind(ctx echo.Context, p *labelfilter.Filter) error { +func (r *filteredSearchRequest) bind(ctx *echo.Context, p *labelfilter.Filter) error { if err := ctx.Bind(r); err != nil { return err } diff --git a/internal/api/handler/risk_threat_remediation.go b/internal/api/handler/risk_threat_remediation.go index dd7548ff..4042444d 100644 --- a/internal/api/handler/risk_threat_remediation.go +++ b/internal/api/handler/risk_threat_remediation.go @@ -9,7 +9,7 @@ import ( svc "github.com/compliance-framework/api/internal/service" riskrel "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" ) @@ -29,7 +29,7 @@ import ( // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/threat-ids [get] -func (h *RiskHandler) ListThreatRefsForSSP(ctx echo.Context) error { +func (h *RiskHandler) ListThreatRefsForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -62,7 +62,7 @@ func (h *RiskHandler) ListThreatRefsForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/threat-ids [get] -func (h *RiskHandler) ListThreatRefs(ctx echo.Context) error { +func (h *RiskHandler) ListThreatRefs(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { rows, total, err := h.riskService.ListThreatRefs(riskID, pagination.Limit, pagination.Offset) if err != nil { @@ -102,7 +102,7 @@ func (h *RiskHandler) ListThreatRefs(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/threat-ids/{threatRefId} [get] -func (h *RiskHandler) GetThreatRefForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetThreatRefForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -134,7 +134,7 @@ func (h *RiskHandler) GetThreatRefForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/threat-ids/{threatRefId} [get] -func (h *RiskHandler) GetThreatRef(ctx echo.Context) error { +func (h *RiskHandler) GetThreatRef(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -181,7 +181,7 @@ func (h *RiskHandler) GetThreatRef(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/threat-ids [post] -func (h *RiskHandler) AddThreatRefForSSP(ctx echo.Context) error { +func (h *RiskHandler) AddThreatRefForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -214,7 +214,7 @@ func (h *RiskHandler) AddThreatRefForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/threat-ids [post] -func (h *RiskHandler) AddThreatRef(ctx echo.Context) error { +func (h *RiskHandler) AddThreatRef(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -271,7 +271,7 @@ func (h *RiskHandler) AddThreatRef(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/threat-ids/{threatRefId} [put] -func (h *RiskHandler) UpdateThreatRefForSSP(ctx echo.Context) error { +func (h *RiskHandler) UpdateThreatRefForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -305,7 +305,7 @@ func (h *RiskHandler) UpdateThreatRefForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/threat-ids/{threatRefId} [put] -func (h *RiskHandler) UpdateThreatRef(ctx echo.Context) error { +func (h *RiskHandler) UpdateThreatRef(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -364,7 +364,7 @@ func (h *RiskHandler) UpdateThreatRef(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/threat-ids/{threatRefId} [delete] -func (h *RiskHandler) DeleteThreatRefForSSP(ctx echo.Context) error { +func (h *RiskHandler) DeleteThreatRefForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -396,7 +396,7 @@ func (h *RiskHandler) DeleteThreatRefForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/threat-ids/{threatRefId} [delete] -func (h *RiskHandler) DeleteThreatRef(ctx echo.Context) error { +func (h *RiskHandler) DeleteThreatRef(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -432,7 +432,7 @@ func (h *RiskHandler) DeleteThreatRef(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/remediation-template [get] -func (h *RiskHandler) GetRemediationTemplateForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetRemediationTemplateForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -463,7 +463,7 @@ func (h *RiskHandler) GetRemediationTemplateForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/remediation-template [get] -func (h *RiskHandler) GetRemediationTemplate(ctx echo.Context) error { +func (h *RiskHandler) GetRemediationTemplate(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -500,7 +500,7 @@ func (h *RiskHandler) GetRemediationTemplate(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/remediation-template [post] -func (h *RiskHandler) CreateRemediationTemplateForSSP(ctx echo.Context) error { +func (h *RiskHandler) CreateRemediationTemplateForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -534,7 +534,7 @@ func (h *RiskHandler) CreateRemediationTemplateForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/remediation-template [post] -func (h *RiskHandler) CreateRemediationTemplate(ctx echo.Context) error { +func (h *RiskHandler) CreateRemediationTemplate(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -580,7 +580,7 @@ func (h *RiskHandler) CreateRemediationTemplate(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/remediation-template [put] -func (h *RiskHandler) UpsertRemediationTemplateForSSP(ctx echo.Context) error { +func (h *RiskHandler) UpsertRemediationTemplateForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -613,7 +613,7 @@ func (h *RiskHandler) UpsertRemediationTemplateForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/remediation-template [put] -func (h *RiskHandler) UpsertRemediationTemplate(ctx echo.Context) error { +func (h *RiskHandler) UpsertRemediationTemplate(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -654,7 +654,7 @@ func (h *RiskHandler) UpsertRemediationTemplate(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/remediation-template [delete] -func (h *RiskHandler) DeleteRemediationTemplateForSSP(ctx echo.Context) error { +func (h *RiskHandler) DeleteRemediationTemplateForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -685,7 +685,7 @@ func (h *RiskHandler) DeleteRemediationTemplateForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/remediation-template [delete] -func (h *RiskHandler) DeleteRemediationTemplate(ctx echo.Context) error { +func (h *RiskHandler) DeleteRemediationTemplate(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/risks.go b/internal/api/handler/risks.go index f48cd499..bedab67c 100644 --- a/internal/api/handler/risks.go +++ b/internal/api/handler/risks.go @@ -19,7 +19,7 @@ import ( poamsvc "github.com/compliance-framework/api/internal/service/relational/poam" riskrel "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -323,7 +323,7 @@ type reviewRiskRequest struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks [get] -func (h *RiskHandler) List(ctx echo.Context) error { +func (h *RiskHandler) List(ctx *echo.Context) error { pagination, err := h.pagination.ParseParams(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -381,7 +381,7 @@ func (h *RiskHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks [post] -func (h *RiskHandler) Create(ctx echo.Context) error { +func (h *RiskHandler) Create(ctx *echo.Context) error { var req createRiskRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -389,7 +389,7 @@ func (h *RiskHandler) Create(ctx echo.Context) error { return h.createFromRequest(ctx, req) } -func (h *RiskHandler) createFromRequest(ctx echo.Context, req createRiskRequest) error { +func (h *RiskHandler) createFromRequest(ctx *echo.Context, req createRiskRequest) error { if req.Title == "" || req.Description == "" { return ctx.JSON(http.StatusBadRequest, api.NewError(fmt.Errorf("title and description are required"))) } @@ -511,7 +511,7 @@ func (h *RiskHandler) createFromRequest(ctx echo.Context, req createRiskRequest) // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks [get] -func (h *RiskHandler) ListForSSP(ctx echo.Context) error { +func (h *RiskHandler) ListForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -544,7 +544,7 @@ func (h *RiskHandler) ListForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks [post] -func (h *RiskHandler) CreateForSSP(ctx echo.Context) error { +func (h *RiskHandler) CreateForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -572,7 +572,7 @@ func (h *RiskHandler) CreateForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id} [get] -func (h *RiskHandler) GetForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -606,7 +606,7 @@ func (h *RiskHandler) GetForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id} [put] -func (h *RiskHandler) UpdateForSSP(ctx echo.Context) error { +func (h *RiskHandler) UpdateForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -637,7 +637,7 @@ func (h *RiskHandler) UpdateForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id} [delete] -func (h *RiskHandler) DeleteForSSP(ctx echo.Context) error { +func (h *RiskHandler) DeleteForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -671,7 +671,7 @@ func (h *RiskHandler) DeleteForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/accept [post] -func (h *RiskHandler) AcceptForSSP(ctx echo.Context) error { +func (h *RiskHandler) AcceptForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -705,7 +705,7 @@ func (h *RiskHandler) AcceptForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/review [post] -func (h *RiskHandler) ReviewForSSP(ctx echo.Context) error { +func (h *RiskHandler) ReviewForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -740,7 +740,7 @@ func (h *RiskHandler) ensureRiskBelongsToSSP(riskID, sspID uuid.UUID) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id} [get] -func (h *RiskHandler) Get(ctx echo.Context) error { +func (h *RiskHandler) Get(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -776,7 +776,7 @@ func (h *RiskHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id} [put] -func (h *RiskHandler) Update(ctx echo.Context) error { +func (h *RiskHandler) Update(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -963,7 +963,7 @@ func (h *RiskHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/accept [post] -func (h *RiskHandler) Accept(ctx echo.Context) error { +func (h *RiskHandler) Accept(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1020,7 +1020,7 @@ func (h *RiskHandler) Accept(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/review [post] -func (h *RiskHandler) Review(ctx echo.Context) error { +func (h *RiskHandler) Review(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1089,7 +1089,7 @@ func (h *RiskHandler) Review(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id} [delete] -func (h *RiskHandler) Delete(ctx echo.Context) error { +func (h *RiskHandler) Delete(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1121,7 +1121,7 @@ func (h *RiskHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/events [get] -func (h *RiskHandler) GetEventsForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetEventsForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1154,7 +1154,7 @@ func (h *RiskHandler) GetEventsForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/events [get] -func (h *RiskHandler) GetEvents(ctx echo.Context) error { +func (h *RiskHandler) GetEvents(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { events, total, err := h.riskService.ListEvents(riskID, pagination.Limit, pagination.Offset) if err != nil { @@ -1181,7 +1181,7 @@ func (h *RiskHandler) GetEvents(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/reviews [get] -func (h *RiskHandler) GetReviewsForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetReviewsForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1214,7 +1214,7 @@ func (h *RiskHandler) GetReviewsForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/reviews [get] -func (h *RiskHandler) GetReviews(ctx echo.Context) error { +func (h *RiskHandler) GetReviews(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { reviews, total, err := h.riskService.ListReviews(riskID, pagination.Limit, pagination.Offset) if err != nil { @@ -1241,7 +1241,7 @@ func (h *RiskHandler) GetReviews(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/score-history [get] -func (h *RiskHandler) GetScoreHistoryForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetScoreHistoryForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1274,7 +1274,7 @@ func (h *RiskHandler) GetScoreHistoryForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/score-history [get] -func (h *RiskHandler) GetScoreHistory(ctx echo.Context) error { +func (h *RiskHandler) GetScoreHistory(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { if err := h.ensureRiskExists(riskID); err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { @@ -1316,7 +1316,7 @@ func (h *RiskHandler) GetScoreHistory(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/score-timeseries [get] -func (h *RiskHandler) GetScoreTimeseriesForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetScoreTimeseriesForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1348,7 +1348,7 @@ func (h *RiskHandler) GetScoreTimeseriesForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/score-timeseries [get] -func (h *RiskHandler) GetScoreTimeseries(ctx echo.Context) error { +func (h *RiskHandler) GetScoreTimeseries(ctx *echo.Context) error { sspID, from, to, bucket, err := parseScoreTimeseriesParams(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1397,7 +1397,7 @@ func (h *RiskHandler) GetScoreTimeseries(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/evidence [get] -func (h *RiskHandler) GetEvidenceLinksForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetEvidenceLinksForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1430,7 +1430,7 @@ func (h *RiskHandler) GetEvidenceLinksForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/evidence [get] -func (h *RiskHandler) GetEvidenceLinks(ctx echo.Context) error { +func (h *RiskHandler) GetEvidenceLinks(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { ids, total, err := h.riskService.ListEvidenceLinks(riskID, pagination.Limit, pagination.Offset) if err != nil { @@ -1457,7 +1457,7 @@ func (h *RiskHandler) GetEvidenceLinks(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/evidence [post] -func (h *RiskHandler) AddEvidenceLinkForSSP(ctx echo.Context) error { +func (h *RiskHandler) AddEvidenceLinkForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1490,7 +1490,7 @@ func (h *RiskHandler) AddEvidenceLinkForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/evidence [post] -func (h *RiskHandler) AddEvidenceLink(ctx echo.Context) error { +func (h *RiskHandler) AddEvidenceLink(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1531,7 +1531,7 @@ func (h *RiskHandler) AddEvidenceLink(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/evidence/{evidenceId} [delete] -func (h *RiskHandler) DeleteEvidenceLinkForSSP(ctx echo.Context) error { +func (h *RiskHandler) DeleteEvidenceLinkForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1562,7 +1562,7 @@ func (h *RiskHandler) DeleteEvidenceLinkForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/evidence/{evidenceId} [delete] -func (h *RiskHandler) DeleteEvidenceLink(ctx echo.Context) error { +func (h *RiskHandler) DeleteEvidenceLink(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1599,7 +1599,7 @@ func (h *RiskHandler) DeleteEvidenceLink(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/controls [get] -func (h *RiskHandler) GetControlLinksForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetControlLinksForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1632,7 +1632,7 @@ func (h *RiskHandler) GetControlLinksForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/controls [get] -func (h *RiskHandler) GetControlLinks(ctx echo.Context) error { +func (h *RiskHandler) GetControlLinks(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { links, total, err := h.riskService.ListControlLinks(riskID, pagination.Limit, pagination.Offset) if err != nil { @@ -1659,7 +1659,7 @@ func (h *RiskHandler) GetControlLinks(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/controls [post] -func (h *RiskHandler) AddControlLinkForSSP(ctx echo.Context) error { +func (h *RiskHandler) AddControlLinkForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1692,7 +1692,7 @@ func (h *RiskHandler) AddControlLinkForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/controls [post] -func (h *RiskHandler) AddControlLink(ctx echo.Context) error { +func (h *RiskHandler) AddControlLink(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1734,7 +1734,7 @@ func (h *RiskHandler) AddControlLink(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/controls/{catalogId}/{controlId} [delete] -func (h *RiskHandler) DeleteControlLinkForSSP(ctx echo.Context) error { +func (h *RiskHandler) DeleteControlLinkForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1766,7 +1766,7 @@ func (h *RiskHandler) DeleteControlLinkForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/controls/{catalogId}/{controlId} [delete] -func (h *RiskHandler) DeleteControlLink(ctx echo.Context) error { +func (h *RiskHandler) DeleteControlLink(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1808,7 +1808,7 @@ func (h *RiskHandler) DeleteControlLink(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/components [get] -func (h *RiskHandler) GetComponentLinksForSSP(ctx echo.Context) error { +func (h *RiskHandler) GetComponentLinksForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1841,7 +1841,7 @@ func (h *RiskHandler) GetComponentLinksForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/components [get] -func (h *RiskHandler) GetComponentLinks(ctx echo.Context) error { +func (h *RiskHandler) GetComponentLinks(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { links, total, err := h.riskService.ListComponentLinks(riskID, pagination.Limit, pagination.Offset) if err != nil { @@ -1868,7 +1868,7 @@ func (h *RiskHandler) GetComponentLinks(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/components [post] -func (h *RiskHandler) AddComponentLinkForSSP(ctx echo.Context) error { +func (h *RiskHandler) AddComponentLinkForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1901,7 +1901,7 @@ func (h *RiskHandler) AddComponentLinkForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/components [post] -func (h *RiskHandler) AddComponentLink(ctx echo.Context) error { +func (h *RiskHandler) AddComponentLink(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1942,7 +1942,7 @@ func (h *RiskHandler) AddComponentLink(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/components/{componentId} [delete] -func (h *RiskHandler) DeleteComponentLinkForSSP(ctx echo.Context) error { +func (h *RiskHandler) DeleteComponentLinkForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -1973,7 +1973,7 @@ func (h *RiskHandler) DeleteComponentLinkForSSP(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/components/{componentId} [delete] -func (h *RiskHandler) DeleteComponentLink(ctx echo.Context) error { +func (h *RiskHandler) DeleteComponentLink(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -2010,7 +2010,7 @@ func (h *RiskHandler) DeleteComponentLink(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/subjects [get] -func (h *RiskHandler) GetSubjectLinks(ctx echo.Context) error { +func (h *RiskHandler) GetSubjectLinks(ctx *echo.Context) error { return h.withRiskListContext(ctx, func(riskID uuid.UUID, pagination *svc.PaginationParams) error { links, total, err := h.riskService.ListSubjectLinks(riskID, pagination.Limit, pagination.Offset) if err != nil { @@ -2036,7 +2036,7 @@ func (h *RiskHandler) GetSubjectLinks(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/subjects [post] -func (h *RiskHandler) AddSubjectLink(ctx echo.Context) error { +func (h *RiskHandler) AddSubjectLink(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -2063,7 +2063,7 @@ func (h *RiskHandler) AddSubjectLink(ctx echo.Context) error { }) } -func parseListFilters(ctx echo.Context) (riskrel.ListFilters, error) { +func parseListFilters(ctx *echo.Context) (riskrel.ListFilters, error) { filters := riskrel.ListFilters{} if v := ctx.QueryParam("status"); v != "" { filters.Status = &v @@ -2130,7 +2130,7 @@ func parseListFilters(ctx echo.Context) (riskrel.ListFilters, error) { return filters, nil } -func parseScoreTimeseriesParams(ctx echo.Context) (*uuid.UUID, time.Time, time.Time, string, error) { +func parseScoreTimeseriesParams(ctx *echo.Context) (*uuid.UUID, time.Time, time.Time, string, error) { var sspID *uuid.UUID if rawSSPID := ctx.QueryParam("sspId"); rawSSPID != "" { parsed, err := uuid.Parse(rawSSPID) @@ -2312,7 +2312,7 @@ func validateAcceptedRequirements(status string, reviewDeadline *time.Time, acce return nil } -func parsePathUUID(ctx echo.Context, name string) (uuid.UUID, error) { +func parsePathUUID(ctx *echo.Context, name string) (uuid.UUID, error) { parsed, err := uuid.Parse(ctx.Param(name)) if err != nil { return uuid.Nil, err @@ -2320,7 +2320,7 @@ func parsePathUUID(ctx echo.Context, name string) (uuid.UUID, error) { return parsed, nil } -func (h *RiskHandler) withRiskListContext(ctx echo.Context, fn func(riskID uuid.UUID, pagination *svc.PaginationParams) error) error { +func (h *RiskHandler) withRiskListContext(ctx *echo.Context, fn func(riskID uuid.UUID, pagination *svc.PaginationParams) error) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -2340,7 +2340,7 @@ func (h *RiskHandler) withRiskListContext(ctx echo.Context, fn func(riskID uuid. return fn(riskID, pagination) } -func (h *RiskHandler) withActorUserID(ctx echo.Context, fn func(actorID *uuid.UUID) error) error { +func (h *RiskHandler) withActorUserID(ctx *echo.Context, fn func(actorID *uuid.UUID) error) error { actorID, code, err := h.resolveActorUserID(ctx) if err != nil { return ctx.JSON(code, api.NewError(err)) @@ -2348,7 +2348,7 @@ func (h *RiskHandler) withActorUserID(ctx echo.Context, fn func(actorID *uuid.UU return fn(actorID) } -func (h *RiskHandler) resolveActorUserID(ctx echo.Context) (*uuid.UUID, int, error) { +func (h *RiskHandler) resolveActorUserID(ctx *echo.Context) (*uuid.UUID, int, error) { claims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || claims == nil { return nil, http.StatusUnauthorized, fmt.Errorf("missing authentication claims") @@ -2365,7 +2365,7 @@ func (h *RiskHandler) resolveActorUserID(ctx echo.Context) (*uuid.UUID, int, err return actorID, http.StatusOK, nil } -func (h *RiskHandler) internalServerError(ctx echo.Context, message string, err error) error { +func (h *RiskHandler) internalServerError(ctx *echo.Context, message string, err error) error { if h.sugar != nil { h.sugar.Errorw(message, "error", err) } @@ -2561,7 +2561,7 @@ type promoteToPoamRequest struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /risks/{id}/promote-to-poam [post] -func (h *RiskHandler) PromoteToPoam(ctx echo.Context) error { +func (h *RiskHandler) PromoteToPoam(ctx *echo.Context) error { riskID, err := parsePathUUID(ctx, "id") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -2628,7 +2628,7 @@ func (h *RiskHandler) PromoteToPoam(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /oscal/system-security-plans/{sspId}/risks/{id}/promote-to-poam [post] -func (h *RiskHandler) PromoteToPoamForSSP(ctx echo.Context) error { +func (h *RiskHandler) PromoteToPoamForSSP(ctx *echo.Context) error { sspID, err := parsePathUUID(ctx, "sspId") if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/risks_integration_test.go b/internal/api/handler/risks_integration_test.go index 6d8bac8a..703e7001 100644 --- a/internal/api/handler/risks_integration_test.go +++ b/internal/api/handler/risks_integration_test.go @@ -20,7 +20,7 @@ import ( riskrel "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/risks_test.go b/internal/api/handler/risks_test.go index 4410a96e..cbe7b330 100644 --- a/internal/api/handler/risks_test.go +++ b/internal/api/handler/risks_test.go @@ -9,7 +9,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" riskrel "github.com/compliance-framework/api/internal/service/relational/risks" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" ) diff --git a/internal/api/handler/role_assignments.go b/internal/api/handler/role_assignments.go index 52001bcd..e1810981 100644 --- a/internal/api/handler/role_assignments.go +++ b/internal/api/handler/role_assignments.go @@ -10,7 +10,7 @@ import ( "github.com/compliance-framework/api/internal/authz" "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -84,7 +84,7 @@ type effectiveRole struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/role-assignments [post] -func (h *RoleAssignmentsHandler) Create(ctx echo.Context) error { +func (h *RoleAssignmentsHandler) Create(ctx *echo.Context) error { var req createRoleAssignmentRequest if err := ctx.Bind(&req); err != nil { h.sugar.Errorw("Failed to bind create role assignment request", "error", err) @@ -136,7 +136,7 @@ func (h *RoleAssignmentsHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/role-assignments [get] -func (h *RoleAssignmentsHandler) List(ctx echo.Context) error { +func (h *RoleAssignmentsHandler) List(ctx *echo.Context) error { q := h.db.Model(&relational.CCFRoleAssignment{}) if t := strings.ToLower(strings.TrimSpace(ctx.QueryParam("assigneeType"))); t != "" { q = q.Where("assignee_type = ?", t) @@ -170,7 +170,7 @@ func (h *RoleAssignmentsHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/role-assignments/{id} [delete] -func (h *RoleAssignmentsHandler) Delete(ctx echo.Context) error { +func (h *RoleAssignmentsHandler) Delete(ctx *echo.Context) error { id, err := uuid.Parse(strings.TrimSpace(ctx.Param("id"))) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("invalid role assignment id"))) @@ -212,7 +212,7 @@ func (h *RoleAssignmentsHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/users/{id}/roles [get] -func (h *RoleAssignmentsHandler) UserRoles(ctx echo.Context) error { +func (h *RoleAssignmentsHandler) UserRoles(ctx *echo.Context) error { userUUID, err := uuid.Parse(strings.TrimSpace(ctx.Param("id"))) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("invalid user id"))) @@ -292,7 +292,7 @@ func (h *RoleAssignmentsHandler) UserRoles(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/groups/{id}/roles [get] -func (h *RoleAssignmentsHandler) GroupRoles(ctx echo.Context) error { +func (h *RoleAssignmentsHandler) GroupRoles(ctx *echo.Context) error { groupUUID, err := uuid.Parse(strings.TrimSpace(ctx.Param("id"))) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(errors.New("invalid group id"))) diff --git a/internal/api/handler/subjects.go b/internal/api/handler/subjects.go index 399a62f0..2eb3c711 100644 --- a/internal/api/handler/subjects.go +++ b/internal/api/handler/subjects.go @@ -9,7 +9,7 @@ import ( svc "github.com/compliance-framework/api/internal/service" "github.com/compliance-framework/api/internal/service/relational/subjects" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -50,7 +50,7 @@ func (h *SubjectHandler) Register(api *echo.Group, middlewares ...echo.Middlewar // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /subjects [get] -func (h *SubjectHandler) List(ctx echo.Context) error { +func (h *SubjectHandler) List(ctx *echo.Context) error { pagination, err := h.pagination.ParseParams(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/subjects_integration_test.go b/internal/api/handler/subjects_integration_test.go index 600ed12d..d6409ff7 100644 --- a/internal/api/handler/subjects_integration_test.go +++ b/internal/api/handler/subjects_integration_test.go @@ -19,7 +19,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/subjects" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/gorm/clause" diff --git a/internal/api/handler/templates/risk_template.go b/internal/api/handler/templates/risk_template.go index a32a34f0..d05f05e7 100644 --- a/internal/api/handler/templates/risk_template.go +++ b/internal/api/handler/templates/risk_template.go @@ -11,7 +11,7 @@ import ( riskrel "github.com/compliance-framework/api/internal/service/relational/risks" templaterel "github.com/compliance-framework/api/internal/service/relational/templates" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -145,7 +145,7 @@ type riskTemplateDataResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/risk-templates [get] -func (h *RiskTemplateHandler) List(ctx echo.Context) error { +func (h *RiskTemplateHandler) List(ctx *echo.Context) error { pagination, err := h.pagination.ParseParams(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -196,7 +196,7 @@ func (h *RiskTemplateHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/risk-templates [post] -func (h *RiskTemplateHandler) Create(ctx echo.Context) error { +func (h *RiskTemplateHandler) Create(ctx *echo.Context) error { var req upsertRiskTemplateRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -225,7 +225,7 @@ func (h *RiskTemplateHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/risk-templates/{id} [get] -func (h *RiskTemplateHandler) Get(ctx echo.Context) error { +func (h *RiskTemplateHandler) Get(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -254,7 +254,7 @@ func (h *RiskTemplateHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/risk-templates/{id} [put] -func (h *RiskTemplateHandler) Update(ctx echo.Context) error { +func (h *RiskTemplateHandler) Update(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -288,7 +288,7 @@ func (h *RiskTemplateHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/risk-templates/{id} [delete] -func (h *RiskTemplateHandler) Delete(ctx echo.Context) error { +func (h *RiskTemplateHandler) Delete(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -396,7 +396,7 @@ type batchUpsertRiskTemplatesResponse struct { // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /agent/risk-templates/batch [post] -func (h *RiskTemplateHandler) BatchUpsert(ctx echo.Context) error { +func (h *RiskTemplateHandler) BatchUpsert(ctx *echo.Context) error { var req batchUpsertRiskTemplatesRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/templates/risk_template_integration_test.go b/internal/api/handler/templates/risk_template_integration_test.go index b680ef77..601bd3ab 100644 --- a/internal/api/handler/templates/risk_template_integration_test.go +++ b/internal/api/handler/templates/risk_template_integration_test.go @@ -18,7 +18,7 @@ import ( templaterel "github.com/compliance-framework/api/internal/service/relational/templates" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/templates/ssp_template.go b/internal/api/handler/templates/ssp_template.go index 5f2907f5..219fb895 100644 --- a/internal/api/handler/templates/ssp_template.go +++ b/internal/api/handler/templates/ssp_template.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/ssptemplates" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -136,7 +136,7 @@ func toSSPTemplateResponse(t ssptemplates.Listed) sspTemplateResponse { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates [get] -func (h *SSPTemplateHandler) List(ctx echo.Context) error { +func (h *SSPTemplateHandler) List(ctx *echo.Context) error { pagination, err := h.pagination.ParseParams(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -165,7 +165,7 @@ func (h *SSPTemplateHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates [post] -func (h *SSPTemplateHandler) Create(ctx echo.Context) error { +func (h *SSPTemplateHandler) Create(ctx *echo.Context) error { var req sspTemplateRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -189,7 +189,7 @@ func (h *SSPTemplateHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates/{id} [get] -func (h *SSPTemplateHandler) Get(ctx echo.Context) error { +func (h *SSPTemplateHandler) Get(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -216,7 +216,7 @@ func (h *SSPTemplateHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates/{id} [put] -func (h *SSPTemplateHandler) Update(ctx echo.Context) error { +func (h *SSPTemplateHandler) Update(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -244,7 +244,7 @@ func (h *SSPTemplateHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates/{id} [delete] -func (h *SSPTemplateHandler) Delete(ctx echo.Context) error { +func (h *SSPTemplateHandler) Delete(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -280,7 +280,7 @@ type sspTemplatePreviewResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates/preview [post] -func (h *SSPTemplateHandler) Preview(ctx echo.Context) error { +func (h *SSPTemplateHandler) Preview(ctx *echo.Context) error { var req sspTemplatePreviewRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -292,7 +292,7 @@ func (h *SSPTemplateHandler) Preview(ctx echo.Context) error { return ctx.JSON(http.StatusOK, sspTemplatePreviewResponse{Data: plan}) } -func (h *SSPTemplateHandler) serviceError(ctx echo.Context, message string, err error) error { +func (h *SSPTemplateHandler) serviceError(ctx *echo.Context, message string, err error) error { switch { case errors.Is(err, ssptemplates.ErrNotFound), errors.Is(err, ssptemplates.ErrInstanceNotFound): return ctx.JSON(http.StatusNotFound, api.NotFound()) diff --git a/internal/api/handler/templates/ssp_template_instances.go b/internal/api/handler/templates/ssp_template_instances.go index d0e42ac6..5cae88de 100644 --- a/internal/api/handler/templates/ssp_template_instances.go +++ b/internal/api/handler/templates/ssp_template_instances.go @@ -9,7 +9,7 @@ import ( svc "github.com/compliance-framework/api/internal/service" "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) type sspTemplateInstanceResponse struct { @@ -39,7 +39,7 @@ type sspTemplateInstanceResponse struct { // @Failure 503 {object} api.Error "background jobs are not available" // @Security OAuth2Password // @Router /admin/ssp-templates/{id}/run [post] -func (h *SSPTemplateHandler) Run(ctx echo.Context) error { +func (h *SSPTemplateHandler) Run(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -71,7 +71,7 @@ func (h *SSPTemplateHandler) Run(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates/{id}/ssps [get] -func (h *SSPTemplateHandler) ListSSPs(ctx echo.Context) error { +func (h *SSPTemplateHandler) ListSSPs(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -117,7 +117,7 @@ func (h *SSPTemplateHandler) ListSSPs(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/ssp-templates/{id}/ssps/{keyHash} [delete] -func (h *SSPTemplateHandler) Forget(ctx echo.Context) error { +func (h *SSPTemplateHandler) Forget(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/templates/ssp_template_integration_test.go b/internal/api/handler/templates/ssp_template_integration_test.go index 38221f12..67066e32 100644 --- a/internal/api/handler/templates/ssp_template_integration_test.go +++ b/internal/api/handler/templates/ssp_template_integration_test.go @@ -21,7 +21,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/sspscope" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/suite" "go.uber.org/zap" "gorm.io/datatypes" diff --git a/internal/api/handler/templates/subject_template.go b/internal/api/handler/templates/subject_template.go index 448fd87f..373a41f7 100644 --- a/internal/api/handler/templates/subject_template.go +++ b/internal/api/handler/templates/subject_template.go @@ -10,7 +10,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" templaterel "github.com/compliance-framework/api/internal/service/relational/templates" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -116,7 +116,7 @@ type subjectTemplateDataResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/subject-templates [get] -func (h *SubjectTemplateHandler) List(ctx echo.Context) error { +func (h *SubjectTemplateHandler) List(ctx *echo.Context) error { pagination, err := h.pagination.ParseParams(ctx) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -166,7 +166,7 @@ func (h *SubjectTemplateHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/subject-templates [post] -func (h *SubjectTemplateHandler) Create(ctx echo.Context) error { +func (h *SubjectTemplateHandler) Create(ctx *echo.Context) error { var req upsertSubjectTemplateRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -197,7 +197,7 @@ func (h *SubjectTemplateHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/subject-templates/{id} [get] -func (h *SubjectTemplateHandler) Get(ctx echo.Context) error { +func (h *SubjectTemplateHandler) Get(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -226,7 +226,7 @@ func (h *SubjectTemplateHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/subject-templates/{id} [put] -func (h *SubjectTemplateHandler) Update(ctx echo.Context) error { +func (h *SubjectTemplateHandler) Update(ctx *echo.Context) error { id, err := uuid.Parse(ctx.Param("id")) if err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -333,7 +333,7 @@ type batchUpsertSubjectTemplatesResponse struct { // @Failure 400 {object} api.Error // @Failure 500 {object} api.Error // @Router /agent/subject-templates/batch [post] -func (h *SubjectTemplateHandler) BatchUpsert(ctx echo.Context) error { +func (h *SubjectTemplateHandler) BatchUpsert(ctx *echo.Context) error { var req batchUpsertSubjectTemplatesRequest if err := ctx.Bind(&req); err != nil { return ctx.JSON(http.StatusBadRequest, api.NewError(err)) diff --git a/internal/api/handler/templates/subject_template_integration_test.go b/internal/api/handler/templates/subject_template_integration_test.go index a59b376d..f023a956 100644 --- a/internal/api/handler/templates/subject_template_integration_test.go +++ b/internal/api/handler/templates/subject_template_integration_test.go @@ -17,7 +17,7 @@ import ( templaterel "github.com/compliance-framework/api/internal/service/relational/templates" "github.com/compliance-framework/api/internal/tests" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "go.uber.org/zap" diff --git a/internal/api/handler/templates/template_handler_util.go b/internal/api/handler/templates/template_handler_util.go index 67179585..000ad9c2 100644 --- a/internal/api/handler/templates/template_handler_util.go +++ b/internal/api/handler/templates/template_handler_util.go @@ -7,12 +7,12 @@ import ( "github.com/compliance-framework/api/internal/api" templaterel "github.com/compliance-framework/api/internal/service/relational/templates" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) -func handleTemplateServiceError(ctx echo.Context, sugar *zap.SugaredLogger, message string, err error) error { +func handleTemplateServiceError(ctx *echo.Context, sugar *zap.SugaredLogger, message string, err error) error { if errors.Is(err, gorm.ErrRecordNotFound) { return ctx.JSON(http.StatusNotFound, api.NotFound()) } @@ -22,7 +22,7 @@ func handleTemplateServiceError(ctx echo.Context, sugar *zap.SugaredLogger, mess return templateInternalServerError(ctx, sugar, message, err) } -func templateInternalServerError(ctx echo.Context, sugar *zap.SugaredLogger, message string, err error) error { +func templateInternalServerError(ctx *echo.Context, sugar *zap.SugaredLogger, message string, err error) error { if sugar != nil { sugar.Errorw(message, "error", err) } diff --git a/internal/api/handler/users.go b/internal/api/handler/users.go index dbf8e885..3a084090 100644 --- a/internal/api/handler/users.go +++ b/internal/api/handler/users.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgconn" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -118,7 +118,7 @@ func (h *UserHandler) RegisterPublicRoutes(api *echo.Group, guard middleware.Res // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/users [get] -func (h *UserHandler) ListUsers(ctx echo.Context) error { +func (h *UserHandler) ListUsers(ctx *echo.Context) error { var users []relational.User if err := h.db.Find(&users).Error; err != nil { @@ -154,7 +154,7 @@ func (h *UserHandler) ListUsers(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /users/select [get] -func (h *UserHandler) ListSelectableUsers(ctx echo.Context) error { +func (h *UserHandler) ListSelectableUsers(ctx *echo.Context) error { search := strings.TrimSpace(ctx.QueryParam("search")) query := h.db.Model(&relational.User{}). Select("id", "first_name", "last_name"). @@ -228,7 +228,7 @@ func (h *UserHandler) ListSelectableUsers(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/users/{id} [get] -func (h *UserHandler) GetUser(ctx echo.Context) error { +func (h *UserHandler) GetUser(ctx *echo.Context) error { userID := ctx.Param("id") userUUID, err := uuid.Parse(userID) @@ -272,7 +272,7 @@ func (h *UserHandler) GetUser(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/users/{id}/groups [get] -func (h *UserHandler) GetUserGroups(ctx echo.Context) error { +func (h *UserHandler) GetUserGroups(ctx *echo.Context) error { userID := ctx.Param("id") userUUID, err := uuid.Parse(userID) @@ -313,7 +313,7 @@ func (h *UserHandler) GetUserGroups(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /users/{id} [get] -func (h *UserHandler) GetPublicUser(ctx echo.Context) error { +func (h *UserHandler) GetPublicUser(ctx *echo.Context) error { userID := ctx.Param("id") userUUID, err := uuid.Parse(userID) @@ -446,7 +446,7 @@ func UserDisplayName(user relational.User) string { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /users/me [get] -func (h *UserHandler) GetMe(ctx echo.Context) error { +func (h *UserHandler) GetMe(ctx *echo.Context) error { userClaims := ctx.Get("user").(*authn.UserClaims) email := userClaims.Subject @@ -486,7 +486,7 @@ func (h *UserHandler) GetMe(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/users [post] -func (h *UserHandler) CreateUser(ctx echo.Context) error { +func (h *UserHandler) CreateUser(ctx *echo.Context) error { type createUserRequest struct { Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"required"` @@ -540,7 +540,7 @@ func (h *UserHandler) CreateUser(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/users/{id} [put] -func (h *UserHandler) UpdateUser(ctx echo.Context) error { +func (h *UserHandler) UpdateUser(ctx *echo.Context) error { type updateUserRequest struct { FirstName *string `json:"firstName"` LastName *string `json:"lastName"` @@ -608,7 +608,7 @@ func (h *UserHandler) UpdateUser(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /admin/users/{id} [delete] -func (h *UserHandler) DeleteUser(ctx echo.Context) error { +func (h *UserHandler) DeleteUser(ctx *echo.Context) error { userID := ctx.Param("id") userUUID, err := uuid.Parse(userID) if err != nil { @@ -664,7 +664,7 @@ func (h *UserHandler) DeleteUser(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /users/me/change-password [post] -func (h *UserHandler) ChangeLoggedInUserPassword(ctx echo.Context) error { +func (h *UserHandler) ChangeLoggedInUserPassword(ctx *echo.Context) error { userClaims := ctx.Get("user").(*authn.UserClaims) email := userClaims.Subject @@ -716,7 +716,7 @@ func (h *UserHandler) ChangeLoggedInUserPassword(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /users/me/subscriptions [get] -func (h *UserHandler) GetSubscriptions(ctx echo.Context) error { +func (h *UserHandler) GetSubscriptions(ctx *echo.Context) error { userClaims := ctx.Get("user").(*authn.UserClaims) email := userClaims.Subject @@ -757,7 +757,7 @@ func (h *UserHandler) GetSubscriptions(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /users/me/subscriptions [put] -func (h *UserHandler) UpdateSubscriptions(ctx echo.Context) error { +func (h *UserHandler) UpdateSubscriptions(ctx *echo.Context) error { userClaims := ctx.Get("user").(*authn.UserClaims) var req UpdateSubscriptionsRequest @@ -933,7 +933,7 @@ func (h *UserHandler) replaceUserNotificationSubscriptions(ctx context.Context, // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /users/{id}/change-password [post] -func (h *UserHandler) ChangePassword(ctx echo.Context) error { +func (h *UserHandler) ChangePassword(ctx *echo.Context) error { userID := ctx.Param("id") userUUID, err := uuid.Parse(userID) if err != nil { diff --git a/internal/api/handler/workflows/base.go b/internal/api/handler/workflows/base.go index 6aa22ff7..96e41415 100644 --- a/internal/api/handler/workflows/base.go +++ b/internal/api/handler/workflows/base.go @@ -11,7 +11,7 @@ import ( relworkflows "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/compliance-framework/api/internal/service/sso" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -49,7 +49,7 @@ func NewBaseHandler(sugar *zap.SugaredLogger) *BaseHandler { } // Bind binds a request without validation (used for Update operations with optional fields) -func (b *BaseHandler) Bind(ctx echo.Context, req interface{}) error { +func (b *BaseHandler) Bind(ctx *echo.Context, req interface{}) error { if err := ctx.Bind(req); err != nil { b.sugar.Errorw("Failed to bind request", "error", err) err = ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -62,7 +62,7 @@ func (b *BaseHandler) Bind(ctx echo.Context, req interface{}) error { } // BindAndValidate binds and validates a request -func (b *BaseHandler) BindAndValidate(ctx echo.Context, req interface{}) error { +func (b *BaseHandler) BindAndValidate(ctx *echo.Context, req interface{}) error { if err := ctx.Bind(req); err != nil { b.sugar.Errorw("Failed to bind request", "error", err) err = ctx.JSON(http.StatusBadRequest, api.NewError(err)) @@ -85,7 +85,7 @@ func (b *BaseHandler) BindAndValidate(ctx echo.Context, req interface{}) error { } // ParseUUID parses a UUID from a path parameter -func (b *BaseHandler) ParseUUID(ctx echo.Context, paramName, entityName string) (*uuid.UUID, error) { +func (b *BaseHandler) ParseUUID(ctx *echo.Context, paramName, entityName string) (*uuid.UUID, error) { idStr := ctx.Param(paramName) id, err := uuid.Parse(idStr) if err != nil { @@ -100,7 +100,7 @@ func (b *BaseHandler) ParseUUID(ctx echo.Context, paramName, entityName string) } // HandleServiceError handles service layer errors with appropriate HTTP status codes -func (b *BaseHandler) HandleServiceError(ctx echo.Context, err error, operation, entityName string) error { +func (b *BaseHandler) HandleServiceError(ctx *echo.Context, err error, operation, entityName string) error { if err == gorm.ErrRecordNotFound || isNotFoundError(err) { return ctx.JSON(http.StatusNotFound, api.NewError(err)) } @@ -113,17 +113,17 @@ func (b *BaseHandler) HandleServiceError(ctx echo.Context, err error, operation, } // RespondOK sends a successful JSON response -func (b *BaseHandler) RespondOK(ctx echo.Context, data interface{}) error { +func (b *BaseHandler) RespondOK(ctx *echo.Context, data interface{}) error { return ctx.JSON(http.StatusOK, data) } // RespondCreated sends a created JSON response -func (b *BaseHandler) RespondCreated(ctx echo.Context, data interface{}) error { +func (b *BaseHandler) RespondCreated(ctx *echo.Context, data interface{}) error { return ctx.JSON(http.StatusCreated, data) } // RespondNoContent sends a no content response -func (b *BaseHandler) RespondNoContent(ctx echo.Context) error { +func (b *BaseHandler) RespondNoContent(ctx *echo.Context) error { return ctx.NoContent(http.StatusNoContent) } @@ -133,7 +133,7 @@ func isNotFoundError(err error) bool { } // GetActorFromClaims resolves the authenticated actor from JWT claims. -func (b *BaseHandler) GetActorFromClaims(ctx echo.Context, db *gorm.DB) (*uuid.UUID, string, error) { +func (b *BaseHandler) GetActorFromClaims(ctx *echo.Context, db *gorm.DB) (*uuid.UUID, string, error) { identity, err := b.GetActorIdentityFromClaims(ctx, db) if err != nil { return nil, "", err @@ -142,7 +142,7 @@ func (b *BaseHandler) GetActorFromClaims(ctx echo.Context, db *gorm.DB) (*uuid.U } // GetActorIdentityFromClaims resolves the authenticated actor and any known group memberships. -func (b *BaseHandler) GetActorIdentityFromClaims(ctx echo.Context, db *gorm.DB) (*ActorIdentity, error) { +func (b *BaseHandler) GetActorIdentityFromClaims(ctx *echo.Context, db *gorm.DB) (*ActorIdentity, error) { userClaims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || userClaims == nil { if err := ctx.JSON(http.StatusUnauthorized, api.NewError(echo.NewHTTPError(http.StatusUnauthorized, "missing authentication claims"))); err != nil { diff --git a/internal/api/handler/workflows/control_relationship.go b/internal/api/handler/workflows/control_relationship.go index 428686f4..46a7c0fb 100644 --- a/internal/api/handler/workflows/control_relationship.go +++ b/internal/api/handler/workflows/control_relationship.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -75,7 +75,7 @@ type ControlRelationshipListResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/control-relationships [post] -func (h *ControlRelationshipHandler) Create(ctx echo.Context) error { +func (h *ControlRelationshipHandler) Create(ctx *echo.Context) error { var req CreateControlRelationshipRequest if err := h.BindAndValidate(ctx, &req); err != nil { return HandleError(err) @@ -141,7 +141,7 @@ func (h *ControlRelationshipHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/control-relationships [get] -func (h *ControlRelationshipHandler) List(ctx echo.Context) error { +func (h *ControlRelationshipHandler) List(ctx *echo.Context) error { workflowDefIDStr := ctx.QueryParam("workflow_definition_id") controlID := ctx.QueryParam("control_id") @@ -182,7 +182,7 @@ func (h *ControlRelationshipHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/control-relationships/{id} [get] -func (h *ControlRelationshipHandler) Get(ctx echo.Context) error { +func (h *ControlRelationshipHandler) Get(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "control relationship") if err != nil { return HandleError(err) @@ -212,7 +212,7 @@ func (h *ControlRelationshipHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/control-relationships/{id} [put] -func (h *ControlRelationshipHandler) Update(ctx echo.Context) error { +func (h *ControlRelationshipHandler) Update(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "control relationship") if err != nil { return HandleError(err) @@ -269,7 +269,7 @@ func (h *ControlRelationshipHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/control-relationships/{id} [delete] -func (h *ControlRelationshipHandler) Delete(ctx echo.Context) error { +func (h *ControlRelationshipHandler) Delete(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "control relationship") if err != nil { return HandleError(err) @@ -308,7 +308,7 @@ func (h *ControlRelationshipHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/control-relationships/{id}/activate [put] -func (h *ControlRelationshipHandler) Activate(ctx echo.Context) error { +func (h *ControlRelationshipHandler) Activate(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "control relationship") if err != nil { return HandleError(err) @@ -352,7 +352,7 @@ func (h *ControlRelationshipHandler) Activate(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/control-relationships/{id}/deactivate [put] -func (h *ControlRelationshipHandler) Deactivate(ctx echo.Context) error { +func (h *ControlRelationshipHandler) Deactivate(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "control relationship") if err != nil { return HandleError(err) diff --git a/internal/api/handler/workflows/control_relationship_integration_test.go b/internal/api/handler/workflows/control_relationship_integration_test.go index 2a1a09db..4dcf4362 100644 --- a/internal/api/handler/workflows/control_relationship_integration_test.go +++ b/internal/api/handler/workflows/control_relationship_integration_test.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -157,8 +157,7 @@ func TestControlRelationshipHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/control-relationships/"+relationship.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(relationship.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: relationship.ID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -175,8 +174,7 @@ func TestControlRelationshipHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/control-relationships/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -216,8 +214,7 @@ func TestControlRelationshipHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(relationship.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: relationship.ID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -252,8 +249,7 @@ func TestControlRelationshipHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/control-relationships/"+relationship.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(relationship.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: relationship.ID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -284,8 +280,7 @@ func TestControlRelationshipHandler_Activate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/control-relationships/"+relationship.ID.String()+"/activate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(relationship.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: relationship.ID.String()}}) err := handler.Activate(c) require.NoError(t, err) @@ -321,8 +316,7 @@ func TestControlRelationshipHandler_Deactivate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/control-relationships/"+relationship.ID.String()+"/deactivate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(relationship.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: relationship.ID.String()}}) err := handler.Deactivate(c) require.NoError(t, err) diff --git a/internal/api/handler/workflows/import.go b/internal/api/handler/workflows/import.go index 48570101..4a89247b 100644 --- a/internal/api/handler/workflows/import.go +++ b/internal/api/handler/workflows/import.go @@ -9,7 +9,7 @@ import ( "github.com/compliance-framework/api/internal/api" workflowseed "github.com/compliance-framework/api/internal/service/relational/workflows" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -18,7 +18,7 @@ const ( maxImportFiles = 10 maxImportFileBytes = 5 * 1024 * 1024 - WorkflowImportBodyLimit = "55000000" + WorkflowImportBodyLimit int64 = 55000000 ) var errImportFileTooLarge = errors.New("workflow import file exceeds size limit") @@ -70,7 +70,7 @@ type WorkflowImportDataResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/import [post] -func (h *WorkflowImportHandler) Import(ctx echo.Context) error { +func (h *WorkflowImportHandler) Import(ctx *echo.Context) error { form, err := ctx.MultipartForm() if err != nil { h.sugar.Errorw("Failed to parse multipart form", "error", err) @@ -122,7 +122,7 @@ func (h *WorkflowImportHandler) Import(ctx echo.Context) error { return ctx.JSON(statusCode, WorkflowImportDataResponse{Data: response}) } -func (h *WorkflowImportHandler) processWorkflowSeedFile(ctx echo.Context, fileHeader *multipart.FileHeader) WorkflowImportFileResult { +func (h *WorkflowImportHandler) processWorkflowSeedFile(ctx *echo.Context, fileHeader *multipart.FileHeader) WorkflowImportFileResult { result := WorkflowImportFileResult{ Filename: fileHeader.Filename, Success: false, diff --git a/internal/api/handler/workflows/import_integration_test.go b/internal/api/handler/workflows/import_integration_test.go index 64a60b9a..26577db1 100644 --- a/internal/api/handler/workflows/import_integration_test.go +++ b/internal/api/handler/workflows/import_integration_test.go @@ -11,7 +11,6 @@ import ( "mime/multipart" "net/http" "net/http/httptest" - "strconv" "testing" "time" @@ -22,8 +21,8 @@ import ( "github.com/compliance-framework/api/internal/service/relational" workflowseed "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/compliance-framework/api/internal/service/sso" - "github.com/labstack/echo/v4" - echomiddleware "github.com/labstack/echo/v4/middleware" + "github.com/labstack/echo/v5" + echomiddleware "github.com/labstack/echo/v5/middleware" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/gorm" @@ -224,8 +223,7 @@ func TestWorkflowImportRouteRequiresAdminGroup(t *testing.T) { token, err := authn.GenerateJWTToken(&user, privateKey) require.NoError(t, err) - bodyLimit, err := strconv.ParseInt(WorkflowImportBodyLimit, 10, 64) - require.NoError(t, err) + bodyLimit := WorkflowImportBodyLimit req := httptest.NewRequest(http.MethodPost, "/workflows/import", http.NoBody) req.Header.Set(echo.HeaderAuthorization, "Bearer "+*token) diff --git a/internal/api/handler/workflows/import_test.go b/internal/api/handler/workflows/import_test.go index 43881aa1..e4f0021b 100644 --- a/internal/api/handler/workflows/import_test.go +++ b/internal/api/handler/workflows/import_test.go @@ -10,8 +10,8 @@ import ( "testing" workflowseed "github.com/compliance-framework/api/internal/service/relational/workflows" - "github.com/labstack/echo/v4" - echomiddleware "github.com/labstack/echo/v4/middleware" + "github.com/labstack/echo/v5" + echomiddleware "github.com/labstack/echo/v5/middleware" "github.com/stretchr/testify/require" "go.uber.org/zap" ) @@ -75,7 +75,7 @@ func TestWorkflowImportBodyLimitAllowsMaxFilesAtMaxSize(t *testing.T) { func TestWorkflowImportPropagatesBodyLimitDuringMultipartParsing(t *testing.T) { e := echo.New() handler := NewWorkflowImportHandler(zap.NewNop().Sugar(), nil) - e.POST("/workflows/import", handler.Import, echomiddleware.BodyLimit("1000")) + e.POST("/workflows/import", handler.Import, echomiddleware.BodyLimit(1000)) body, contentType := newMultipartBody(t, 1, bytes.Repeat([]byte("x"), 128*1024)) req := httptest.NewRequest(http.MethodPost, "/workflows/import", io.NopCloser(&readerWithoutLen{ diff --git a/internal/api/handler/workflows/role_assignment.go b/internal/api/handler/workflows/role_assignment.go index 60c0cd5e..ec08bde8 100644 --- a/internal/api/handler/workflows/role_assignment.go +++ b/internal/api/handler/workflows/role_assignment.go @@ -7,7 +7,7 @@ import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -71,7 +71,7 @@ type RoleAssignmentListResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/role-assignments [post] -func (h *RoleAssignmentHandler) Create(ctx echo.Context) error { +func (h *RoleAssignmentHandler) Create(ctx *echo.Context) error { var req CreateRoleAssignmentRequest if err := h.BindAndValidate(ctx, &req); err != nil { return HandleError(err) @@ -111,7 +111,7 @@ func (h *RoleAssignmentHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/role-assignments [get] -func (h *RoleAssignmentHandler) List(ctx echo.Context) error { +func (h *RoleAssignmentHandler) List(ctx *echo.Context) error { workflowInstIDStr := ctx.QueryParam("workflow_instance_id") roleName := ctx.QueryParam("role_name") @@ -156,7 +156,7 @@ func (h *RoleAssignmentHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/role-assignments/{id} [get] -func (h *RoleAssignmentHandler) Get(ctx echo.Context) error { +func (h *RoleAssignmentHandler) Get(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "role assignment") if err != nil { return HandleError(err) @@ -186,7 +186,7 @@ func (h *RoleAssignmentHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/role-assignments/{id} [put] -func (h *RoleAssignmentHandler) Update(ctx echo.Context) error { +func (h *RoleAssignmentHandler) Update(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "role assignment") if err != nil { return HandleError(err) @@ -235,7 +235,7 @@ func (h *RoleAssignmentHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/role-assignments/{id} [delete] -func (h *RoleAssignmentHandler) Delete(ctx echo.Context) error { +func (h *RoleAssignmentHandler) Delete(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "role assignment") if err != nil { return HandleError(err) @@ -263,7 +263,7 @@ func (h *RoleAssignmentHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/role-assignments/{id}/activate [put] -func (h *RoleAssignmentHandler) Activate(ctx echo.Context) error { +func (h *RoleAssignmentHandler) Activate(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "role assignment") if err != nil { return HandleError(err) @@ -302,7 +302,7 @@ func (h *RoleAssignmentHandler) Activate(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/role-assignments/{id}/deactivate [put] -func (h *RoleAssignmentHandler) Deactivate(ctx echo.Context) error { +func (h *RoleAssignmentHandler) Deactivate(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "role assignment") if err != nil { return HandleError(err) diff --git a/internal/api/handler/workflows/role_assignment_integration_test.go b/internal/api/handler/workflows/role_assignment_integration_test.go index 44eb438e..b1aeb525 100644 --- a/internal/api/handler/workflows/role_assignment_integration_test.go +++ b/internal/api/handler/workflows/role_assignment_integration_test.go @@ -12,7 +12,7 @@ import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -177,8 +177,7 @@ func TestRoleAssignmentHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/role-assignments/"+assignment.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(assignment.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: assignment.ID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -195,8 +194,7 @@ func TestRoleAssignmentHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/role-assignments/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -242,8 +240,7 @@ func TestRoleAssignmentHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(assignment.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: assignment.ID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -286,8 +283,7 @@ func TestRoleAssignmentHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/role-assignments/"+assignment.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(assignment.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: assignment.ID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -326,8 +322,7 @@ func TestRoleAssignmentHandler_Activate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/role-assignments/"+assignment.ID.String()+"/activate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(assignment.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: assignment.ID.String()}}) err := handler.Activate(c) require.NoError(t, err) @@ -371,8 +366,7 @@ func TestRoleAssignmentHandler_Deactivate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/role-assignments/"+assignment.ID.String()+"/deactivate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(assignment.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: assignment.ID.String()}}) err := handler.Deactivate(c) require.NoError(t, err) diff --git a/internal/api/handler/workflows/step_execution.go b/internal/api/handler/workflows/step_execution.go index 6bca3eaa..99a1174e 100644 --- a/internal/api/handler/workflows/step_execution.go +++ b/internal/api/handler/workflows/step_execution.go @@ -15,7 +15,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/compliance-framework/api/internal/workflow" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -116,7 +116,7 @@ type MyAssignmentsResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions/my [get] -func (h *StepExecutionHandler) ListMy(ctx echo.Context) error { +func (h *StepExecutionHandler) ListMy(ctx *echo.Context) error { // Get user from JWT claims userClaims, ok := ctx.Get("user").(*authn.UserClaims) if !ok || userClaims == nil { @@ -219,7 +219,7 @@ func (h *StepExecutionHandler) ListMy(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions [get] -func (h *StepExecutionHandler) List(ctx echo.Context) error { +func (h *StepExecutionHandler) List(ctx *echo.Context) error { workflowExecIDStr := ctx.QueryParam("workflow_execution_id") if workflowExecIDStr == "" { return ctx.JSON(http.StatusBadRequest, api.NewError(echo.NewHTTPError(http.StatusBadRequest, "workflow_execution_id is required"))) @@ -252,7 +252,7 @@ func (h *StepExecutionHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions/{id} [get] -func (h *StepExecutionHandler) Get(ctx echo.Context) error { +func (h *StepExecutionHandler) Get(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step execution") if err != nil { return HandleError(err) @@ -283,7 +283,7 @@ func (h *StepExecutionHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions/{id}/transition [put] -func (h *StepExecutionHandler) TransitionStep(ctx echo.Context) error { +func (h *StepExecutionHandler) TransitionStep(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step execution") if err != nil { return HandleError(err) @@ -363,7 +363,7 @@ func (h *StepExecutionHandler) TransitionStep(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions/{id}/evidence-requirements [get] -func (h *StepExecutionHandler) GetEvidenceRequirements(ctx echo.Context) error { +func (h *StepExecutionHandler) GetEvidenceRequirements(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step execution") if err != nil { return HandleError(err) @@ -394,7 +394,7 @@ func (h *StepExecutionHandler) GetEvidenceRequirements(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions/{id}/can-transition [get] -func (h *StepExecutionHandler) CanTransition(ctx echo.Context) error { +func (h *StepExecutionHandler) CanTransition(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step execution") if err != nil { return HandleError(err) @@ -437,7 +437,7 @@ func (h *StepExecutionHandler) CanTransition(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions/{id}/fail [put] -func (h *StepExecutionHandler) Fail(ctx echo.Context) error { +func (h *StepExecutionHandler) Fail(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step execution") if err != nil { return HandleError(err) @@ -477,7 +477,7 @@ func (h *StepExecutionHandler) Fail(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/step-executions/{id}/reassign [put] -func (h *StepExecutionHandler) Reassign(ctx echo.Context) error { +func (h *StepExecutionHandler) Reassign(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step execution") if err != nil { return HandleError(err) diff --git a/internal/api/handler/workflows/step_execution_integration_test.go b/internal/api/handler/workflows/step_execution_integration_test.go index b2173643..813050bc 100644 --- a/internal/api/handler/workflows/step_execution_integration_test.go +++ b/internal/api/handler/workflows/step_execution_integration_test.go @@ -21,7 +21,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/compliance-framework/api/internal/workflow" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -190,8 +190,7 @@ func TestStepExecutionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/step-executions/"+stepExec.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepExec.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepExec.ID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -208,8 +207,7 @@ func TestStepExecutionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/step-executions/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -293,8 +291,7 @@ func TestStepExecutionHandler_TransitionStep(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepExec.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepExec.ID.String()}}) c.Set("user", claims) err = handler.TransitionStep(c) @@ -327,8 +324,7 @@ func TestStepExecutionHandler_TransitionStep(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec = httptest.NewRecorder() c = e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepExec.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepExec.ID.String()}}) c.Set("user", claims) err = handler.TransitionStep(c) @@ -399,8 +395,7 @@ func TestStepExecutionHandler_TransitionStep(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(overdueStep.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: overdueStep.ID.String()}}) c.Set("user", claims) err = handler.TransitionStep(c) @@ -457,8 +452,7 @@ func TestStepExecutionHandler_GetEvidenceRequirements(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/step-executions/"+stepExec.ID.String()+"/evidence-requirements", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepExec.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepExec.ID.String()}}) err := handler.GetEvidenceRequirements(c) require.NoError(t, err) @@ -523,8 +517,7 @@ func TestStepExecutionHandler_Fail(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepExec.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepExec.ID.String()}}) err = handler.Fail(c) require.NoError(t, err) @@ -677,7 +670,7 @@ func TestStepExecutionHandler_ListMy(t *testing.T) { require.NoError(t, db.Create(stepExec4).Error) // Helper to create context with JWT claims - createContextWithClaims := func(req *http.Request, rec *httptest.ResponseRecorder, email string) echo.Context { + createContextWithClaims := func(req *http.Request, rec *httptest.ResponseRecorder, email string) *echo.Context { c := e.NewContext(req, rec) c.Set("user", &authn.UserClaims{ GivenName: "Test", @@ -995,7 +988,7 @@ func TestStepExecutionHandler_Reassign(t *testing.T) { } require.NoError(t, db.Create(stepExec).Error) - createActorContext := func(req *http.Request, rec *httptest.ResponseRecorder) echo.Context { + createActorContext := func(req *http.Request, rec *httptest.ResponseRecorder) *echo.Context { c := e.NewContext(req, rec) c.Set("user", &authn.UserClaims{ GivenName: actor.FirstName, @@ -1003,8 +996,7 @@ func TestStepExecutionHandler_Reassign(t *testing.T) { }) claims := c.Get("user").(*authn.UserClaims) claims.Subject = actor.Email - c.SetParamNames("id") - c.SetParamValues(stepExec.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepExec.ID.String()}}) return c } @@ -1099,8 +1091,7 @@ func TestStepExecutionHandler_Reassign(t *testing.T) { }) claims := c.Get("user").(*authn.UserClaims) claims.Subject = actor.Email - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err = handler.Reassign(c) require.NoError(t, err) diff --git a/internal/api/handler/workflows/workflow_definition.go b/internal/api/handler/workflows/workflow_definition.go index aec40192..d5a940d3 100644 --- a/internal/api/handler/workflows/workflow_definition.go +++ b/internal/api/handler/workflows/workflow_definition.go @@ -3,7 +3,7 @@ package workflows import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/service/relational/workflows" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -68,7 +68,7 @@ type WorkflowDefinitionListResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/definitions [post] -func (h *WorkflowDefinitionHandler) Create(ctx echo.Context) error { +func (h *WorkflowDefinitionHandler) Create(ctx *echo.Context) error { var req CreateWorkflowDefinitionRequest if err := h.BindAndValidate(ctx, &req); err != nil { return HandleError(err) @@ -107,7 +107,7 @@ func (h *WorkflowDefinitionHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/definitions [get] -func (h *WorkflowDefinitionHandler) List(ctx echo.Context) error { +func (h *WorkflowDefinitionHandler) List(ctx *echo.Context) error { // For now, return all definitions without pagination // TODO: Add pagination query parameters definitions, _, err := h.service.GetAll(1000, 0) @@ -132,7 +132,7 @@ func (h *WorkflowDefinitionHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/definitions/{id} [get] -func (h *WorkflowDefinitionHandler) Get(ctx echo.Context) error { +func (h *WorkflowDefinitionHandler) Get(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow definition") if err != nil { return HandleError(err) @@ -162,7 +162,7 @@ func (h *WorkflowDefinitionHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/definitions/{id} [put] -func (h *WorkflowDefinitionHandler) Update(ctx echo.Context) error { +func (h *WorkflowDefinitionHandler) Update(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow definition") if err != nil { return HandleError(err) @@ -222,7 +222,7 @@ func (h *WorkflowDefinitionHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/definitions/{id} [delete] -func (h *WorkflowDefinitionHandler) Delete(ctx echo.Context) error { +func (h *WorkflowDefinitionHandler) Delete(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow definition") if err != nil { return HandleError(err) diff --git a/internal/api/handler/workflows/workflow_definition_integration_test.go b/internal/api/handler/workflows/workflow_definition_integration_test.go index 1bc90ee9..b71d72d8 100644 --- a/internal/api/handler/workflows/workflow_definition_integration_test.go +++ b/internal/api/handler/workflows/workflow_definition_integration_test.go @@ -13,7 +13,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -180,8 +180,7 @@ func TestWorkflowDefinitionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/definitions/"+definition.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(definition.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: definition.ID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -200,8 +199,7 @@ func TestWorkflowDefinitionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/definitions/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -212,8 +210,7 @@ func TestWorkflowDefinitionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/definitions/invalid-id", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues("invalid-id") + c.SetPathValues(echo.PathValues{{Name: "id", Value: "invalid-id"}}) err := handler.Get(c) require.NoError(t, err) @@ -250,8 +247,7 @@ func TestWorkflowDefinitionHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(definition.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: definition.ID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -280,8 +276,7 @@ func TestWorkflowDefinitionHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(definition.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: definition.ID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -311,8 +306,7 @@ func TestWorkflowDefinitionHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(definition.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: definition.ID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -338,8 +332,7 @@ func TestWorkflowDefinitionHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -359,8 +352,7 @@ func TestWorkflowDefinitionHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues("invalid-id") + c.SetPathValues(echo.PathValues{{Name: "id", Value: "invalid-id"}}) err = handler.Update(c) require.NoError(t, err) @@ -402,8 +394,7 @@ func TestWorkflowDefinitionHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/definitions/"+definition.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(definition.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: definition.ID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -424,8 +415,7 @@ func TestWorkflowDefinitionHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/definitions/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -436,8 +426,7 @@ func TestWorkflowDefinitionHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/definitions/invalid-id", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues("invalid-id") + c.SetPathValues(echo.PathValues{{Name: "id", Value: "invalid-id"}}) err := handler.Delete(c) require.NoError(t, err) diff --git a/internal/api/handler/workflows/workflow_execution.go b/internal/api/handler/workflows/workflow_execution.go index df64ddf0..9ea846e0 100644 --- a/internal/api/handler/workflows/workflow_execution.go +++ b/internal/api/handler/workflows/workflow_execution.go @@ -9,7 +9,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/compliance-framework/api/internal/workflow" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -106,7 +106,7 @@ type BulkReassignRoleResponseData struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions [post] -func (h *WorkflowExecutionHandler) Start(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) Start(ctx *echo.Context) error { var req StartWorkflowExecutionRequest if err := h.BindAndValidate(ctx, &req); err != nil { return HandleError(err) @@ -148,7 +148,7 @@ func (h *WorkflowExecutionHandler) Start(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions [get] -func (h *WorkflowExecutionHandler) List(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) List(ctx *echo.Context) error { workflowInstanceIDStr := ctx.QueryParam("workflow_instance_id") if workflowInstanceIDStr == "" { return ctx.JSON(http.StatusBadRequest, api.NewError(echo.NewHTTPError(http.StatusBadRequest, "workflow_instance_id is required"))) @@ -197,7 +197,7 @@ func (h *WorkflowExecutionHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions/{id} [get] -func (h *WorkflowExecutionHandler) Get(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) Get(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow execution") if err != nil { return HandleError(err) @@ -225,7 +225,7 @@ func (h *WorkflowExecutionHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions/{id}/status [get] -func (h *WorkflowExecutionHandler) GetStatus(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) GetStatus(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow execution") if err != nil { return HandleError(err) @@ -254,7 +254,7 @@ func (h *WorkflowExecutionHandler) GetStatus(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions/{id}/metrics [get] -func (h *WorkflowExecutionHandler) GetMetrics(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) GetMetrics(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow execution") if err != nil { return HandleError(err) @@ -285,7 +285,7 @@ func (h *WorkflowExecutionHandler) GetMetrics(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions/{id}/cancel [put] -func (h *WorkflowExecutionHandler) Cancel(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) Cancel(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow execution") if err != nil { return HandleError(err) @@ -325,7 +325,7 @@ func (h *WorkflowExecutionHandler) Cancel(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions/{id}/retry [post] -func (h *WorkflowExecutionHandler) Retry(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) Retry(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow execution") if err != nil { return HandleError(err) @@ -357,7 +357,7 @@ func (h *WorkflowExecutionHandler) Retry(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/executions/{id}/reassign-role [put] -func (h *WorkflowExecutionHandler) ReassignRole(ctx echo.Context) error { +func (h *WorkflowExecutionHandler) ReassignRole(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow execution") if err != nil { return HandleError(err) diff --git a/internal/api/handler/workflows/workflow_execution_integration_test.go b/internal/api/handler/workflows/workflow_execution_integration_test.go index 0b06ca96..4f96a079 100644 --- a/internal/api/handler/workflows/workflow_execution_integration_test.go +++ b/internal/api/handler/workflows/workflow_execution_integration_test.go @@ -16,7 +16,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/compliance-framework/api/internal/workflow" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/riverqueue/river" "github.com/riverqueue/river/rivertype" "github.com/stretchr/testify/assert" @@ -219,8 +219,7 @@ func TestWorkflowExecutionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/executions/"+execution.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(execution.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: execution.ID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -238,8 +237,7 @@ func TestWorkflowExecutionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/executions/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -337,7 +335,7 @@ func TestWorkflowExecutionHandler_ReassignRole(t *testing.T) { } require.NoError(t, db.Create(otherRoleStep).Error) - createContext := func(req *http.Request, rec *httptest.ResponseRecorder, executionID string) echo.Context { + createContext := func(req *http.Request, rec *httptest.ResponseRecorder, executionID string) *echo.Context { c := e.NewContext(req, rec) c.Set("user", &authn.UserClaims{ GivenName: actor.FirstName, @@ -345,8 +343,7 @@ func TestWorkflowExecutionHandler_ReassignRole(t *testing.T) { }) claims := c.Get("user").(*authn.UserClaims) claims.Subject = actor.Email - c.SetParamNames("id") - c.SetParamValues(executionID) + c.SetPathValues(echo.PathValues{{Name: "id", Value: executionID}}) return c } @@ -479,8 +476,7 @@ func TestWorkflowExecutionHandler_GetStatus(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/executions/"+execution.ID.String()+"/status", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(execution.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: execution.ID.String()}}) err := handler.GetStatus(c) require.NoError(t, err) @@ -525,8 +521,7 @@ func TestWorkflowExecutionHandler_GetMetrics(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/executions/"+execution.ID.String()+"/metrics", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(execution.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: execution.ID.String()}}) err := handler.GetMetrics(c) require.NoError(t, err) @@ -578,8 +573,7 @@ func TestWorkflowExecutionHandler_Cancel(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(execution.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: execution.ID.String()}}) err = handler.Cancel(c) require.NoError(t, err) @@ -622,8 +616,7 @@ func TestWorkflowExecutionHandler_Retry(t *testing.T) { req := httptest.NewRequest(http.MethodPost, "/workflows/executions/"+execution.ID.String()+"/retry", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(execution.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: execution.ID.String()}}) err := handler.Retry(c) require.NoError(t, err) diff --git a/internal/api/handler/workflows/workflow_instance.go b/internal/api/handler/workflows/workflow_instance.go index 1a196691..aa79fc5d 100644 --- a/internal/api/handler/workflows/workflow_instance.go +++ b/internal/api/handler/workflows/workflow_instance.go @@ -4,7 +4,7 @@ import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -73,7 +73,7 @@ type WorkflowInstanceListResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/instances [post] -func (h *WorkflowInstanceHandler) Create(ctx echo.Context) error { +func (h *WorkflowInstanceHandler) Create(ctx *echo.Context) error { var req CreateWorkflowInstanceRequest if err := h.BindAndValidate(ctx, &req); err != nil { return HandleError(err) @@ -126,7 +126,7 @@ func (h *WorkflowInstanceHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/instances [get] -func (h *WorkflowInstanceHandler) List(ctx echo.Context) error { +func (h *WorkflowInstanceHandler) List(ctx *echo.Context) error { workflowDefIDStr := ctx.QueryParam("workflow_definition_id") systemSecurityPlanIDStr := ctx.QueryParam("system_security_plan_id") isActiveStr := ctx.QueryParam("is_active") @@ -186,7 +186,7 @@ func (h *WorkflowInstanceHandler) List(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/instances/{id} [get] -func (h *WorkflowInstanceHandler) Get(ctx echo.Context) error { +func (h *WorkflowInstanceHandler) Get(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow instance") if err != nil { return HandleError(err) @@ -216,7 +216,7 @@ func (h *WorkflowInstanceHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/instances/{id} [put] -func (h *WorkflowInstanceHandler) Update(ctx echo.Context) error { +func (h *WorkflowInstanceHandler) Update(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow instance") if err != nil { return HandleError(err) @@ -276,7 +276,7 @@ func (h *WorkflowInstanceHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/instances/{id} [delete] -func (h *WorkflowInstanceHandler) Delete(ctx echo.Context) error { +func (h *WorkflowInstanceHandler) Delete(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow instance") if err != nil { return HandleError(err) @@ -304,7 +304,7 @@ func (h *WorkflowInstanceHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/instances/{id}/activate [put] -func (h *WorkflowInstanceHandler) Activate(ctx echo.Context) error { +func (h *WorkflowInstanceHandler) Activate(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow instance") if err != nil { return HandleError(err) @@ -343,7 +343,7 @@ func (h *WorkflowInstanceHandler) Activate(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/instances/{id}/deactivate [put] -func (h *WorkflowInstanceHandler) Deactivate(ctx echo.Context) error { +func (h *WorkflowInstanceHandler) Deactivate(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "workflow instance") if err != nil { return HandleError(err) diff --git a/internal/api/handler/workflows/workflow_instance_integration_test.go b/internal/api/handler/workflows/workflow_instance_integration_test.go index 8493b6ce..074620e0 100644 --- a/internal/api/handler/workflows/workflow_instance_integration_test.go +++ b/internal/api/handler/workflows/workflow_instance_integration_test.go @@ -14,7 +14,7 @@ import ( "github.com/compliance-framework/api/internal/service/relational" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -34,7 +34,7 @@ func createTestUser(t *testing.T, db *gorm.DB) *relational.User { return user } -func setAuthClaims(c echo.Context, user *relational.User) { +func setAuthClaims(c *echo.Context, user *relational.User) { claims := &authn.UserClaims{GivenName: user.FirstName, FamilyName: user.LastName} claims.Subject = user.Email c.Set("user", claims) @@ -263,8 +263,7 @@ func TestWorkflowInstanceHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/instances/"+instance.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(instance.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: instance.ID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -283,8 +282,7 @@ func TestWorkflowInstanceHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/instances/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -333,8 +331,7 @@ func TestWorkflowInstanceHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(instance.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: instance.ID.String()}}) setAuthClaims(c, testUser) err = handler.Update(c) @@ -367,8 +364,7 @@ func TestWorkflowInstanceHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) setAuthClaims(c, testUser) err = handler.Update(c) @@ -401,8 +397,7 @@ func TestWorkflowInstanceHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/instances/"+instance.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(instance.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: instance.ID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -419,8 +414,7 @@ func TestWorkflowInstanceHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/instances/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -453,8 +447,7 @@ func TestWorkflowInstanceHandler_Activate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/instances/"+instance.ID.String()+"/activate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(instance.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: instance.ID.String()}}) err := handler.Activate(c) require.NoError(t, err) @@ -471,8 +464,7 @@ func TestWorkflowInstanceHandler_Activate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/instances/"+nonExistentID.String()+"/activate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Activate(c) require.NoError(t, err) @@ -505,8 +497,7 @@ func TestWorkflowInstanceHandler_Deactivate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/instances/"+instance.ID.String()+"/deactivate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(instance.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: instance.ID.String()}}) err := handler.Deactivate(c) require.NoError(t, err) @@ -523,8 +514,7 @@ func TestWorkflowInstanceHandler_Deactivate(t *testing.T) { req := httptest.NewRequest(http.MethodPut, "/workflows/instances/"+nonExistentID.String()+"/deactivate", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Deactivate(c) require.NoError(t, err) diff --git a/internal/api/handler/workflows/workflow_step_definition.go b/internal/api/handler/workflows/workflow_step_definition.go index e11eb141..a8754245 100644 --- a/internal/api/handler/workflows/workflow_step_definition.go +++ b/internal/api/handler/workflows/workflow_step_definition.go @@ -9,7 +9,7 @@ import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "gorm.io/gorm" ) @@ -145,7 +145,7 @@ type WorkflowStepDefinitionListResponse struct { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/steps [post] -func (h *WorkflowStepDefinitionHandler) Create(ctx echo.Context) error { +func (h *WorkflowStepDefinitionHandler) Create(ctx *echo.Context) error { var req CreateWorkflowStepDefinitionRequest if err := h.BindAndValidate(ctx, &req); err != nil { return HandleError(err) @@ -199,7 +199,7 @@ func (h *WorkflowStepDefinitionHandler) Create(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/steps [get] -func (h *WorkflowStepDefinitionHandler) ListByWorkflowDefinition(ctx echo.Context) error { +func (h *WorkflowStepDefinitionHandler) ListByWorkflowDefinition(ctx *echo.Context) error { workflowDefIDStr := ctx.QueryParam("workflow_definition_id") if workflowDefIDStr == "" { return ctx.JSON(http.StatusBadRequest, api.NewError(echo.NewHTTPError(http.StatusBadRequest, "workflow_definition_id is required"))) @@ -233,7 +233,7 @@ func (h *WorkflowStepDefinitionHandler) ListByWorkflowDefinition(ctx echo.Contex // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/steps/{id} [get] -func (h *WorkflowStepDefinitionHandler) Get(ctx echo.Context) error { +func (h *WorkflowStepDefinitionHandler) Get(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step definition") if err != nil { return HandleError(err) @@ -263,7 +263,7 @@ func (h *WorkflowStepDefinitionHandler) Get(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/steps/{id} [put] -func (h *WorkflowStepDefinitionHandler) Update(ctx echo.Context) error { +func (h *WorkflowStepDefinitionHandler) Update(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step definition") if err != nil { return HandleError(err) @@ -334,7 +334,7 @@ func (h *WorkflowStepDefinitionHandler) Update(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/steps/{id} [delete] -func (h *WorkflowStepDefinitionHandler) Delete(ctx echo.Context) error { +func (h *WorkflowStepDefinitionHandler) Delete(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step definition") if err != nil { return HandleError(err) @@ -362,7 +362,7 @@ func (h *WorkflowStepDefinitionHandler) Delete(ctx echo.Context) error { // @Failure 500 {object} api.Error // @Security OAuth2Password // @Router /workflows/steps/{id}/dependencies [get] -func (h *WorkflowStepDefinitionHandler) GetDependencies(ctx echo.Context) error { +func (h *WorkflowStepDefinitionHandler) GetDependencies(ctx *echo.Context) error { id, err := h.ParseUUID(ctx, "id", "step definition") if err != nil { return HandleError(err) diff --git a/internal/api/handler/workflows/workflow_step_definition_integration_test.go b/internal/api/handler/workflows/workflow_step_definition_integration_test.go index 9abc6074..a1cceaca 100644 --- a/internal/api/handler/workflows/workflow_step_definition_integration_test.go +++ b/internal/api/handler/workflows/workflow_step_definition_integration_test.go @@ -12,7 +12,7 @@ import ( "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/service/relational/workflows" "github.com/google/uuid" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -217,8 +217,7 @@ func TestWorkflowStepDefinitionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/steps/"+stepDef.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepDef.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepDef.ID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -237,8 +236,7 @@ func TestWorkflowStepDefinitionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/steps/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Get(c) require.NoError(t, err) @@ -249,8 +247,7 @@ func TestWorkflowStepDefinitionHandler_Get(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/steps/invalid-id", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues("invalid-id") + c.SetPathValues(echo.PathValues{{Name: "id", Value: "invalid-id"}}) err := handler.Get(c) require.NoError(t, err) @@ -294,8 +291,7 @@ func TestWorkflowStepDefinitionHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepDef.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepDef.ID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -325,8 +321,7 @@ func TestWorkflowStepDefinitionHandler_Update(t *testing.T) { req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err = handler.Update(c) require.NoError(t, err) @@ -355,8 +350,7 @@ func TestWorkflowStepDefinitionHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/steps/"+stepDef.ID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(stepDef.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: stepDef.ID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -373,8 +367,7 @@ func TestWorkflowStepDefinitionHandler_Delete(t *testing.T) { req := httptest.NewRequest(http.MethodDelete, "/workflows/steps/"+nonExistentID.String(), nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(nonExistentID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: nonExistentID.String()}}) err := handler.Delete(c) require.NoError(t, err) @@ -421,8 +414,7 @@ func TestWorkflowStepDefinitionHandler_GetDependencies(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/steps/"+step3.ID.String()+"/dependencies", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(step3.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: step3.ID.String()}}) err := handler.GetDependencies(c) require.NoError(t, err) @@ -438,8 +430,7 @@ func TestWorkflowStepDefinitionHandler_GetDependencies(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/workflows/steps/"+step1.ID.String()+"/dependencies", nil) rec := httptest.NewRecorder() c := e.NewContext(req, rec) - c.SetParamNames("id") - c.SetParamValues(step1.ID.String()) + c.SetPathValues(echo.PathValues{{Name: "id", Value: step1.ID.String()}}) err := handler.GetDependencies(c) require.NoError(t, err) diff --git a/internal/api/metrics.go b/internal/api/metrics.go index ce15e9bd..a87bd7bd 100644 --- a/internal/api/metrics.go +++ b/internal/api/metrics.go @@ -3,9 +3,9 @@ package api import ( "context" - "github.com/labstack/echo-contrib/echoprometheus" - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" + "github.com/labstack/echo-contrib/v5/echoprometheus" + "github.com/labstack/echo/v5" + "github.com/labstack/echo/v5/middleware" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "go.uber.org/zap" @@ -72,13 +72,12 @@ func (m *PrometheusMetrics) Registry() *prometheus.Registry { func (m *PrometheusMetrics) StartMetricsServer(port string) { go func() { metrics := echo.New() - metrics.HideBanner = true metrics.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ LogURI: true, LogStatus: true, LogMethod: true, LogLatency: true, - LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { + LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error { m.logger.Debugw("metrics request", zap.String("method", v.Method), zap.String("uri", v.URI), @@ -91,14 +90,9 @@ func (m *PrometheusMetrics) StartMetricsServer(port string) { metrics.GET("/metrics", echoprometheus.NewHandlerWithConfig(echoprometheus.HandlerConfig{ Gatherer: m.registry, })) - if err := metrics.Start(port); err != nil { + // Serves until m.ctx is cancelled, then shuts down gracefully. + if err := (echo.StartConfig{Address: port, HideBanner: true}).Start(m.ctx, metrics); err != nil { m.logger.Error(err) - return - } - <-m.ctx.Done() - err := metrics.Shutdown(m.ctx) - if err != nil { - m.logger.Errorw("failed to shutdown metrics server", "error", err) } }() } diff --git a/internal/api/middleware/agent_ingest.go b/internal/api/middleware/agent_ingest.go index b9beb6af..a74a12ad 100644 --- a/internal/api/middleware/agent_ingest.go +++ b/internal/api/middleware/agent_ingest.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/authn" "github.com/compliance-framework/api/internal/service/relational" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" ) @@ -24,7 +24,7 @@ func AgentJWTMiddleware(db *gorm.DB, publicKey *rsa.PublicKey) echo.MiddlewareFu func AgentJWTOrPublicMiddleware(db *gorm.DB, publicKey *rsa.PublicKey, allowPublic bool) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { + return func(c *echo.Context) error { if c.Request().Method == http.MethodOptions { return next(c) } @@ -39,7 +39,7 @@ func AgentJWTOrPublicMiddleware(db *gorm.DB, publicKey *rsa.PublicKey, allowPubl tokenString, err := getTokenFromHeader(authHeader) if err != nil { - return echo.NewHTTPError(http.StatusUnauthorized, err) + return echo.NewHTTPError(http.StatusUnauthorized, err.Error()) } claims, agent, key, err := verifyAgentRequest(db, tokenString, publicKey, c) @@ -58,7 +58,7 @@ func AgentJWTOrPublicMiddleware(db *gorm.DB, publicKey *rsa.PublicKey, allowPubl } } -func verifyAgentRequest(db *gorm.DB, tokenString string, publicKey *rsa.PublicKey, c echo.Context) (*authn.AgentClaims, *relational.Agent, *relational.AgentServiceAccountKey, error) { +func verifyAgentRequest(db *gorm.DB, tokenString string, publicKey *rsa.PublicKey, c *echo.Context) (*authn.AgentClaims, *relational.Agent, *relational.AgentServiceAccountKey, error) { claims, err := authn.VerifyAgentJWTToken(tokenString, publicKey) if err != nil { return nil, nil, nil, echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired token") @@ -69,7 +69,7 @@ func verifyAgentRequest(db *gorm.DB, tokenString string, publicKey *rsa.PublicKe if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil, nil, echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired token") } - c.Logger().Errorf("failed to load agent for authenticated agent request: %v (agent_id=%v)", err, claims.AgentID) + c.Logger().Error("failed to load agent for authenticated agent request", "error", err, "agent_id", claims.AgentID) return nil, nil, nil, echo.NewHTTPError(http.StatusInternalServerError, "failed to load agent") } if !agent.IsActive { @@ -81,7 +81,7 @@ func verifyAgentRequest(db *gorm.DB, tokenString string, publicKey *rsa.PublicKe if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil, nil, echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired token") } - c.Logger().Errorf("failed to load agent key for authenticated agent request: %v (agent_id=%v credential_id=%v)", err, agent.ID, claims.CredentialID) + c.Logger().Error("failed to load agent key for authenticated agent request", "error", err, "agent_id", agent.ID, "credential_id", claims.CredentialID) return nil, nil, nil, echo.NewHTTPError(http.StatusInternalServerError, "failed to load agent key") } now := time.Now().UTC() diff --git a/internal/api/middleware/auth.go b/internal/api/middleware/auth.go index e8e4a793..a66b047d 100644 --- a/internal/api/middleware/auth.go +++ b/internal/api/middleware/auth.go @@ -7,13 +7,13 @@ import ( "strings" "github.com/compliance-framework/api/internal/authn" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) // JWTMiddleware returns an Echo middleware function that verifies JWT tokens using the provided RSA public key. func JWTMiddleware(publicKey *rsa.PublicKey) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { + return func(c *echo.Context) error { if c.Request().Method == http.MethodOptions { // Allow preflight requests without authentication return next(c) @@ -27,7 +27,7 @@ func JWTMiddleware(publicKey *rsa.PublicKey) echo.MiddlewareFunc { } else { tokenString, err = getTokenFromHeader(c.Request().Header.Get("Authorization")) if err != nil { - return echo.NewHTTPError(http.StatusUnauthorized, err) + return echo.NewHTTPError(http.StatusUnauthorized, err.Error()) } } diff --git a/internal/api/middleware/authorize.go b/internal/api/middleware/authorize.go index 4dc0efdc..a0f4e8cf 100644 --- a/internal/api/middleware/authorize.go +++ b/internal/api/middleware/authorize.go @@ -7,7 +7,7 @@ import ( "github.com/compliance-framework/api/internal/authn" "github.com/compliance-framework/api/internal/authz" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" ) @@ -124,7 +124,7 @@ func (p *PEP) Authorize(resource, action string, opts ...AuthorizeOption) echo.M o(&cfg) } return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { + return func(c *echo.Context) error { subject := SubjectFromContext(c) res := authz.Resource{Type: resource, ID: c.Param(cfg.idParam)} for attr, param := range cfg.scopeParams { @@ -227,7 +227,7 @@ func camelToSnake(s string) string { // subject on public-allowed routes. It is the single source of subject derivation, shared // by the PEP and the /me/permissions handler. Attributes are intentionally minimal in // Phase 1; the authoritative attribute surface is designed in BCH-1319. -func SubjectFromContext(c echo.Context) authz.Subject { +func SubjectFromContext(c *echo.Context) authz.Subject { if claims, ok := c.Get("user").(*authn.UserClaims); ok && claims != nil { props := map[string]any{ "given_name": claims.GivenName, diff --git a/internal/api/middleware/authorize_guard_test.go b/internal/api/middleware/authorize_guard_test.go index 30850d89..8a37edd9 100644 --- a/internal/api/middleware/authorize_guard_test.go +++ b/internal/api/middleware/authorize_guard_test.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/authn" "github.com/compliance-framework/api/internal/authz" "github.com/golang-jwt/jwt/v5" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) // runGuarded runs a single ResourceGuard-produced middleware against a request from the given @@ -22,9 +22,9 @@ func runGuarded(t *testing.T, subjectID string, mw echo.MiddlewareFunc) (int, bo c.Set("user", &authn.UserClaims{RegisteredClaims: jwt.RegisteredClaims{Subject: subjectID}}) called := false - next := func(c echo.Context) error { called = true; return c.NoContent(http.StatusOK) } + next := func(c *echo.Context) error { called = true; return c.NoContent(http.StatusOK) } if err := mw(next)(c); err != nil { - e.HTTPErrorHandler(err, c) + e.HTTPErrorHandler(c, err) } return rec.Code, called } diff --git a/internal/api/middleware/authorize_scope_test.go b/internal/api/middleware/authorize_scope_test.go index ade562c8..89ab680e 100644 --- a/internal/api/middleware/authorize_scope_test.go +++ b/internal/api/middleware/authorize_scope_test.go @@ -7,7 +7,7 @@ import ( "github.com/compliance-framework/api/internal/authn" "github.com/compliance-framework/api/internal/authz" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "go.uber.org/zap" "go.uber.org/zap/zaptest/observer" ) @@ -38,11 +38,14 @@ func runScopedAuthorize(t *testing.T, paramNames, paramValues []string, opts ... pdp := &fakePDP{decision: authz.Decision{Allow: true}} e := echo.New() c := e.NewContext(httptest.NewRequest(http.MethodGet, "/", http.NoBody), httptest.NewRecorder()) - c.SetParamNames(paramNames...) - c.SetParamValues(paramValues...) + pathValues := make(echo.PathValues, len(paramNames)) + for i, name := range paramNames { + pathValues[i] = echo.PathValue{Name: name, Value: paramValues[i]} + } + c.SetPathValues(pathValues) pep := NewPEP(pdp, authz.FailClosed, nil) - h := pep.Authorize("risk", authz.ActionRead, opts...)(func(c echo.Context) error { return c.NoContent(http.StatusOK) }) + h := pep.Authorize("risk", authz.ActionRead, opts...)(func(c *echo.Context) error { return c.NoContent(http.StatusOK) }) if err := h(c); err != nil { t.Fatalf("handler error: %v", err) } @@ -95,9 +98,9 @@ func runAuditedAuthorize(t *testing.T, pdp authz.PDP, failMode authz.FailMode) * e := echo.New() c := e.NewContext(httptest.NewRequest(http.MethodPost, "/evidence", http.NoBody), httptest.NewRecorder()) pep := NewPEP(pdp, failMode, zap.New(core).Sugar()) - h := pep.Authorize(authz.ResourceEvidence, authz.ActionCreate)(func(c echo.Context) error { return c.NoContent(http.StatusOK) }) + h := pep.Authorize(authz.ResourceEvidence, authz.ActionCreate)(func(c *echo.Context) error { return c.NoContent(http.StatusOK) }) if err := h(c); err != nil { - e.HTTPErrorHandler(err, c) + e.HTTPErrorHandler(c, err) } return logs } diff --git a/internal/api/middleware/authorize_test.go b/internal/api/middleware/authorize_test.go index 1e502c75..87080796 100644 --- a/internal/api/middleware/authorize_test.go +++ b/internal/api/middleware/authorize_test.go @@ -8,7 +8,7 @@ import ( "github.com/compliance-framework/api/internal/authn" "github.com/compliance-framework/api/internal/authz" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) // fakePDP returns a programmed decision/error and records the last subject it saw. @@ -35,7 +35,7 @@ func (f *fakePDP) Evaluations(_ context.Context, reqs []authz.EvalRequest) ([]au return out, f.err } -func runAuthorize(t *testing.T, pdp authz.PDP, failMode authz.FailMode, setup func(c echo.Context)) (int, bool) { +func runAuthorize(t *testing.T, pdp authz.PDP, failMode authz.FailMode, setup func(c *echo.Context)) (int, bool) { t.Helper() e := echo.New() req := httptest.NewRequest(http.MethodPost, "/evidence", http.NoBody) @@ -46,7 +46,7 @@ func runAuthorize(t *testing.T, pdp authz.PDP, failMode authz.FailMode, setup fu } called := false - next := func(c echo.Context) error { + next := func(c *echo.Context) error { called = true return c.NoContent(http.StatusOK) } @@ -54,7 +54,7 @@ func runAuthorize(t *testing.T, pdp authz.PDP, failMode authz.FailMode, setup fu pep := NewPEP(pdp, failMode, nil) h := pep.Authorize(authz.ResourceEvidence, authz.ActionCreate)(next) if err := h(c); err != nil { - e.HTTPErrorHandler(err, c) + e.HTTPErrorHandler(c, err) } return rec.Code, called } @@ -112,7 +112,7 @@ func TestPEPInternalErrorIs500(t *testing.T) { func TestPEPBuildsSubjectFromContext(t *testing.T) { t.Run("user", func(t *testing.T) { pdp := &fakePDP{decision: authz.Decision{Allow: true}} - runAuthorize(t, pdp, authz.FailClosed, func(c echo.Context) { + runAuthorize(t, pdp, authz.FailClosed, func(c *echo.Context) { c.Set("user", &authn.UserClaims{GivenName: "Al", FamilyName: "Ice"}) }) if pdp.lastSub.Type != "user" { @@ -122,7 +122,7 @@ func TestPEPBuildsSubjectFromContext(t *testing.T) { t.Run("agent", func(t *testing.T) { pdp := &fakePDP{decision: authz.Decision{Allow: true}} - runAuthorize(t, pdp, authz.FailClosed, func(c echo.Context) { + runAuthorize(t, pdp, authz.FailClosed, func(c *echo.Context) { c.Set("agent_claims", &authn.AgentClaims{AgentID: "agent-7"}) }) if pdp.lastSub.Type != "agent" { diff --git a/internal/api/middleware/evidence_auth.go b/internal/api/middleware/evidence_auth.go index 499bc940..272d3560 100644 --- a/internal/api/middleware/evidence_auth.go +++ b/internal/api/middleware/evidence_auth.go @@ -5,7 +5,7 @@ import ( "net/http" "github.com/compliance-framework/api/internal/authn" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" "gorm.io/gorm" ) @@ -13,7 +13,7 @@ import ( // or unauthenticated public requests when allowPublic is true. func OptionalUserOrAgentJWTMiddleware(db *gorm.DB, publicKey *rsa.PublicKey, allowPublic bool) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { + return func(c *echo.Context) error { if c.Request().Method == http.MethodOptions { return next(c) } @@ -21,7 +21,7 @@ func OptionalUserOrAgentJWTMiddleware(db *gorm.DB, publicKey *rsa.PublicKey, all if authHeader := c.Request().Header.Get(echo.HeaderAuthorization); authHeader != "" { tokenString, err := getTokenFromHeader(authHeader) if err != nil { - return echo.NewHTTPError(http.StatusUnauthorized, err) + return echo.NewHTTPError(http.StatusUnauthorized, err.Error()) } if claims, err := authn.VerifyJWTToken(tokenString, publicKey); err == nil { diff --git a/internal/api/server.go b/internal/api/server.go index 2ec08ec1..2974673e 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -3,17 +3,20 @@ package api import ( "cmp" "context" + "os" + "os/signal" "slices" + "syscall" "github.com/compliance-framework/api/internal/api/binders" mw "github.com/compliance-framework/api/internal/api/middleware" "github.com/compliance-framework/api/internal/config" _ "github.com/compliance-framework/api/docs" - "github.com/labstack/echo-contrib/echoprometheus" - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" - echoSwagger "github.com/swaggo/echo-swagger" + "github.com/labstack/echo-contrib/v5/echoprometheus" + "github.com/labstack/echo/v5" + "github.com/labstack/echo/v5/middleware" + echoSwagger "github.com/swaggo/echo-swagger/v2" "go.uber.org/zap" ) @@ -32,7 +35,6 @@ const LineageGeneratedAtHeader = "X-Lineage-Generated-At" func NewServer(ctx context.Context, s *zap.SugaredLogger, config *config.Config, metrics *PrometheusMetrics) *Server { e := echo.New() e.Binder = &binders.CustomBinder{} - e.HideBanner = true e.Pre(middleware.RemoveTrailingSlash()) e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ LogURI: true, @@ -40,7 +42,7 @@ func NewServer(ctx context.Context, s *zap.SugaredLogger, config *config.Config, LogMethod: true, LogUserAgent: true, LogLatency: true, - LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error { + LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error { s.Debugw("request", zap.String("method", v.Method), zap.String("uri", v.URI), @@ -54,11 +56,18 @@ func NewServer(ctx context.Context, s *zap.SugaredLogger, config *config.Config, })) // A handler panic becomes a 500 (logged above) instead of a dropped connection. e.Use(middleware.Recover()) + allowOrigins := config.APIAllowedOrigins + if len(allowOrigins) == 0 { + // Any origin, as echo v4 defaulted to. Loaded configs always set at least one. + allowOrigins = []string{"*"} + } e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - AllowOrigins: config.APIAllowedOrigins, - AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAuthorization, "If-Match", "If-None-Match"}, - ExposeHeaders: []string{"ETag", LineageGeneratedAtHeader}, - AllowCredentials: true, + AllowOrigins: allowOrigins, + AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAuthorization, "If-Match", "If-None-Match"}, + ExposeHeaders: []string{"ETag", LineageGeneratedAtHeader}, + // Echo refuses "*" with credentials (browsers reject that pair anyway), so a + // wildcard allows every origin without them instead of failing at startup. + AllowCredentials: !slices.Contains(allowOrigins, "*"), })) e.Use(echoprometheus.NewMiddlewareWithConfig(echoprometheus.MiddlewareConfig{ Registerer: metrics.Registry(), @@ -74,30 +83,23 @@ func NewServer(ctx context.Context, s *zap.SugaredLogger, config *config.Config, } } -// Start starts the echo server +// Start serves until SIGINT/SIGTERM, then shuts the server down gracefully. func (s *Server) Start(address string) error { - return s.echo.Start(address) + ctx, stop := signal.NotifyContext(s.ctx, os.Interrupt, syscall.SIGTERM) + defer stop() + return echo.StartConfig{Address: address, HideBanner: true}.Start(ctx, s.echo) } func (s *Server) E() *echo.Echo { return s.echo } -func (s *Server) Stop() error { - err := s.echo.Shutdown(s.ctx) - if err != nil { - return err - } - - return nil -} - func (s *Server) API() *echo.Group { return s.echo.Group("/api") } func (s *Server) PrintRoutes() { - for _, route := range slices.SortedFunc(slices.Values(s.echo.Routes()), func(a, b *echo.Route) int { + for _, route := range slices.SortedFunc(slices.Values(s.echo.Router().Routes()), func(a, b echo.RouteInfo) int { return cmp.Compare(a.Path, b.Path) }) { s.sugar.Infof("%s %s", route.Method, route.Path) diff --git a/internal/service/pagination.go b/internal/service/pagination.go index 03455c07..8c5fa63b 100644 --- a/internal/service/pagination.go +++ b/internal/service/pagination.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/labstack/echo/v4" + "github.com/labstack/echo/v5" ) // PaginationConfig holds configuration for pagination behavior @@ -29,7 +29,7 @@ type PaginationParams struct { } // ParseParams extracts and validates pagination parameters from echo context -func (cfg *PaginationConfig) ParseParams(ctx echo.Context) (*PaginationParams, error) { +func (cfg *PaginationConfig) ParseParams(ctx *echo.Context) (*PaginationParams, error) { page := 1 limit := cfg.DefaultLimit diff --git a/sdk/integration_base_test.go b/sdk/integration_base_test.go index 256b7a11..fd5f8065 100644 --- a/sdk/integration_base_test.go +++ b/sdk/integration_base_test.go @@ -5,9 +5,8 @@ package sdk_test import ( "context" "fmt" - "net" "net/http" - "strings" + "net/http/httptest" "time" "github.com/compliance-framework/api/internal/api" @@ -22,7 +21,6 @@ import ( "github.com/compliance-framework/api/sdk" "github.com/google/uuid" - "github.com/labstack/echo/v4" "github.com/stretchr/testify/suite" "github.com/testcontainers/testcontainers-go" postgresContainers "github.com/testcontainers/testcontainers-go/modules/postgres" @@ -40,11 +38,13 @@ type IntegrationBaseTestSuite struct { Config *config.Config Server *api.Server + // httpServer serves Server's routes on a free local port. + httpServer *httptest.Server } func (suite *IntegrationBaseTestSuite) GetSDKTestClient() *sdk.Client { config := &sdk.Config{ - BaseURL: "http://" + suite.Server.E().ListenerAddr().String(), + BaseURL: suite.httpServer.URL, } return sdk.NewClient(http.DefaultClient, config) } @@ -77,7 +77,7 @@ func (suite *IntegrationBaseTestSuite) GetAuthenticatedSDKTestClientWithLogger(l } return sdk.NewClient(http.DefaultClient, &sdk.Config{ - BaseURL: "http://" + suite.Server.E().ListenerAddr().String(), + BaseURL: suite.httpServer.URL, Logger: logger, AgentAuth: &sdk.AgentAuthConfig{ ClientID: key.ClientID, @@ -160,14 +160,7 @@ func (suite *IntegrationBaseTestSuite) SetupSuite() { suite.Server = server - errChan := make(chan error) - go func() { - err := suite.Server.E().Start("localhost:") - if err != nil { - errChan <- err - } - }() - err = waitForServerStart(suite.Server.E(), errChan, false) + suite.httpServer = httptest.NewServer(suite.Server.E()) } // syncEvidenceBatchQueue processes each evidence batch chunk as soon as it is enqueued, @@ -192,6 +185,7 @@ func (q *syncEvidenceBatchQueue) EnqueueEvidenceBatchChunks(ctx context.Context, } func (suite *IntegrationBaseTestSuite) TearDownSuite() { + suite.httpServer.Close() err := testcontainers.TerminateContainer(suite.dbcontainer) if err != nil { suite.T().Fatal(err) @@ -207,33 +201,3 @@ func (suite *IntegrationBaseTestSuite) GetAuthToken() (*string, error) { return authn.GenerateJWTToken(&dummyUser, suite.Config.JWTPrivateKey) } - -func waitForServerStart(e *echo.Echo, errChan <-chan error, isTLS bool) error { - ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond) - defer cancel() - - ticker := time.NewTicker(5 * time.Millisecond) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return ctx.Err() - case <-ticker.C: - var addr net.Addr - if isTLS { - addr = e.TLSListenerAddr() - } else { - addr = e.ListenerAddr() - } - if addr != nil && strings.Contains(addr.String(), ":") { - return nil // was started - } - case err := <-errChan: - if err == http.ErrServerClosed { - return nil - } - return err - } - } -}