Refactor createVotes in two different functions (only for the part that was nested in ifs)

This commit is contained in:
2025-01-10 10:31:59 +01:00
parent 0b0ecaba9b
commit 5927e9c855

View File

@ -2,6 +2,7 @@ package main
import (
api "code.dlmw.ch/dlmw/qv/internal"
"code.dlmw.ch/dlmw/qv/internal/models"
"code.dlmw.ch/dlmw/qv/internal/validator"
"database/sql"
"encoding/json"
@ -165,71 +166,17 @@ func (app *application) createVotes(w http.ResponseWriter, r *http.Request) {
return
}
// this snippet of code also inserts in the `voters` table
voterIdentity := func() string {
var voterIdentity string
if election.AreVotersKnown {
if request.VoterIdentity == nil || validator.Blank(*request.VoterIdentity) {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("election has known voters; you must provide an identity provided by the organizer"))
return ""
}
voterIdentity = *request.VoterIdentity
hasCastVotes, err := app.votes.Exists(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return ""
}
if hasCastVotes {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("you already voted"))
return ""
}
voterExists, err := app.voters.Exists(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return ""
}
if !voterExists {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("invalid voter identity"))
return ""
}
} else {
voterIdentity = r.RemoteAddr
// if voters are known, voter will always exist
voterExists, err := app.voters.Exists(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return ""
}
if voterExists {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("you already voted"))
return ""
}
_, err = app.voters.Insert(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return ""
}
}
return voterIdentity
}()
if voterIdentity == "" {
return
}
if !election.AreVotersKnown {
voterCount, err := app.voters.CountByElection(election.ID)
if err != nil && !errors.Is(sql.ErrNoRows, err) {
app.serverError(w, r, err)
var voterIdentity string
if election.AreVotersKnown {
voterIdentity, err = app.createVotesHandleKnownVotersElection(w, r, request, election)
if err != nil {
// everything will have been logged already
return
}
// if voters are known, voterCount == election.MaxVoters in all cases
if voterCount == election.MaxVoters {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("maximum voters reached"))
} else {
voterIdentity, err = app.createVotesHandleUnknownVotersElection(w, r, election)
if err != nil {
// everything will have been logged already
return
}
}
@ -243,3 +190,70 @@ func (app *application) createVotes(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
}
func (app *application) createVotesHandleKnownVotersElection(w http.ResponseWriter, r *http.Request, request createVotesRequestWithValidator, election *models.Election) (string, error) {
if request.VoterIdentity == nil || validator.Blank(*request.VoterIdentity) {
err := fmt.Errorf("election has known voters; you must provide an identity provided by the organizer")
app.unprocessableEntityErrorSingle(w, err)
return "", err
}
voterIdentity := *request.VoterIdentity
hasCastVotes, err := app.votes.Exists(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return "", err
}
if hasCastVotes {
err := fmt.Errorf("you already voted")
app.unprocessableEntityErrorSingle(w, err)
return "", err
}
voterExists, err := app.voters.Exists(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return "", err
}
if !voterExists {
err := fmt.Errorf("invalid voter identity")
app.unprocessableEntityErrorSingle(w, err)
return "", err
}
return voterIdentity, nil
}
func (app *application) createVotesHandleUnknownVotersElection(w http.ResponseWriter, r *http.Request, election *models.Election) (string, error) {
voterIdentity := r.RemoteAddr
voterExists, err := app.voters.Exists(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return "", err
}
if voterExists {
err := fmt.Errorf("you already voted")
app.unprocessableEntityErrorSingle(w, err)
return "", err
}
_, err = app.voters.Insert(voterIdentity, election.ID)
if err != nil {
app.serverError(w, r, err)
return "", err
}
voterCount, err := app.voters.CountByElection(election.ID)
if err != nil && !errors.Is(sql.ErrNoRows, err) {
app.serverError(w, r, err)
return "", err
}
if voterCount == election.MaxVoters {
err := fmt.Errorf("maximum voters reached")
app.unprocessableEntityErrorSingle(w, err)
return "", err
}
return voterIdentity, nil
}