138 lines
3.5 KiB
Go
138 lines
3.5 KiB
Go
package http
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"code.c-base.org/baccenfutter/govote/store"
|
|
"code.c-base.org/baccenfutter/govote/utils"
|
|
"code.c-base.org/baccenfutter/govote/voting"
|
|
"code.c-base.org/baccenfutter/govote/voting/quorum"
|
|
"code.c-base.org/baccenfutter/govote/voting/threshold"
|
|
"code.c-base.org/baccenfutter/govote/voting/vote"
|
|
"github.com/google/uuid"
|
|
"github.com/labstack/echo"
|
|
"github.com/labstack/echo/middleware"
|
|
)
|
|
|
|
func Serve(bindAddr string) error {
|
|
e := echo.New()
|
|
e.Pre(middleware.RemoveTrailingSlash())
|
|
// e.Use(middleware.Recover())
|
|
|
|
NewTemplateRenderer(e, "tmpl/*.html")
|
|
|
|
e.Static("/static", "static")
|
|
e.GET("/", handleIndex)
|
|
e.GET("/v", handleVotingForm)
|
|
e.POST("/v", handleNewVoting)
|
|
e.GET("/v/:id", handleShowVoting)
|
|
e.POST("/v/:id", handleVote)
|
|
|
|
return e.Start(bindAddr)
|
|
}
|
|
|
|
func handleIndex(ctx echo.Context) error {
|
|
// return ctx.Redirect(http.StatusTemporaryRedirect, "/v")
|
|
return ctx.String(200, ctx.Request().Header.Get("X-Remote-User"))
|
|
}
|
|
|
|
func handleNewVoting(ctx echo.Context) error {
|
|
id :=utils.GenerateRandomString(11)
|
|
var (
|
|
formReferendum = ctx.FormValue("referendum")
|
|
formDeadline = ctx.FormValue("deadline")
|
|
formQuorum = ctx.FormValue("quorum")
|
|
formThreshold = ctx.FormValue("threshold")
|
|
formElectors = ctx.FormValue("electors")
|
|
formAnonymous = ctx.FormValue("anonymous")
|
|
)
|
|
|
|
var (
|
|
err error
|
|
r string
|
|
d time.Time
|
|
q quorum.Quorum
|
|
t threshold.Threshold
|
|
e = []string{}
|
|
a bool
|
|
)
|
|
|
|
r = formReferendum
|
|
deadlineNum := fmt.Sprintf("%s", formDeadline[:len(formDeadline)-1])
|
|
deadlineUnit := fmt.Sprintf("%s", formDeadline[len(formDeadline)-1:])
|
|
deadlineInt, err := strconv.Atoi(deadlineNum)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
switch deadlineUnit {
|
|
case "m", "":
|
|
d = time.Now().UTC().Add(time.Duration(deadlineInt)*time.Minute).Round(time.Second)
|
|
case "h":
|
|
d = time.Now().UTC().Add(time.Duration(deadlineInt)*time.Hour).Round(time.Second)
|
|
case "d":
|
|
d = time.Now().UTC().Add(time.Duration(deadlineInt)*time.Hour*24).Round(time.Second)
|
|
default:
|
|
panic("this code should never be reached")
|
|
}
|
|
|
|
if q, err = quorum.FromString(formQuorum); err != nil {
|
|
return err
|
|
}
|
|
if t, err = threshold.FromString(formThreshold); err != nil {
|
|
return err
|
|
}
|
|
e = strings.Split(formElectors, " ")
|
|
if formAnonymous == "on" {
|
|
a = true
|
|
}
|
|
|
|
store.NewVoting(id, r, d, q, t, e, a)
|
|
return ctx.Redirect(http.StatusFound, fmt.Sprintf("/v/%s", id))
|
|
}
|
|
|
|
func handleVotingForm(ctx echo.Context) error {
|
|
return ctx.Render(http.StatusOK, "voting_form", nil)
|
|
}
|
|
|
|
func handleVote(ctx echo.Context) error {
|
|
var (
|
|
id = uuid.New().String()
|
|
vid = ctx.Param("id")
|
|
elector = ctx.Request().Header.Get("X-Remote-User")
|
|
choice = ctx.FormValue("vote")
|
|
v *voting.Voting
|
|
c vote.Choice
|
|
err error
|
|
)
|
|
v, err = store.GetVoting(vid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if time.Now().UTC().After(v.Deadline()) {
|
|
return ctx.Redirect(http.StatusFound, fmt.Sprintf("/v/%s", vid))
|
|
}
|
|
if c, err = vote.ChoiceFromString(choice); err != nil {
|
|
return err
|
|
}
|
|
store.PlaceVote(id, vid, elector, c)
|
|
return ctx.Render(http.StatusFound, "thanks", map[string]interface{}{
|
|
"Id": id,
|
|
"Vid": vid,
|
|
})
|
|
}
|
|
|
|
func handleShowVoting(ctx echo.Context) error {
|
|
v, err := store.GetVoting(ctx.Param("id"))
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return err
|
|
}
|
|
return ctx.Render(http.StatusOK, "voting", map[string]interface{}{
|
|
"Voting": v,
|
|
})
|
|
}
|