|
|
|
@ -53,6 +53,7 @@ const (
|
|
|
|
|
ctxVoter
|
|
|
|
|
ctxDecision
|
|
|
|
|
ctxVote
|
|
|
|
|
ctxAuthenticatedCert
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func authenticateRequest(w http.ResponseWriter, r *http.Request, handler func(http.ResponseWriter, *http.Request)) {
|
|
|
|
@ -66,7 +67,9 @@ func authenticateRequest(w http.ResponseWriter, r *http.Request, handler func(ht
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if voter != nil {
|
|
|
|
|
handler(w, r.WithContext(context.WithValue(r.Context(), ctxVoter, voter)))
|
|
|
|
|
requestContext := context.WithValue(r.Context(), ctxVoter, voter)
|
|
|
|
|
requestContext = context.WithValue(requestContext, ctxAuthenticatedCert, cert)
|
|
|
|
|
handler(w, r.WithContext(requestContext))
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -475,12 +478,12 @@ func (h motionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type voteHandler struct {
|
|
|
|
|
type directVoteHandler struct {
|
|
|
|
|
FlashMessageAction
|
|
|
|
|
authenticationRequiredHandler
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (h *voteHandler) Handle(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
func (h *directVoteHandler) Handle(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
decision, ok := getDecisionFromRequest(r)
|
|
|
|
|
if !ok {
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
@ -496,10 +499,37 @@ func (h *voteHandler) Handle(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintln(w, "to be implemented")
|
|
|
|
|
fmt.Fprintln(w, "Decision:", decision)
|
|
|
|
|
fmt.Fprintln(w, "Voter:", voter)
|
|
|
|
|
fmt.Fprintln(w, "Vote:", vote)
|
|
|
|
|
switch r.Method {
|
|
|
|
|
case http.MethodPost:
|
|
|
|
|
voteResult := &Vote{
|
|
|
|
|
VoterId: voter.Id, Vote: vote, DecisionId: decision.Id, Voted: time.Now().UTC(),
|
|
|
|
|
Notes: fmt.Sprintf("Direct Vote\n\n%s", getPEMClientCert(r))}
|
|
|
|
|
if err := voteResult.Save(); err != nil {
|
|
|
|
|
logger.Println("ERROR", "Problem saving vote:", err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NotifyMailChannel <- NewNotificationDirectVote(&decision.Decision, voter, voteResult)
|
|
|
|
|
|
|
|
|
|
if err := h.AddFlash(w, r, "Your vote has been registered."); err != nil {
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
http.Redirect(w, r, "/motions/", http.StatusMovedPermanently)
|
|
|
|
|
default:
|
|
|
|
|
templates := []string{"direct_vote_form.html", "header.html", "footer.html", "motion_fragments.html"}
|
|
|
|
|
var templateContext struct {
|
|
|
|
|
Decision *DecisionForDisplay
|
|
|
|
|
VoteChoice VoteChoice
|
|
|
|
|
PageTitle string
|
|
|
|
|
Flashes interface{}
|
|
|
|
|
}
|
|
|
|
|
templateContext.Decision = decision
|
|
|
|
|
templateContext.VoteChoice = vote
|
|
|
|
|
renderTemplate(w, templates, templateContext)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type proxyVoteHandler struct {
|
|
|
|
@ -509,7 +539,8 @@ type proxyVoteHandler struct {
|
|
|
|
|
|
|
|
|
|
func getPEMClientCert(r *http.Request) string {
|
|
|
|
|
clientCertPEM := bytes.NewBufferString("")
|
|
|
|
|
pem.Encode(clientCertPEM, &pem.Block{Type: "CERTIFICATE", Bytes: r.TLS.PeerCertificates[0].Raw})
|
|
|
|
|
authenticatedCertificate := r.Context().Value(ctxAuthenticatedCert).(*x509.Certificate)
|
|
|
|
|
pem.Encode(clientCertPEM, &pem.Block{Type: "CERTIFICATE", Bytes: authenticatedCertificate.Raw})
|
|
|
|
|
return clientCertPEM.String()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -604,13 +635,17 @@ func (h *decisionVoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
|
|
|
|
|
})
|
|
|
|
|
case strings.HasPrefix(r.URL.Path, "/vote/"):
|
|
|
|
|
parts := strings.Split(r.URL.Path[len("/vote/"):], "/")
|
|
|
|
|
if len(parts) != 2 {
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
motionTag := parts[0]
|
|
|
|
|
voteValue, ok := VoteValues[parts[1]]
|
|
|
|
|
if !ok {
|
|
|
|
|
http.NotFound(w, r)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
handler := &voteHandler{}
|
|
|
|
|
handler := &directVoteHandler{}
|
|
|
|
|
authenticateRequest(
|
|
|
|
|
w, r.WithContext(context.WithValue(r.Context(), ctxNeedsAuth, true)),
|
|
|
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|