package main import ( api "code.dlmw.ch/dlmw/qv/internal" "code.dlmw.ch/dlmw/qv/internal/validator" "encoding/json" "math/rand" "net/http" "time" ) type createElectionRequestWithValidator struct { api.CreateElectionRequest validator.Validator } func (app *application) createElection(w http.ResponseWriter, r *http.Request) { var request createElectionRequestWithValidator if err := app.unmarshalRequest(r, &request); err != nil { app.clientError(w, http.StatusBadRequest, err.Error()) return } if !isRequestValid(&request) { app.unprocessableEntityError(w, request.Validator) return } electionId, err := app.elections.Insert( request.Name, request.Tokens, request.AreVotersKnown, request.MaxVoters, request.Choices, request.ExpiresAt, ) if err != nil { app.serverError(w, r, err) return } var res []byte if request.AreVotersKnown { voterIdentities := make([]string, 0, request.MaxVoters) for i := 0; i < request.MaxVoters; i++ { randomIdentity := randomVoterIdentity() _, err := app.voters.Insert(randomIdentity, electionId) if err != nil { app.serverError(w, r, err) } voterIdentities = append(voterIdentities, randomIdentity) } res, err = json.Marshal(api.CreateElectionResponse{VoterIdentities: &voterIdentities}) if err != nil { app.serverError(w, r, err) return } } w.Write(res) } func isRequestValid(r *createElectionRequestWithValidator) bool { r.CheckField(validator.NotBlank(r.Name), "name", "must not be blank") r.CheckField(validator.GreaterThan(r.Tokens, 0), "tokens", "must be greater than 0") r.CheckField(validator.After(r.ExpiresAt, time.Now()), "expiresAt", "must expire in a future date") r.CheckField(validator.GreaterThan(len(r.Choices), 1), "choices", "there must be more than 1 choice") r.CheckField( !(r.AreVotersKnown && r.MaxVoters < 1), "maxVoters", "must be greater than 0 when voters are known", ) return r.Valid() } func randomVoterIdentity() string { const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" b := make([]byte, 16) for i := range b { b[i] = charset[rand.Intn(len(charset))] } return string(b) }