diff --git a/api/accounts.go b/api/accounts.go index 7de92ac00..f0d552b58 100644 --- a/api/accounts.go +++ b/api/accounts.go @@ -367,7 +367,16 @@ func (a *API) accountElectionsListByPageHandler(_ *apirest.APIdata, ctx *httprou return ErrMissingParameter } - return a.sendElectionList(ctx, params) + list, err := a.electionList(params) + if err != nil { + // keep legacy behaviour of sending an empty list rather than a 404 + if errors.Is(err, ErrPageNotFound) { + return marshalAndSend(ctx, emptyElectionsList()) + } + return err + } + + return marshalAndSend(ctx, list) } // accountElectionsListByStatusAndPageHandler @@ -398,7 +407,16 @@ func (a *API) accountElectionsListByStatusAndPageHandler(_ *apirest.APIdata, ctx return ErrMissingParameter } - return a.sendElectionList(ctx, params) + list, err := a.electionList(params) + if err != nil { + // keep legacy behaviour of sending an empty list rather than a 404 + if errors.Is(err, ErrPageNotFound) { + return marshalAndSend(ctx, emptyElectionsList()) + } + return err + } + + return marshalAndSend(ctx, list) } // accountElectionsCountHandler diff --git a/api/elections.go b/api/elections.go index 89b4d7411..f5f8a22e0 100644 --- a/api/elections.go +++ b/api/elections.go @@ -169,7 +169,16 @@ func (a *API) electionListByFilterAndPageHandler(msg *apirest.APIdata, ctx *http return ErrMissingParameter } - return a.sendElectionList(ctx, params) + list, err := a.electionList(params) + if err != nil { + // keep legacy behaviour of sending an empty list rather than a 404 + if errors.Is(err, ErrPageNotFound) { + return marshalAndSend(ctx, emptyElectionsList()) + } + return err + } + + return marshalAndSend(ctx, list) } // electionListByFilterHandler @@ -191,7 +200,16 @@ func (a *API) electionListByFilterHandler(msg *apirest.APIdata, ctx *httprouter. return ErrCantParseDataAsJSON.WithErr(err) } - return a.sendElectionList(ctx, params) + list, err := a.electionList(params) + if err != nil { + // keep legacy behaviour of sending an empty list rather than a 404 + if errors.Is(err, ErrPageNotFound) { + return marshalAndSend(ctx, emptyElectionsList()) + } + return err + } + + return marshalAndSend(ctx, list) } // electionListByPageHandler @@ -213,7 +231,17 @@ func (a *API) electionListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTP if err != nil { return err } - return a.sendElectionList(ctx, params) + + list, err := a.electionList(params) + if err != nil { + // keep legacy behaviour of sending an empty list rather than a 404 + if errors.Is(err, ErrPageNotFound) { + return marshalAndSend(ctx, emptyElectionsList()) + } + return err + } + + return marshalAndSend(ctx, list) } // electionListHandler @@ -251,21 +279,26 @@ func (a *API) electionListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContex if err != nil { return err } - return a.sendElectionList(ctx, params) + + list, err := a.electionList(params) + if err != nil { + return err + } + + return marshalAndSend(ctx, list) } -// sendElectionList produces a filtered, paginated ElectionsList, -// and sends it marshalled over ctx.Send +// electionList produces a filtered, paginated ElectionsList. // // Errors returned are always of type APIerror. -func (a *API) sendElectionList(ctx *httprouter.HTTPContext, params *ElectionParams) error { +func (a *API) electionList(params *ElectionParams) (*ElectionsList, error) { if params.OrganizationID != "" && !a.indexer.EntityExists(params.OrganizationID) { - return ErrOrgNotFound + return nil, ErrOrgNotFound } status, err := parseStatus(params.Status) if err != nil { - return err + return nil, err } eids, total, err := a.indexer.ProcessList( @@ -285,12 +318,12 @@ func (a *API) sendElectionList(ctx *httprouter.HTTPContext, params *ElectionPara params.EndDateBefore, ) if err != nil { - return ErrIndexerQueryFailed.WithErr(err) + return nil, ErrIndexerQueryFailed.WithErr(err) } pagination, err := calculatePagination(params.Page, params.Limit, total) if err != nil { - return err + return nil, err } list := &ElectionsList{ @@ -300,11 +333,11 @@ func (a *API) sendElectionList(ctx *httprouter.HTTPContext, params *ElectionPara for _, eid := range eids { e, err := a.indexer.ProcessInfo(eid) if err != nil { - return ErrCantFetchElection.Withf("(%x): %v", eid, err) + return nil, ErrCantFetchElection.Withf("(%x): %v", eid, err) } list.Elections = append(list.Elections, a.electionSummary(e)) } - return marshalAndSend(ctx, list) + return list, nil } // electionHandler @@ -483,7 +516,16 @@ func (a *API) electionVotesListByPageHandler(_ *apirest.APIdata, ctx *httprouter if err != nil { return err } - return a.sendVotesList(ctx, params) + list, err := a.votesList(params) + if err != nil { + // keep legacy behaviour of sending an empty list rather than a 404 + if errors.Is(err, ErrPageNotFound) { + return marshalAndSend(ctx, emptyVotesList()) + } + return err + } + + return marshalAndSend(ctx, list) } // electionScrutinyHandler diff --git a/api/legacy.go b/api/legacy.go new file mode 100644 index 000000000..436ea1531 --- /dev/null +++ b/api/legacy.go @@ -0,0 +1,61 @@ +package api + +// +// Legacy lists used to return an empty list (instead of null or an error) +// + +func emptyElectionsList() any { + return struct { + List []any `json:"elections"` + }{ + List: []any{}, + } +} + +func emptyOrganizationsList() any { + return struct { + List []any `json:"organizations"` + }{ + List: []any{}, + } +} + +func emptyVotesList() any { + return struct { + List []any `json:"votes"` + }{ + List: []any{}, + } +} + +func emptyTransactionsList() any { + return struct { + List []any `json:"transactions"` + }{ + List: []any{}, + } +} + +func emptyFeesList() any { + return struct { + List []any `json:"fees"` + }{ + List: []any{}, + } +} + +func emptyTransfersList() any { + return struct { + List []any `json:"transfers"` + }{ + List: []any{}, + } +} + +func emptyAccountsList() any { + return struct { + List []any `json:"accounts"` + }{ + List: []any{}, + } +} diff --git a/api/vote.go b/api/vote.go index 33322b103..5fccccd5f 100644 --- a/api/vote.go +++ b/api/vote.go @@ -218,16 +218,22 @@ func (a *API) votesListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) if err != nil { return err } - return a.sendVotesList(ctx, params) + + list, err := a.votesList(params) + if err != nil { + return err + } + + return marshalAndSend(ctx, list) } -// sendVotesList produces a filtered, paginated VotesList, +// votesList produces a filtered, paginated VotesList, // and sends it marshalled over ctx.Send // // Errors returned are always of type APIerror. -func (a *API) sendVotesList(ctx *httprouter.HTTPContext, params *VoteParams) error { +func (a *API) votesList(params *VoteParams) (*VotesList, error) { if params.ElectionID != "" && !a.indexer.ProcessExists(params.ElectionID) { - return ErrElectionNotFound + return nil, ErrElectionNotFound } votes, total, err := a.indexer.VoteList( @@ -237,12 +243,12 @@ func (a *API) sendVotesList(ctx *httprouter.HTTPContext, params *VoteParams) err "", ) if err != nil { - return ErrIndexerQueryFailed.WithErr(err) + return nil, ErrIndexerQueryFailed.WithErr(err) } pagination, err := calculatePagination(params.Page, params.Limit, total) if err != nil { - return err + return nil, err } list := &VotesList{ @@ -259,7 +265,7 @@ func (a *API) sendVotesList(ctx *httprouter.HTTPContext, params *VoteParams) err TransactionIndex: &vote.TxIndex, }) } - return marshalAndSend(ctx, list) + return list, nil } // parseVoteParams returns an VoteParams filled with the passed params