Skip to content

Commit

Permalink
api hotfix: properly handle a mix of POST params and URLParams
Browse files Browse the repository at this point in the history
  • Loading branch information
altergui committed Jul 19, 2024
1 parent 3309566 commit 88d4bef
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 38 deletions.
12 changes: 6 additions & 6 deletions api/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,33 @@ type PaginationParams struct {

// ElectionParams allows the client to filter elections results
type ElectionParams struct {
*PaginationParams
PaginationParams
OrganizationID types.HexBytes `json:"organizationId,omitempty"`
ElectionID types.HexBytes `json:"electionId,omitempty"`
WithResults *bool `json:"withResults,omitempty"`
WithResults bool `json:"withResults,omitempty"`
Status string `json:"status,omitempty"`
}

// OrganizationParams allows the client to filter organizations results
type OrganizationParams struct {
*PaginationParams
PaginationParams
OrganizationID types.HexBytes `json:"organizationId,omitempty"`
}

// AccountParams allows the client to filter accounts results
type AccountParams struct {
*PaginationParams
PaginationParams
}

// TransactionParams allows the client to filter transactions results
type TransactionParams struct {
*PaginationParams
PaginationParams
Height uint64 `json:"height,omitempty"`
}

// VoteParams allows the client to filter votes
type VoteParams struct {
*PaginationParams
PaginationParams
ElectionID types.HexBytes `json:"electionId,omitempty"`
}

Expand Down
18 changes: 9 additions & 9 deletions api/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,21 +288,21 @@ func (a *API) organizationListByPageHandler(_ *apirest.APIdata, ctx *httprouter.
func (a *API) organizationListByFilterAndPageHandler(msg *apirest.APIdata, ctx *httprouter.HTTPContext) error {
// get organizationId from the request params
params := &OrganizationParams{}

// but support legacy URLParam
urlParams, err := parsePaginationParams(ctx.URLParam(ParamPage), "")
if err != nil {
return err
}
params.PaginationParams = urlParams

if err := json.Unmarshal(msg.Data, &params); err != nil {
return ErrCantParseDataAsJSON.WithErr(err)
}
// check that at least one filter is set
if params.OrganizationID == nil {
if params == nil { // happens when client POSTs a literal `null` JSON
return ErrMissingParameter
}

if ctx.URLParam(ParamPage) != "" {
urlParams, err := parsePaginationParams(ctx.URLParam(ParamPage), "")
if err != nil {
return err
}
params.Page = urlParams.Page
}
return a.sendOrganizationList(ctx, params)
}

Expand Down
32 changes: 14 additions & 18 deletions api/elections.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,26 +149,26 @@ func (a *API) enableElectionHandlers() error {
// @Produce json
// @Param page path number true "Page"
// @Param body body ElectionParams true "Filtered by partial organizationId, partial electionId, election status and with results available or not"
// @Success 200 {object} ElectionSummary
// @Success 200 {object} ElectionsList
// @Router /elections/filter/page/{page} [post]
func (a *API) electionListByFilterAndPageHandler(msg *apirest.APIdata, ctx *httprouter.HTTPContext) error {
// get params from the request body
params := &ElectionParams{}

// but support legacy URLParam
urlParams, err := parsePaginationParams(ctx.URLParam(ParamPage), "")
if err != nil {
return err
}
params.PaginationParams = urlParams

if err := json.Unmarshal(msg.Data, &params); err != nil {
return ErrCantParseDataAsJSON.WithErr(err)
}
// check that at least one filter is set
if params.OrganizationID == nil && params.ElectionID == nil && params.Status == "" && params.WithResults == nil {
if params == nil { // happens when client POSTs a literal `null` JSON
return ErrMissingParameter
}

if ctx.URLParam(ParamPage) != "" {
urlParams, err := parsePaginationParams(ctx.URLParam(ParamPage), "")
if err != nil {
return err
}
params.Page = urlParams.Page
}
return a.sendElectionList(ctx, params)
}

Expand All @@ -180,20 +180,16 @@ func (a *API) electionListByFilterAndPageHandler(msg *apirest.APIdata, ctx *http
// @Tags Elections
// @Accept json
// @Produce json
// @Param page path number true "Page"
// @Param page query number false "Page"
// @Param body body ElectionParams true "Filtered by partial organizationId, partial electionId, election status and with results available or not"
// @Success 200 {object} ElectionSummary
// @Success 200 {object} ElectionsList
// @Router /elections/filter [post]
func (a *API) electionListByFilterHandler(msg *apirest.APIdata, ctx *httprouter.HTTPContext) error {
// get params from the request body
params := &ElectionParams{}
if err := json.Unmarshal(msg.Data, &params); err != nil {
return ErrCantParseDataAsJSON.WithErr(err)
}
// check that at least one filter is set
if params.OrganizationID == nil && params.ElectionID == nil && params.Status == "" && params.WithResults == nil {
return ErrMissingParameter
}

return a.sendElectionList(ctx, params)
}
Expand Down Expand Up @@ -273,7 +269,7 @@ func (a *API) sendElectionList(ctx *httprouter.HTTPContext, params *ElectionPara
0,
0,
status,
*params.WithResults,
params.WithResults,
)
if err != nil {
return ErrIndexerQueryFailed.WithErr(err)
Expand Down Expand Up @@ -778,7 +774,7 @@ func parseElectionParams(paramPage, paramLimit, paramStatus,
PaginationParams: pagination,
OrganizationID: organizationID,
ElectionID: electionID,
WithResults: &withResults,
WithResults: withResults,
Status: paramStatus,
}, nil
}
8 changes: 4 additions & 4 deletions api/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,18 +276,18 @@ func parseBool(s string) (bool, error) {
}

// parsePaginationParams returns a PaginationParams filled with the passed params
func parsePaginationParams(paramPage, paramLimit string) (*PaginationParams, error) {
func parsePaginationParams(paramPage, paramLimit string) (PaginationParams, error) {
page, err := parsePage(paramPage)
if err != nil {
return nil, err
return PaginationParams{}, err
}

limit, err := parseLimit(paramLimit)
if err != nil {
return nil, err
return PaginationParams{}, err
}

return &PaginationParams{
return PaginationParams{
Page: page,
Limit: limit,
}, nil
Expand Down
8 changes: 7 additions & 1 deletion test/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ func TestAPIElectionsList(t *testing.T) {
fetchEL := func(method string, jsonBody any, query string, urlPath ...string) api.ElectionsList {
resp, code := c.RequestWithQuery(method, jsonBody, query, urlPath...)
elections := api.ElectionsList{}
qt.Assert(t, code, qt.Equals, 200)
qt.Assert(t, code, qt.Equals, 200, qt.Commentf("resp: %q", resp))
err := json.Unmarshal(resp, &elections)
qt.Assert(t, err, qt.IsNil)
return elections
Expand All @@ -939,6 +939,10 @@ func TestAPIElectionsList(t *testing.T) {
el["p0"] = fetchEL("GET", nil, "", "elections", "page", "0")
el["p1"] = fetchEL("GET", nil, "", "elections", "page", "1")

body := api.ElectionParams{WithResults: false}
el["fp0"] = fetchEL("POST", body, "", "elections", "filter", "page", "0")
el["fp1"] = fetchEL("POST", body, "", "elections", "filter", "page", "1")

qt.Assert(t, el["0"], qt.Not(qt.DeepEquals), el["1"])
qt.Assert(t, el["0"], qt.DeepEquals, el["p0"])
qt.Assert(t, el["1"], qt.DeepEquals, el["p1"])
Expand All @@ -947,6 +951,8 @@ func TestAPIElectionsList(t *testing.T) {
qt.Assert(t, el["1"].Pagination.TotalItems, qt.Equals, el["0"].Pagination.TotalItems)
qt.Assert(t, el["p0"].Pagination.TotalItems, qt.Equals, el["0"].Pagination.TotalItems)
qt.Assert(t, el["p1"].Pagination.TotalItems, qt.Equals, el["0"].Pagination.TotalItems)
qt.Assert(t, el["fp0"].Pagination.TotalItems, qt.Equals, el["0"].Pagination.TotalItems)
qt.Assert(t, el["fp1"].Pagination.TotalItems, qt.Equals, el["0"].Pagination.TotalItems)

for _, item := range el {
qt.Assert(t, len(item.Elections), qt.Equals, api.DefaultItemsPerPage)
Expand Down

0 comments on commit 88d4bef

Please sign in to comment.