Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api: endpoint /elections can now filter startDate and endDate #1361

Merged
merged 2 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 13 additions & 18 deletions api/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ func (a *API) accountSetHandler(msg *apirest.APIdata, ctx *httprouter.HTTPContex
//
// @Summary Total number of accounts
// @Description Returns the count of total number of existing accounts
// @Deprecated
// @Description (deprecated, in favor of /accounts which reports totalItems)
// @Tags Accounts
// @Accept json
// @Produce json
Expand Down Expand Up @@ -353,15 +355,9 @@ func (a *API) accountCountHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContex
// @Success 200 {object} ElectionsList
// @Router /accounts/{organizationId}/elections/page/{page} [get]
func (a *API) accountElectionsListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseElectionParams(
ctx.URLParam(ParamPage),
"",
"",
ctx.URLParam(ParamOrganizationId),
"",
"",
"",
"",
params, err := electionParams(ctx.URLParam,
ParamPage,
ParamOrganizationId,
)
if err != nil {
return err
Expand Down Expand Up @@ -389,15 +385,10 @@ func (a *API) accountElectionsListByPageHandler(_ *apirest.APIdata, ctx *httprou
// @Success 200 {object} ElectionsList
// @Router /accounts/{organizationId}/elections/status/{status}/page/{page} [get]
func (a *API) accountElectionsListByStatusAndPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseElectionParams(
ctx.URLParam(ParamPage),
"",
ctx.URLParam(ParamStatus),
ctx.URLParam(ParamOrganizationId),
"",
"",
"",
"",
params, err := electionParams(ctx.URLParam,
ParamPage,
ParamStatus,
ParamOrganizationId,
)
if err != nil {
return err
Expand All @@ -414,6 +405,8 @@ func (a *API) accountElectionsListByStatusAndPageHandler(_ *apirest.APIdata, ctx
//
// @Summary Count organization elections
// @Description Returns the number of elections for an organization
// @Deprecated
// @Description (deprecated, in favor of /elections?organizationId=xxx which reports totalItems)
// @Tags Accounts
// @Accept json
// @Produce json
Expand Down Expand Up @@ -504,6 +497,8 @@ func (a *API) tokenFeesHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext)
//
// @Summary Total number of sent and received transactions
// @Description Returns the count of total number of sent and received transactions for an account. A transaction is a token transfer from one account to another existing account
// @Deprecated
// @Description (deprecated, in favor of /chain/transfers?accountId=xxx which reports totalItems)
// @Tags Accounts
// @Accept json
// @Produce json
Expand Down
36 changes: 20 additions & 16 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,26 @@ const (
//
//nolint:revive
const (
ParamAccountId = "accountId"
ParamCensusId = "censusId"
ParamElectionId = "electionId"
ParamOrganizationId = "organizationId"
ParamVoteId = "voteId"
ParamPage = "page"
ParamLimit = "limit"
ParamStatus = "status"
ParamWithResults = "withResults"
ParamFinalResults = "finalResults"
ParamManuallyEnded = "manuallyEnded"
ParamHeight = "height"
ParamReference = "reference"
ParamType = "type"
ParamAccountIdFrom = "accountIdFrom"
ParamAccountIdTo = "accountIdTo"
ParamAccountId = "accountId"
ParamCensusId = "censusId"
ParamElectionId = "electionId"
ParamOrganizationId = "organizationId"
ParamVoteId = "voteId"
ParamPage = "page"
ParamLimit = "limit"
ParamStatus = "status"
ParamWithResults = "withResults"
ParamFinalResults = "finalResults"
ParamManuallyEnded = "manuallyEnded"
ParamHeight = "height"
ParamReference = "reference"
ParamType = "type"
ParamAccountIdFrom = "accountIdFrom"
ParamAccountIdTo = "accountIdTo"
ParamStartDateAfter = "startDateAfter"
ParamStartDateBefore = "startDateBefore"
ParamEndDateAfter = "endDateAfter"
ParamEndDateBefore = "endDateBefore"
)

var (
Expand Down
16 changes: 10 additions & 6 deletions api/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ type PaginationParams struct {
// ElectionParams allows the client to filter elections
type ElectionParams struct {
PaginationParams
OrganizationID string `json:"organizationId,omitempty"`
ElectionID string `json:"electionId,omitempty"`
Status string `json:"status,omitempty"`
WithResults *bool `json:"withResults,omitempty"`
FinalResults *bool `json:"finalResults,omitempty"`
ManuallyEnded *bool `json:"manuallyEnded,omitempty"`
OrganizationID string `json:"organizationId,omitempty"`
ElectionID string `json:"electionId,omitempty"`
Status string `json:"status,omitempty"`
WithResults *bool `json:"withResults,omitempty"`
FinalResults *bool `json:"finalResults,omitempty"`
ManuallyEnded *bool `json:"manuallyEnded,omitempty"`
StartDateAfter *time.Time `json:"startDateAfter,omitempty"`
StartDateBefore *time.Time `json:"startDateBefore,omitempty"`
EndDateAfter *time.Time `json:"endDateAfter,omitempty"`
EndDateBefore *time.Time `json:"endDateBefore,omitempty"`
}

// OrganizationParams allows the client to filter organizations
Expand Down
4 changes: 4 additions & 0 deletions api/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ func (a *API) sendOrganizationList(ctx *httprouter.HTTPContext, params *Organiza
//
// @Summary Count organizations
// @Description Return the number of organizations
// @Deprecated
// @Description (deprecated, in favor of /chain/organizations which reports totalItems)
// @Tags Chain
// @Accept json
// @Produce json
Expand Down Expand Up @@ -928,6 +930,8 @@ func (a *API) chainBlockByHashHandler(_ *apirest.APIdata, ctx *httprouter.HTTPCo
//
// @Summary Transactions count
// @Description Returns the number of transactions
// @Deprecated
// @Description (deprecated, in favor of /chain/transactions which reports totalItems)
// @Tags Chain
// @Accept json
// @Produce json
Expand Down
88 changes: 47 additions & 41 deletions api/elections.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (a *API) enableElectionHandlers() error {
// @Accept json
// @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"
// @Param body body ElectionParams true "Filtered by exact organizationId, partial electionId, election status, results available or not, etc"
// @Success 200 {object} ElectionsList
// @Router /elections/filter/page/{page} [post]
func (a *API) electionListByFilterAndPageHandler(msg *apirest.APIdata, ctx *httprouter.HTTPContext) error {
Expand Down Expand Up @@ -207,15 +207,8 @@ func (a *API) electionListByFilterHandler(msg *apirest.APIdata, ctx *httprouter.
// @Success 200 {object} ElectionsList
// @Router /elections/page/{page} [get]
func (a *API) electionListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseElectionParams(
ctx.URLParam(ParamPage),
"",
"",
"",
"",
"",
"",
"",
params, err := electionParams(ctx.URLParam,
ParamPage,
)
if err != nil {
return err
Expand All @@ -241,15 +234,19 @@ func (a *API) electionListByPageHandler(_ *apirest.APIdata, ctx *httprouter.HTTP
// @Success 200 {object} ElectionsList
// @Router /elections [get]
func (a *API) electionListHandler(_ *apirest.APIdata, ctx *httprouter.HTTPContext) error {
params, err := parseElectionParams(
ctx.QueryParam(ParamPage),
ctx.QueryParam(ParamLimit),
ctx.QueryParam(ParamStatus),
ctx.QueryParam(ParamOrganizationId),
ctx.QueryParam(ParamElectionId),
ctx.QueryParam(ParamWithResults),
ctx.QueryParam(ParamFinalResults),
ctx.QueryParam(ParamManuallyEnded),
params, err := electionParams(ctx.QueryParam,
ParamPage,
ParamLimit,
ParamStatus,
ParamOrganizationId,
ParamElectionId,
ParamWithResults,
ParamFinalResults,
ParamManuallyEnded,
ParamStartDateAfter,
ParamStartDateBefore,
ParamEndDateAfter,
ParamEndDateBefore,
)
if err != nil {
return err
Expand Down Expand Up @@ -282,6 +279,10 @@ func (a *API) sendElectionList(ctx *httprouter.HTTPContext, params *ElectionPara
params.WithResults,
params.FinalResults,
params.ManuallyEnded,
params.StartDateAfter,
params.StartDateBefore,
params.EndDateAfter,
params.EndDateBefore,
)
if err != nil {
return ErrIndexerQueryFailed.WithErr(err)
Expand Down Expand Up @@ -757,38 +758,43 @@ func (a *API) buildElectionIDHandler(msg *apirest.APIdata, ctx *httprouter.HTTPC
return ctx.Send(data, apirest.HTTPstatusOK)
}

// parseElectionParams returns an ElectionParams filled with the passed params
func parseElectionParams(paramPage, paramLimit, paramStatus,
paramOrganizationID, paramElectionID,
paramWithResults, paramFinalResults, paramManuallyEnded string,
) (*ElectionParams, error) {
pagination, err := parsePaginationParams(paramPage, paramLimit)
if err != nil {
return nil, err
}
// electionParams produces an ElectionParams, calling the passed func (ctx.QueryParam or ctx.URLParam)
// to retrieve all the values of all keys passed.
func electionParams(f func(key string) string, keys ...string) (*ElectionParams, error) {
strings := paramsFromCtxFunc(f, keys...)

withResults, err := parseBool(paramWithResults)
pagination, err := parsePaginationParams(strings[ParamPage], strings[ParamLimit])
if err != nil {
return nil, err
}

finalResults, err := parseBool(paramFinalResults)
if err != nil {
return nil, err
bools := make(map[string]*bool)
for _, v := range []string{ParamWithResults, ParamFinalResults, ParamManuallyEnded} {
bools[v], err = parseBool(strings[v])
if err != nil {
return nil, err
}
}

manuallyEnded, err := parseBool(paramManuallyEnded)
if err != nil {
return nil, err
dates := make(map[string]*time.Time)
for _, v := range []string{ParamStartDateAfter, ParamStartDateBefore, ParamEndDateAfter, ParamEndDateBefore} {
dates[v], err = parseDate(strings[v])
if err != nil {
return nil, err
}
}

return &ElectionParams{
PaginationParams: pagination,
OrganizationID: util.TrimHex(paramOrganizationID),
ElectionID: util.TrimHex(paramElectionID),
Status: paramStatus,
WithResults: withResults,
FinalResults: finalResults,
ManuallyEnded: manuallyEnded,
OrganizationID: util.TrimHex(strings[ParamOrganizationId]),
ElectionID: util.TrimHex(strings[ParamElectionId]),
Status: strings[ParamStatus],
WithResults: bools[ParamWithResults],
FinalResults: bools[ParamFinalResults],
ManuallyEnded: bools[ParamManuallyEnded],
StartDateAfter: dates[ParamStartDateAfter],
StartDateBefore: dates[ParamStartDateBefore],
EndDateAfter: dates[ParamEndDateAfter],
EndDateBefore: dates[ParamEndDateBefore],
}, nil
}
1 change: 1 addition & 0 deletions api/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ var (
ErrCantParseBoolean = apirest.APIerror{Code: 4055, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("cannot parse string into boolean")}
ErrCantParseHexString = apirest.APIerror{Code: 4056, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("cannot parse string into hex bytes")}
ErrPageNotFound = apirest.APIerror{Code: 4057, HTTPstatus: apirest.HTTPstatusNotFound, Err: fmt.Errorf("page not found")}
ErrCantParseDate = apirest.APIerror{Code: 4058, HTTPstatus: apirest.HTTPstatusBadRequest, Err: fmt.Errorf("cannot parse date")}
ErrVochainEmptyReply = apirest.APIerror{Code: 5000, HTTPstatus: apirest.HTTPstatusInternalErr, Err: fmt.Errorf("vochain returned an empty reply")}
ErrVochainSendTxFailed = apirest.APIerror{Code: 5001, HTTPstatus: apirest.HTTPstatusInternalErr, Err: fmt.Errorf("vochain SendTx failed")}
ErrVochainGetTxFailed = apirest.APIerror{Code: 5002, HTTPstatus: apirest.HTTPstatusInternalErr, Err: fmt.Errorf("vochain GetTx failed")}
Expand Down
28 changes: 28 additions & 0 deletions api/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"math/big"
"strconv"
"strings"
"time"

cometpool "github.com/cometbft/cometbft/mempool"
cometcoretypes "github.com/cometbft/cometbft/rpc/core/types"
Expand Down Expand Up @@ -275,6 +276,24 @@ func parseBool(s string) (*bool, error) {
return &b, nil
}

// parseDate parses an RFC3339 string into a time.Time value.
// As a convenience, accepts also time.DateOnly format (i.e. 2006-01-02).
//
// The empty string "" is treated specially, returns a nil pointer with no error.
func parseDate(s string) (*time.Time, error) {
if s == "" {
return nil, nil
}
b, err := time.Parse(time.RFC3339, s)
if err != nil {
if b, err := time.Parse(time.DateOnly, s); err == nil {
return &b, nil
}
return nil, ErrCantParseDate.WithErr(err)
}
return &b, nil
}

// parsePaginationParams returns a PaginationParams filled with the passed params
func parsePaginationParams(paramPage, paramLimit string) (PaginationParams, error) {
page, err := parsePage(paramPage)
Expand Down Expand Up @@ -325,3 +344,12 @@ func calculatePagination(page int, limit int, totalItems uint64) (*Pagination, e
LastPage: uint64(lastp),
}, nil
}

// paramsFromCtxFunc calls f(key) for each key passed, and the resulting value is saved in map[key] of the returned map
func paramsFromCtxFunc(f func(key string) string, keys ...string) map[string]string {
m := make(map[string]string)
for _, key := range keys {
m[key] = f(key)
}
return m
}
12 changes: 12 additions & 0 deletions vochain/indexer/db/processes.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading