Skip to content

Commit

Permalink
lots of dedup, unify 4 endpoints into electionList
Browse files Browse the repository at this point in the history
  • Loading branch information
altergui committed Jun 20, 2024
1 parent 18080df commit 5ef60c1
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 145 deletions.
65 changes: 10 additions & 55 deletions api/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,63 +358,18 @@ func (a *API) electionListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContex
return ErrCantParseOrgID.Withf("%q", ctx.URLParam("organizationID"))
}

page := 0
if ctx.URLParam("page") != "" {
page, err = strconv.Atoi(ctx.URLParam("page"))
if err != nil {
return ErrCantParsePageNumber
}
}
page = page * MaxPageSize

var pids [][]byte
switch ctx.URLParam("status") {
case "ready":
pids, _, err = a.indexer.ProcessList(organizationID, page, MaxPageSize, "", 0, 0, "READY", false)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
}
case "paused":
pids, _, err = a.indexer.ProcessList(organizationID, page, MaxPageSize, "", 0, 0, "PAUSED", false)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
}
case "canceled":
pids, _, err = a.indexer.ProcessList(organizationID, page, MaxPageSize, "", 0, 0, "CANCELED", false)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
}
case "ended", "results":
pids, _, err = a.indexer.ProcessList(organizationID, page, MaxPageSize, "", 0, 0, "RESULTS", false)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
}
pids2, _, err := a.indexer.ProcessList(organizationID, page, MaxPageSize, "", 0, 0, "ENDED", false)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
}
pids = append(pids, pids2...)
case "":
pids, _, err = a.indexer.ProcessList(organizationID, page, MaxPageSize, "", 0, 0, "", false)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
}
default:
return ErrParamStatusMissing
list, err := a.electionList(
ctx.URLParam(ParamPage),
ctx.URLParam(ParamStatus),
organizationID,
"",
false,
)
if err != nil {
return err
}

elections := []*ElectionSummary{}
for _, pid := range pids {
procInfo, err := a.indexer.ProcessInfo(pid)
if err != nil {
return ErrCantFetchElection.WithErr(err)
}
summary := a.electionSummary(procInfo)
elections = append(elections, &summary)
}
data, err := json.Marshal(&Organization{
Elections: elections,
})
data, err := json.Marshal(list)
if err != nil {
return ErrMarshalingServerJSONFailed.WithErr(err)
}
Expand Down
3 changes: 2 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ const (
MaxPageSize = 10

// These consts define the keywords for both query (?param=) and url (/url/param/) params
ParamPage = "page"
ParamPage = "page"
ParamStatus = "status"
)

var (
Expand Down
137 changes: 76 additions & 61 deletions api/elections.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"go.vocdoni.io/dvote/httprouter/apirest"
"go.vocdoni.io/dvote/log"
"go.vocdoni.io/dvote/statedb"
"go.vocdoni.io/dvote/types"
"go.vocdoni.io/dvote/util"
"go.vocdoni.io/dvote/vochain/indexer"
"go.vocdoni.io/dvote/vochain/processid"
Expand Down Expand Up @@ -144,15 +145,22 @@ func (a *API) enableElectionHandlers() error {
// @Success 200 {object} ElectionsList
// @Router /elections/page/{page} [get]
func (a *API) electionFullListLegacyHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
page := 0
if p := ctx.URLParam(ParamPage); p != "" {
var err error
page, err = strconv.Atoi(p)
if err != nil {
return ErrCantParsePageNumber.With(p)
}
list, err := a.electionList(
ctx.URLParam(ParamPage),
"",
nil,
"",
false,
)
if err != nil {
return err
}
return a.electionFullList(ctx, page)

data, err := json.Marshal(list)
if err != nil {
return ErrMarshalingServerJSONFailed.WithErr(err)
}
return ctx.Send(data, apirest.HTTPstatusOK)
}

// electionFullListHandler
Expand All @@ -166,34 +174,17 @@ func (a *API) electionFullListLegacyHandler(_ *apirest.APIdata, ctx *httprouter.
// @Success 200 {object} ElectionsList
// @Router /elections [get]
func (a *API) electionFullListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
page := 0
if p := ctx.QueryParam(ParamPage); p != "" {
var err error
page, err = strconv.Atoi(p)
if err != nil {
return ErrCantParsePageNumber.With(p)
}
}
return a.electionFullList(ctx, page)
}

// electionFullList sends a marshalled ElectionsList over ctx.Send
func (a *API) electionFullList(ctx *httprouter.HTTPContext, page int) error {
elections, total, err := a.indexer.ProcessList(nil, page*MaxPageSize, MaxPageSize, "", 0, 0, "", false)
list, err := a.electionList(
ctx.QueryParam(ParamPage),
"",
nil,
"",
false,
)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
return err
}

list := ElectionsList{
Total: total,
}
for _, eid := range elections {
e, err := a.indexer.ProcessInfo(eid)
if err != nil {
return ErrCantFetchElection.Withf("(%x): %v", eid, err)
}
list.Elections = append(list.Elections, a.electionSummary(e))
}
data, err := json.Marshal(list)
if err != nil {
return ErrMarshalingServerJSONFailed.WithErr(err)
Expand Down Expand Up @@ -667,52 +658,76 @@ func (a *API) electionFilterPaginatedHandler(msg *apirest.APIdata, ctx *httprout
if body.OrganizationID == nil && body.ElectionID == nil && body.Status == "" && body.WithResults == nil {
return ErrMissingParameter
}
// get page
var err error
page := 0
if ctx.URLParam("page") != "" {
page, err = strconv.Atoi(ctx.URLParam("page"))
if err != nil {
return ErrCantParsePageNumber.WithErr(err)
}
}
page = page * MaxPageSize

if body.WithResults == nil {
withResults := false
body.WithResults = &withResults
}
// TODO: use returned total
elections, _, err := a.indexer.ProcessList(

list, err := a.electionList(
ctx.URLParam(ParamPage),
body.Status,
body.OrganizationID,
page,
MaxPageSize,
body.ElectionID.String(),
*body.WithResults,
)
if err != nil {
return err
}

data, err := json.Marshal(list)
if err != nil {
return ErrMarshalingServerJSONFailed.WithErr(err)
}
return ctx.Send(data, apirest.HTTPstatusOK)
}

// electionList queries the indexer and returns a filtered, paginated ElectionsList
//
// Errors returned are always of type APIerror.
// TODO: turn this long list of args into a struct.
func (a *API) electionList(pageStr, statusStr string,
orgID types.HexBytes, searchTerm string,
withResults bool,
) (*ElectionsList, error) {
page, err := parseNumber(pageStr)
if err != nil {
return nil, err
}

status, err := parseStatus(statusStr)
if err != nil {
return nil, err
}

eids, total, err := a.indexer.ProcessList(
orgID,
page*MaxPageSize,
MaxPageSize,
searchTerm,
0,
0,
body.Status,
*body.WithResults,
status,
withResults,
)
if err != nil {
return ErrCantFetchElectionList.WithErr(err)
return nil, ErrCantFetchElectionList.WithErr(err)
}
if len(elections) == 0 {
return ErrElectionNotFound
if len(eids) == 0 {
return nil, ErrElectionNotFound
}

var list ElectionsList
// get election summary
for _, eid := range elections {
list := &ElectionsList{
Total: total,
}
for _, eid := range eids {
e, err := a.indexer.ProcessInfo(eid)
if err != nil {
return ErrCantFetchElection.WithErr(err)
return nil, ErrCantFetchElection.Withf("(%x): %v", eid, err)
}
list.Elections = append(list.Elections, a.electionSummary(e))
}
data, err := json.Marshal(list)
if err != nil {
return ErrMarshalingServerJSONFailed.WithErr(err)
}
return ctx.Send(data, apirest.HTTPstatusOK)
return list, nil
}

// buildElectionIDHandler
Expand Down
2 changes: 1 addition & 1 deletion api/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ var (
ErrCensusTypeMismatch = apirest.APIerror{Code: 4028, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("census type mismatch")}
ErrCensusIndexedFlagMismatch = apirest.APIerror{Code: 4029, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("census indexed flag mismatch")}
ErrCensusRootHashMismatch = apirest.APIerror{Code: 4030, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("census root hash mismatch after importing dump")}
ErrParamStatusMissing = apirest.APIerror{Code: 4031, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("parameter (status) missing or invalid")}
ErrParamStatusInvalid = apirest.APIerror{Code: 4031, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("parameter (status) invalid")}
ErrParamParticipantsMissing = apirest.APIerror{Code: 4032, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("parameter (participants) missing")}
ErrParamParticipantsTooBig = apirest.APIerror{Code: 4033, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("parameter (participants) exceeds max length per call")}
ErrParamDumpOrRootMissing = apirest.APIerror{Code: 4034, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("parameter (dump or root) missing")}
Expand Down
32 changes: 32 additions & 0 deletions api/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"errors"
"fmt"
"math/big"
"strconv"
"strings"

cometpool "github.com/cometbft/cometbft/mempool"
cometcoretypes "github.com/cometbft/cometbft/rpc/core/types"
Expand Down Expand Up @@ -162,3 +164,33 @@ func decryptVotePackage(vp []byte, privKeys []string, indexes []uint32) ([]byte,
}
return vp, nil
}

// parseNumber returns the int parsed from the string.
// If the string is not parseable, returns an APIerror.
//
// The empty string "" is treated specially, returns 0 with no error.
func parseNumber(s string) (int, error) {
if s == "" {
return 0, nil
}
page, err := strconv.Atoi(s)
if err != nil {
return 0, ErrCantParsePageNumber.With(s)
}
return page, nil
}

// parseStatus converts a string ("READY", "ready", "PAUSED", etc) to a models.ProcessStatus.
// If the string doesn't map to a value, returns an APIerror.
//
// The empty string "" is treated specially, returns 0 with no error.
func parseStatus(s string) (models.ProcessStatus, error) {
if s == "" {
return 0, nil
}
status, found := models.ProcessStatus_value[strings.ToUpper(s)]
if !found {
return 0, ErrParamStatusInvalid.With(s)
}
return models.ProcessStatus(status), nil
}
3 changes: 2 additions & 1 deletion test/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ func TestAPIAccountsList(t *testing.T) {
qt.Assert(t, el["0"], qt.DeepEquals, el["p0"])
qt.Assert(t, el["1"], qt.DeepEquals, el["p1"])

qt.Assert(t, el["0"].Total, qt.Equals, uint64(1+20))
// 2 accounts pre-exist: server.Start creates a random account, and InitChain a faucet account
qt.Assert(t, el["0"].Total, qt.Equals, uint64(2+20))
qt.Assert(t, el["1"].Total, qt.Equals, el["0"].Total)
qt.Assert(t, el["p0"].Total, qt.Equals, el["0"].Total)
qt.Assert(t, el["p1"].Total, qt.Equals, el["0"].Total)
Expand Down
Loading

0 comments on commit 5ef60c1

Please sign in to comment.