Dirty implementation of createVotes

This commit is contained in:
2025-01-08 13:57:49 +01:00
parent ca824726b4
commit 49a1df06d2
7 changed files with 223 additions and 17 deletions

View File

@ -9,6 +9,7 @@ import (
"fmt"
"math/rand"
"net/http"
"slices"
"time"
)
@ -140,22 +141,95 @@ func (app *application) createVotes(w http.ResponseWriter, r *http.Request) {
app.serverError(w, r, err)
}
// TODO check if he has voted
//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"))
for _, c := range request.Choices {
choiceExists := slices.Contains(election.Choices, c.ChoiceText)
if !choiceExists {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("choice %v doesn't exist", c.ChoiceText))
return
}
//voterIdentity = *request.VoterIdentity
} else {
// TODO: get requester's IP address as identity
}
// TODO verify if choice exists
// TODO count tokens to make sure user isn't trying to cheat
tokensUsed := 0
for _, c := range request.Choices {
tokensUsed += c.Tokens
}
json, _ := json.Marshal(election)
w.Write(json)
if tokensUsed > election.Tokens {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("you used too many tokens; must not exceed %v tokens", election.Tokens))
return
}
electionHasExpired := election.ExpiresAt.Before(time.Now())
if electionHasExpired {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("election has expired"))
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 ""
}
} 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)
return
}
// if voters are known, voterCount == election.MaxVoters in all cases
if voterCount == election.MaxVoters {
app.unprocessableEntityErrorSingle(w, fmt.Errorf("maximum voters reached"))
return
}
}
for _, c := range request.Choices {
_, err := app.votes.Insert(voterIdentity, election.ID, c.ChoiceText, c.Tokens)
if err != nil {
app.serverError(w, r, err)
}
}
w.WriteHeader(http.StatusCreated)
}